From 81b9fe77043193965b4c6125172786333448d0d9 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 19 Oct 2021 21:27:23 +0100 Subject: [PATCH] Add LZMA SDK. --- 3rdparty/CMakeLists.txt | 4 +- 3rdparty/lzma-21.03beta/Asm/arm/7zCrcOpt.asm | 100 + 3rdparty/lzma-21.03beta/Asm/arm64/7zAsm.S | 181 + .../lzma-21.03beta/Asm/arm64/LzmaDecOpt.S | 1487 ++++++ 3rdparty/lzma-21.03beta/Asm/x86/7zAsm.asm | 271 + 3rdparty/lzma-21.03beta/Asm/x86/7zCrcOpt.asm | 180 + 3rdparty/lzma-21.03beta/Asm/x86/AesOpt.asm | 734 +++ 3rdparty/lzma-21.03beta/Asm/x86/LzFindOpt.asm | 513 ++ .../lzma-21.03beta/Asm/x86/LzmaDecOpt.asm | 1303 +++++ 3rdparty/lzma-21.03beta/Asm/x86/Sha256Opt.asm | 263 + .../lzma-21.03beta/Asm/x86/XzCrc64Opt.asm | 239 + 3rdparty/lzma-21.03beta/C/7z.h | 204 + 3rdparty/lzma-21.03beta/C/7zAlloc.c | 80 + 3rdparty/lzma-21.03beta/C/7zAlloc.h | 19 + 3rdparty/lzma-21.03beta/C/7zArcIn.c | 1783 +++++++ 3rdparty/lzma-21.03beta/C/7zBuf.c | 36 + 3rdparty/lzma-21.03beta/C/7zBuf.h | 35 + 3rdparty/lzma-21.03beta/C/7zBuf2.c | 52 + 3rdparty/lzma-21.03beta/C/7zCrc.c | 322 ++ 3rdparty/lzma-21.03beta/C/7zCrc.h | 25 + 3rdparty/lzma-21.03beta/C/7zCrcOpt.c | 117 + 3rdparty/lzma-21.03beta/C/7zDec.c | 600 +++ 3rdparty/lzma-21.03beta/C/7zFile.c | 442 ++ 3rdparty/lzma-21.03beta/C/7zFile.h | 91 + 3rdparty/lzma-21.03beta/C/7zStream.c | 176 + 3rdparty/lzma-21.03beta/C/7zTypes.h | 524 ++ 3rdparty/lzma-21.03beta/C/7zVersion.h | 27 + 3rdparty/lzma-21.03beta/C/7zVersion.rc | 55 + 3rdparty/lzma-21.03beta/C/7zip_gcc_c.mak | 301 ++ 3rdparty/lzma-21.03beta/C/Aes.c | 375 ++ 3rdparty/lzma-21.03beta/C/Aes.h | 60 + 3rdparty/lzma-21.03beta/C/AesOpt.c | 776 +++ 3rdparty/lzma-21.03beta/C/Alloc.c | 463 ++ 3rdparty/lzma-21.03beta/C/Alloc.h | 58 + 3rdparty/lzma-21.03beta/C/Bcj2.c | 257 + 3rdparty/lzma-21.03beta/C/Bcj2.h | 146 + 3rdparty/lzma-21.03beta/C/Bcj2Enc.c | 311 ++ 3rdparty/lzma-21.03beta/C/Bra.c | 230 + 3rdparty/lzma-21.03beta/C/Bra.h | 64 + 3rdparty/lzma-21.03beta/C/Bra86.c | 82 + 3rdparty/lzma-21.03beta/C/BraIA64.c | 53 + 3rdparty/lzma-21.03beta/C/Compiler.h | 43 + 3rdparty/lzma-21.03beta/C/CpuArch.c | 478 ++ 3rdparty/lzma-21.03beta/C/CpuArch.h | 442 ++ 3rdparty/lzma-21.03beta/C/Delta.c | 169 + 3rdparty/lzma-21.03beta/C/Delta.h | 19 + 3rdparty/lzma-21.03beta/C/DllSecur.c | 108 + 3rdparty/lzma-21.03beta/C/DllSecur.h | 20 + 3rdparty/lzma-21.03beta/C/LzFind.c | 1621 ++++++ 3rdparty/lzma-21.03beta/C/LzFind.h | 136 + 3rdparty/lzma-21.03beta/C/LzFindMt.c | 1400 +++++ 3rdparty/lzma-21.03beta/C/LzFindMt.h | 109 + 3rdparty/lzma-21.03beta/C/LzHash.h | 34 + 3rdparty/lzma-21.03beta/C/Lzma2Dec.c | 489 ++ 3rdparty/lzma-21.03beta/C/Lzma2Dec.h | 120 + 3rdparty/lzma-21.03beta/C/Lzma2DecMt.c | 1090 ++++ 3rdparty/lzma-21.03beta/C/Lzma2DecMt.h | 79 + 3rdparty/lzma-21.03beta/C/Lzma2Enc.c | 803 +++ 3rdparty/lzma-21.03beta/C/Lzma2Enc.h | 55 + 3rdparty/lzma-21.03beta/C/Lzma86.h | 111 + 3rdparty/lzma-21.03beta/C/Lzma86Dec.c | 54 + 3rdparty/lzma-21.03beta/C/Lzma86Enc.c | 104 + 3rdparty/lzma-21.03beta/C/LzmaDec.c | 1363 +++++ 3rdparty/lzma-21.03beta/C/LzmaDec.h | 236 + 3rdparty/lzma-21.03beta/C/LzmaEnc.c | 3163 ++++++++++++ 3rdparty/lzma-21.03beta/C/LzmaEnc.h | 78 + 3rdparty/lzma-21.03beta/C/LzmaLib.c | 40 + 3rdparty/lzma-21.03beta/C/LzmaLib.h | 138 + 3rdparty/lzma-21.03beta/C/MtCoder.c | 595 +++ 3rdparty/lzma-21.03beta/C/MtCoder.h | 141 + 3rdparty/lzma-21.03beta/C/MtDec.c | 1139 +++++ 3rdparty/lzma-21.03beta/C/MtDec.h | 202 + 3rdparty/lzma-21.03beta/C/Ppmd.h | 167 + 3rdparty/lzma-21.03beta/C/Ppmd7.c | 1104 ++++ 3rdparty/lzma-21.03beta/C/Ppmd7.h | 181 + 3rdparty/lzma-21.03beta/C/Ppmd7Dec.c | 297 ++ 3rdparty/lzma-21.03beta/C/Ppmd7Enc.c | 323 ++ 3rdparty/lzma-21.03beta/C/Precomp.h | 10 + 3rdparty/lzma-21.03beta/C/RotateDefs.h | 30 + 3rdparty/lzma-21.03beta/C/Sha256.c | 486 ++ 3rdparty/lzma-21.03beta/C/Sha256.h | 76 + 3rdparty/lzma-21.03beta/C/Sha256Opt.c | 373 ++ 3rdparty/lzma-21.03beta/C/Sort.c | 141 + 3rdparty/lzma-21.03beta/C/Sort.h | 18 + 3rdparty/lzma-21.03beta/C/Threads.c | 540 ++ 3rdparty/lzma-21.03beta/C/Threads.h | 203 + 3rdparty/lzma-21.03beta/C/Util/7z/7z.dsp | 241 + 3rdparty/lzma-21.03beta/C/Util/7z/7z.dsw | 29 + 3rdparty/lzma-21.03beta/C/Util/7z/7zMain.c | 887 ++++ 3rdparty/lzma-21.03beta/C/Util/7z/Precomp.c | 4 + 3rdparty/lzma-21.03beta/C/Util/7z/Precomp.h | 10 + 3rdparty/lzma-21.03beta/C/Util/7z/makefile | 40 + .../lzma-21.03beta/C/Util/7z/makefile.gcc | 34 + .../lzma-21.03beta/C/Util/Lzma/LzmaUtil.c | 283 + .../lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsp | 168 + .../lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsw | 29 + 3rdparty/lzma-21.03beta/C/Util/Lzma/makefile | 28 + .../lzma-21.03beta/C/Util/Lzma/makefile.gcc | 19 + .../lzma-21.03beta/C/Util/LzmaLib/LzmaLib.def | 4 + .../lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsp | 182 + .../lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsw | 29 + .../C/Util/LzmaLib/LzmaLibExports.c | 14 + .../lzma-21.03beta/C/Util/LzmaLib/makefile | 35 + .../lzma-21.03beta/C/Util/LzmaLib/resource.rc | 3 + .../lzma-21.03beta/C/Util/SfxSetup/Precomp.c | 4 + .../lzma-21.03beta/C/Util/SfxSetup/Precomp.h | 10 + .../lzma-21.03beta/C/Util/SfxSetup/SfxSetup.c | 640 +++ .../C/Util/SfxSetup/SfxSetup.dsp | 231 + .../C/Util/SfxSetup/SfxSetup.dsw | 29 + .../lzma-21.03beta/C/Util/SfxSetup/makefile | 37 + .../C/Util/SfxSetup/makefile_con | 38 + .../C/Util/SfxSetup/resource.rc | 5 + .../lzma-21.03beta/C/Util/SfxSetup/setup.ico | Bin 0 -> 1078 bytes 3rdparty/lzma-21.03beta/C/Xz.c | 90 + 3rdparty/lzma-21.03beta/C/Xz.h | 517 ++ 3rdparty/lzma-21.03beta/C/XzCrc64.c | 86 + 3rdparty/lzma-21.03beta/C/XzCrc64.h | 26 + 3rdparty/lzma-21.03beta/C/XzCrc64Opt.c | 71 + 3rdparty/lzma-21.03beta/C/XzDec.c | 2836 +++++++++++ 3rdparty/lzma-21.03beta/C/XzEnc.c | 1330 +++++ 3rdparty/lzma-21.03beta/C/XzEnc.h | 60 + 3rdparty/lzma-21.03beta/C/XzIn.c | 324 ++ 3rdparty/lzma-21.03beta/C/var_clang.mak | 11 + 3rdparty/lzma-21.03beta/C/var_clang_arm64.mak | 11 + 3rdparty/lzma-21.03beta/C/var_clang_x64.mak | 11 + 3rdparty/lzma-21.03beta/C/var_clang_x86.mak | 11 + 3rdparty/lzma-21.03beta/C/var_gcc.mak | 12 + 3rdparty/lzma-21.03beta/C/var_gcc_arm64.mak | 12 + 3rdparty/lzma-21.03beta/C/var_gcc_x64.mak | 10 + 3rdparty/lzma-21.03beta/C/var_gcc_x86.mak | 10 + 3rdparty/lzma-21.03beta/C/var_mac_arm64.mak | 11 + 3rdparty/lzma-21.03beta/C/var_mac_x64.mak | 11 + 3rdparty/lzma-21.03beta/C/warn_clang.mak | 37 + 3rdparty/lzma-21.03beta/C/warn_clang_mac.mak | 37 + 3rdparty/lzma-21.03beta/C/warn_gcc.mak | 51 + 3rdparty/lzma-21.03beta/CPP/7zip/7zip.mak | 240 + 3rdparty/lzma-21.03beta/CPP/7zip/7zip_gcc.mak | 1195 +++++ 3rdparty/lzma-21.03beta/CPP/7zip/Aes.mak | 10 + .../CPP/7zip/Archive/7z/7zCompressionMode.cpp | 3 + .../CPP/7zip/Archive/7z/7zCompressionMode.h | 78 + .../CPP/7zip/Archive/7z/7zDecode.cpp | 583 +++ .../CPP/7zip/Archive/7z/7zDecode.h | 70 + .../CPP/7zip/Archive/7z/7zEncode.cpp | 679 +++ .../CPP/7zip/Archive/7z/7zEncode.h | 92 + .../CPP/7zip/Archive/7z/7zExtract.cpp | 428 ++ .../CPP/7zip/Archive/7z/7zFolderInStream.cpp | 139 + .../CPP/7zip/Archive/7z/7zFolderInStream.h | 61 + .../CPP/7zip/Archive/7z/7zHandler.cpp | 778 +++ .../CPP/7zip/Archive/7z/7zHandler.h | 185 + .../CPP/7zip/Archive/7z/7zHandlerOut.cpp | 968 ++++ .../CPP/7zip/Archive/7z/7zHeader.cpp | 19 + .../CPP/7zip/Archive/7z/7zHeader.h | 149 + .../CPP/7zip/Archive/7z/7zIn.cpp | 1710 +++++++ .../lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.h | 451 ++ .../CPP/7zip/Archive/7z/7zItem.h | 202 + .../CPP/7zip/Archive/7z/7zOut.cpp | 961 ++++ .../CPP/7zip/Archive/7z/7zOut.h | 335 ++ .../CPP/7zip/Archive/7z/7zProperties.cpp | 174 + .../CPP/7zip/Archive/7z/7zProperties.h | 22 + .../CPP/7zip/Archive/7z/7zRegister.cpp | 21 + .../CPP/7zip/Archive/7z/7zSpecStream.cpp | 22 + .../CPP/7zip/Archive/7z/7zSpecStream.h | 35 + .../CPP/7zip/Archive/7z/7zUpdate.cpp | 2514 +++++++++ .../CPP/7zip/Archive/7z/7zUpdate.h | 139 + .../CPP/7zip/Archive/7z/StdAfx.cpp | 3 + .../CPP/7zip/Archive/7z/StdAfx.h | 8 + .../CPP/7zip/Archive/Archive.def | 12 + .../CPP/7zip/Archive/Archive2.def | 19 + .../CPP/7zip/Archive/ArchiveExports.cpp | 156 + .../CPP/7zip/Archive/Common/CoderMixer2.cpp | 1142 +++++ .../CPP/7zip/Archive/Common/CoderMixer2.h | 453 ++ .../7zip/Archive/Common/DummyOutStream.cpp | 17 + .../CPP/7zip/Archive/Common/DummyOutStream.h | 25 + .../CPP/7zip/Archive/Common/HandlerOut.cpp | 232 + .../CPP/7zip/Archive/Common/HandlerOut.h | 110 + .../7zip/Archive/Common/InStreamWithCRC.cpp | 46 + .../CPP/7zip/Archive/Common/InStreamWithCRC.h | 67 + .../CPP/7zip/Archive/Common/ItemNameUtils.cpp | 112 + .../CPP/7zip/Archive/Common/ItemNameUtils.h | 28 + .../CPP/7zip/Archive/Common/MultiStream.cpp | 191 + .../CPP/7zip/Archive/Common/MultiStream.h | 89 + .../7zip/Archive/Common/OutStreamWithCRC.cpp | 18 + .../7zip/Archive/Common/OutStreamWithCRC.h | 37 + .../7zip/Archive/Common/ParseProperties.cpp | 3 + .../CPP/7zip/Archive/Common/ParseProperties.h | 6 + .../CPP/7zip/Archive/Common/StdAfx.h | 8 + .../CPP/7zip/Archive/DllExports2.cpp | 157 + .../CPP/7zip/Archive/IArchive.h | 633 +++ .../CPP/7zip/Archive/Icons/7z.ico | Bin 0 -> 4710 bytes .../CPP/7zip/Archive/LzmaHandler.cpp | 624 +++ .../CPP/7zip/Archive/SplitHandler.cpp | 359 ++ .../lzma-21.03beta/CPP/7zip/Archive/StdAfx.h | 8 + .../CPP/7zip/Archive/XzHandler.cpp | 1361 +++++ .../CPP/7zip/Archive/XzHandler.h | 11 + 3rdparty/lzma-21.03beta/CPP/7zip/Asm.mak | 9 + .../CPP/7zip/Bundles/Alone7z/Alone.dsp | 1979 +++++++ .../CPP/7zip/Bundles/Alone7z/Alone.dsw | 29 + .../CPP/7zip/Bundles/Alone7z/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/Alone7z/StdAfx.h | 8 + .../CPP/7zip/Bundles/Alone7z/makefile | 160 + .../CPP/7zip/Bundles/Alone7z/makefile.gcc | 268 + .../CPP/7zip/Bundles/Alone7z/resource.rc | 7 + .../7zip/Bundles/Format7zExtractR/StdAfx.cpp | 3 + .../7zip/Bundles/Format7zExtractR/StdAfx.h | 8 + .../7zip/Bundles/Format7zExtractR/makefile | 96 + .../7zip/Bundles/Format7zExtractR/resource.rc | 5 + .../CPP/7zip/Bundles/Format7zR/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/Format7zR/StdAfx.h | 8 + .../CPP/7zip/Bundles/Format7zR/makefile | 118 + .../CPP/7zip/Bundles/Format7zR/resource.rc | 5 + .../CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | 810 +++ .../CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp | 510 ++ .../CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw | 29 + .../CPP/7zip/Bundles/LzmaCon/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/LzmaCon/StdAfx.h | 8 + .../CPP/7zip/Bundles/LzmaCon/makefile | 63 + .../CPP/7zip/Bundles/LzmaCon/makefile.gcc | 116 + .../CPP/7zip/Bundles/LzmaCon/resource.rc | 3 + .../CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp | 715 +++ .../CPP/7zip/Bundles/SFXCon/7z.ico | Bin 0 -> 1078 bytes .../CPP/7zip/Bundles/SFXCon/SFXCon.dsp | 921 ++++ .../CPP/7zip/Bundles/SFXCon/SFXCon.dsw | 29 + .../CPP/7zip/Bundles/SFXCon/SfxCon.cpp | 504 ++ .../CPP/7zip/Bundles/SFXCon/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/SFXCon/StdAfx.h | 8 + .../CPP/7zip/Bundles/SFXCon/makefile | 133 + .../CPP/7zip/Bundles/SFXCon/makefile.gcc | 204 + .../CPP/7zip/Bundles/SFXCon/resource.rc | 5 + .../Bundles/SFXSetup/ExtractCallbackSfx.cpp | 246 + .../Bundles/SFXSetup/ExtractCallbackSfx.h | 86 + .../7zip/Bundles/SFXSetup/ExtractEngine.cpp | 137 + .../CPP/7zip/Bundles/SFXSetup/ExtractEngine.h | 11 + .../CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp | 803 +++ .../CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw | 29 + .../CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | 366 ++ .../CPP/7zip/Bundles/SFXSetup/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/SFXSetup/StdAfx.h | 13 + .../CPP/7zip/Bundles/SFXSetup/makefile | 117 + .../CPP/7zip/Bundles/SFXSetup/resource.h | 6 + .../CPP/7zip/Bundles/SFXSetup/resource.rc | 16 + .../CPP/7zip/Bundles/SFXSetup/setup.ico | Bin 0 -> 1078 bytes .../CPP/7zip/Bundles/SFXWin/7z.ico | Bin 0 -> 1078 bytes .../CPP/7zip/Bundles/SFXWin/SFXWin.dsp | 997 ++++ .../CPP/7zip/Bundles/SFXWin/SFXWin.dsw | 29 + .../CPP/7zip/Bundles/SFXWin/SfxWin.cpp | 243 + .../CPP/7zip/Bundles/SFXWin/StdAfx.cpp | 3 + .../CPP/7zip/Bundles/SFXWin/StdAfx.h | 14 + .../CPP/7zip/Bundles/SFXWin/makefile | 153 + .../CPP/7zip/Bundles/SFXWin/resource.h | 1 + .../CPP/7zip/Bundles/SFXWin/resource.rc | 50 + .../CPP/7zip/Common/CWrappers.cpp | 347 ++ .../CPP/7zip/Common/CWrappers.h | 182 + .../CPP/7zip/Common/CreateCoder.cpp | 544 ++ .../CPP/7zip/Common/CreateCoder.h | 192 + .../CPP/7zip/Common/FilePathAutoRename.cpp | 46 + .../CPP/7zip/Common/FilePathAutoRename.h | 10 + .../CPP/7zip/Common/FileStreams.cpp | 542 ++ .../CPP/7zip/Common/FileStreams.h | 151 + .../CPP/7zip/Common/FilterCoder.cpp | 436 ++ .../CPP/7zip/Common/FilterCoder.h | 205 + .../CPP/7zip/Common/InBuffer.cpp | 163 + .../lzma-21.03beta/CPP/7zip/Common/InBuffer.h | 109 + .../CPP/7zip/Common/InOutTempBuffer.cpp | 171 + .../CPP/7zip/Common/InOutTempBuffer.h | 66 + .../CPP/7zip/Common/LimitedStreams.cpp | 367 ++ .../CPP/7zip/Common/LimitedStreams.h | 252 + .../CPP/7zip/Common/LockedStream.cpp | 3 + .../CPP/7zip/Common/LockedStream.h | 6 + .../CPP/7zip/Common/MethodId.cpp | 3 + .../lzma-21.03beta/CPP/7zip/Common/MethodId.h | 10 + .../CPP/7zip/Common/MethodProps.cpp | 542 ++ .../CPP/7zip/Common/MethodProps.h | 292 ++ .../CPP/7zip/Common/OffsetStream.cpp | 39 + .../CPP/7zip/Common/OffsetStream.h | 26 + .../CPP/7zip/Common/OutBuffer.cpp | 111 + .../CPP/7zip/Common/OutBuffer.h | 66 + .../CPP/7zip/Common/ProgressUtils.cpp | 51 + .../CPP/7zip/Common/ProgressUtils.h | 35 + .../lzma-21.03beta/CPP/7zip/Common/PropId.cpp | 108 + .../CPP/7zip/Common/RegisterArc.h | 78 + .../CPP/7zip/Common/RegisterCodec.h | 106 + .../lzma-21.03beta/CPP/7zip/Common/StdAfx.h | 8 + .../CPP/7zip/Common/StreamBinder.cpp | 158 + .../CPP/7zip/Common/StreamBinder.h | 78 + .../CPP/7zip/Common/StreamObjects.cpp | 293 ++ .../CPP/7zip/Common/StreamObjects.h | 166 + .../CPP/7zip/Common/StreamUtils.cpp | 56 + .../CPP/7zip/Common/StreamUtils.h | 13 + .../CPP/7zip/Common/UniqBlocks.cpp | 57 + .../CPP/7zip/Common/UniqBlocks.h | 26 + .../CPP/7zip/Common/VirtThread.cpp | 47 + .../CPP/7zip/Common/VirtThread.h | 24 + .../CPP/7zip/Compress/Bcj2Coder.cpp | 666 +++ .../CPP/7zip/Compress/Bcj2Coder.h | 120 + .../CPP/7zip/Compress/Bcj2Register.cpp | 24 + .../CPP/7zip/Compress/BcjCoder.cpp | 24 + .../CPP/7zip/Compress/BcjCoder.h | 31 + .../CPP/7zip/Compress/BcjRegister.cpp | 17 + .../CPP/7zip/Compress/BranchMisc.cpp | 23 + .../CPP/7zip/Compress/BranchMisc.h | 35 + .../CPP/7zip/Compress/BranchRegister.cpp | 41 + .../CPP/7zip/Compress/ByteSwap.cpp | 92 + .../CPP/7zip/Compress/CodecExports.cpp | 368 ++ .../CPP/7zip/Compress/CopyCoder.cpp | 120 + .../CPP/7zip/Compress/CopyCoder.h | 49 + .../CPP/7zip/Compress/CopyRegister.cpp | 15 + .../CPP/7zip/Compress/DeltaFilter.cpp | 128 + .../CPP/7zip/Compress/Lzma2Decoder.cpp | 265 + .../CPP/7zip/Compress/Lzma2Decoder.h | 96 + .../CPP/7zip/Compress/Lzma2Encoder.cpp | 126 + .../CPP/7zip/Compress/Lzma2Encoder.h | 42 + .../CPP/7zip/Compress/Lzma2Register.cpp | 22 + .../CPP/7zip/Compress/LzmaDecoder.cpp | 346 ++ .../CPP/7zip/Compress/LzmaDecoder.h | 113 + .../CPP/7zip/Compress/LzmaEncoder.cpp | 346 ++ .../CPP/7zip/Compress/LzmaEncoder.h | 46 + .../CPP/7zip/Compress/LzmaRegister.cpp | 22 + .../CPP/7zip/Compress/PpmdDecoder.cpp | 220 + .../CPP/7zip/Compress/PpmdDecoder.h | 91 + .../CPP/7zip/Compress/PpmdEncoder.cpp | 193 + .../CPP/7zip/Compress/PpmdEncoder.h | 57 + .../CPP/7zip/Compress/PpmdRegister.cpp | 22 + .../lzma-21.03beta/CPP/7zip/Compress/StdAfx.h | 8 + .../CPP/7zip/Compress/XzDecoder.cpp | 150 + .../CPP/7zip/Compress/XzDecoder.h | 93 + .../CPP/7zip/Compress/XzEncoder.cpp | 245 + .../CPP/7zip/Compress/XzEncoder.h | 46 + 3rdparty/lzma-21.03beta/CPP/7zip/Crc.mak | 8 + 3rdparty/lzma-21.03beta/CPP/7zip/Crc64.mak | 8 + .../lzma-21.03beta/CPP/7zip/Crypto/7zAes.cpp | 317 ++ .../lzma-21.03beta/CPP/7zip/Crypto/7zAes.h | 129 + .../CPP/7zip/Crypto/7zAesRegister.cpp | 17 + .../lzma-21.03beta/CPP/7zip/Crypto/MyAes.cpp | 205 + .../lzma-21.03beta/CPP/7zip/Crypto/MyAes.h | 79 + .../CPP/7zip/Crypto/MyAesReg.cpp | 30 + .../CPP/7zip/Crypto/RandGen.cpp | 237 + .../lzma-21.03beta/CPP/7zip/Crypto/RandGen.h | 40 + .../lzma-21.03beta/CPP/7zip/Crypto/StdAfx.h | 8 + 3rdparty/lzma-21.03beta/CPP/7zip/GuiCommon.rc | 84 + 3rdparty/lzma-21.03beta/CPP/7zip/Guid.txt | 222 + 3rdparty/lzma-21.03beta/CPP/7zip/ICoder.h | 432 ++ 3rdparty/lzma-21.03beta/CPP/7zip/IDecl.h | 28 + 3rdparty/lzma-21.03beta/CPP/7zip/IPassword.h | 53 + 3rdparty/lzma-21.03beta/CPP/7zip/IProgress.h | 19 + 3rdparty/lzma-21.03beta/CPP/7zip/IStream.h | 136 + .../lzma-21.03beta/CPP/7zip/LzFindOpt.mak | 7 + 3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec.mak | 7 + .../lzma-21.03beta/CPP/7zip/LzmaDec_gcc.mak | 14 + 3rdparty/lzma-21.03beta/CPP/7zip/MyVersion.h | 2 + .../lzma-21.03beta/CPP/7zip/MyVersionInfo.rc | 2 + 3rdparty/lzma-21.03beta/CPP/7zip/PropID.h | 127 + 3rdparty/lzma-21.03beta/CPP/7zip/Sha256.mak | 13 + 3rdparty/lzma-21.03beta/CPP/7zip/SubBuild.mak | 3 + .../CPP/7zip/UI/Client7z/Client7z.cpp | 1048 ++++ .../CPP/7zip/UI/Client7z/Client7z.dsp | 235 + .../CPP/7zip/UI/Client7z/Client7z.dsw | 29 + .../CPP/7zip/UI/Client7z/StdAfx.cpp | 3 + .../CPP/7zip/UI/Client7z/StdAfx.h | 8 + .../CPP/7zip/UI/Client7z/makefile | 28 + .../CPP/7zip/UI/Client7z/makefile.gcc | 59 + .../CPP/7zip/UI/Client7z/resource.rc | 3 + .../CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1480 ++++++ .../CPP/7zip/UI/Common/ArchiveCommandLine.h | 154 + .../7zip/UI/Common/ArchiveExtractCallback.cpp | 2192 ++++++++ .../7zip/UI/Common/ArchiveExtractCallback.h | 500 ++ .../CPP/7zip/UI/Common/ArchiveName.cpp | 155 + .../CPP/7zip/UI/Common/ArchiveName.h | 10 + .../7zip/UI/Common/ArchiveOpenCallback.cpp | 158 + .../CPP/7zip/UI/Common/ArchiveOpenCallback.h | 117 + .../CPP/7zip/UI/Common/Bench.cpp | 4535 +++++++++++++++++ .../lzma-21.03beta/CPP/7zip/UI/Common/Bench.h | 122 + .../CPP/7zip/UI/Common/DefaultName.cpp | 37 + .../CPP/7zip/UI/Common/DefaultName.h | 11 + .../CPP/7zip/UI/Common/DirItem.h | 212 + .../CPP/7zip/UI/Common/EnumDirItems.cpp | 1403 +++++ .../CPP/7zip/UI/Common/EnumDirItems.h | 38 + .../CPP/7zip/UI/Common/ExitCode.h | 27 + .../CPP/7zip/UI/Common/Extract.cpp | 503 ++ .../CPP/7zip/UI/Common/Extract.h | 94 + .../CPP/7zip/UI/Common/ExtractMode.h | 34 + .../CPP/7zip/UI/Common/ExtractingFilePath.cpp | 287 ++ .../CPP/7zip/UI/Common/ExtractingFilePath.h | 31 + .../CPP/7zip/UI/Common/HashCalc.cpp | 366 ++ .../CPP/7zip/UI/Common/HashCalc.h | 120 + .../CPP/7zip/UI/Common/IFileExtractCallback.h | 114 + .../CPP/7zip/UI/Common/LoadCodecs.cpp | 1205 +++++ .../CPP/7zip/UI/Common/LoadCodecs.h | 436 ++ .../CPP/7zip/UI/Common/OpenArchive.cpp | 3626 +++++++++++++ .../CPP/7zip/UI/Common/OpenArchive.h | 443 ++ .../CPP/7zip/UI/Common/PropIDUtils.cpp | 696 +++ .../CPP/7zip/UI/Common/PropIDUtils.h | 18 + .../CPP/7zip/UI/Common/Property.h | 14 + .../CPP/7zip/UI/Common/SetProperties.cpp | 87 + .../CPP/7zip/UI/Common/SetProperties.h | 10 + .../CPP/7zip/UI/Common/SortUtils.cpp | 25 + .../CPP/7zip/UI/Common/SortUtils.h | 10 + .../CPP/7zip/UI/Common/StdAfx.h | 8 + .../CPP/7zip/UI/Common/TempFiles.cpp | 19 + .../CPP/7zip/UI/Common/TempFiles.h | 16 + .../CPP/7zip/UI/Common/Update.cpp | 1705 +++++++ .../CPP/7zip/UI/Common/Update.h | 208 + .../CPP/7zip/UI/Common/UpdateAction.cpp | 64 + .../CPP/7zip/UI/Common/UpdateAction.h | 66 + .../CPP/7zip/UI/Common/UpdateCallback.cpp | 834 +++ .../CPP/7zip/UI/Common/UpdateCallback.h | 163 + .../CPP/7zip/UI/Common/UpdatePair.cpp | 235 + .../CPP/7zip/UI/Common/UpdatePair.h | 27 + .../CPP/7zip/UI/Common/UpdateProduce.cpp | 70 + .../CPP/7zip/UI/Common/UpdateProduce.h | 55 + .../CPP/7zip/UI/Common/WorkDir.cpp | 93 + .../CPP/7zip/UI/Common/WorkDir.h | 26 + .../CPP/7zip/UI/Common/ZipRegistry.h | 130 + .../CPP/7zip/UI/Console/BenchCon.cpp | 41 + .../CPP/7zip/UI/Console/BenchCon.h | 14 + .../CPP/7zip/UI/Console/Console.mak | 43 + .../CPP/7zip/UI/Console/Console.manifest | 13 + .../CPP/7zip/UI/Console/ConsoleClose.cpp | 100 + .../CPP/7zip/UI/Console/ConsoleClose.h | 39 + .../UI/Console/ExtractCallbackConsole.cpp | 834 +++ .../7zip/UI/Console/ExtractCallbackConsole.h | 167 + .../CPP/7zip/UI/Console/HashCon.cpp | 363 ++ .../CPP/7zip/UI/Console/HashCon.h | 48 + .../CPP/7zip/UI/Console/List.cpp | 1361 +++++ .../lzma-21.03beta/CPP/7zip/UI/Console/List.h | 27 + .../CPP/7zip/UI/Console/Main.cpp | 1457 ++++++ .../CPP/7zip/UI/Console/MainAr.cpp | 181 + .../7zip/UI/Console/OpenCallbackConsole.cpp | 115 + .../CPP/7zip/UI/Console/OpenCallbackConsole.h | 68 + .../CPP/7zip/UI/Console/PercentPrinter.cpp | 183 + .../CPP/7zip/UI/Console/PercentPrinter.h | 62 + .../CPP/7zip/UI/Console/StdAfx.cpp | 3 + .../CPP/7zip/UI/Console/StdAfx.h | 8 + .../7zip/UI/Console/UpdateCallbackConsole.cpp | 709 +++ .../7zip/UI/Console/UpdateCallbackConsole.h | 127 + .../CPP/7zip/UI/Console/UserInputUtils.cpp | 110 + .../CPP/7zip/UI/Console/UserInputUtils.h | 27 + .../CPP/7zip/UI/Console/makefile | 65 + .../CPP/7zip/UI/Console/makefile.gcc | 171 + .../CPP/7zip/UI/Console/resource.rc | 7 + .../CPP/7zip/UI/Explorer/MyMessages.cpp | 37 + .../CPP/7zip/UI/Explorer/MyMessages.h | 16 + .../CPP/7zip/UI/FileManager/BrowseDialog.cpp | 1025 ++++ .../CPP/7zip/UI/FileManager/BrowseDialog.h | 21 + .../CPP/7zip/UI/FileManager/BrowseDialogRes.h | 9 + .../CPP/7zip/UI/FileManager/ComboDialog.cpp | 64 + .../CPP/7zip/UI/FileManager/ComboDialog.h | 28 + .../CPP/7zip/UI/FileManager/ComboDialogRes.h | 4 + .../CPP/7zip/UI/FileManager/DialogSize.h | 16 + .../7zip/UI/FileManager/ExtractCallback.cpp | 1045 ++++ .../CPP/7zip/UI/FileManager/ExtractCallback.h | 326 ++ .../CPP/7zip/UI/FileManager/FormatUtils.cpp | 28 + .../CPP/7zip/UI/FileManager/FormatUtils.h | 14 + .../CPP/7zip/UI/FileManager/LangUtils.h | 40 + .../CPP/7zip/UI/FileManager/MyWindowsNew.h | 76 + .../7zip/UI/FileManager/OverwriteDialog.cpp | 138 + .../CPP/7zip/UI/FileManager/OverwriteDialog.h | 79 + .../7zip/UI/FileManager/OverwriteDialog.rc | 91 + .../7zip/UI/FileManager/OverwriteDialogRes.h | 17 + .../7zip/UI/FileManager/PasswordDialog.cpp | 58 + .../CPP/7zip/UI/FileManager/PasswordDialog.h | 28 + .../CPP/7zip/UI/FileManager/PasswordDialog.rc | 14 + .../7zip/UI/FileManager/PasswordDialogRes.h | 5 + .../7zip/UI/FileManager/ProgressDialog.cpp | 199 + .../CPP/7zip/UI/FileManager/ProgressDialog.h | 170 + .../CPP/7zip/UI/FileManager/ProgressDialog.rc | 12 + .../7zip/UI/FileManager/ProgressDialog2.cpp | 1355 +++++ .../CPP/7zip/UI/FileManager/ProgressDialog2.h | 353 ++ .../7zip/UI/FileManager/ProgressDialog2.rc | 40 + .../7zip/UI/FileManager/ProgressDialog2Res.h | 49 + .../7zip/UI/FileManager/ProgressDialog2a.rc | 85 + .../7zip/UI/FileManager/ProgressDialogRes.h | 3 + .../CPP/7zip/UI/FileManager/PropertyName.cpp | 23 + .../CPP/7zip/UI/FileManager/PropertyName.h | 10 + .../CPP/7zip/UI/FileManager/PropertyNameRes.h | 95 + .../CPP/7zip/UI/FileManager/SysIconUtils.cpp | 255 + .../CPP/7zip/UI/FileManager/SysIconUtils.h | 62 + .../CPP/7zip/UI/FileManager/resource.h | 182 + .../CPP/7zip/UI/FileManager/resourceGui.h | 15 + .../lzma-21.03beta/CPP/7zip/UI/GUI/Extract.rc | 59 + .../CPP/7zip/UI/GUI/ExtractDialog.cpp | 421 ++ .../CPP/7zip/UI/GUI/ExtractDialog.h | 113 + .../CPP/7zip/UI/GUI/ExtractDialog.rc | 98 + .../CPP/7zip/UI/GUI/ExtractDialogRes.h | 24 + .../CPP/7zip/UI/GUI/ExtractGUI.cpp | 280 + .../CPP/7zip/UI/GUI/ExtractGUI.h | 38 + .../CPP/7zip/UI/GUI/ExtractRes.h | 51 + .../lzma-21.03beta/CPP/7zip/UI/GUI/HashGUI.h | 27 + .../CPP/7zip/UI/GUI/resource2.h | 2 + .../lzma-21.03beta/CPP/7zip/cmpl_clang.mak | 3 + .../CPP/7zip/cmpl_clang_arm64.mak | 3 + .../CPP/7zip/cmpl_clang_x64.mak | 3 + .../CPP/7zip/cmpl_clang_x86.mak | 3 + 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc.mak | 3 + .../CPP/7zip/cmpl_gcc_arm64.mak | 3 + .../lzma-21.03beta/CPP/7zip/cmpl_gcc_x64.mak | 3 + .../lzma-21.03beta/CPP/7zip/cmpl_gcc_x86.mak | 3 + .../CPP/7zip/cmpl_mac_arm64.mak | 3 + .../lzma-21.03beta/CPP/7zip/cmpl_mac_x64.mak | 3 + .../lzma-21.03beta/CPP/7zip/var_clang.mak | 11 + .../CPP/7zip/var_clang_arm64.mak | 11 + .../lzma-21.03beta/CPP/7zip/var_clang_x64.mak | 12 + .../lzma-21.03beta/CPP/7zip/var_clang_x86.mak | 12 + 3rdparty/lzma-21.03beta/CPP/7zip/var_gcc.mak | 12 + .../lzma-21.03beta/CPP/7zip/var_gcc_arm64.mak | 12 + .../lzma-21.03beta/CPP/7zip/var_gcc_x64.mak | 10 + .../lzma-21.03beta/CPP/7zip/var_gcc_x86.mak | 11 + .../lzma-21.03beta/CPP/7zip/var_mac_arm64.mak | 11 + .../lzma-21.03beta/CPP/7zip/var_mac_x64.mak | 11 + .../lzma-21.03beta/CPP/7zip/warn_clang.mak | 37 + .../CPP/7zip/warn_clang_mac.mak | 39 + 3rdparty/lzma-21.03beta/CPP/7zip/warn_gcc.mak | 57 + 3rdparty/lzma-21.03beta/CPP/Build.mak | 200 + 3rdparty/lzma-21.03beta/CPP/Common/AutoPtr.h | 35 + 3rdparty/lzma-21.03beta/CPP/Common/CRC.cpp | 7 + .../lzma-21.03beta/CPP/Common/C_FileIO.cpp | 3 + 3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.h | 6 + 3rdparty/lzma-21.03beta/CPP/Common/ComTry.h | 21 + .../CPP/Common/CommandLineParser.cpp | 197 + .../CPP/Common/CommandLineParser.h | 63 + 3rdparty/lzma-21.03beta/CPP/Common/Common.h | 57 + 3rdparty/lzma-21.03beta/CPP/Common/CrcReg.cpp | 95 + 3rdparty/lzma-21.03beta/CPP/Common/Defs.h | 16 + .../lzma-21.03beta/CPP/Common/DynamicBuffer.h | 64 + .../lzma-21.03beta/CPP/Common/IntToString.cpp | 192 + .../lzma-21.03beta/CPP/Common/IntToString.h | 30 + 3rdparty/lzma-21.03beta/CPP/Common/Lang.h | 23 + .../CPP/Common/ListFileUtils.cpp | 150 + .../lzma-21.03beta/CPP/Common/ListFileUtils.h | 18 + .../CPP/Common/LzFindPrepare.cpp | 7 + 3rdparty/lzma-21.03beta/CPP/Common/MyBuffer.h | 277 + .../lzma-21.03beta/CPP/Common/MyBuffer2.h | 139 + 3rdparty/lzma-21.03beta/CPP/Common/MyCom.h | 306 ++ .../lzma-21.03beta/CPP/Common/MyException.h | 14 + .../lzma-21.03beta/CPP/Common/MyGuidDef.h | 57 + .../lzma-21.03beta/CPP/Common/MyInitGuid.h | 49 + 3rdparty/lzma-21.03beta/CPP/Common/MyLinux.h | 42 + .../lzma-21.03beta/CPP/Common/MyString.cpp | 1722 +++++++ 3rdparty/lzma-21.03beta/CPP/Common/MyString.h | 932 ++++ 3rdparty/lzma-21.03beta/CPP/Common/MyTypes.h | 46 + .../lzma-21.03beta/CPP/Common/MyUnknown.h | 17 + .../lzma-21.03beta/CPP/Common/MyVector.cpp | 3 + 3rdparty/lzma-21.03beta/CPP/Common/MyVector.h | 634 +++ .../lzma-21.03beta/CPP/Common/MyWindows.cpp | 292 ++ .../lzma-21.03beta/CPP/Common/MyWindows.h | 268 + .../lzma-21.03beta/CPP/Common/NewHandler.cpp | 163 + .../lzma-21.03beta/CPP/Common/NewHandler.h | 88 + .../CPP/Common/Sha256Prepare.cpp | 7 + .../lzma-21.03beta/CPP/Common/Sha256Reg.cpp | 70 + 3rdparty/lzma-21.03beta/CPP/Common/StdAfx.h | 8 + .../lzma-21.03beta/CPP/Common/StdInStream.cpp | 95 + .../lzma-21.03beta/CPP/Common/StdInStream.h | 44 + .../CPP/Common/StdOutStream.cpp | 158 + .../lzma-21.03beta/CPP/Common/StdOutStream.h | 76 + .../CPP/Common/StringConvert.cpp | 757 +++ .../lzma-21.03beta/CPP/Common/StringConvert.h | 110 + .../lzma-21.03beta/CPP/Common/StringToInt.cpp | 144 + .../lzma-21.03beta/CPP/Common/StringToInt.h | 21 + .../lzma-21.03beta/CPP/Common/TextConfig.cpp | 124 + .../lzma-21.03beta/CPP/Common/TextConfig.h | 19 + .../lzma-21.03beta/CPP/Common/UTFConvert.cpp | 863 ++++ .../lzma-21.03beta/CPP/Common/UTFConvert.h | 384 ++ .../lzma-21.03beta/CPP/Common/Wildcard.cpp | 708 +++ 3rdparty/lzma-21.03beta/CPP/Common/Wildcard.h | 177 + .../lzma-21.03beta/CPP/Common/XzCrc64Init.cpp | 7 + .../lzma-21.03beta/CPP/Common/XzCrc64Reg.cpp | 42 + 3rdparty/lzma-21.03beta/CPP/Windows/COM.h | 70 + .../CPP/Windows/CommonDialog.cpp | 208 + .../lzma-21.03beta/CPP/Windows/CommonDialog.h | 23 + .../CPP/Windows/Control/ComboBox.cpp | 66 + .../CPP/Windows/Control/ComboBox.h | 77 + .../CPP/Windows/Control/CommandBar.h | 52 + .../CPP/Windows/Control/Dialog.cpp | 260 + .../CPP/Windows/Control/Dialog.h | 190 + .../lzma-21.03beta/CPP/Windows/Control/Edit.h | 19 + .../CPP/Windows/Control/ImageList.cpp | 10 + .../CPP/Windows/Control/ImageList.h | 87 + .../CPP/Windows/Control/ListView.cpp | 155 + .../CPP/Windows/Control/ListView.h | 147 + .../CPP/Windows/Control/ProgressBar.h | 35 + .../CPP/Windows/Control/PropertyPage.cpp | 143 + .../CPP/Windows/Control/PropertyPage.h | 50 + .../CPP/Windows/Control/ReBar.h | 34 + .../CPP/Windows/Control/Static.h | 28 + .../CPP/Windows/Control/StatusBar.h | 42 + .../CPP/Windows/Control/StdAfx.h | 8 + .../CPP/Windows/Control/ToolBar.h | 43 + .../CPP/Windows/Control/Trackbar.h | 27 + .../CPP/Windows/Control/Window2.cpp | 200 + .../CPP/Windows/Control/Window2.h | 51 + 3rdparty/lzma-21.03beta/CPP/Windows/DLL.cpp | 191 + 3rdparty/lzma-21.03beta/CPP/Windows/DLL.h | 84 + 3rdparty/lzma-21.03beta/CPP/Windows/Defs.h | 18 + .../lzma-21.03beta/CPP/Windows/ErrorMsg.cpp | 133 + .../lzma-21.03beta/CPP/Windows/ErrorMsg.h | 16 + .../lzma-21.03beta/CPP/Windows/FileDir.cpp | 1078 ++++ 3rdparty/lzma-21.03beta/CPP/Windows/FileDir.h | 125 + .../lzma-21.03beta/CPP/Windows/FileFind.cpp | 1216 +++++ .../lzma-21.03beta/CPP/Windows/FileFind.h | 279 + .../lzma-21.03beta/CPP/Windows/FileIO.cpp | 730 +++ 3rdparty/lzma-21.03beta/CPP/Windows/FileIO.h | 330 ++ .../lzma-21.03beta/CPP/Windows/FileLink.cpp | 613 +++ .../CPP/Windows/FileMapping.cpp | 12 + .../lzma-21.03beta/CPP/Windows/FileMapping.h | 66 + .../lzma-21.03beta/CPP/Windows/FileName.cpp | 885 ++++ .../lzma-21.03beta/CPP/Windows/FileName.h | 119 + .../lzma-21.03beta/CPP/Windows/FileSystem.cpp | 135 + .../lzma-21.03beta/CPP/Windows/FileSystem.h | 31 + 3rdparty/lzma-21.03beta/CPP/Windows/Handle.h | 39 + .../lzma-21.03beta/CPP/Windows/MemoryLock.cpp | 112 + .../lzma-21.03beta/CPP/Windows/MemoryLock.h | 40 + 3rdparty/lzma-21.03beta/CPP/Windows/NtCheck.h | 48 + .../CPP/Windows/PropVariant.cpp | 349 ++ .../lzma-21.03beta/CPP/Windows/PropVariant.h | 114 + .../CPP/Windows/PropVariantConv.cpp | 138 + .../CPP/Windows/PropVariantConv.h | 37 + .../lzma-21.03beta/CPP/Windows/Registry.cpp | 406 ++ .../lzma-21.03beta/CPP/Windows/Registry.h | 84 + .../CPP/Windows/ResourceString.cpp | 103 + .../CPP/Windows/ResourceString.h | 16 + .../CPP/Windows/SecurityUtils.cpp | 181 + .../CPP/Windows/SecurityUtils.h | 167 + 3rdparty/lzma-21.03beta/CPP/Windows/Shell.cpp | 358 ++ 3rdparty/lzma-21.03beta/CPP/Windows/Shell.h | 94 + 3rdparty/lzma-21.03beta/CPP/Windows/StdAfx.h | 8 + .../CPP/Windows/Synchronization.cpp | 63 + .../CPP/Windows/Synchronization.h | 393 ++ .../lzma-21.03beta/CPP/Windows/System.cpp | 231 + 3rdparty/lzma-21.03beta/CPP/Windows/System.h | 129 + .../lzma-21.03beta/CPP/Windows/SystemInfo.cpp | 897 ++++ .../lzma-21.03beta/CPP/Windows/SystemInfo.h | 18 + 3rdparty/lzma-21.03beta/CPP/Windows/Thread.h | 44 + .../lzma-21.03beta/CPP/Windows/TimeUtils.cpp | 234 + .../lzma-21.03beta/CPP/Windows/TimeUtils.h | 32 + .../lzma-21.03beta/CPP/Windows/Window.cpp | 179 + 3rdparty/lzma-21.03beta/CPP/Windows/Window.h | 284 ++ 3rdparty/lzma-21.03beta/CS/7zip/Common/CRC.cs | 55 + .../CS/7zip/Common/CommandLineParser.cs | 274 + .../lzma-21.03beta/CS/7zip/Common/InBuffer.cs | 72 + .../CS/7zip/Common/OutBuffer.cs | 47 + .../CS/7zip/Compress/LZ/IMatchFinder.cs | 24 + .../CS/7zip/Compress/LZ/LzBinTree.cs | 367 ++ .../CS/7zip/Compress/LZ/LzInWindow.cs | 132 + .../CS/7zip/Compress/LZ/LzOutWindow.cs | 110 + .../CS/7zip/Compress/LZMA/LzmaBase.cs | 76 + .../CS/7zip/Compress/LZMA/LzmaDecoder.cs | 398 ++ .../CS/7zip/Compress/LZMA/LzmaEncoder.cs | 1480 ++++++ .../CS/7zip/Compress/LzmaAlone/LzmaAlone.cs | 364 ++ .../CS/7zip/Compress/LzmaAlone/LzmaAlone.sln | 20 + .../CS/7zip/Compress/LzmaAlone/LzmaBench.cs | 340 ++ .../LzmaAlone/Properties/AssemblyInfo.cs | 29 + .../LzmaAlone/Properties/Resources.cs | 70 + .../Compress/LzmaAlone/Properties/Settings.cs | 42 + .../CS/7zip/Compress/RangeCoder/RangeCoder.cs | 234 + .../7zip/Compress/RangeCoder/RangeCoderBit.cs | 117 + .../Compress/RangeCoder/RangeCoderBitTree.cs | 157 + 3rdparty/lzma-21.03beta/CS/7zip/ICoder.cs | 157 + 3rdparty/lzma-21.03beta/DOC/7zC.txt | 187 + 3rdparty/lzma-21.03beta/DOC/7zFormat.txt | 469 ++ 3rdparty/lzma-21.03beta/DOC/Methods.txt | 173 + 3rdparty/lzma-21.03beta/DOC/installer.txt | 166 + 3rdparty/lzma-21.03beta/DOC/lzma-history.txt | 490 ++ 3rdparty/lzma-21.03beta/DOC/lzma-sdk.txt | 404 ++ .../lzma-21.03beta/DOC/lzma-specification.txt | 1176 +++++ 3rdparty/lzma-21.03beta/DOC/lzma.txt | 328 ++ .../lzma-21.03beta/Java/SevenZip/CRC.java | 52 + .../Java/SevenZip/Compression/LZ/BinTree.java | 382 ++ .../SevenZip/Compression/LZ/InWindow.java | 131 + .../SevenZip/Compression/LZ/OutWindow.java | 85 + .../Java/SevenZip/Compression/LZMA/Base.java | 88 + .../SevenZip/Compression/LZMA/Decoder.java | 329 ++ .../SevenZip/Compression/LZMA/Encoder.java | 1416 +++++ .../RangeCoder/BitTreeDecoder.java | 55 + .../RangeCoder/BitTreeEncoder.java | 99 + .../Compression/RangeCoder/Decoder.java | 88 + .../Compression/RangeCoder/Encoder.java | 151 + .../Java/SevenZip/ICodeProgress.java | 6 + .../Java/SevenZip/LzmaAlone.java | 253 + .../Java/SevenZip/LzmaBench.java | 392 ++ 3rdparty/lzma-21.03beta/bin/7zS2.sfx | Bin 0 -> 35328 bytes 3rdparty/lzma-21.03beta/bin/7zS2con.sfx | Bin 0 -> 34816 bytes 3rdparty/lzma-21.03beta/bin/7zSD.sfx | Bin 0 -> 125952 bytes 3rdparty/lzma-21.03beta/bin/7zdec.exe | Bin 0 -> 43008 bytes 3rdparty/lzma-21.03beta/bin/7zr.exe | Bin 0 -> 544256 bytes .../lzma-21.03beta/bin/installer/config.txt | 5 + 3rdparty/lzma-21.03beta/bin/installer/cr.bat | 5 + 3rdparty/lzma-21.03beta/bin/lzma.exe | Bin 0 -> 121344 bytes 3rdparty/lzma-21.03beta/bin/x64/7zr.exe | Bin 0 -> 833024 bytes 3rdparty/lzma.cmake | 142 + CMakeLists.txt | 2 +- tests/CMakeLists.txt | 5 +- tests/data/lzfse.bin | Bin 0 -> 1059299 bytes tests/data/lzma.bin | Bin 0 -> 1200275 bytes tests/data/zstd.zst | Bin 0 -> 1048613 bytes tests/lzma.cpp | 82 + 694 files changed, 154058 insertions(+), 3 deletions(-) create mode 100644 3rdparty/lzma-21.03beta/Asm/arm/7zCrcOpt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/arm64/7zAsm.S create mode 100644 3rdparty/lzma-21.03beta/Asm/arm64/LzmaDecOpt.S create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/7zAsm.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/7zCrcOpt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/AesOpt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/LzFindOpt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/LzmaDecOpt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/Sha256Opt.asm create mode 100644 3rdparty/lzma-21.03beta/Asm/x86/XzCrc64Opt.asm create mode 100644 3rdparty/lzma-21.03beta/C/7z.h create mode 100644 3rdparty/lzma-21.03beta/C/7zAlloc.c create mode 100644 3rdparty/lzma-21.03beta/C/7zAlloc.h create mode 100644 3rdparty/lzma-21.03beta/C/7zArcIn.c create mode 100644 3rdparty/lzma-21.03beta/C/7zBuf.c create mode 100644 3rdparty/lzma-21.03beta/C/7zBuf.h create mode 100644 3rdparty/lzma-21.03beta/C/7zBuf2.c create mode 100644 3rdparty/lzma-21.03beta/C/7zCrc.c create mode 100644 3rdparty/lzma-21.03beta/C/7zCrc.h create mode 100644 3rdparty/lzma-21.03beta/C/7zCrcOpt.c create mode 100644 3rdparty/lzma-21.03beta/C/7zDec.c create mode 100644 3rdparty/lzma-21.03beta/C/7zFile.c create mode 100644 3rdparty/lzma-21.03beta/C/7zFile.h create mode 100644 3rdparty/lzma-21.03beta/C/7zStream.c create mode 100644 3rdparty/lzma-21.03beta/C/7zTypes.h create mode 100644 3rdparty/lzma-21.03beta/C/7zVersion.h create mode 100644 3rdparty/lzma-21.03beta/C/7zVersion.rc create mode 100644 3rdparty/lzma-21.03beta/C/7zip_gcc_c.mak create mode 100644 3rdparty/lzma-21.03beta/C/Aes.c create mode 100644 3rdparty/lzma-21.03beta/C/Aes.h create mode 100644 3rdparty/lzma-21.03beta/C/AesOpt.c create mode 100644 3rdparty/lzma-21.03beta/C/Alloc.c create mode 100644 3rdparty/lzma-21.03beta/C/Alloc.h create mode 100644 3rdparty/lzma-21.03beta/C/Bcj2.c create mode 100644 3rdparty/lzma-21.03beta/C/Bcj2.h create mode 100644 3rdparty/lzma-21.03beta/C/Bcj2Enc.c create mode 100644 3rdparty/lzma-21.03beta/C/Bra.c create mode 100644 3rdparty/lzma-21.03beta/C/Bra.h create mode 100644 3rdparty/lzma-21.03beta/C/Bra86.c create mode 100644 3rdparty/lzma-21.03beta/C/BraIA64.c create mode 100644 3rdparty/lzma-21.03beta/C/Compiler.h create mode 100644 3rdparty/lzma-21.03beta/C/CpuArch.c create mode 100644 3rdparty/lzma-21.03beta/C/CpuArch.h create mode 100644 3rdparty/lzma-21.03beta/C/Delta.c create mode 100644 3rdparty/lzma-21.03beta/C/Delta.h create mode 100644 3rdparty/lzma-21.03beta/C/DllSecur.c create mode 100644 3rdparty/lzma-21.03beta/C/DllSecur.h create mode 100644 3rdparty/lzma-21.03beta/C/LzFind.c create mode 100644 3rdparty/lzma-21.03beta/C/LzFind.h create mode 100644 3rdparty/lzma-21.03beta/C/LzFindMt.c create mode 100644 3rdparty/lzma-21.03beta/C/LzFindMt.h create mode 100644 3rdparty/lzma-21.03beta/C/LzHash.h create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2Dec.c create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2Dec.h create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2DecMt.c create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2DecMt.h create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2Enc.c create mode 100644 3rdparty/lzma-21.03beta/C/Lzma2Enc.h create mode 100644 3rdparty/lzma-21.03beta/C/Lzma86.h create mode 100644 3rdparty/lzma-21.03beta/C/Lzma86Dec.c create mode 100644 3rdparty/lzma-21.03beta/C/Lzma86Enc.c create mode 100644 3rdparty/lzma-21.03beta/C/LzmaDec.c create mode 100644 3rdparty/lzma-21.03beta/C/LzmaDec.h create mode 100644 3rdparty/lzma-21.03beta/C/LzmaEnc.c create mode 100644 3rdparty/lzma-21.03beta/C/LzmaEnc.h create mode 100644 3rdparty/lzma-21.03beta/C/LzmaLib.c create mode 100644 3rdparty/lzma-21.03beta/C/LzmaLib.h create mode 100644 3rdparty/lzma-21.03beta/C/MtCoder.c create mode 100644 3rdparty/lzma-21.03beta/C/MtCoder.h create mode 100644 3rdparty/lzma-21.03beta/C/MtDec.c create mode 100644 3rdparty/lzma-21.03beta/C/MtDec.h create mode 100644 3rdparty/lzma-21.03beta/C/Ppmd.h create mode 100644 3rdparty/lzma-21.03beta/C/Ppmd7.c create mode 100644 3rdparty/lzma-21.03beta/C/Ppmd7.h create mode 100644 3rdparty/lzma-21.03beta/C/Ppmd7Dec.c create mode 100644 3rdparty/lzma-21.03beta/C/Ppmd7Enc.c create mode 100644 3rdparty/lzma-21.03beta/C/Precomp.h create mode 100644 3rdparty/lzma-21.03beta/C/RotateDefs.h create mode 100644 3rdparty/lzma-21.03beta/C/Sha256.c create mode 100644 3rdparty/lzma-21.03beta/C/Sha256.h create mode 100644 3rdparty/lzma-21.03beta/C/Sha256Opt.c create mode 100644 3rdparty/lzma-21.03beta/C/Sort.c create mode 100644 3rdparty/lzma-21.03beta/C/Sort.h create mode 100644 3rdparty/lzma-21.03beta/C/Threads.c create mode 100644 3rdparty/lzma-21.03beta/C/Threads.h create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/7z.dsp create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/7z.dsw create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/7zMain.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/Precomp.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/Precomp.h create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/makefile create mode 100644 3rdparty/lzma-21.03beta/C/Util/7z/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsp create mode 100644 3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsw create mode 100644 3rdparty/lzma-21.03beta/C/Util/Lzma/makefile create mode 100644 3rdparty/lzma-21.03beta/C/Util/Lzma/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.def create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsp create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsw create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLibExports.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/makefile create mode 100644 3rdparty/lzma-21.03beta/C/Util/LzmaLib/resource.rc create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.h create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.c create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsp create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsw create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile_con create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/resource.rc create mode 100644 3rdparty/lzma-21.03beta/C/Util/SfxSetup/setup.ico create mode 100644 3rdparty/lzma-21.03beta/C/Xz.c create mode 100644 3rdparty/lzma-21.03beta/C/Xz.h create mode 100644 3rdparty/lzma-21.03beta/C/XzCrc64.c create mode 100644 3rdparty/lzma-21.03beta/C/XzCrc64.h create mode 100644 3rdparty/lzma-21.03beta/C/XzCrc64Opt.c create mode 100644 3rdparty/lzma-21.03beta/C/XzDec.c create mode 100644 3rdparty/lzma-21.03beta/C/XzEnc.c create mode 100644 3rdparty/lzma-21.03beta/C/XzEnc.h create mode 100644 3rdparty/lzma-21.03beta/C/XzIn.c create mode 100644 3rdparty/lzma-21.03beta/C/var_clang.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_clang_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_clang_x64.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_clang_x86.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_gcc_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_gcc_x64.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_gcc_x86.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_mac_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/C/var_mac_x64.mak create mode 100644 3rdparty/lzma-21.03beta/C/warn_clang.mak create mode 100644 3rdparty/lzma-21.03beta/C/warn_clang_mac.mak create mode 100644 3rdparty/lzma-21.03beta/C/warn_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/7zip.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/7zip_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Aes.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zExtract.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandlerOut.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zItem.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive.def create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive2.def create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/ArchiveExports.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/DllExports2.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/IArchive.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/Icons/7z.ico create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/LzmaHandler.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/SplitHandler.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Asm.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/7z.ico create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SFXCon.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SFXCon.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SfxCon.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/setup.ico create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/7z.ico create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SFXWin.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SFXWin.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SfxWin.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/PropId.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterArc.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterCodec.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Register.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/ByteSwap.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/CodecExports.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/DeltaFilter.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Register.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crc64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAesRegister.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAesReg.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Crypto/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/GuiCommon.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Guid.txt create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/ICoder.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/IDecl.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/IPassword.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/IProgress.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/IStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/LzFindOpt.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/MyVersion.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/MyVersionInfo.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/PropID.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/Sha256.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/SubBuild.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsw create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DirItem.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExitCode.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractMode.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/IFileExtractCallback.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Property.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ZipRegistry.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.manifest create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Main.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/MainAr.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile.gcc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/resource.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/DialogSize.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/LangUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/MyWindowsNew.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2Res.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2a.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyNameRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resource.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resourceGui.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/Extract.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.rc create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialogRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractRes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/HashGUI.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/resource2.h create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x86.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x86.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_clang.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_clang_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x86.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x86.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_mac_arm64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/var_mac_x64.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/warn_clang.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/warn_clang_mac.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/7zip/warn_gcc.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/Build.mak create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/AutoPtr.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/CRC.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/ComTry.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Common.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/CrcReg.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Defs.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/DynamicBuffer.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/IntToString.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/IntToString.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Lang.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/LzFindPrepare.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyBuffer.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyBuffer2.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyCom.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyException.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyGuidDef.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyInitGuid.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyLinux.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyString.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyString.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyTypes.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyUnknown.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyVector.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyVector.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyWindows.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/MyWindows.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/NewHandler.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/NewHandler.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Sha256Prepare.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Sha256Reg.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StdInStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StdInStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StringConvert.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StringConvert.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StringToInt.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/StringToInt.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/TextConfig.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/TextConfig.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Wildcard.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/Wildcard.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Init.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Reg.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/COM.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/CommandBar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Edit.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ProgressBar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ReBar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Static.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/StatusBar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/ToolBar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Trackbar.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/DLL.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/DLL.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Defs.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileDir.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileDir.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileFind.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileFind.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileIO.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileIO.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileLink.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileName.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileName.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Handle.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/NtCheck.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Registry.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Registry.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Shell.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Shell.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/StdAfx.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/System.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/System.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Thread.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.h create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Window.cpp create mode 100644 3rdparty/lzma-21.03beta/CPP/Windows/Window.h create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Common/CRC.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Common/CommandLineParser.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Common/InBuffer.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Common/OutBuffer.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/IMatchFinder.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzBinTree.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzInWindow.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzOutWindow.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaBase.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaDecoder.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaEncoder.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaBench.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoder.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs create mode 100644 3rdparty/lzma-21.03beta/CS/7zip/ICoder.cs create mode 100644 3rdparty/lzma-21.03beta/DOC/7zC.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/7zFormat.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/Methods.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/installer.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/lzma-history.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/lzma-sdk.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/lzma-specification.txt create mode 100644 3rdparty/lzma-21.03beta/DOC/lzma.txt create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/CRC.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/BinTree.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/InWindow.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/OutWindow.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Base.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Decoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Encoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Decoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Encoder.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/ICodeProgress.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/LzmaAlone.java create mode 100644 3rdparty/lzma-21.03beta/Java/SevenZip/LzmaBench.java create mode 100644 3rdparty/lzma-21.03beta/bin/7zS2.sfx create mode 100644 3rdparty/lzma-21.03beta/bin/7zS2con.sfx create mode 100644 3rdparty/lzma-21.03beta/bin/7zSD.sfx create mode 100644 3rdparty/lzma-21.03beta/bin/7zdec.exe create mode 100644 3rdparty/lzma-21.03beta/bin/7zr.exe create mode 100644 3rdparty/lzma-21.03beta/bin/installer/config.txt create mode 100644 3rdparty/lzma-21.03beta/bin/installer/cr.bat create mode 100644 3rdparty/lzma-21.03beta/bin/lzma.exe create mode 100644 3rdparty/lzma-21.03beta/bin/x64/7zr.exe create mode 100644 3rdparty/lzma.cmake create mode 100644 tests/data/lzfse.bin create mode 100644 tests/data/lzma.bin create mode 100644 tests/data/zstd.zst create mode 100644 tests/lzma.cpp diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 909e6bb..24b40fc 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -13,4 +13,6 @@ set(ZSTD_BUILD_PROGRAMS OFF) set(ZSTD_BUILD_SHARED OFF) set(ZSTD_MULTITHREAD_SUPPORT OFF) # Not really sure if it works properly set(ZSTD_LEGACY_SUPPORT ON) # Unsure if may ever be needed, just in case -add_subdirectory(zstd-1.5.0/build/cmake) \ No newline at end of file +add_subdirectory(zstd-1.5.0/build/cmake) + +include(lzma.cmake) \ No newline at end of file diff --git a/3rdparty/lzma-21.03beta/Asm/arm/7zCrcOpt.asm b/3rdparty/lzma-21.03beta/Asm/arm/7zCrcOpt.asm new file mode 100644 index 0000000..6001d8e --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/arm/7zCrcOpt.asm @@ -0,0 +1,100 @@ + CODE32 + + EXPORT |CrcUpdateT4@16| + + AREA |.text|, CODE, ARM + + MACRO + CRC32_STEP_1 + + ldrb r4, [r1], #1 + subs r2, r2, #1 + eor r4, r4, r0 + and r4, r4, #0xFF + ldr r4, [r3, +r4, lsl #2] + eor r0, r4, r0, lsr #8 + + MEND + + + MACRO + CRC32_STEP_4 $STREAM_WORD + + eor r7, r7, r8 + eor r7, r7, r9 + eor r0, r0, r7 + eor r0, r0, $STREAM_WORD + ldr $STREAM_WORD, [r1], #4 + + and r7, r0, #0xFF + and r8, r0, #0xFF00 + and r9, r0, #0xFF0000 + and r0, r0, #0xFF000000 + + ldr r7, [r6, +r7, lsl #2] + ldr r8, [r5, +r8, lsr #6] + ldr r9, [r4, +r9, lsr #14] + ldr r0, [r3, +r0, lsr #22] + + MEND + + +|CrcUpdateT4@16| PROC + + stmdb sp!, {r4-r11, lr} + cmp r2, #0 + beq |$fin| + +|$v1| + tst r1, #7 + beq |$v2| + CRC32_STEP_1 + bne |$v1| + +|$v2| + cmp r2, #16 + blo |$v3| + + ldr r10, [r1], #4 + ldr r11, [r1], #4 + + add r4, r3, #0x400 + add r5, r3, #0x800 + add r6, r3, #0xC00 + + mov r7, #0 + mov r8, #0 + mov r9, #0 + + sub r2, r2, #16 + +|$loop| + ; pld [r1, #0x40] + + CRC32_STEP_4 r10 + CRC32_STEP_4 r11 + + subs r2, r2, #8 + bhs |$loop| + + sub r1, r1, #8 + add r2, r2, #16 + + eor r7, r7, r8 + eor r7, r7, r9 + eor r0, r0, r7 + +|$v3| + cmp r2, #0 + beq |$fin| + +|$v4| + CRC32_STEP_1 + bne |$v4| + +|$fin| + ldmia sp!, {r4-r11, pc} + +|CrcUpdateT4@16| ENDP + + END diff --git a/3rdparty/lzma-21.03beta/Asm/arm64/7zAsm.S b/3rdparty/lzma-21.03beta/Asm/arm64/7zAsm.S new file mode 100644 index 0000000..12e950b --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/arm64/7zAsm.S @@ -0,0 +1,181 @@ +// 7zAsm.S -- ASM macros for arm64 +// 2021-04-25 : Igor Pavlov : Public domain + +#define r0 x0 +#define r1 x1 +#define r2 x2 +#define r3 x3 +#define r4 x4 +#define r5 x5 +#define r6 x6 +#define r7 x7 +#define r8 x8 +#define r9 x9 +#define r10 x10 +#define r11 x11 +#define r12 x12 +#define r13 x13 +#define r14 x14 +#define r15 x15 +#define r16 x16 +#define r17 x17 +#define r18 x18 +#define r19 x19 +#define r20 x20 +#define r21 x21 +#define r22 x22 +#define r23 x23 +#define r24 x24 +#define r25 x25 +#define r26 x26 +#define r27 x27 +#define r28 x28 +#define r29 x29 +#define r30 x30 + +#define REG_ABI_PARAM_0 r0 +#define REG_ABI_PARAM_1 r1 +#define REG_ABI_PARAM_2 r2 + + +.macro p2_add reg:req, param:req + add \reg, \reg, \param +.endm + +.macro p2_sub reg:req, param:req + sub \reg, \reg, \param +.endm + +.macro p2_sub_s reg:req, param:req + subs \reg, \reg, \param +.endm + +.macro p2_and reg:req, param:req + and \reg, \reg, \param +.endm + +.macro xor reg:req, param:req + eor \reg, \reg, \param +.endm + +.macro or reg:req, param:req + orr \reg, \reg, \param +.endm + +.macro shl reg:req, param:req + lsl \reg, \reg, \param +.endm + +.macro shr reg:req, param:req + lsr \reg, \reg, \param +.endm + +.macro sar reg:req, param:req + asr \reg, \reg, \param +.endm + +.macro p1_neg reg:req + neg \reg, \reg +.endm + +.macro dec reg:req + sub \reg, \reg, 1 +.endm + +.macro dec_s reg:req + subs \reg, \reg, 1 +.endm + +.macro inc reg:req + add \reg, \reg, 1 +.endm + +.macro inc_s reg:req + adds \reg, \reg, 1 +.endm + + +.macro imul reg:req, param:req + mul \reg, \reg, \param +.endm + +/* +arm64 and arm use reverted c flag after subs/cmp instructions: + arm64-arm : x86 + b.lo / b.cc : jb / jc + b.hs / b.cs : jae / jnc +*/ + +.macro jmp lab:req + b \lab +.endm + +.macro je lab:req + b.eq \lab +.endm + +.macro jz lab:req + b.eq \lab +.endm + +.macro jnz lab:req + b.ne \lab +.endm + +.macro jne lab:req + b.ne \lab +.endm + +.macro jb lab:req + b.lo \lab +.endm + +.macro jbe lab:req + b.ls \lab +.endm + +.macro ja lab:req + b.hi \lab +.endm + +.macro jae lab:req + b.hs \lab +.endm + + +.macro cmove dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, eq +.endm + +.macro cmovne dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, ne +.endm + +.macro cmovs dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, mi +.endm + +.macro cmovns dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, pl +.endm + +.macro cmovb dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, lo +.endm + +.macro cmovae dest:req, srcTrue:req + csel \dest, \srcTrue, \dest, hs +.endm + + +.macro MY_ALIGN_16 macro + .p2align 4,, (1 << 4) - 1 +.endm + +.macro MY_ALIGN_32 macro + .p2align 5,, (1 << 5) - 1 +.endm + +.macro MY_ALIGN_64 macro + .p2align 6,, (1 << 6) - 1 +.endm diff --git a/3rdparty/lzma-21.03beta/Asm/arm64/LzmaDecOpt.S b/3rdparty/lzma-21.03beta/Asm/arm64/LzmaDecOpt.S new file mode 100644 index 0000000..10dc473 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/arm64/LzmaDecOpt.S @@ -0,0 +1,1487 @@ +// LzmaDecOpt.S -- ARM64-ASM version of LzmaDec_DecodeReal_3() function +// 2021-04-25 : Igor Pavlov : Public domain + +/* +; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() +; function for check at link time. +; That code is tightly coupled with LzmaDec_TryDummy() +; and with another functions in LzmaDec.c file. +; CLzmaDec structure, (probs) array layout, input and output of +; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). +*/ + + +#include "7zAsm.S" + + // .arch armv8-a + // .file "LzmaDecOpt.c" + .text + .align 2 + .p2align 4,,15 +#ifdef __APPLE__ + .globl _LzmaDec_DecodeReal_3 +#else + .global LzmaDec_DecodeReal_3 +#endif + // .type LzmaDec_DecodeReal_3, %function + +// #define _LZMA_SIZE_OPT 1 + +#define LZMA_USE_4BYTES_FILL 1 +// #define LZMA_USE_2BYTES_COPY 1 +// #define LZMA_USE_CMOV_LZ_WRAP 1 +// #define _LZMA_PROB32 1 + +#define MY_ALIGN_FOR_ENTRY MY_ALIGN_32 +#define MY_ALIGN_FOR_LOOP MY_ALIGN_32 +#define MY_ALIGN_FOR_LOOP_16 MY_ALIGN_16 + +#ifdef _LZMA_PROB32 + .equ PSHIFT , 2 + .macro PLOAD dest:req, mem:req + ldr \dest, [\mem] + .endm + .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req + ldr \dest, [\mem, \offset]! + .endm + .macro PLOAD_2 dest:req, mem1:req, mem2:req + ldr \dest, [\mem1, \mem2] + .endm + .macro PLOAD_LSL dest:req, mem1:req, mem2:req + ldr \dest, [\mem1, \mem2, lsl #PSHIFT] + .endm + .macro PSTORE src:req, mem:req + str \src, [\mem] + .endm + .macro PSTORE_2 src:req, mem1:req, mem2:req + str \src, [\mem1, \mem2] + .endm + .macro PSTORE_LSL src:req, mem1:req, mem2:req + str \src, [\mem1, \mem2, lsl #PSHIFT] + .endm + .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req + // you must check that temp_reg is free register when macro is used + add \temp_reg, \mem1, \mem2 + str \src, [\temp_reg, \mem2] + .endm +#else + // .equ PSHIFT , 1 + #define PSHIFT 1 + .macro PLOAD dest:req, mem:req + ldrh \dest, [\mem] + .endm + .macro PLOAD_PREINDEXED dest:req, mem:req, offset:req + ldrh \dest, [\mem, \offset]! + .endm + .macro PLOAD_2 dest:req, mem1:req, mem2:req + ldrh \dest, [\mem1, \mem2] + .endm + .macro PLOAD_LSL dest:req, mem1:req, mem2:req + ldrh \dest, [\mem1, \mem2, lsl #PSHIFT] + .endm + .macro PSTORE src:req, mem:req + strh \src, [\mem] + .endm + .macro PSTORE_2 src:req, mem1:req, mem2:req + strh \src, [\mem1, \mem2] + .endm + .macro PSTORE_LSL src:req, mem1:req, mem2:req + strh \src, [\mem1, \mem2, lsl #PSHIFT] + .endm + .macro PSTORE_LSL_M1 src:req, mem1:req, mem2:req, temp_reg:req + strh \src, [\mem1, \mem2] + .endm +#endif + +.equ PMULT , (1 << PSHIFT) +.equ PMULT_2 , (2 << PSHIFT) + +.equ kMatchSpecLen_Error_Data , (1 << 9) + +# x7 t0 : NORM_CALC : prob2 (IF_BIT_1) +# x6 t1 : NORM_CALC : probs_state +# x8 t2 : (LITM) temp : (TREE) temp +# x4 t3 : (LITM) bit : (TREE) temp : UPDATE_0/UPDATE_0 temp +# x10 t4 : (LITM) offs : (TREE) probs_PMULT : numBits +# x9 t5 : (LITM) match : sym2 (ShortDist) +# x1 t6 : (LITM) litm_prob : (TREE) prob_reg : pbPos +# x2 t7 : (LITM) prm : probBranch : cnt +# x3 sym : dist +# x12 len +# x0 range +# x5 cod + + +#define range w0 + +// t6 +#define pbPos w1 +#define pbPos_R r1 +#define prob_reg w1 +#define litm_prob prob_reg + +// t7 +#define probBranch w2 +#define cnt w2 +#define cnt_R r2 +#define prm r2 + +#define sym w3 +#define sym_R r3 +#define dist sym + +#define t3 w4 +#define bit w4 +#define bit_R r4 +#define update_temp_reg r4 + +#define cod w5 + +#define t1 w6 +#define t1_R r6 +#define probs_state t1_R + +#define t0 w7 +#define t0_R r7 +#define prob2 t0 + +#define t2 w8 +#define t2_R r8 + +// t5 +#define match w9 +#define sym2 w9 +#define sym2_R r9 + +#define t4 w10 +#define t4_R r10 + +#define offs w10 +#define offs_R r10 + +#define probs r11 + +#define len w12 +#define len_R x12 + +#define state w13 +#define state_R r13 + +#define dicPos r14 +#define buf r15 +#define bufLimit r16 +#define dicBufSize r17 + +#define limit r19 +#define rep0 w20 +#define rep0_R r20 +#define rep1 w21 +#define rep2 w22 +#define rep3 w23 +#define dic r24 +#define probs_IsMatch r25 +#define probs_Spec r26 +#define checkDicSize w27 +#define processedPos w28 +#define pbMask w29 +#define lc2_lpMask w30 + + +.equ kNumBitModelTotalBits , 11 +.equ kBitModelTotal , (1 << kNumBitModelTotalBits) +.equ kNumMoveBits , 5 +.equ kBitModelOffset , (kBitModelTotal - (1 << kNumMoveBits) + 1) + +.macro NORM_2 macro + ldrb t0, [buf], 1 + shl range, 8 + orr cod, t0, cod, lsl 8 + /* + mov t0, cod + ldrb cod, [buf], 1 + shl range, 8 + bfi cod, t0, #8, #24 + */ +.endm + +.macro TEST_HIGH_BYTE_range macro + tst range, 0xFF000000 +.endm + +.macro NORM macro + TEST_HIGH_BYTE_range + jnz 1f + NORM_2 +1: +.endm + + +# ---------- Branch MACROS ---------- + +.macro UPDATE_0__0 + sub prob2, probBranch, kBitModelOffset +.endm + +.macro UPDATE_0__1 + sub probBranch, probBranch, prob2, asr #(kNumMoveBits) +.endm + +.macro UPDATE_0__2 probsArray:req, probOffset:req, probDisp:req + .if \probDisp == 0 + PSTORE_2 probBranch, \probsArray, \probOffset + .elseif \probOffset == 0 + PSTORE_2 probBranch, \probsArray, \probDisp * PMULT + .else + .error "unsupported" + // add update_temp_reg, \probsArray, \probOffset + PSTORE_2 probBranch, update_temp_reg, \probDisp * PMULT + .endif +.endm + +.macro UPDATE_0 probsArray:req, probOffset:req, probDisp:req + UPDATE_0__0 + UPDATE_0__1 + UPDATE_0__2 \probsArray, \probOffset, \probDisp +.endm + + +.macro UPDATE_1 probsArray:req, probOffset:req, probDisp:req + // sub cod, cod, prob2 + // sub range, range, prob2 + p2_sub cod, range + sub range, prob2, range + sub prob2, probBranch, probBranch, lsr #(kNumMoveBits) + .if \probDisp == 0 + PSTORE_2 prob2, \probsArray, \probOffset + .elseif \probOffset == 0 + PSTORE_2 prob2, \probsArray, \probDisp * PMULT + .else + .error "unsupported" + // add update_temp_reg, \probsArray, \probOffset + PSTORE_2 prob2, update_temp_reg, \probDisp * PMULT + .endif +.endm + + +.macro CMP_COD_BASE + NORM + // lsr prob2, range, kNumBitModelTotalBits + // imul prob2, probBranch + // cmp cod, prob2 + mov prob2, range + shr range, kNumBitModelTotalBits + imul range, probBranch + cmp cod, range +.endm + +.macro CMP_COD_1 probsArray:req + PLOAD probBranch, \probsArray + CMP_COD_BASE +.endm + +.macro CMP_COD_3 probsArray:req, probOffset:req, probDisp:req + .if \probDisp == 0 + PLOAD_2 probBranch, \probsArray, \probOffset + .elseif \probOffset == 0 + PLOAD_2 probBranch, \probsArray, \probDisp * PMULT + .else + .error "unsupported" + add update_temp_reg, \probsArray, \probOffset + PLOAD_2 probBranch, update_temp_reg, \probDisp * PMULT + .endif + CMP_COD_BASE +.endm + + +.macro IF_BIT_1_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD_3 \probsArray, \probOffset, \probDisp + jae \toLabel +.endm + + +.macro IF_BIT_1 probsArray:req, probOffset:req, probDisp:req, toLabel:req + IF_BIT_1_NOUP \probsArray, \probOffset, \probDisp, \toLabel + UPDATE_0 \probsArray, \probOffset, \probDisp +.endm + + +.macro IF_BIT_0_NOUP probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD_3 \probsArray, \probOffset, \probDisp + jb \toLabel +.endm + +.macro IF_BIT_0_NOUP_1 probsArray:req, toLabel:req + CMP_COD_1 \probsArray + jb \toLabel +.endm + + +# ---------- CMOV MACROS ---------- + +.macro NORM_LSR + NORM + lsr t0, range, #kNumBitModelTotalBits +.endm + +.macro COD_RANGE_SUB + subs t1, cod, t0 + p2_sub range, t0 +.endm + +.macro RANGE_IMUL prob:req + imul t0, \prob +.endm + +.macro NORM_CALC prob:req + NORM_LSR + RANGE_IMUL \prob + COD_RANGE_SUB +.endm + +.macro CMOV_range + cmovb range, t0 +.endm + +.macro CMOV_code + cmovae cod, t1 +.endm + +.macro CMOV_code_Model_Pre prob:req + sub t0, \prob, kBitModelOffset + CMOV_code + cmovae t0, \prob +.endm + + +.macro PUP_BASE_2 prob:req, dest_reg:req + # only sar works for both 16/32 bit prob modes + sub \dest_reg, \prob, \dest_reg, asr #(kNumMoveBits) +.endm + +.macro PUP prob:req, probPtr:req, mem2:req + PUP_BASE_2 \prob, t0 + PSTORE_2 t0, \probPtr, \mem2 +.endm + + + +#define probs_PMULT t4_R + +.macro BIT_01 + add probs_PMULT, probs, PMULT +.endm + + +.macro BIT_0_R prob:req + PLOAD_2 \prob, probs, 1 * PMULT + NORM_LSR + sub t3, \prob, kBitModelOffset + RANGE_IMUL \prob + PLOAD_2 t2, probs, 1 * PMULT_2 + COD_RANGE_SUB + CMOV_range + cmovae t3, \prob + PLOAD_2 t0, probs, 1 * PMULT_2 + PMULT + PUP_BASE_2 \prob, t3 + csel \prob, t2, t0, lo + CMOV_code + mov sym, 2 + PSTORE_2 t3, probs, 1 * PMULT + adc sym, sym, wzr + BIT_01 +.endm + +.macro BIT_1_R prob:req + NORM_LSR + p2_add sym, sym + sub t3, \prob, kBitModelOffset + RANGE_IMUL \prob + PLOAD_LSL t2, probs, sym_R + COD_RANGE_SUB + CMOV_range + cmovae t3, \prob + PLOAD_LSL t0, probs_PMULT, sym_R + PUP_BASE_2 \prob, t3 + csel \prob, t2, t0, lo + CMOV_code + PSTORE_LSL_M1 t3, probs, sym_R, t2_R + adc sym, sym, wzr +.endm + + +.macro BIT_2_R prob:req + NORM_LSR + p2_add sym, sym + sub t3, \prob, kBitModelOffset + RANGE_IMUL \prob + COD_RANGE_SUB + CMOV_range + cmovae t3, \prob + CMOV_code + PUP_BASE_2 \prob, t3 + PSTORE_LSL_M1 t3, probs, sym_R, t2_R + adc sym, sym, wzr +.endm + + +# ---------- MATCHED LITERAL ---------- + +.macro LITM_0 macro + shl match, (PSHIFT + 1) + and bit, match, 256 * PMULT + add prm, probs, 256 * PMULT + 1 * PMULT + p2_add match, match + p2_add prm, bit_R + eor offs, bit, 256 * PMULT + PLOAD litm_prob, prm + + NORM_LSR + sub t2, litm_prob, kBitModelOffset + RANGE_IMUL litm_prob + COD_RANGE_SUB + cmovae offs, bit + CMOV_range + and bit, match, offs + cmovae t2, litm_prob + CMOV_code + mov sym, 2 + PUP_BASE_2 litm_prob, t2 + PSTORE t2, prm + add prm, probs, offs_R + adc sym, sym, wzr +.endm + +.macro LITM macro + p2_add prm, bit_R + xor offs, bit + PLOAD_LSL litm_prob, prm, sym_R + + NORM_LSR + p2_add match, match + sub t2, litm_prob, kBitModelOffset + RANGE_IMUL litm_prob + COD_RANGE_SUB + cmovae offs, bit + CMOV_range + and bit, match, offs + cmovae t2, litm_prob + CMOV_code + PUP_BASE_2 litm_prob, t2 + PSTORE_LSL t2, prm, sym_R + add prm, probs, offs_R + adc sym, sym, sym +.endm + + +.macro LITM_2 macro + p2_add prm, bit_R + PLOAD_LSL litm_prob, prm, sym_R + + NORM_LSR + sub t2, litm_prob, kBitModelOffset + RANGE_IMUL litm_prob + COD_RANGE_SUB + CMOV_range + cmovae t2, litm_prob + CMOV_code + PUP_BASE_2 litm_prob, t2 + PSTORE_LSL t2, prm, sym_R + adc sym, sym, sym +.endm + + +# ---------- REVERSE BITS ---------- + +.macro REV_0 prob:req + NORM_CALC \prob + CMOV_range + PLOAD t2, sym2_R + PLOAD_2 t3, probs, 3 * PMULT + CMOV_code_Model_Pre \prob + add t1_R, probs, 3 * PMULT + cmovae sym2_R, t1_R + PUP \prob, probs, 1 * PMULT + csel \prob, t2, t3, lo +.endm + + +.macro REV_1 prob:req, step:req + NORM_LSR + PLOAD_PREINDEXED t2, sym2_R, (\step * PMULT) + RANGE_IMUL \prob + COD_RANGE_SUB + CMOV_range + PLOAD_2 t3, sym2_R, (\step * PMULT) + sub t0, \prob, kBitModelOffset + CMOV_code + add t1_R, sym2_R, \step * PMULT + cmovae t0, \prob + cmovae sym2_R, t1_R + PUP_BASE_2 \prob, t0 + csel \prob, t2, t3, lo + PSTORE_2 t0, t1_R, 0 - \step * PMULT_2 +.endm + + +.macro REV_2 prob:req, step:req + sub t1_R, sym2_R, probs + NORM_LSR + orr sym, sym, t1, lsr #PSHIFT + RANGE_IMUL \prob + COD_RANGE_SUB + sub t2, sym, \step + CMOV_range + cmovb sym, t2 + CMOV_code_Model_Pre \prob + PUP \prob, sym2_R, 0 +.endm + + +.macro REV_1_VAR prob:req + PLOAD \prob, sym_R + mov probs, sym_R + p2_add sym_R, sym2_R + NORM_LSR + add t2_R, sym_R, sym2_R + RANGE_IMUL \prob + COD_RANGE_SUB + cmovae sym_R, t2_R + CMOV_range + CMOV_code_Model_Pre \prob + p2_add sym2, sym2 + PUP \prob, probs, 0 +.endm + + +.macro add_big dest:req, src:req, param:req + .if (\param) < (1 << 12) + add \dest, \src, \param + .else + #ifndef _LZMA_PROB32 + .error "unexpcted add_big expansion" + #endif + add \dest, \src, (\param) / 2 + add \dest, \dest, (\param) - (\param) / 2 + .endif +.endm + +.macro sub_big dest:req, src:req, param:req + .if (\param) < (1 << 12) + sub \dest, \src, \param + .else + #ifndef _LZMA_PROB32 + .error "unexpcted sub_big expansion" + #endif + sub \dest, \src, (\param) / 2 + sub \dest, \dest, (\param) - (\param) / 2 + .endif +.endm + + +.macro SET_probs offset:req + // add_big probs, probs_Spec, (\offset) * PMULT + add probs, probs_IsMatch, ((\offset) - IsMatch) * PMULT +.endm + + +.macro LIT_PROBS + add sym, sym, processedPos, lsl 8 + inc processedPos + UPDATE_0__0 + shl sym, lc2_lpMask + SET_probs Literal + p2_and sym, lc2_lpMask + // p2_add probs_state, pbPos_R + p2_add probs, sym_R + UPDATE_0__1 + add probs, probs, sym_R, lsl 1 + UPDATE_0__2 probs_state, pbPos_R, 0 +.endm + + + +.equ kNumPosBitsMax , 4 +.equ kNumPosStatesMax , (1 << kNumPosBitsMax) + +.equ kLenNumLowBits , 3 +.equ kLenNumLowSymbols , (1 << kLenNumLowBits) +.equ kLenNumHighBits , 8 +.equ kLenNumHighSymbols , (1 << kLenNumHighBits) +.equ kNumLenProbs , (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) + +.equ LenLow , 0 +.equ LenChoice , LenLow +.equ LenChoice2 , (LenLow + kLenNumLowSymbols) +.equ LenHigh , (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) + +.equ kNumStates , 12 +.equ kNumStates2 , 16 +.equ kNumLitStates , 7 + +.equ kStartPosModelIndex , 4 +.equ kEndPosModelIndex , 14 +.equ kNumFullDistances , (1 << (kEndPosModelIndex >> 1)) + +.equ kNumPosSlotBits , 6 +.equ kNumLenToPosStates , 4 + +.equ kNumAlignBits , 4 +.equ kAlignTableSize , (1 << kNumAlignBits) + +.equ kMatchMinLen , 2 +.equ kMatchSpecLenStart , (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +// .equ kStartOffset , 1408 +.equ kStartOffset , 0 +.equ SpecPos , (-kStartOffset) +.equ IsRep0Long , (SpecPos + kNumFullDistances) +.equ RepLenCoder , (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) +.equ LenCoder , (RepLenCoder + kNumLenProbs) +.equ IsMatch , (LenCoder + kNumLenProbs) +.equ kAlign , (IsMatch + (kNumStates2 << kNumPosBitsMax)) +.equ IsRep , (kAlign + kAlignTableSize) +.equ IsRepG0 , (IsRep + kNumStates) +.equ IsRepG1 , (IsRepG0 + kNumStates) +.equ IsRepG2 , (IsRepG1 + kNumStates) +.equ PosSlot , (IsRepG2 + kNumStates) +.equ Literal , (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +.equ NUM_BASE_PROBS , (Literal + kStartOffset) + +.if kStartOffset != 0 // && IsMatch != 0 + .error "Stop_Compiling_Bad_StartOffset" +.endif + +.if NUM_BASE_PROBS != 1984 + .error "Stop_Compiling_Bad_LZMA_PROBS" +.endif + +.equ offset_lc , 0 +.equ offset_lp , 1 +.equ offset_pb , 2 +.equ offset_dicSize , 4 +.equ offset_probs , 4 + offset_dicSize +.equ offset_probs_1664 , 8 + offset_probs +.equ offset_dic , 8 + offset_probs_1664 +.equ offset_dicBufSize , 8 + offset_dic +.equ offset_dicPos , 8 + offset_dicBufSize +.equ offset_buf , 8 + offset_dicPos +.equ offset_range , 8 + offset_buf +.equ offset_code , 4 + offset_range +.equ offset_processedPos , 4 + offset_code +.equ offset_checkDicSize , 4 + offset_processedPos +.equ offset_rep0 , 4 + offset_checkDicSize +.equ offset_rep1 , 4 + offset_rep0 +.equ offset_rep2 , 4 + offset_rep1 +.equ offset_rep3 , 4 + offset_rep2 +.equ offset_state , 4 + offset_rep3 +.equ offset_remainLen , 4 + offset_state +.equ offset_TOTAL_SIZE , 4 + offset_remainLen + +.if offset_TOTAL_SIZE != 96 + .error "Incorrect offset_TOTAL_SIZE" +.endif + + +.macro IsMatchBranch_Pre + # prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + and pbPos, pbMask, processedPos, lsl #(kLenNumLowBits + 1 + PSHIFT) + add probs_state, probs_IsMatch, state_R +.endm + + +/* +.macro IsMatchBranch + IsMatchBranch_Pre + IF_BIT_1 probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label +.endm +*/ + +.macro CheckLimits + cmp buf, bufLimit + jae fin_OK + cmp dicPos, limit + jae fin_OK +.endm + +#define CheckLimits_lit CheckLimits +/* +.macro CheckLimits_lit + cmp buf, bufLimit + jae fin_OK_lit + cmp dicPos, limit + jae fin_OK_lit +.endm +*/ + + +#define PARAM_lzma REG_ABI_PARAM_0 +#define PARAM_limit REG_ABI_PARAM_1 +#define PARAM_bufLimit REG_ABI_PARAM_2 + + +.macro LOAD_LZMA_VAR reg:req, struct_offs:req + ldr \reg, [PARAM_lzma, \struct_offs] +.endm + +.macro LOAD_LZMA_BYTE reg:req, struct_offs:req + ldrb \reg, [PARAM_lzma, \struct_offs] +.endm + +.macro LOAD_LZMA_PAIR reg0:req, reg1:req, struct_offs:req + ldp \reg0, \reg1, [PARAM_lzma, \struct_offs] +.endm + + +LzmaDec_DecodeReal_3: +_LzmaDec_DecodeReal_3: +/* +.LFB0: + .cfi_startproc +*/ + + stp x19, x20, [sp, -128]! + stp x21, x22, [sp, 16] + stp x23, x24, [sp, 32] + stp x25, x26, [sp, 48] + stp x27, x28, [sp, 64] + stp x29, x30, [sp, 80] + + str PARAM_lzma, [sp, 120] + + mov bufLimit, PARAM_bufLimit + mov limit, PARAM_limit + + LOAD_LZMA_PAIR dic, dicBufSize, offset_dic + LOAD_LZMA_PAIR dicPos, buf, offset_dicPos + LOAD_LZMA_PAIR rep0, rep1, offset_rep0 + LOAD_LZMA_PAIR rep2, rep3, offset_rep2 + + mov t0, 1 << (kLenNumLowBits + 1 + PSHIFT) + LOAD_LZMA_BYTE pbMask, offset_pb + p2_add limit, dic + mov len, wzr // we can set it in all requiread branches instead + lsl pbMask, t0, pbMask + p2_add dicPos, dic + p2_sub pbMask, t0 + + LOAD_LZMA_BYTE lc2_lpMask, offset_lc + mov t0, 256 << PSHIFT + LOAD_LZMA_BYTE t1, offset_lp + p2_add t1, lc2_lpMask + p2_sub lc2_lpMask, (256 << PSHIFT) - PSHIFT + shl t0, t1 + p2_add lc2_lpMask, t0 + + LOAD_LZMA_VAR probs_Spec, offset_probs + LOAD_LZMA_VAR checkDicSize, offset_checkDicSize + LOAD_LZMA_VAR processedPos, offset_processedPos + LOAD_LZMA_VAR state, offset_state + // range is r0 : this load must be last don't move + LOAD_LZMA_PAIR range, cod, offset_range + mov sym, wzr + shl state, PSHIFT + + add_big probs_IsMatch, probs_Spec, ((IsMatch - SpecPos) << PSHIFT) + + // if (processedPos != 0 || checkDicSize != 0) + orr t0, checkDicSize, processedPos + cbz t0, 1f + add t0_R, dicBufSize, dic + cmp dicPos, dic + cmovne t0_R, dicPos + ldrb sym, [t0_R, -1] +1: + IsMatchBranch_Pre + cmp state, 4 * PMULT + jb lit_end + cmp state, kNumLitStates * PMULT + jb lit_matched_end + jmp lz_end + + + +#define BIT_0 BIT_0_R prob_reg +#define BIT_1 BIT_1_R prob_reg +#define BIT_2 BIT_2_R prob_reg + +# ---------- LITERAL ---------- +MY_ALIGN_64 +lit_start: + mov state, wzr +lit_start_2: + LIT_PROBS + + #ifdef _LZMA_SIZE_OPT + + PLOAD_2 prob_reg, probs, 1 * PMULT + mov sym, 1 + BIT_01 +MY_ALIGN_FOR_LOOP +lit_loop: + BIT_1 + tbz sym, 7, lit_loop + + #else + + BIT_0 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + + #endif + + BIT_2 + IsMatchBranch_Pre + strb sym, [dicPos], 1 + p2_and sym, 255 + + CheckLimits_lit +lit_end: + IF_BIT_0_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), lit_start + + # jmp IsMatch_label + + +#define FLAG_STATE_BITS (4 + PSHIFT) + +# ---------- MATCHES ---------- +# MY_ALIGN_FOR_ENTRY +IsMatch_label: + UPDATE_1 probs_state, pbPos_R, (IsMatch - IsMatch) + IF_BIT_1 probs_state, 0, (IsRep - IsMatch), IsRep_label + + SET_probs LenCoder + or state, (1 << FLAG_STATE_BITS) + +# ---------- LEN DECODE ---------- +len_decode: + mov len, 8 - kMatchMinLen + IF_BIT_0_NOUP_1 probs, len_mid_0 + UPDATE_1 probs, 0, 0 + p2_add probs, (1 << (kLenNumLowBits + PSHIFT)) + mov len, 0 - kMatchMinLen + IF_BIT_0_NOUP_1 probs, len_mid_0 + UPDATE_1 probs, 0, 0 + p2_add probs, LenHigh * PMULT - (1 << (kLenNumLowBits + PSHIFT)) + + #if 0 == 1 + BIT_0 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + #else + PLOAD_2 prob_reg, probs, 1 * PMULT + mov sym, 1 + BIT_01 +MY_ALIGN_FOR_LOOP +len8_loop: + BIT_1 + tbz sym, 6, len8_loop + #endif + + mov len, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - kMatchMinLen + jmp len_mid_2 + +MY_ALIGN_FOR_ENTRY +len_mid_0: + UPDATE_0 probs, 0, 0 + p2_add probs, pbPos_R + BIT_0 +len_mid_2: + BIT_1 + BIT_2 + sub len, sym, len + tbz state, FLAG_STATE_BITS, copy_match + +# ---------- DECODE DISTANCE ---------- + // probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + + mov t0, 3 + kMatchMinLen + cmp len, 3 + kMatchMinLen + cmovb t0, len + SET_probs PosSlot - (kMatchMinLen << (kNumPosSlotBits)) + add probs, probs, t0_R, lsl #(kNumPosSlotBits + PSHIFT) + + #ifdef _LZMA_SIZE_OPT + + PLOAD_2 prob_reg, probs, 1 * PMULT + mov sym, 1 + BIT_01 +MY_ALIGN_FOR_LOOP +slot_loop: + BIT_1 + tbz sym, 5, slot_loop + + #else + + BIT_0 + BIT_1 + BIT_1 + BIT_1 + BIT_1 + + #endif + + #define numBits t4 + mov numBits, sym + BIT_2 + // we need only low bits + p2_and sym, 3 + cmp numBits, 32 + kEndPosModelIndex / 2 + jb short_dist + + SET_probs kAlign + + # unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + p2_sub numBits, (32 + 1 + kNumAlignBits) + # distance = (2 | (distance & 1)); + or sym, 2 + PLOAD_2 prob_reg, probs, 1 * PMULT + add sym2_R, probs, 2 * PMULT + +# ---------- DIRECT DISTANCE ---------- + +.macro DIRECT_1 + shr range, 1 + subs t0, cod, range + p2_add sym, sym + // add t1, sym, 1 + csel cod, cod, t0, mi + csinc sym, sym, sym, mi + // csel sym, t1, sym, pl + // adc sym, sym, sym // not 100% compatible for "corruptued-allowed" LZMA streams + dec_s numBits + je direct_end +.endm + + #ifdef _LZMA_SIZE_OPT + + jmp direct_norm +MY_ALIGN_FOR_ENTRY +direct_loop: + DIRECT_1 +direct_norm: + TEST_HIGH_BYTE_range + jnz direct_loop + NORM_2 + jmp direct_loop + + #else + +.macro DIRECT_2 + TEST_HIGH_BYTE_range + jz direct_unroll + DIRECT_1 +.endm + + DIRECT_2 + DIRECT_2 + DIRECT_2 + DIRECT_2 + DIRECT_2 + DIRECT_2 + DIRECT_2 + DIRECT_2 + +direct_unroll: + NORM_2 + DIRECT_1 + DIRECT_1 + DIRECT_1 + DIRECT_1 + DIRECT_1 + DIRECT_1 + DIRECT_1 + DIRECT_1 + jmp direct_unroll + + #endif + +MY_ALIGN_FOR_ENTRY +direct_end: + shl sym, kNumAlignBits + REV_0 prob_reg + REV_1 prob_reg, 2 + REV_1 prob_reg, 4 + REV_2 prob_reg, 8 + +decode_dist_end: + + // if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + + tst checkDicSize, checkDicSize + csel t0, processedPos, checkDicSize, eq + cmp sym, t0 + jae end_of_payload + // jmp end_of_payload # for debug + + mov rep3, rep2 + mov rep2, rep1 + mov rep1, rep0 + add rep0, sym, 1 + +.macro STATE_UPDATE_FOR_MATCH + // state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + // cmp state, (kNumStates + kNumLitStates) * PMULT + cmp state, kNumLitStates * PMULT + (1 << FLAG_STATE_BITS) + mov state, kNumLitStates * PMULT + mov t0, (kNumLitStates + 3) * PMULT + cmovae state, t0 +.endm + STATE_UPDATE_FOR_MATCH + +# ---------- COPY MATCH ---------- +copy_match: + + // if ((rem = limit - dicPos) == 0) break // return SZ_ERROR_DATA; + subs cnt_R, limit, dicPos + // jz fin_dicPos_LIMIT + jz fin_OK + + // curLen = ((rem < len) ? (unsigned)rem : len); + cmp cnt_R, len_R + cmovae cnt, len + + sub t0_R, dicPos, dic + p2_add dicPos, cnt_R + p2_add processedPos, cnt + p2_sub len, cnt + + // pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + p2_sub_s t0_R, rep0_R + jae 1f + + cmn t0_R, cnt_R + p2_add t0_R, dicBufSize + ja copy_match_cross +1: +# ---------- COPY MATCH FAST ---------- + # t0_R : src_pos + p2_add t0_R, dic + ldrb sym, [t0_R] + p2_add t0_R, cnt_R + p1_neg cnt_R + +copy_common: + dec dicPos + + # dicPos : (ptr_to_last_dest_BYTE) + # t0_R : (src_lim) + # cnt_R : (-curLen) + + IsMatchBranch_Pre + + inc_s cnt_R + jz copy_end + + cmp rep0, 1 + je copy_match_0 + + #ifdef LZMA_USE_2BYTES_COPY + strb sym, [dicPos, cnt_R] + dec dicPos + # dicPos : (ptr_to_last_dest_16bitWORD) + p2_and cnt_R, -2 + ldrh sym, [t0_R, cnt_R] + adds cnt_R, cnt_R, 2 + jz 2f +MY_ALIGN_FOR_LOOP +1: + /* + strh sym, [dicPos, cnt_R] + ldrh sym, [t0_R, cnt_R] + adds cnt_R, cnt_R, 2 + jz 2f + */ + + strh sym, [dicPos, cnt_R] + ldrh sym, [t0_R, cnt_R] + adds cnt_R, cnt_R, 2 + jnz 1b +2: + + /* + // for universal little/big endian code, but slow + strh sym, [dicPos] + inc dicPos + ldrb sym, [t0_R, -1] + */ + + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + // we must improve big-endian detection for another compilers + // for big-endian we need to revert bytes + rev16 sym, sym + #endif + + // (sym) must represent as little-endian here: + strb sym, [dicPos], 1 + shr sym, 8 + + #else + +MY_ALIGN_FOR_LOOP +1: + strb sym, [dicPos, cnt_R] + ldrb sym, [t0_R, cnt_R] + inc_s cnt_R + jz copy_end + + strb sym, [dicPos, cnt_R] + ldrb sym, [t0_R, cnt_R] + inc_s cnt_R + jnz 1b + #endif + +copy_end: +lz_end_match: + strb sym, [dicPos], 1 + + # IsMatchBranch_Pre + CheckLimits +lz_end: + IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label + + + +# ---------- LITERAL MATCHED ---------- + + LIT_PROBS + + // matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + + sub t0_R, dicPos, dic + p2_sub_s t0_R, rep0_R + + #ifdef LZMA_USE_CMOV_LZ_WRAP + add t1_R, t0_R, dicBufSize + cmovb t0_R, t1_R + #else + jae 1f + p2_add t0_R, dicBufSize +1: + #endif + + ldrb match, [dic, t0_R] + + // state -= (state < 10) ? 3 : 6; + sub sym, state, 6 * PMULT + cmp state, 10 * PMULT + p2_sub state, 3 * PMULT + cmovae state, sym + + #ifdef _LZMA_SIZE_OPT + + mov offs, 256 * PMULT + shl match, (PSHIFT + 1) + mov sym, 1 + and bit, match, offs + add prm, probs, offs_R + +MY_ALIGN_FOR_LOOP +litm_loop: + LITM + tbz sym, 8, litm_loop + + #else + + LITM_0 + LITM + LITM + LITM + LITM + LITM + LITM + LITM_2 + + #endif + + IsMatchBranch_Pre + strb sym, [dicPos], 1 + p2_and sym, 255 + + // mov len, wzr // LITM uses same regisetr (len / offs). So we clear it + CheckLimits_lit +lit_matched_end: + IF_BIT_1_NOUP probs_state, pbPos_R, (IsMatch - IsMatch), IsMatch_label + # IsMatchBranch + p2_sub state, 3 * PMULT + jmp lit_start_2 + + + +# ---------- REP 0 LITERAL ---------- +MY_ALIGN_FOR_ENTRY +IsRep0Short_label: + UPDATE_0 probs_state, pbPos_R, 0 + + // dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + sub t0_R, dicPos, dic + + // state = state < kNumLitStates ? 9 : 11; + or state, 1 * PMULT + + # the caller doesn't allow (dicPos >= limit) case for REP_SHORT + # so we don't need the following (dicPos == limit) check here: + # cmp dicPos, limit + # jae fin_dicPos_LIMIT_REP_SHORT + # // jmp fin_dicPos_LIMIT_REP_SHORT // for testing/debug puposes + + inc processedPos + + IsMatchBranch_Pre + + p2_sub_s t0_R, rep0_R + #ifdef LZMA_USE_CMOV_LZ_WRAP + add sym_R, t0_R, dicBufSize + cmovb t0_R, sym_R + #else + jae 1f + p2_add t0_R, dicBufSize +1: + #endif + + ldrb sym, [dic, t0_R] + // mov len, wzr + jmp lz_end_match + +MY_ALIGN_FOR_ENTRY +IsRep_label: + UPDATE_1 probs_state, 0, (IsRep - IsMatch) + + # The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. + # So we don't check it here. + + # mov t0, processedPos + # or t0, checkDicSize + # jz fin_ERROR_2 + + // state = state < kNumLitStates ? 8 : 11; + cmp state, kNumLitStates * PMULT + mov state, 8 * PMULT + mov probBranch, 11 * PMULT + cmovae state, probBranch + + SET_probs RepLenCoder + + IF_BIT_1 probs_state, 0, (IsRepG0 - IsMatch), IsRepG0_label + sub_big probs_state, probs_state, (IsMatch - IsRep0Long) << PSHIFT + IF_BIT_0_NOUP probs_state, pbPos_R, 0, IsRep0Short_label + UPDATE_1 probs_state, pbPos_R, 0 + jmp len_decode + +MY_ALIGN_FOR_ENTRY +IsRepG0_label: + UPDATE_1 probs_state, 0, (IsRepG0 - IsMatch) + IF_BIT_1 probs_state, 0, (IsRepG1 - IsMatch), IsRepG1_label + mov dist, rep1 + mov rep1, rep0 + mov rep0, dist + jmp len_decode + +# MY_ALIGN_FOR_ENTRY +IsRepG1_label: + UPDATE_1 probs_state, 0, (IsRepG1 - IsMatch) + IF_BIT_1 probs_state, 0, (IsRepG2 - IsMatch), IsRepG2_label + mov dist, rep2 + mov rep2, rep1 + mov rep1, rep0 + mov rep0, dist + jmp len_decode + +# MY_ALIGN_FOR_ENTRY +IsRepG2_label: + UPDATE_1 probs_state, 0, (IsRepG2 - IsMatch) + mov dist, rep3 + mov rep3, rep2 + mov rep2, rep1 + mov rep1, rep0 + mov rep0, dist + jmp len_decode + + + +# ---------- SPEC SHORT DISTANCE ---------- + +MY_ALIGN_FOR_ENTRY +short_dist: + p2_sub_s numBits, 32 + 1 + jbe decode_dist_end + or sym, 2 + shl sym, numBits + add sym_R, probs_Spec, sym_R, lsl #PSHIFT + p2_add sym_R, SpecPos * PMULT + 1 * PMULT + mov sym2, PMULT // # step +MY_ALIGN_FOR_LOOP +spec_loop: + REV_1_VAR prob_reg + dec_s numBits + jnz spec_loop + + p2_add sym2_R, probs_Spec + .if SpecPos != 0 + p2_add sym2_R, SpecPos * PMULT + .endif + p2_sub sym_R, sym2_R + shr sym, PSHIFT + + jmp decode_dist_end + + + +# ---------- COPY MATCH 0 ---------- +MY_ALIGN_FOR_ENTRY +copy_match_0: + #ifdef LZMA_USE_4BYTES_FILL + strb sym, [dicPos, cnt_R] + inc_s cnt_R + jz copy_end + + strb sym, [dicPos, cnt_R] + inc_s cnt_R + jz copy_end + + strb sym, [dicPos, cnt_R] + inc_s cnt_R + jz copy_end + + orr t3, sym, sym, lsl 8 + p2_and cnt_R, -4 + orr t3, t3, t3, lsl 16 +MY_ALIGN_FOR_LOOP_16 +1: + /* + str t3, [dicPos, cnt_R] + adds cnt_R, cnt_R, 4 + jz 2f + */ + + str t3, [dicPos, cnt_R] + adds cnt_R, cnt_R, 4 + jnz 1b +2: + // p2_and sym, 255 + #else + +MY_ALIGN_FOR_LOOP +1: + strb sym, [dicPos, cnt_R] + inc_s cnt_R + jz copy_end + + strb sym, [dicPos, cnt_R] + inc_s cnt_R + jnz 1b + #endif + + jmp copy_end + + +# ---------- COPY MATCH CROSS ---------- +copy_match_cross: + # t0_R - src pos + # cnt_R - total copy len + + p1_neg cnt_R +1: + ldrb sym, [dic, t0_R] + inc t0_R + strb sym, [dicPos, cnt_R] + inc cnt_R + cmp t0_R, dicBufSize + jne 1b + + ldrb sym, [dic] + sub t0_R, dic, cnt_R + jmp copy_common + + + + +/* +fin_dicPos_LIMIT_REP_SHORT: + mov len, 1 + jmp fin_OK +*/ + +/* +fin_dicPos_LIMIT: + jmp fin_OK + # For more strict mode we can stop decoding with error + # mov sym, 1 + # jmp fin +*/ + +fin_ERROR_MATCH_DIST: + # rep0 = distance + 1; + p2_add len, kMatchSpecLen_Error_Data + mov rep3, rep2 + mov rep2, rep1 + mov rep1, rep0 + mov rep0, sym + STATE_UPDATE_FOR_MATCH + # jmp fin_OK + mov sym, 1 + jmp fin + +end_of_payload: + inc_s sym + jnz fin_ERROR_MATCH_DIST + + mov len, kMatchSpecLenStart + xor state, (1 << FLAG_STATE_BITS) + jmp fin_OK + +/* +fin_OK_lit: + mov len, wzr +*/ + +fin_OK: + mov sym, wzr + +fin: + NORM + + #define fin_lzma_reg t0_R + + .macro STORE_LZMA_VAR reg:req, struct_offs:req + str \reg, [fin_lzma_reg, \struct_offs] + .endm + + .macro STORE_LZMA_PAIR reg0:req, reg1:req, struct_offs:req + stp \reg0, \reg1, [fin_lzma_reg, \struct_offs] + .endm + + ldr fin_lzma_reg, [sp, 120] + p2_sub dicPos, dic + shr state, PSHIFT + + STORE_LZMA_PAIR dicPos, buf, offset_dicPos + STORE_LZMA_PAIR range, cod, offset_range + STORE_LZMA_VAR processedPos, offset_processedPos + STORE_LZMA_PAIR rep0, rep1, offset_rep0 + STORE_LZMA_PAIR rep2, rep3, offset_rep2 + STORE_LZMA_PAIR state, len, offset_state + + mov w0, sym + + ldp x29, x30, [sp, 80] + ldp x27, x28, [sp, 64] + ldp x25, x26, [sp, 48] + ldp x23, x24, [sp, 32] + ldp x21, x22, [sp, 16] + ldp x19, x20, [sp], 128 + + ret +/* + .cfi_endproc +.LFE0: + .size LzmaDec_DecodeReal_3, .-LzmaDec_DecodeReal_3 + .ident "TAG_LZMA" + .section .note.GNU-stack,"",@progbits +*/ diff --git a/3rdparty/lzma-21.03beta/Asm/x86/7zAsm.asm b/3rdparty/lzma-21.03beta/Asm/x86/7zAsm.asm new file mode 100644 index 0000000..34c278c --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/7zAsm.asm @@ -0,0 +1,271 @@ +; 7zAsm.asm -- ASM macros +; 2021-07-13 : Igor Pavlov : Public domain + +ifdef RAX + x64 equ 1 +endif + +ifdef x64 + IS_X64 equ 1 +else + IS_X64 equ 0 +endif + +ifdef ABI_LINUX + IS_LINUX equ 1 +else + IS_LINUX equ 0 +endif + +ifndef x64 +; Use ABI_CDECL for x86 (32-bit) only +; if ABI_CDECL is not defined, we use fastcall abi +ifdef ABI_CDECL + IS_CDECL equ 1 +else + IS_CDECL equ 0 +endif +endif + + +MY_ASM_START macro + ifdef x64 + .code + else + .386 + .model flat + _TEXT$00 SEGMENT PARA PUBLIC 'CODE' + endif +endm + +MY_PROC macro name:req, numParams:req + align 16 + proc_numParams = numParams + if (IS_X64 gt 0) + proc_name equ name + elseif (IS_LINUX gt 0) + proc_name equ name + elseif (IS_CDECL gt 0) + proc_name equ @CatStr(_,name) + else + proc_name equ @CatStr(@,name,@, %numParams * 4) + endif + proc_name PROC +endm + +MY_ENDP macro + if (IS_X64 gt 0) + ret + elseif (IS_CDECL gt 0) + ret + elseif (proc_numParams LT 3) + ret + else + ret (proc_numParams - 2) * 4 + endif + proc_name ENDP +endm + + +ifdef x64 + REG_SIZE equ 8 + REG_LOGAR_SIZE equ 3 +else + REG_SIZE equ 4 + REG_LOGAR_SIZE equ 2 +endif + + x0 equ EAX + x1 equ ECX + x2 equ EDX + x3 equ EBX + x4 equ ESP + x5 equ EBP + x6 equ ESI + x7 equ EDI + + x0_W equ AX + x1_W equ CX + x2_W equ DX + x3_W equ BX + + x5_W equ BP + x6_W equ SI + x7_W equ DI + + x0_L equ AL + x1_L equ CL + x2_L equ DL + x3_L equ BL + + x0_H equ AH + x1_H equ CH + x2_H equ DH + x3_H equ BH + +ifdef x64 + x5_L equ BPL + x6_L equ SIL + x7_L equ DIL + + r0 equ RAX + r1 equ RCX + r2 equ RDX + r3 equ RBX + r4 equ RSP + r5 equ RBP + r6 equ RSI + r7 equ RDI + x8 equ r8d + x9 equ r9d + x10 equ r10d + x11 equ r11d + x12 equ r12d + x13 equ r13d + x14 equ r14d + x15 equ r15d +else + r0 equ x0 + r1 equ x1 + r2 equ x2 + r3 equ x3 + r4 equ x4 + r5 equ x5 + r6 equ x6 + r7 equ x7 +endif + + +ifdef x64 +ifdef ABI_LINUX + +MY_PUSH_2_REGS macro + push r3 + push r5 +endm + +MY_POP_2_REGS macro + pop r5 + pop r3 +endm + +endif +endif + + +MY_PUSH_4_REGS macro + push r3 + push r5 + push r6 + push r7 +endm + +MY_POP_4_REGS macro + pop r7 + pop r6 + pop r5 + pop r3 +endm + + +; for fastcall and for WIN-x64 +REG_PARAM_0_x equ x1 +REG_PARAM_0 equ r1 +REG_PARAM_1_x equ x2 +REG_PARAM_1 equ r2 + +ifndef x64 +; for x86-fastcall + +REG_ABI_PARAM_0_x equ REG_PARAM_0_x +REG_ABI_PARAM_0 equ REG_PARAM_0 +REG_ABI_PARAM_1_x equ REG_PARAM_1_x +REG_ABI_PARAM_1 equ REG_PARAM_1 + +else +; x64 + +if (IS_LINUX eq 0) + +; for WIN-x64: +REG_PARAM_2_x equ x8 +REG_PARAM_2 equ r8 +REG_PARAM_3 equ r9 + +REG_ABI_PARAM_0_x equ REG_PARAM_0_x +REG_ABI_PARAM_0 equ REG_PARAM_0 +REG_ABI_PARAM_1_x equ REG_PARAM_1_x +REG_ABI_PARAM_1 equ REG_PARAM_1 +REG_ABI_PARAM_2_x equ REG_PARAM_2_x +REG_ABI_PARAM_2 equ REG_PARAM_2 +REG_ABI_PARAM_3 equ REG_PARAM_3 + +else +; for LINUX-x64: +REG_LINUX_PARAM_0_x equ x7 +REG_LINUX_PARAM_0 equ r7 +REG_LINUX_PARAM_1_x equ x6 +REG_LINUX_PARAM_1 equ r6 +REG_LINUX_PARAM_2 equ r2 +REG_LINUX_PARAM_3 equ r1 +REG_LINUX_PARAM_4_x equ x8 +REG_LINUX_PARAM_4 equ r8 +REG_LINUX_PARAM_5 equ r9 + +REG_ABI_PARAM_0_x equ REG_LINUX_PARAM_0_x +REG_ABI_PARAM_0 equ REG_LINUX_PARAM_0 +REG_ABI_PARAM_1_x equ REG_LINUX_PARAM_1_x +REG_ABI_PARAM_1 equ REG_LINUX_PARAM_1 +REG_ABI_PARAM_2 equ REG_LINUX_PARAM_2 +REG_ABI_PARAM_3 equ REG_LINUX_PARAM_3 +REG_ABI_PARAM_4_x equ REG_LINUX_PARAM_4_x +REG_ABI_PARAM_4 equ REG_LINUX_PARAM_4 +REG_ABI_PARAM_5 equ REG_LINUX_PARAM_5 + +MY_ABI_LINUX_TO_WIN_2 macro + mov r2, r6 + mov r1, r7 +endm + +MY_ABI_LINUX_TO_WIN_3 macro + mov r8, r2 + mov r2, r6 + mov r1, r7 +endm + +MY_ABI_LINUX_TO_WIN_4 macro + mov r9, r1 + mov r8, r2 + mov r2, r6 + mov r1, r7 +endm + +endif ; IS_LINUX + + +MY_PUSH_PRESERVED_ABI_REGS macro + if (IS_LINUX gt 0) + MY_PUSH_2_REGS + else + MY_PUSH_4_REGS + endif + push r12 + push r13 + push r14 + push r15 +endm + + +MY_POP_PRESERVED_ABI_REGS macro + pop r15 + pop r14 + pop r13 + pop r12 + if (IS_LINUX gt 0) + MY_POP_2_REGS + else + MY_POP_4_REGS + endif +endm + +endif ; x64 diff --git a/3rdparty/lzma-21.03beta/Asm/x86/7zCrcOpt.asm b/3rdparty/lzma-21.03beta/Asm/x86/7zCrcOpt.asm new file mode 100644 index 0000000..0fee206 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/7zCrcOpt.asm @@ -0,0 +1,180 @@ +; 7zCrcOpt.asm -- CRC32 calculation : optimized version +; 2021-02-07 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +rD equ r2 +rN equ r7 +rT equ r5 + +ifdef x64 + num_VAR equ r8 + table_VAR equ r9 +else + if (IS_CDECL gt 0) + crc_OFFS equ (REG_SIZE * 5) + data_OFFS equ (REG_SIZE + crc_OFFS) + size_OFFS equ (REG_SIZE + data_OFFS) + else + size_OFFS equ (REG_SIZE * 5) + endif + table_OFFS equ (REG_SIZE + size_OFFS) + num_VAR equ [r4 + size_OFFS] + table_VAR equ [r4 + table_OFFS] +endif + +SRCDAT equ rD + rN * 1 + 4 * + +CRC macro op:req, dest:req, src:req, t:req + op dest, DWORD PTR [rT + src * 4 + 0400h * t] +endm + +CRC_XOR macro dest:req, src:req, t:req + CRC xor, dest, src, t +endm + +CRC_MOV macro dest:req, src:req, t:req + CRC mov, dest, src, t +endm + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shr x0, 8 + CRC xor, x0, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + + ifdef x64 + if (IS_LINUX gt 0) + MY_PUSH_2_REGS + mov x0, REG_ABI_PARAM_0_x ; x0 = x7 + mov rT, REG_ABI_PARAM_3 ; r5 = r1 + mov rN, REG_ABI_PARAM_2 ; r7 = r2 + mov rD, REG_ABI_PARAM_1 ; r2 = r6 + else + MY_PUSH_4_REGS + mov x0, REG_ABI_PARAM_0_x ; x0 = x1 + mov rT, REG_ABI_PARAM_3 ; r5 = r9 + mov rN, REG_ABI_PARAM_2 ; r7 = r8 + ; mov rD, REG_ABI_PARAM_1 ; r2 = r2 + endif + else + MY_PUSH_4_REGS + if (IS_CDECL gt 0) + mov x0, [r4 + crc_OFFS] + mov rD, [r4 + data_OFFS] + else + mov x0, REG_ABI_PARAM_0_x + endif + mov rN, num_VAR + mov rT, table_VAR + endif + + test rN, rN + jz crc_end + @@: + test rD, 7 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 16 + jb crc_end + add rN, rD + mov num_VAR, rN + sub rN, 8 + and rN, NOT 7 + sub rD, rN + xor x0, [SRCDAT 0] +endm + +MY_EPILOG macro crc_end:req + xor x0, [SRCDAT 0] + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + if (IS_X64 gt 0) and (IS_LINUX gt 0) + MY_POP_2_REGS + else + MY_POP_4_REGS + endif +endm + +MY_PROC CrcUpdateT8, 4 + MY_PROLOG crc_end_8 + mov x1, [SRCDAT 1] + align 16 + main_loop_8: + mov x6, [SRCDAT 2] + movzx x3, x1_L + CRC_XOR x6, r3, 3 + movzx x3, x1_H + CRC_XOR x6, r3, 2 + shr x1, 16 + movzx x3, x1_L + movzx x1, x1_H + CRC_XOR x6, r3, 1 + movzx x3, x0_L + CRC_XOR x6, r1, 0 + + mov x1, [SRCDAT 3] + CRC_XOR x6, r3, 7 + movzx x3, x0_H + shr x0, 16 + CRC_XOR x6, r3, 6 + movzx x3, x0_L + CRC_XOR x6, r3, 5 + movzx x3, x0_H + CRC_MOV x0, r3, 4 + xor x0, x6 + add rD, 8 + jnz main_loop_8 + + MY_EPILOG crc_end_8 +MY_ENDP + +MY_PROC CrcUpdateT4, 4 + MY_PROLOG crc_end_4 + align 16 + main_loop_4: + movzx x1, x0_L + movzx x3, x0_H + shr x0, 16 + movzx x6, x0_H + and x0, 0FFh + CRC_MOV x1, r1, 3 + xor x1, [SRCDAT 1] + CRC_XOR x1, r3, 2 + CRC_XOR x1, r6, 0 + CRC_XOR x1, r0, 1 + + movzx x0, x1_L + movzx x3, x1_H + shr x1, 16 + movzx x6, x1_H + and x1, 0FFh + CRC_MOV x0, r0, 3 + xor x0, [SRCDAT 2] + CRC_XOR x0, r3, 2 + CRC_XOR x0, r6, 0 + CRC_XOR x0, r1, 1 + add rD, 8 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +end diff --git a/3rdparty/lzma-21.03beta/Asm/x86/AesOpt.asm b/3rdparty/lzma-21.03beta/Asm/x86/AesOpt.asm new file mode 100644 index 0000000..62c1ba2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/AesOpt.asm @@ -0,0 +1,734 @@ +; AesOpt.asm -- AES optimized code for x86 AES hardware instructions +; 2021-03-10 : Igor Pavlov : Public domain + +include 7zAsm.asm + +ifdef ymm0 + use_vaes_256 equ 1 + ECHO "++ VAES 256" +else + ECHO "-- NO VAES 256" +endif + +ifdef x64 + ECHO "x86-64" +else + ECHO "x86" +if (IS_CDECL gt 0) + ECHO "ABI : CDECL" +else + ECHO "ABI : no CDECL : FASTCALL" +endif +endif + +if (IS_LINUX gt 0) + ECHO "ABI : LINUX" +else + ECHO "ABI : WINDOWS" +endif + +MY_ASM_START + +ifndef x64 + .686 + .xmm +endif + + +; MY_ALIGN EQU ALIGN(64) +MY_ALIGN EQU + +SEG_ALIGN EQU MY_ALIGN + +MY_SEG_PROC macro name:req, numParams:req + ; seg_name equ @CatStr(_TEXT$, name) + ; seg_name SEGMENT SEG_ALIGN 'CODE' + MY_PROC name, numParams +endm + +MY_SEG_ENDP macro + ; seg_name ENDS +endm + + +NUM_AES_KEYS_MAX equ 15 + +; the number of push operators in function PROLOG +if (IS_LINUX eq 0) or (IS_X64 eq 0) +num_regs_push equ 2 +stack_param_offset equ (REG_SIZE * (1 + num_regs_push)) +endif + +ifdef x64 + num_param equ REG_ABI_PARAM_2 +else + if (IS_CDECL gt 0) + ; size_t size + ; void * data + ; UInt32 * aes + ; ret-ip <- (r4) + aes_OFFS equ (stack_param_offset) + data_OFFS equ (REG_SIZE + aes_OFFS) + size_OFFS equ (REG_SIZE + data_OFFS) + num_param equ [r4 + size_OFFS] + else + num_param equ [r4 + stack_param_offset] + endif +endif + +keys equ REG_PARAM_0 ; r1 +rD equ REG_PARAM_1 ; r2 +rN equ r0 + +koffs_x equ x7 +koffs_r equ r7 + +ksize_x equ x6 +ksize_r equ r6 + +keys2 equ r3 + +state equ xmm0 +key equ xmm0 +key_ymm equ ymm0 +key_ymm_n equ 0 + +ifdef x64 + ways = 11 +else + ways = 4 +endif + +ways_start_reg equ 1 + +iv equ @CatStr(xmm, %(ways_start_reg + ways)) +iv_ymm equ @CatStr(ymm, %(ways_start_reg + ways)) + + +WOP macro op, op2 + i = 0 + rept ways + op @CatStr(xmm, %(ways_start_reg + i)), op2 + i = i + 1 + endm +endm + + +ifndef ABI_LINUX +ifdef x64 + +; we use 32 bytes of home space in stack in WIN64-x64 +NUM_HOME_MM_REGS equ (32 / 16) +; we preserve xmm registers starting from xmm6 in WIN64-x64 +MM_START_SAVE_REG equ 6 + +SAVE_XMM macro num_used_mm_regs:req + num_save_mm_regs = num_used_mm_regs - MM_START_SAVE_REG + if num_save_mm_regs GT 0 + num_save_mm_regs2 = num_save_mm_regs - NUM_HOME_MM_REGS + ; RSP is (16*x + 8) after entering the function in WIN64-x64 + stack_offset = 16 * num_save_mm_regs2 + (stack_param_offset mod 16) + + i = 0 + rept num_save_mm_regs + + if i eq NUM_HOME_MM_REGS + sub r4, stack_offset + endif + + if i lt NUM_HOME_MM_REGS + movdqa [r4 + stack_param_offset + i * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i)) + else + movdqa [r4 + (i - NUM_HOME_MM_REGS) * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i)) + endif + + i = i + 1 + endm + endif +endm + +RESTORE_XMM macro num_used_mm_regs:req + if num_save_mm_regs GT 0 + i = 0 + if num_save_mm_regs2 GT 0 + rept num_save_mm_regs2 + movdqa @CatStr(xmm, %(MM_START_SAVE_REG + NUM_HOME_MM_REGS + i)), [r4 + i * 16] + i = i + 1 + endm + add r4, stack_offset + endif + + num_low_regs = num_save_mm_regs - i + i = 0 + rept num_low_regs + movdqa @CatStr(xmm, %(MM_START_SAVE_REG + i)), [r4 + stack_param_offset + i * 16] + i = i + 1 + endm + endif +endm + +endif ; x64 +endif ; ABI_LINUX + + +MY_PROLOG macro num_used_mm_regs:req + ; num_regs_push: must be equal to the number of push operators + ; push r3 + ; push r5 + if (IS_LINUX eq 0) or (IS_X64 eq 0) + push r6 + push r7 + endif + + mov rN, num_param ; don't move it; num_param can use stack pointer (r4) + + if (IS_X64 eq 0) + if (IS_CDECL gt 0) + mov rD, [r4 + data_OFFS] + mov keys, [r4 + aes_OFFS] + endif + elseif (IS_LINUX gt 0) + MY_ABI_LINUX_TO_WIN_2 + endif + + + ifndef ABI_LINUX + ifdef x64 + SAVE_XMM num_used_mm_regs + endif + endif + + mov ksize_x, [keys + 16] + shl ksize_x, 5 +endm + + +MY_EPILOG macro + ifndef ABI_LINUX + ifdef x64 + RESTORE_XMM num_save_mm_regs + endif + endif + + if (IS_LINUX eq 0) or (IS_X64 eq 0) + pop r7 + pop r6 + endif + ; pop r5 + ; pop r3 + MY_ENDP +endm + + +OP_KEY macro op:req, offs:req + op state, [keys + offs] +endm + + +WOP_KEY macro op:req, offs:req + movdqa key, [keys + offs] + WOP op, key +endm + + +; ---------- AES-CBC Decode ---------- + + +XOR_WITH_DATA macro reg, _ppp_ + pxor reg, [rD + i * 16] +endm + +WRITE_TO_DATA macro reg, _ppp_ + movdqa [rD + i * 16], reg +endm + + +; state0 equ @CatStr(xmm, %(ways_start_reg)) + +key0 equ @CatStr(xmm, %(ways_start_reg + ways + 1)) +key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1)) + +key_last equ @CatStr(xmm, %(ways_start_reg + ways + 2)) +key_last_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2)) +key_last_ymm_n equ (ways_start_reg + ways + 2) + +NUM_CBC_REGS equ (ways_start_reg + ways + 3) + + +MY_SEG_PROC AesCbc_Decode_HW, 3 + + AesCbc_Decode_HW_start:: + MY_PROLOG NUM_CBC_REGS + + AesCbc_Decode_HW_start_2:: + movdqa iv, [keys] + add keys, 32 + + movdqa key0, [keys + 1 * ksize_r] + movdqa key_last, [keys] + sub ksize_x, 16 + + jmp check2 + align 16 + nextBlocks2: + WOP movdqa, [rD + i * 16] + mov koffs_x, ksize_x + ; WOP_KEY pxor, ksize_r + 16 + WOP pxor, key0 + ; align 16 + @@: + WOP_KEY aesdec, 1 * koffs_r + sub koffs_r, 16 + jnz @B + ; WOP_KEY aesdeclast, 0 + WOP aesdeclast, key_last + + pxor @CatStr(xmm, %(ways_start_reg)), iv + i = 1 + rept ways - 1 + pxor @CatStr(xmm, %(ways_start_reg + i)), [rD + i * 16 - 16] + i = i + 1 + endm + movdqa iv, [rD + ways * 16 - 16] + WOP WRITE_TO_DATA + + add rD, ways * 16 + AesCbc_Decode_HW_start_3:: + check2: + sub rN, ways + jnc nextBlocks2 + add rN, ways + + sub ksize_x, 16 + + jmp check + nextBlock: + movdqa state, [rD] + mov koffs_x, ksize_x + ; OP_KEY pxor, 1 * ksize_r + 32 + pxor state, key0 + ; movdqa state0, [rD] + ; movdqa state, key0 + ; pxor state, state0 + @@: + OP_KEY aesdec, 1 * koffs_r + 16 + OP_KEY aesdec, 1 * koffs_r + sub koffs_r, 32 + jnz @B + OP_KEY aesdec, 16 + ; OP_KEY aesdeclast, 0 + aesdeclast state, key_last + + pxor state, iv + movdqa iv, [rD] + ; movdqa iv, state0 + movdqa [rD], state + + add rD, 16 + check: + sub rN, 1 + jnc nextBlock + + movdqa [keys - 32], iv +MY_EPILOG + + + + +; ---------- AVX ---------- + + +AVX__WOP_n macro op + i = 0 + rept ways + op (ways_start_reg + i) + i = i + 1 + endm +endm + +AVX__WOP macro op + i = 0 + rept ways + op @CatStr(ymm, %(ways_start_reg + i)) + i = i + 1 + endm +endm + + +AVX__WOP_KEY macro op:req, offs:req + vmovdqa key_ymm, ymmword ptr [keys2 + offs] + AVX__WOP_n op +endm + + +AVX__CBC_START macro reg + ; vpxor reg, key_ymm, ymmword ptr [rD + 32 * i] + vpxor reg, key0_ymm, ymmword ptr [rD + 32 * i] +endm + +AVX__CBC_END macro reg + if i eq 0 + vpxor reg, reg, iv_ymm + else + vpxor reg, reg, ymmword ptr [rD + i * 32 - 16] + endif +endm + + +AVX__WRITE_TO_DATA macro reg + vmovdqu ymmword ptr [rD + 32 * i], reg +endm + +AVX__XOR_WITH_DATA macro reg + vpxor reg, reg, ymmword ptr [rD + 32 * i] +endm + +AVX__CTR_START macro reg + vpaddq iv_ymm, iv_ymm, one_ymm + ; vpxor reg, iv_ymm, key_ymm + vpxor reg, iv_ymm, key0_ymm +endm + + +MY_VAES_INSTR_2 macro cmd, dest, a1, a2 + db 0c4H + db 2 + 040H + 020h * (1 - (a2) / 8) + 080h * (1 - (dest) / 8) + db 5 + 8 * ((not (a1)) and 15) + db cmd + db 0c0H + 8 * ((dest) and 7) + ((a2) and 7) +endm + +MY_VAES_INSTR macro cmd, dest, a + MY_VAES_INSTR_2 cmd, dest, dest, a +endm + +MY_vaesenc macro dest, a + MY_VAES_INSTR 0dcH, dest, a +endm +MY_vaesenclast macro dest, a + MY_VAES_INSTR 0ddH, dest, a +endm +MY_vaesdec macro dest, a + MY_VAES_INSTR 0deH, dest, a +endm +MY_vaesdeclast macro dest, a + MY_VAES_INSTR 0dfH, dest, a +endm + + +AVX__VAES_DEC macro reg + MY_vaesdec reg, key_ymm_n +endm + +AVX__VAES_DEC_LAST_key_last macro reg + ; MY_vaesdeclast reg, key_ymm_n + MY_vaesdeclast reg, key_last_ymm_n +endm + +AVX__VAES_ENC macro reg + MY_vaesenc reg, key_ymm_n +endm + +AVX__VAES_ENC_LAST macro reg + MY_vaesenclast reg, key_ymm_n +endm + +AVX__vinserti128_TO_HIGH macro dest, src + vinserti128 dest, dest, src, 1 +endm + + +MY_PROC AesCbc_Decode_HW_256, 3 + ifdef use_vaes_256 + MY_PROLOG NUM_CBC_REGS + + cmp rN, ways * 2 + jb AesCbc_Decode_HW_start_2 + + vmovdqa iv, xmmword ptr [keys] + add keys, 32 + + vbroadcasti128 key0_ymm, xmmword ptr [keys + 1 * ksize_r] + vbroadcasti128 key_last_ymm, xmmword ptr [keys] + sub ksize_x, 16 + mov koffs_x, ksize_x + add ksize_x, ksize_x + + AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 2) * 32) + push keys2 + sub r4, AVX_STACK_SUB + ; sub r4, 32 + ; sub r4, ksize_r + ; lea keys2, [r4 + 32] + mov keys2, r4 + and keys2, -32 + broad: + vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r] + vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm + sub koffs_r, 16 + ; jnc broad + jnz broad + + sub rN, ways * 2 + + align 16 + avx_cbcdec_nextBlock2: + mov koffs_x, ksize_x + ; AVX__WOP_KEY AVX__CBC_START, 1 * koffs_r + 32 + AVX__WOP AVX__CBC_START + @@: + AVX__WOP_KEY AVX__VAES_DEC, 1 * koffs_r + sub koffs_r, 32 + jnz @B + ; AVX__WOP_KEY AVX__VAES_DEC_LAST, 0 + AVX__WOP_n AVX__VAES_DEC_LAST_key_last + + AVX__vinserti128_TO_HIGH iv_ymm, xmmword ptr [rD] + AVX__WOP AVX__CBC_END + + vmovdqa iv, xmmword ptr [rD + ways * 32 - 16] + AVX__WOP AVX__WRITE_TO_DATA + + add rD, ways * 32 + sub rN, ways * 2 + jnc avx_cbcdec_nextBlock2 + add rN, ways * 2 + + shr ksize_x, 1 + + ; lea r4, [r4 + 1 * ksize_r + 32] + add r4, AVX_STACK_SUB + pop keys2 + + vzeroupper + jmp AesCbc_Decode_HW_start_3 + else + jmp AesCbc_Decode_HW_start + endif +MY_ENDP +MY_SEG_ENDP + + + + +; ---------- AES-CBC Encode ---------- + +e0 equ xmm1 + +CENC_START_KEY equ 2 +CENC_NUM_REG_KEYS equ (3 * 2) +; last_key equ @CatStr(xmm, %(CENC_START_KEY + CENC_NUM_REG_KEYS)) + +MY_SEG_PROC AesCbc_Encode_HW, 3 + MY_PROLOG (CENC_START_KEY + CENC_NUM_REG_KEYS + 0) + + movdqa state, [keys] + add keys, 32 + + i = 0 + rept CENC_NUM_REG_KEYS + movdqa @CatStr(xmm, %(CENC_START_KEY + i)), [keys + i * 16] + i = i + 1 + endm + + add keys, ksize_r + neg ksize_r + add ksize_r, (16 * CENC_NUM_REG_KEYS) + ; movdqa last_key, [keys] + jmp check_e + + align 16 + nextBlock_e: + movdqa e0, [rD] + mov koffs_r, ksize_r + pxor e0, @CatStr(xmm, %(CENC_START_KEY)) + pxor state, e0 + + i = 1 + rept (CENC_NUM_REG_KEYS - 1) + aesenc state, @CatStr(xmm, %(CENC_START_KEY + i)) + i = i + 1 + endm + + @@: + OP_KEY aesenc, 1 * koffs_r + OP_KEY aesenc, 1 * koffs_r + 16 + add koffs_r, 32 + jnz @B + OP_KEY aesenclast, 0 + ; aesenclast state, last_key + + movdqa [rD], state + add rD, 16 + check_e: + sub rN, 1 + jnc nextBlock_e + + ; movdqa [keys - 32], state + movdqa [keys + 1 * ksize_r - (16 * CENC_NUM_REG_KEYS) - 32], state +MY_EPILOG +MY_SEG_ENDP + + + +; ---------- AES-CTR ---------- + +ifdef x64 + ; ways = 11 +endif + + +one equ @CatStr(xmm, %(ways_start_reg + ways + 1)) +one_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1)) +key0 equ @CatStr(xmm, %(ways_start_reg + ways + 2)) +key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2)) +NUM_CTR_REGS equ (ways_start_reg + ways + 3) + +INIT_CTR macro reg, _ppp_ + paddq iv, one + movdqa reg, iv +endm + + +MY_SEG_PROC AesCtr_Code_HW, 3 + Ctr_start:: + MY_PROLOG NUM_CTR_REGS + + Ctr_start_2:: + movdqa iv, [keys] + add keys, 32 + movdqa key0, [keys] + + add keys, ksize_r + neg ksize_r + add ksize_r, 16 + + Ctr_start_3:: + mov koffs_x, 1 + movd one, koffs_x + jmp check2_c + + align 16 + nextBlocks2_c: + WOP INIT_CTR, 0 + mov koffs_r, ksize_r + ; WOP_KEY pxor, 1 * koffs_r -16 + WOP pxor, key0 + @@: + WOP_KEY aesenc, 1 * koffs_r + add koffs_r, 16 + jnz @B + WOP_KEY aesenclast, 0 + + WOP XOR_WITH_DATA + WOP WRITE_TO_DATA + add rD, ways * 16 + check2_c: + sub rN, ways + jnc nextBlocks2_c + add rN, ways + + sub keys, 16 + add ksize_r, 16 + + jmp check_c + + ; align 16 + nextBlock_c: + paddq iv, one + ; movdqa state, [keys + 1 * koffs_r - 16] + movdqa state, key0 + mov koffs_r, ksize_r + pxor state, iv + + @@: + OP_KEY aesenc, 1 * koffs_r + OP_KEY aesenc, 1 * koffs_r + 16 + add koffs_r, 32 + jnz @B + OP_KEY aesenc, 0 + OP_KEY aesenclast, 16 + + pxor state, [rD] + movdqa [rD], state + add rD, 16 + check_c: + sub rN, 1 + jnc nextBlock_c + + ; movdqa [keys - 32], iv + movdqa [keys + 1 * ksize_r - 16 - 32], iv +MY_EPILOG + + +MY_PROC AesCtr_Code_HW_256, 3 + ifdef use_vaes_256 + MY_PROLOG NUM_CTR_REGS + + cmp rN, ways * 2 + jb Ctr_start_2 + + vbroadcasti128 iv_ymm, xmmword ptr [keys] + add keys, 32 + vbroadcasti128 key0_ymm, xmmword ptr [keys] + mov koffs_x, 1 + vmovd one, koffs_x + vpsubq iv_ymm, iv_ymm, one_ymm + vpaddq one, one, one + AVX__vinserti128_TO_HIGH one_ymm, one + + add keys, ksize_r + sub ksize_x, 16 + neg ksize_r + mov koffs_r, ksize_r + add ksize_r, ksize_r + + AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 1) * 32) + push keys2 + lea keys2, [r4 - 32] + sub r4, AVX_STACK_SUB + and keys2, -32 + vbroadcasti128 key_ymm, xmmword ptr [keys] + vmovdqa ymmword ptr [keys2], key_ymm + @@: + vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r] + vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm + add koffs_r, 16 + jnz @B + + sub rN, ways * 2 + + align 16 + avx_ctr_nextBlock2: + mov koffs_r, ksize_r + AVX__WOP AVX__CTR_START + ; AVX__WOP_KEY AVX__CTR_START, 1 * koffs_r - 32 + @@: + AVX__WOP_KEY AVX__VAES_ENC, 1 * koffs_r + add koffs_r, 32 + jnz @B + AVX__WOP_KEY AVX__VAES_ENC_LAST, 0 + + AVX__WOP AVX__XOR_WITH_DATA + AVX__WOP AVX__WRITE_TO_DATA + + add rD, ways * 32 + sub rN, ways * 2 + jnc avx_ctr_nextBlock2 + add rN, ways * 2 + + vextracti128 iv, iv_ymm, 1 + sar ksize_r, 1 + + add r4, AVX_STACK_SUB + pop keys2 + + vzeroupper + jmp Ctr_start_3 + else + jmp Ctr_start + endif +MY_ENDP +MY_SEG_ENDP + +end diff --git a/3rdparty/lzma-21.03beta/Asm/x86/LzFindOpt.asm b/3rdparty/lzma-21.03beta/Asm/x86/LzFindOpt.asm new file mode 100644 index 0000000..bc3a6fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/LzFindOpt.asm @@ -0,0 +1,513 @@ +; LzFindOpt.asm -- ASM version of GetMatchesSpecN_2() function +; 2021-07-13: Igor Pavlov : Public domain +; + +ifndef x64 +; x64=1 +; .err +endif + +include 7zAsm.asm + +MY_ASM_START + +_TEXT$LZFINDOPT SEGMENT ALIGN(64) 'CODE' + +MY_ALIGN macro num:req + align num +endm + +MY_ALIGN_32 macro + MY_ALIGN 32 +endm + +MY_ALIGN_64 macro + MY_ALIGN 64 +endm + + +t0_L equ x0_L +t0_x equ x0 +t0 equ r0 +t1_x equ x3 +t1 equ r3 + +cp_x equ t1_x +cp_r equ t1 +m equ x5 +m_r equ r5 +len_x equ x6 +len equ r6 +diff_x equ x7 +diff equ r7 +len0 equ r10 +len1_x equ x11 +len1 equ r11 +maxLen_x equ x12 +maxLen equ r12 +d equ r13 +ptr0 equ r14 +ptr1 equ r15 + +d_lim equ m_r +cycSize equ len_x +hash_lim equ len0 +delta1_x equ len1_x +delta1_r equ len1 +delta_x equ maxLen_x +delta_r equ maxLen +hash equ ptr0 +src equ ptr1 + + + +if (IS_LINUX gt 0) + +; r1 r2 r8 r9 : win32 +; r7 r6 r2 r1 r8 r9 : linux + +lenLimit equ r8 +lenLimit_x equ x8 +; pos_r equ r2 +pos equ x2 +cur equ r1 +son equ r9 + +else + +lenLimit equ REG_ABI_PARAM_2 +lenLimit_x equ REG_ABI_PARAM_2_x +pos equ REG_ABI_PARAM_1_x +cur equ REG_ABI_PARAM_0 +son equ REG_ABI_PARAM_3 + +endif + + +if (IS_LINUX gt 0) + maxLen_OFFS equ (REG_SIZE * (6 + 1)) +else + cutValue_OFFS equ (REG_SIZE * (8 + 1 + 4)) + d_OFFS equ (REG_SIZE + cutValue_OFFS) + maxLen_OFFS equ (REG_SIZE + d_OFFS) +endif + hash_OFFS equ (REG_SIZE + maxLen_OFFS) + limit_OFFS equ (REG_SIZE + hash_OFFS) + size_OFFS equ (REG_SIZE + limit_OFFS) + cycPos_OFFS equ (REG_SIZE + size_OFFS) + cycSize_OFFS equ (REG_SIZE + cycPos_OFFS) + posRes_OFFS equ (REG_SIZE + cycSize_OFFS) + +if (IS_LINUX gt 0) +else + cutValue_PAR equ [r0 + cutValue_OFFS] + d_PAR equ [r0 + d_OFFS] +endif + maxLen_PAR equ [r0 + maxLen_OFFS] + hash_PAR equ [r0 + hash_OFFS] + limit_PAR equ [r0 + limit_OFFS] + size_PAR equ [r0 + size_OFFS] + cycPos_PAR equ [r0 + cycPos_OFFS] + cycSize_PAR equ [r0 + cycSize_OFFS] + posRes_PAR equ [r0 + posRes_OFFS] + + + cutValue_VAR equ DWORD PTR [r4 + 8 * 0] + cutValueCur_VAR equ DWORD PTR [r4 + 8 * 0 + 4] + cycPos_VAR equ DWORD PTR [r4 + 8 * 1 + 0] + cycSize_VAR equ DWORD PTR [r4 + 8 * 1 + 4] + hash_VAR equ QWORD PTR [r4 + 8 * 2] + limit_VAR equ QWORD PTR [r4 + 8 * 3] + size_VAR equ QWORD PTR [r4 + 8 * 4] + distances equ QWORD PTR [r4 + 8 * 5] + maxLen_VAR equ QWORD PTR [r4 + 8 * 6] + + Old_RSP equ QWORD PTR [r4 + 8 * 7] + LOCAL_SIZE equ 8 * 8 + +COPY_VAR_32 macro dest_var, src_var + mov x3, src_var + mov dest_var, x3 +endm + +COPY_VAR_64 macro dest_var, src_var + mov r3, src_var + mov dest_var, r3 +endm + + +; MY_ALIGN_64 +MY_PROC GetMatchesSpecN_2, 13 +MY_PUSH_PRESERVED_ABI_REGS + mov r0, RSP + lea r3, [r0 - LOCAL_SIZE] + and r3, -64 + mov RSP, r3 + mov Old_RSP, r0 + +if (IS_LINUX gt 0) + mov d, REG_ABI_PARAM_5 ; r13 = r9 + mov cutValue_VAR, REG_ABI_PARAM_4_x ; = r8 + mov son, REG_ABI_PARAM_3 ; r9 = r1 + mov r8, REG_ABI_PARAM_2 ; r8 = r2 + mov pos, REG_ABI_PARAM_1_x ; r2 = x6 + mov r1, REG_ABI_PARAM_0 ; r1 = r7 +else + COPY_VAR_32 cutValue_VAR, cutValue_PAR + mov d, d_PAR +endif + + COPY_VAR_64 limit_VAR, limit_PAR + + mov hash_lim, size_PAR + mov size_VAR, hash_lim + + mov cp_x, cycPos_PAR + mov hash, hash_PAR + + mov cycSize, cycSize_PAR + mov cycSize_VAR, cycSize + + ; we want cur in (rcx). So we change the cur and lenLimit variables + sub lenLimit, cur + neg lenLimit_x + inc lenLimit_x + + mov t0_x, maxLen_PAR + sub t0, lenLimit + mov maxLen_VAR, t0 + + jmp main_loop + +MY_ALIGN_64 +fill_empty: + ; ptr0 = *ptr1 = kEmptyHashValue; + mov QWORD PTR [ptr1], 0 + inc pos + inc cp_x + mov DWORD PTR [d - 4], 0 + cmp d, limit_VAR + jae fin + cmp hash, hash_lim + je fin + +; MY_ALIGN_64 +main_loop: + ; UInt32 delta = *hash++; + mov diff_x, [hash] ; delta + add hash, 4 + ; mov cycPos_VAR, cp_x + + inc cur + add d, 4 + mov m, pos + sub m, diff_x; ; matchPos + + ; CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2; + lea ptr1, [son + 8 * cp_r] + ; mov cycSize, cycSize_VAR + cmp pos, cycSize + jb directMode ; if (pos < cycSize_VAR) + + ; CYC MODE + + cmp diff_x, cycSize + jae fill_empty ; if (delta >= cycSize_VAR) + + xor t0_x, t0_x + mov cycPos_VAR, cp_x + sub cp_x, diff_x + ; jae prepare_for_tree_loop + ; add cp_x, cycSize + cmovb t0_x, cycSize + add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0) + jmp prepare_for_tree_loop + + +directMode: + cmp diff_x, pos + je fill_empty ; if (delta == pos) + jae fin_error ; if (delta >= pos) + + mov cycPos_VAR, cp_x + mov cp_x, m + +prepare_for_tree_loop: + mov len0, lenLimit + mov hash_VAR, hash + ; CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1; + lea ptr0, [ptr1 + 4] + ; UInt32 *_distances = ++d; + mov distances, d + + neg len0 + mov len1, len0 + + mov t0_x, cutValue_VAR + mov maxLen, maxLen_VAR + mov cutValueCur_VAR, t0_x + +MY_ALIGN_32 +tree_loop: + neg diff + mov len, len0 + cmp len1, len0 + cmovb len, len1 ; len = (len1 < len0 ? len1 : len0); + add diff, cur + + mov t0_x, [son + cp_r * 8] ; prefetch + movzx t0_x, BYTE PTR [diff + 1 * len] + lea cp_r, [son + cp_r * 8] + cmp [cur + 1 * len], t0_L + je matched_1 + + jb left_0 + + mov [ptr1], m + mov m, [cp_r + 4] + lea ptr1, [cp_r + 4] + sub diff, cur ; FIX32 + jmp next_node + +MY_ALIGN_32 +left_0: + mov [ptr0], m + mov m, [cp_r] + mov ptr0, cp_r + sub diff, cur ; FIX32 + ; jmp next_node + +; ------------ NEXT NODE ------------ +; MY_ALIGN_32 +next_node: + mov cycSize, cycSize_VAR + dec cutValueCur_VAR + je finish_tree + + add diff_x, pos ; prev_match = pos + diff + cmp m, diff_x + jae fin_error ; if (new_match >= prev_match) + + mov diff_x, pos + sub diff_x, m ; delta = pos - new_match + cmp pos, cycSize + jae cyc_mode_2 ; if (pos >= cycSize) + + mov cp_x, m + test m, m + jne tree_loop ; if (m != 0) + +finish_tree: + ; ptr0 = *ptr1 = kEmptyHashValue; + mov DWORD PTR [ptr0], 0 + mov DWORD PTR [ptr1], 0 + + inc pos + + ; _distances[-1] = (UInt32)(d - _distances); + mov t0, distances + mov t1, d + sub t1, t0 + shr t1_x, 2 + mov [t0 - 4], t1_x + + cmp d, limit_VAR + jae fin ; if (d >= limit) + + mov cp_x, cycPos_VAR + mov hash, hash_VAR + mov hash_lim, size_VAR + inc cp_x + cmp hash, hash_lim + jne main_loop ; if (hash != size) + jmp fin + + +MY_ALIGN_32 +cyc_mode_2: + cmp diff_x, cycSize + jae finish_tree ; if (delta >= cycSize) + + mov cp_x, cycPos_VAR + xor t0_x, t0_x + sub cp_x, diff_x ; cp_x = cycPos - delta + cmovb t0_x, cycSize + add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0) + jmp tree_loop + + +MY_ALIGN_32 +matched_1: + + inc len + ; cmp len_x, lenLimit_x + je short lenLimit_reach + movzx t0_x, BYTE PTR [diff + 1 * len] + cmp [cur + 1 * len], t0_L + jne mismatch + + +MY_ALIGN_32 +match_loop: + ; while (++len != lenLimit) (len[diff] != len[0]) ; + + inc len + ; cmp len_x, lenLimit_x + je short lenLimit_reach + movzx t0_x, BYTE PTR [diff + 1 * len] + cmp BYTE PTR [cur + 1 * len], t0_L + je match_loop + +mismatch: + jb left_2 + + mov [ptr1], m + mov m, [cp_r + 4] + lea ptr1, [cp_r + 4] + mov len1, len + + jmp max_update + +MY_ALIGN_32 +left_2: + mov [ptr0], m + mov m, [cp_r] + mov ptr0, cp_r + mov len0, len + +max_update: + sub diff, cur ; restore diff + + cmp maxLen, len + jae next_node + + mov maxLen, len + add len, lenLimit + mov [d], len_x + mov t0_x, diff_x + not t0_x + mov [d + 4], t0_x + add d, 8 + + jmp next_node + + + +MY_ALIGN_32 +lenLimit_reach: + + mov delta_r, cur + sub delta_r, diff + lea delta1_r, [delta_r - 1] + + mov t0_x, [cp_r] + mov [ptr1], t0_x + mov t0_x, [cp_r + 4] + mov [ptr0], t0_x + + mov [d], lenLimit_x + mov [d + 4], delta1_x + add d, 8 + + ; _distances[-1] = (UInt32)(d - _distances); + mov t0, distances + mov t1, d + sub t1, t0 + shr t1_x, 2 + mov [t0 - 4], t1_x + + mov hash, hash_VAR + mov hash_lim, size_VAR + + inc pos + mov cp_x, cycPos_VAR + inc cp_x + + mov d_lim, limit_VAR + mov cycSize, cycSize_VAR + ; if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit) + ; break; + cmp hash, hash_lim + je fin + cmp d, d_lim + jae fin + cmp delta_x, [hash] + jne main_loop + movzx t0_x, BYTE PTR [diff] + cmp [cur], t0_L + jne main_loop + + ; jmp main_loop ; bypass for debug + + mov cycPos_VAR, cp_x + shl len, 3 ; cycSize * 8 + sub diff, cur ; restore diff + xor t0_x, t0_x + cmp cp_x, delta_x ; cmp (cycPos_VAR, delta) + lea cp_r, [son + 8 * cp_r] ; dest + lea src, [cp_r + 8 * diff] + cmovb t0, len ; t0 = (cycPos_VAR < delta ? cycSize * 8 : 0) + add src, t0 + add len, son ; len = son + cycSize * 8 + + +MY_ALIGN_32 +long_loop: + add hash, 4 + + ; *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff]; + + mov t0, [src] + add src, 8 + mov [cp_r], t0 + add cp_r, 8 + cmp src, len + cmove src, son ; if end of (son) buffer is reached, we wrap to begin + + mov DWORD PTR [d], 2 + mov [d + 4], lenLimit_x + mov [d + 8], delta1_x + add d, 12 + + inc cur + + cmp hash, hash_lim + je long_footer + cmp delta_x, [hash] + jne long_footer + movzx t0_x, BYTE PTR [diff + cur] + cmp [cur], t0_L + jne long_footer + cmp d, d_lim + jb long_loop + +long_footer: + sub cp_r, son + shr cp_r, 3 + add pos, cp_x + sub pos, cycPos_VAR + mov cycSize, cycSize_VAR + + cmp d, d_lim + jae fin + cmp hash, hash_lim + jne main_loop + jmp fin + + + +fin_error: + xor d, d + +fin: + mov RSP, Old_RSP + mov t0, [r4 + posRes_OFFS] + mov [t0], pos + mov r0, d + +MY_POP_PRESERVED_ABI_REGS +MY_ENDP + +_TEXT$LZFINDOPT ENDS + +end diff --git a/3rdparty/lzma-21.03beta/Asm/x86/LzmaDecOpt.asm b/3rdparty/lzma-21.03beta/Asm/x86/LzmaDecOpt.asm new file mode 100644 index 0000000..f2818e7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/LzmaDecOpt.asm @@ -0,0 +1,1303 @@ +; LzmaDecOpt.asm -- ASM version of LzmaDec_DecodeReal_3() function +; 2021-02-23: Igor Pavlov : Public domain +; +; 3 - is the code compatibility version of LzmaDec_DecodeReal_*() +; function for check at link time. +; That code is tightly coupled with LzmaDec_TryDummy() +; and with another functions in LzmaDec.c file. +; CLzmaDec structure, (probs) array layout, input and output of +; LzmaDec_DecodeReal_*() must be equal in both versions (C / ASM). + +ifndef x64 +; x64=1 +; .err +endif + +include 7zAsm.asm + +MY_ASM_START + +_TEXT$LZMADECOPT SEGMENT ALIGN(64) 'CODE' + +MY_ALIGN macro num:req + align num +endm + +MY_ALIGN_16 macro + MY_ALIGN 16 +endm + +MY_ALIGN_32 macro + MY_ALIGN 32 +endm + +MY_ALIGN_64 macro + MY_ALIGN 64 +endm + + +; _LZMA_SIZE_OPT equ 1 + +; _LZMA_PROB32 equ 1 + +ifdef _LZMA_PROB32 + PSHIFT equ 2 + PLOAD macro dest, mem + mov dest, dword ptr [mem] + endm + PSTORE macro src, mem + mov dword ptr [mem], src + endm +else + PSHIFT equ 1 + PLOAD macro dest, mem + movzx dest, word ptr [mem] + endm + PSTORE macro src, mem + mov word ptr [mem], @CatStr(src, _W) + endm +endif + +PMULT equ (1 SHL PSHIFT) +PMULT_HALF equ (1 SHL (PSHIFT - 1)) +PMULT_2 equ (1 SHL (PSHIFT + 1)) + +kMatchSpecLen_Error_Data equ (1 SHL 9) + +; x0 range +; x1 pbPos / (prob) TREE +; x2 probBranch / prm (MATCHED) / pbPos / cnt +; x3 sym +;====== r4 === RSP +; x5 cod +; x6 t1 NORM_CALC / probs_state / dist +; x7 t0 NORM_CALC / prob2 IF_BIT_1 +; x8 state +; x9 match (MATCHED) / sym2 / dist2 / lpMask_reg +; x10 kBitModelTotal_reg +; r11 probs +; x12 offs (MATCHED) / dic / len_temp +; x13 processedPos +; x14 bit (MATCHED) / dicPos +; r15 buf + + +cod equ x5 +cod_L equ x5_L +range equ x0 +state equ x8 +state_R equ r8 +buf equ r15 +processedPos equ x13 +kBitModelTotal_reg equ x10 + +probBranch equ x2 +probBranch_R equ r2 +probBranch_W equ x2_W + +pbPos equ x1 +pbPos_R equ r1 + +cnt equ x2 +cnt_R equ r2 + +lpMask_reg equ x9 +dicPos equ r14 + +sym equ x3 +sym_R equ r3 +sym_L equ x3_L + +probs equ r11 +dic equ r12 + +t0 equ x7 +t0_W equ x7_W +t0_R equ r7 + +prob2 equ t0 +prob2_W equ t0_W + +t1 equ x6 +t1_R equ r6 + +probs_state equ t1 +probs_state_R equ t1_R + +prm equ r2 +match equ x9 +match_R equ r9 +offs equ x12 +offs_R equ r12 +bit equ x14 +bit_R equ r14 + +sym2 equ x9 +sym2_R equ r9 + +len_temp equ x12 + +dist equ sym +dist2 equ x9 + + + +kNumBitModelTotalBits equ 11 +kBitModelTotal equ (1 SHL kNumBitModelTotalBits) +kNumMoveBits equ 5 +kBitModelOffset equ ((1 SHL kNumMoveBits) - 1) +kTopValue equ (1 SHL 24) + +NORM_2 macro + ; movzx t0, BYTE PTR [buf] + shl cod, 8 + mov cod_L, BYTE PTR [buf] + shl range, 8 + ; or cod, t0 + inc buf +endm + + +NORM macro + cmp range, kTopValue + jae SHORT @F + NORM_2 +@@: +endm + + +; ---------- Branch MACROS ---------- + +UPDATE_0 macro probsArray:req, probOffset:req, probDisp:req + mov prob2, kBitModelTotal_reg + sub prob2, probBranch + shr prob2, kNumMoveBits + add probBranch, prob2 + PSTORE probBranch, probOffset * 1 + probsArray + probDisp * PMULT +endm + + +UPDATE_1 macro probsArray:req, probOffset:req, probDisp:req + sub prob2, range + sub cod, range + mov range, prob2 + mov prob2, probBranch + shr probBranch, kNumMoveBits + sub prob2, probBranch + PSTORE prob2, probOffset * 1 + probsArray + probDisp * PMULT +endm + + +CMP_COD macro probsArray:req, probOffset:req, probDisp:req + PLOAD probBranch, probOffset * 1 + probsArray + probDisp * PMULT + NORM + mov prob2, range + shr range, kNumBitModelTotalBits + imul range, probBranch + cmp cod, range +endm + + +IF_BIT_1_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD probsArray, probOffset, probDisp + jae toLabel +endm + + +IF_BIT_1 macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + IF_BIT_1_NOUP probsArray, probOffset, probDisp, toLabel + UPDATE_0 probsArray, probOffset, probDisp +endm + + +IF_BIT_0_NOUP macro probsArray:req, probOffset:req, probDisp:req, toLabel:req + CMP_COD probsArray, probOffset, probDisp + jb toLabel +endm + + +; ---------- CMOV MACROS ---------- + +NORM_CALC macro prob:req + NORM + mov t0, range + shr range, kNumBitModelTotalBits + imul range, prob + sub t0, range + mov t1, cod + sub cod, range +endm + + +PUP macro prob:req, probPtr:req + sub t0, prob + ; only sar works for both 16/32 bit prob modes + sar t0, kNumMoveBits + add t0, prob + PSTORE t0, probPtr +endm + + +PUP_SUB macro prob:req, probPtr:req, symSub:req + sbb sym, symSub + PUP prob, probPtr +endm + + +PUP_COD macro prob:req, probPtr:req, symSub:req + mov t0, kBitModelOffset + cmovb cod, t1 + mov t1, sym + cmovb t0, kBitModelTotal_reg + PUP_SUB prob, probPtr, symSub +endm + + +BIT_0 macro prob:req, probNext:req + PLOAD prob, probs + 1 * PMULT + PLOAD probNext, probs + 1 * PMULT_2 + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + 1 * PMULT_2 + PMULT + cmovae probNext, t0 + mov t0, kBitModelOffset + cmovb cod, t1 + cmovb t0, kBitModelTotal_reg + mov sym, 2 + PUP_SUB prob, probs + 1 * PMULT, 0 - 1 +endm + + +BIT_1 macro prob:req, probNext:req + PLOAD probNext, probs + sym_R * PMULT_2 + add sym, sym + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + sym_R * PMULT + PMULT + cmovae probNext, t0 + PUP_COD prob, probs + t1_R * PMULT_HALF, 0 - 1 +endm + + +BIT_2 macro prob:req, symSub:req + add sym, sym + + NORM_CALC prob + + cmovae range, t0 + PUP_COD prob, probs + t1_R * PMULT_HALF, symSub +endm + + +; ---------- MATCHED LITERAL ---------- + +LITM_0 macro + mov offs, 256 * PMULT + shl match, (PSHIFT + 1) + mov bit, offs + and bit, match + PLOAD x1, probs + 256 * PMULT + bit_R * 1 + 1 * PMULT + lea prm, [probs + 256 * PMULT + bit_R * 1 + 1 * PMULT] + ; lea prm, [probs + 256 * PMULT + 1 * PMULT] + ; add prm, bit_R + xor offs, bit + add match, match + + NORM_CALC x1 + + cmovae offs, bit + mov bit, match + cmovae range, t0 + mov t0, kBitModelOffset + cmovb cod, t1 + cmovb t0, kBitModelTotal_reg + mov sym, 0 + PUP_SUB x1, prm, -2-1 +endm + + +LITM macro + and bit, offs + lea prm, [probs + offs_R * 1] + add prm, bit_R + PLOAD x1, prm + sym_R * PMULT + xor offs, bit + add sym, sym + add match, match + + NORM_CALC x1 + + cmovae offs, bit + mov bit, match + cmovae range, t0 + PUP_COD x1, prm + t1_R * PMULT_HALF, - 1 +endm + + +LITM_2 macro + and bit, offs + lea prm, [probs + offs_R * 1] + add prm, bit_R + PLOAD x1, prm + sym_R * PMULT + add sym, sym + + NORM_CALC x1 + + cmovae range, t0 + PUP_COD x1, prm + t1_R * PMULT_HALF, 256 - 1 +endm + + +; ---------- REVERSE BITS ---------- + +REV_0 macro prob:req, probNext:req + ; PLOAD prob, probs + 1 * PMULT + ; lea sym2_R, [probs + 2 * PMULT] + ; PLOAD probNext, probs + 2 * PMULT + PLOAD probNext, sym2_R + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, probs + 3 * PMULT + cmovae probNext, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + lea t1_R, [probs + 3 * PMULT] + cmovae sym2_R, t1_R + PUP prob, probs + 1 * PMULT +endm + + +REV_1 macro prob:req, probNext:req, step:req + add sym2_R, step * PMULT + PLOAD probNext, sym2_R + + NORM_CALC prob + + cmovae range, t0 + PLOAD t0, sym2_R + step * PMULT + cmovae probNext, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + lea t1_R, [sym2_R + step * PMULT] + cmovae sym2_R, t1_R + PUP prob, t1_R - step * PMULT_2 +endm + + +REV_2 macro prob:req, step:req + sub sym2_R, probs + shr sym2, PSHIFT + or sym, sym2 + + NORM_CALC prob + + cmovae range, t0 + lea t0, [sym - step] + cmovb sym, t0 + cmovb cod, t1 + mov t0, kBitModelOffset + cmovb t0, kBitModelTotal_reg + PUP prob, probs + sym2_R * PMULT +endm + + +REV_1_VAR macro prob:req + PLOAD prob, sym_R + mov probs, sym_R + add sym_R, sym2_R + + NORM_CALC prob + + cmovae range, t0 + lea t0_R, [sym_R + 1 * sym2_R] + cmovae sym_R, t0_R + mov t0, kBitModelOffset + cmovb cod, t1 + ; mov t1, kBitModelTotal + ; cmovb t0, t1 + cmovb t0, kBitModelTotal_reg + add sym2, sym2 + PUP prob, probs +endm + + + + +LIT_PROBS macro lpMaskParam:req + ; prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); + mov t0, processedPos + shl t0, 8 + add sym, t0 + and sym, lpMaskParam + add probs_state_R, pbPos_R + mov x1, LOC lc2 + lea sym, dword ptr[sym_R + 2 * sym_R] + add probs, Literal * PMULT + shl sym, x1_L + add probs, sym_R + UPDATE_0 probs_state_R, 0, IsMatch + inc processedPos +endm + + + +kNumPosBitsMax equ 4 +kNumPosStatesMax equ (1 SHL kNumPosBitsMax) + +kLenNumLowBits equ 3 +kLenNumLowSymbols equ (1 SHL kLenNumLowBits) +kLenNumHighBits equ 8 +kLenNumHighSymbols equ (1 SHL kLenNumHighBits) +kNumLenProbs equ (2 * kLenNumLowSymbols * kNumPosStatesMax + kLenNumHighSymbols) + +LenLow equ 0 +LenChoice equ LenLow +LenChoice2 equ (LenLow + kLenNumLowSymbols) +LenHigh equ (LenLow + 2 * kLenNumLowSymbols * kNumPosStatesMax) + +kNumStates equ 12 +kNumStates2 equ 16 +kNumLitStates equ 7 + +kStartPosModelIndex equ 4 +kEndPosModelIndex equ 14 +kNumFullDistances equ (1 SHL (kEndPosModelIndex SHR 1)) + +kNumPosSlotBits equ 6 +kNumLenToPosStates equ 4 + +kNumAlignBits equ 4 +kAlignTableSize equ (1 SHL kNumAlignBits) + +kMatchMinLen equ 2 +kMatchSpecLenStart equ (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +kStartOffset equ 1664 +SpecPos equ (-kStartOffset) +IsRep0Long equ (SpecPos + kNumFullDistances) +RepLenCoder equ (IsRep0Long + (kNumStates2 SHL kNumPosBitsMax)) +LenCoder equ (RepLenCoder + kNumLenProbs) +IsMatch equ (LenCoder + kNumLenProbs) +kAlign equ (IsMatch + (kNumStates2 SHL kNumPosBitsMax)) +IsRep equ (kAlign + kAlignTableSize) +IsRepG0 equ (IsRep + kNumStates) +IsRepG1 equ (IsRepG0 + kNumStates) +IsRepG2 equ (IsRepG1 + kNumStates) +PosSlot equ (IsRepG2 + kNumStates) +Literal equ (PosSlot + (kNumLenToPosStates SHL kNumPosSlotBits)) +NUM_BASE_PROBS equ (Literal + kStartOffset) + +if kAlign ne 0 + .err +endif + +if NUM_BASE_PROBS ne 1984 + .err +endif + + +PTR_FIELD equ dq ? + +CLzmaDec_Asm struct + lc db ? + lp db ? + pb db ? + _pad_ db ? + dicSize dd ? + + probs_Spec PTR_FIELD + probs_1664 PTR_FIELD + dic_Spec PTR_FIELD + dicBufSize PTR_FIELD + dicPos_Spec PTR_FIELD + buf_Spec PTR_FIELD + + range_Spec dd ? + code_Spec dd ? + processedPos_Spec dd ? + checkDicSize dd ? + rep0 dd ? + rep1 dd ? + rep2 dd ? + rep3 dd ? + state_Spec dd ? + remainLen dd ? +CLzmaDec_Asm ends + + +CLzmaDec_Asm_Loc struct + OLD_RSP PTR_FIELD + lzmaPtr PTR_FIELD + _pad0_ PTR_FIELD + _pad1_ PTR_FIELD + _pad2_ PTR_FIELD + dicBufSize PTR_FIELD + probs_Spec PTR_FIELD + dic_Spec PTR_FIELD + + limit PTR_FIELD + bufLimit PTR_FIELD + lc2 dd ? + lpMask dd ? + pbMask dd ? + checkDicSize dd ? + + _pad_ dd ? + remainLen dd ? + dicPos_Spec PTR_FIELD + rep0 dd ? + rep1 dd ? + rep2 dd ? + rep3 dd ? +CLzmaDec_Asm_Loc ends + + +GLOB_2 equ [sym_R].CLzmaDec_Asm. +GLOB equ [r1].CLzmaDec_Asm. +LOC_0 equ [r0].CLzmaDec_Asm_Loc. +LOC equ [RSP].CLzmaDec_Asm_Loc. + + +COPY_VAR macro name + mov t0, GLOB_2 name + mov LOC_0 name, t0 +endm + + +RESTORE_VAR macro name + mov t0, LOC name + mov GLOB name, t0 +endm + + + +IsMatchBranch_Pre macro reg + ; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + mov pbPos, LOC pbMask + and pbPos, processedPos + shl pbPos, (kLenNumLowBits + 1 + PSHIFT) + lea probs_state_R, [probs + 1 * state_R] +endm + + +IsMatchBranch macro reg + IsMatchBranch_Pre + IF_BIT_1 probs_state_R, pbPos_R, IsMatch, IsMatch_label +endm + + +CheckLimits macro reg + cmp buf, LOC bufLimit + jae fin_OK + cmp dicPos, LOC limit + jae fin_OK +endm + + + +; RSP is (16x + 8) bytes aligned in WIN64-x64 +; LocalSize equ ((((SIZEOF CLzmaDec_Asm_Loc) + 7) / 16 * 16) + 8) + +PARAM_lzma equ REG_ABI_PARAM_0 +PARAM_limit equ REG_ABI_PARAM_1 +PARAM_bufLimit equ REG_ABI_PARAM_2 + +; MY_ALIGN_64 +MY_PROC LzmaDec_DecodeReal_3, 3 +MY_PUSH_PRESERVED_ABI_REGS + + lea r0, [RSP - (SIZEOF CLzmaDec_Asm_Loc)] + and r0, -128 + mov r5, RSP + mov RSP, r0 + mov LOC_0 Old_RSP, r5 + mov LOC_0 lzmaPtr, PARAM_lzma + + mov LOC_0 remainLen, 0 ; remainLen must be ZERO + + mov LOC_0 bufLimit, PARAM_bufLimit + mov sym_R, PARAM_lzma ; CLzmaDec_Asm_Loc pointer for GLOB_2 + mov dic, GLOB_2 dic_Spec + add PARAM_limit, dic + mov LOC_0 limit, PARAM_limit + + COPY_VAR(rep0) + COPY_VAR(rep1) + COPY_VAR(rep2) + COPY_VAR(rep3) + + mov dicPos, GLOB_2 dicPos_Spec + add dicPos, dic + mov LOC_0 dicPos_Spec, dicPos + mov LOC_0 dic_Spec, dic + + mov x1_L, GLOB_2 pb + mov t0, 1 + shl t0, x1_L + dec t0 + mov LOC_0 pbMask, t0 + + ; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + ; unsigned lc = p->prop.lc; + ; unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); + + mov x1_L, GLOB_2 lc + mov x2, 100h + mov t0, x2 + shr x2, x1_L + ; inc x1 + add x1_L, PSHIFT + mov LOC_0 lc2, x1 + mov x1_L, GLOB_2 lp + shl t0, x1_L + sub t0, x2 + mov LOC_0 lpMask, t0 + mov lpMask_reg, t0 + + ; mov probs, GLOB_2 probs_Spec + ; add probs, kStartOffset SHL PSHIFT + mov probs, GLOB_2 probs_1664 + mov LOC_0 probs_Spec, probs + + mov t0_R, GLOB_2 dicBufSize + mov LOC_0 dicBufSize, t0_R + + mov x1, GLOB_2 checkDicSize + mov LOC_0 checkDicSize, x1 + + mov processedPos, GLOB_2 processedPos_Spec + + mov state, GLOB_2 state_Spec + shl state, PSHIFT + + mov buf, GLOB_2 buf_Spec + mov range, GLOB_2 range_Spec + mov cod, GLOB_2 code_Spec + mov kBitModelTotal_reg, kBitModelTotal + xor sym, sym + + ; if (processedPos != 0 || checkDicSize != 0) + or x1, processedPos + jz @f + + add t0_R, dic + cmp dicPos, dic + cmovnz t0_R, dicPos + movzx sym, byte ptr[t0_R - 1] + +@@: + IsMatchBranch_Pre + cmp state, 4 * PMULT + jb lit_end + cmp state, kNumLitStates * PMULT + jb lit_matched_end + jmp lz_end + + + + +; ---------- LITERAL ---------- +MY_ALIGN_64 +lit_start: + xor state, state +lit_start_2: + LIT_PROBS lpMask_reg + + ifdef _LZMA_SIZE_OPT + + PLOAD x1, probs + 1 * PMULT + mov sym, 1 +MY_ALIGN_16 +lit_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 127 + jbe lit_loop + + else + + BIT_0 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + + endif + + BIT_2 x2, 256 - 1 + + ; mov dic, LOC dic_Spec + mov probs, LOC probs_Spec + IsMatchBranch_Pre + mov byte ptr[dicPos], sym_L + inc dicPos + + CheckLimits +lit_end: + IF_BIT_0_NOUP probs_state_R, pbPos_R, IsMatch, lit_start + + ; jmp IsMatch_label + +; ---------- MATCHES ---------- +; MY_ALIGN_32 +IsMatch_label: + UPDATE_1 probs_state_R, pbPos_R, IsMatch + IF_BIT_1 probs_state_R, 0, IsRep, IsRep_label + + add probs, LenCoder * PMULT + add state, kNumStates * PMULT + +; ---------- LEN DECODE ---------- +len_decode: + mov len_temp, 8 - 1 - kMatchMinLen + IF_BIT_0_NOUP probs, 0, 0, len_mid_0 + UPDATE_1 probs, 0, 0 + add probs, (1 SHL (kLenNumLowBits + PSHIFT)) + mov len_temp, -1 - kMatchMinLen + IF_BIT_0_NOUP probs, 0, 0, len_mid_0 + UPDATE_1 probs, 0, 0 + add probs, LenHigh * PMULT - (1 SHL (kLenNumLowBits + PSHIFT)) + mov sym, 1 + PLOAD x1, probs + 1 * PMULT + +MY_ALIGN_32 +len8_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 64 + jb len8_loop + + mov len_temp, (kLenNumHighSymbols - kLenNumLowSymbols * 2) - 1 - kMatchMinLen + jmp short len_mid_2 ; we use short here for MASM that doesn't optimize that code as another assembler programs + +MY_ALIGN_32 +len_mid_0: + UPDATE_0 probs, 0, 0 + add probs, pbPos_R + BIT_0 x2, x1 +len_mid_2: + BIT_1 x1, x2 + BIT_2 x2, len_temp + mov probs, LOC probs_Spec + cmp state, kNumStates * PMULT + jb copy_match + + +; ---------- DECODE DISTANCE ---------- + ; probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + + mov t0, 3 + kMatchMinLen + cmp sym, 3 + kMatchMinLen + cmovb t0, sym + add probs, PosSlot * PMULT - (kMatchMinLen SHL (kNumPosSlotBits + PSHIFT)) + shl t0, (kNumPosSlotBits + PSHIFT) + add probs, t0_R + + ; sym = Len + ; mov LOC remainLen, sym + mov len_temp, sym + + ifdef _LZMA_SIZE_OPT + + PLOAD x1, probs + 1 * PMULT + mov sym, 1 +MY_ALIGN_16 +slot_loop: + BIT_1 x1, x2 + mov x1, x2 + cmp sym, 32 + jb slot_loop + + else + + BIT_0 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + BIT_1 x2, x1 + BIT_1 x1, x2 + + endif + + mov x1, sym + BIT_2 x2, 64-1 + + and sym, 3 + mov probs, LOC probs_Spec + cmp x1, 32 + kEndPosModelIndex / 2 + jb short_dist + + ; unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + sub x1, (32 + 1 + kNumAlignBits) + ; distance = (2 | (distance & 1)); + or sym, 2 + PLOAD x2, probs + 1 * PMULT + shl sym, kNumAlignBits + 1 + lea sym2_R, [probs + 2 * PMULT] + + jmp direct_norm + ; lea t1, [sym_R + (1 SHL kNumAlignBits)] + ; cmp range, kTopValue + ; jb direct_norm + +; ---------- DIRECT DISTANCE ---------- +MY_ALIGN_32 +direct_loop: + shr range, 1 + mov t0, cod + sub cod, range + cmovs cod, t0 + cmovns sym, t1 + + comment ~ + sub cod, range + mov x2, cod + sar x2, 31 + lea sym, dword ptr [r2 + sym_R * 2 + 1] + and x2, range + add cod, x2 + ~ + dec x1 + je direct_end + + add sym, sym +direct_norm: + lea t1, [sym_R + (1 SHL kNumAlignBits)] + cmp range, kTopValue + jae near ptr direct_loop + ; we align for 32 here with "near ptr" command above + NORM_2 + jmp direct_loop + +MY_ALIGN_32 +direct_end: + ; prob = + kAlign; + ; distance <<= kNumAlignBits; + REV_0 x2, x1 + REV_1 x1, x2, 2 + REV_1 x2, x1, 4 + REV_2 x1, 8 + +decode_dist_end: + + ; if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + + mov t1, LOC rep0 + mov x1, LOC rep1 + mov x2, LOC rep2 + + mov t0, LOC checkDicSize + test t0, t0 + cmove t0, processedPos + cmp sym, t0 + jae end_of_payload + ; jmp end_of_payload ; for debug + + ; rep3 = rep2; + ; rep2 = rep1; + ; rep1 = rep0; + ; rep0 = distance + 1; + + inc sym + mov LOC rep0, sym + ; mov sym, LOC remainLen + mov sym, len_temp + mov LOC rep1, t1 + mov LOC rep2, x1 + mov LOC rep3, x2 + + ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + cmp state, (kNumStates + kNumLitStates) * PMULT + mov state, kNumLitStates * PMULT + mov t0, (kNumLitStates + 3) * PMULT + cmovae state, t0 + + +; ---------- COPY MATCH ---------- +copy_match: + + ; len += kMatchMinLen; + ; add sym, kMatchMinLen + + ; if ((rem = limit - dicPos) == 0) + ; { + ; p->dicPos = dicPos; + ; return SZ_ERROR_DATA; + ; } + mov cnt_R, LOC limit + sub cnt_R, dicPos + jz fin_dicPos_LIMIT + + ; curLen = ((rem < len) ? (unsigned)rem : len); + cmp cnt_R, sym_R + ; cmovae cnt_R, sym_R ; 64-bit + cmovae cnt, sym ; 32-bit + + mov dic, LOC dic_Spec + mov x1, LOC rep0 + + mov t0_R, dicPos + add dicPos, cnt_R + ; processedPos += curLen; + add processedPos, cnt + ; len -= curLen; + sub sym, cnt + mov LOC remainLen, sym + + sub t0_R, dic + + ; pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + sub t0_R, r1 + jae @f + + mov r1, LOC dicBufSize + add t0_R, r1 + sub r1, t0_R + cmp cnt_R, r1 + ja copy_match_cross +@@: + ; if (curLen <= dicBufSize - pos) + +; ---------- COPY MATCH FAST ---------- + ; Byte *dest = dic + dicPos; + ; mov r1, dic + ; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + ; sub t0_R, dicPos + ; dicPos += curLen; + + ; const Byte *lim = dest + curLen; + add t0_R, dic + movzx sym, byte ptr[t0_R] + add t0_R, cnt_R + neg cnt_R + ; lea r1, [dicPos - 1] +copy_common: + dec dicPos + ; cmp LOC rep0, 1 + ; je rep0Label + + ; t0_R - src_lim + ; r1 - dest_lim - 1 + ; cnt_R - (-cnt) + + IsMatchBranch_Pre + inc cnt_R + jz copy_end +MY_ALIGN_16 +@@: + mov byte ptr[cnt_R * 1 + dicPos], sym_L + movzx sym, byte ptr[cnt_R * 1 + t0_R] + inc cnt_R + jnz @b + +copy_end: +lz_end_match: + mov byte ptr[dicPos], sym_L + inc dicPos + + ; IsMatchBranch_Pre + CheckLimits +lz_end: + IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label + + + +; ---------- LITERAL MATCHED ---------- + + LIT_PROBS LOC lpMask + + ; matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + mov x1, LOC rep0 + ; mov dic, LOC dic_Spec + mov LOC dicPos_Spec, dicPos + + ; state -= (state < 10) ? 3 : 6; + lea t0, [state_R - 6 * PMULT] + sub state, 3 * PMULT + cmp state, 7 * PMULT + cmovae state, t0 + + sub dicPos, dic + sub dicPos, r1 + jae @f + add dicPos, LOC dicBufSize +@@: + comment ~ + xor t0, t0 + sub dicPos, r1 + cmovb t0_R, LOC dicBufSize + ~ + + movzx match, byte ptr[dic + dicPos * 1] + + ifdef _LZMA_SIZE_OPT + + mov offs, 256 * PMULT + shl match, (PSHIFT + 1) + mov bit, match + mov sym, 1 +MY_ALIGN_16 +litm_loop: + LITM + cmp sym, 256 + jb litm_loop + sub sym, 256 + + else + + LITM_0 + LITM + LITM + LITM + LITM + LITM + LITM + LITM_2 + + endif + + mov probs, LOC probs_Spec + IsMatchBranch_Pre + ; mov dic, LOC dic_Spec + mov dicPos, LOC dicPos_Spec + mov byte ptr[dicPos], sym_L + inc dicPos + + CheckLimits +lit_matched_end: + IF_BIT_1_NOUP probs_state_R, pbPos_R, IsMatch, IsMatch_label + ; IsMatchBranch + mov lpMask_reg, LOC lpMask + sub state, 3 * PMULT + jmp lit_start_2 + + + +; ---------- REP 0 LITERAL ---------- +MY_ALIGN_32 +IsRep0Short_label: + UPDATE_0 probs_state_R, pbPos_R, IsRep0Long + + ; dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + mov dic, LOC dic_Spec + mov t0_R, dicPos + mov probBranch, LOC rep0 + sub t0_R, dic + + sub probs, RepLenCoder * PMULT + + ; state = state < kNumLitStates ? 9 : 11; + or state, 1 * PMULT + + ; the caller doesn't allow (dicPos >= limit) case for REP_SHORT + ; so we don't need the following (dicPos == limit) check here: + ; cmp dicPos, LOC limit + ; jae fin_dicPos_LIMIT_REP_SHORT + + inc processedPos + + IsMatchBranch_Pre + +; xor sym, sym +; sub t0_R, probBranch_R +; cmovb sym_R, LOC dicBufSize +; add t0_R, sym_R + sub t0_R, probBranch_R + jae @f + add t0_R, LOC dicBufSize +@@: + movzx sym, byte ptr[dic + t0_R * 1] + jmp lz_end_match + + +MY_ALIGN_32 +IsRep_label: + UPDATE_1 probs_state_R, 0, IsRep + + ; The (checkDicSize == 0 && processedPos == 0) case was checked before in LzmaDec.c with kBadRepCode. + ; So we don't check it here. + + ; mov t0, processedPos + ; or t0, LOC checkDicSize + ; jz fin_ERROR_2 + + ; state = state < kNumLitStates ? 8 : 11; + cmp state, kNumLitStates * PMULT + mov state, 8 * PMULT + mov probBranch, 11 * PMULT + cmovae state, probBranch + + ; prob = probs + RepLenCoder; + add probs, RepLenCoder * PMULT + + IF_BIT_1 probs_state_R, 0, IsRepG0, IsRepG0_label + IF_BIT_0_NOUP probs_state_R, pbPos_R, IsRep0Long, IsRep0Short_label + UPDATE_1 probs_state_R, pbPos_R, IsRep0Long + jmp len_decode + +MY_ALIGN_32 +IsRepG0_label: + UPDATE_1 probs_state_R, 0, IsRepG0 + mov dist2, LOC rep0 + mov dist, LOC rep1 + mov LOC rep1, dist2 + + IF_BIT_1 probs_state_R, 0, IsRepG1, IsRepG1_label + mov LOC rep0, dist + jmp len_decode + +; MY_ALIGN_32 +IsRepG1_label: + UPDATE_1 probs_state_R, 0, IsRepG1 + mov dist2, LOC rep2 + mov LOC rep2, dist + + IF_BIT_1 probs_state_R, 0, IsRepG2, IsRepG2_label + mov LOC rep0, dist2 + jmp len_decode + +; MY_ALIGN_32 +IsRepG2_label: + UPDATE_1 probs_state_R, 0, IsRepG2 + mov dist, LOC rep3 + mov LOC rep3, dist2 + mov LOC rep0, dist + jmp len_decode + + + +; ---------- SPEC SHORT DISTANCE ---------- + +MY_ALIGN_32 +short_dist: + sub x1, 32 + 1 + jbe decode_dist_end + or sym, 2 + shl sym, x1_L + lea sym_R, [probs + sym_R * PMULT + SpecPos * PMULT + 1 * PMULT] + mov sym2, PMULT ; step +MY_ALIGN_32 +spec_loop: + REV_1_VAR x2 + dec x1 + jnz spec_loop + + mov probs, LOC probs_Spec + sub sym, sym2 + sub sym, SpecPos * PMULT + sub sym_R, probs + shr sym, PSHIFT + + jmp decode_dist_end + + +; ---------- COPY MATCH CROSS ---------- +copy_match_cross: + ; t0_R - src pos + ; r1 - len to dicBufSize + ; cnt_R - total copy len + + mov t1_R, t0_R ; srcPos + mov t0_R, dic + mov r1, LOC dicBufSize ; + neg cnt_R +@@: + movzx sym, byte ptr[t1_R * 1 + t0_R] + inc t1_R + mov byte ptr[cnt_R * 1 + dicPos], sym_L + inc cnt_R + cmp t1_R, r1 + jne @b + + movzx sym, byte ptr[t0_R] + sub t0_R, cnt_R + jmp copy_common + + + + +; fin_dicPos_LIMIT_REP_SHORT: + ; mov sym, 1 + +fin_dicPos_LIMIT: + mov LOC remainLen, sym + jmp fin_OK + ; For more strict mode we can stop decoding with error + ; mov sym, 1 + ; jmp fin + + +fin_ERROR_MATCH_DIST: + + ; rep3 = rep2; + ; rep2 = rep1; + ; rep1 = rep0; + ; rep0 = distance + 1; + + add len_temp, kMatchSpecLen_Error_Data + mov LOC remainLen, len_temp + + mov LOC rep0, sym + mov LOC rep1, t1 + mov LOC rep2, x1 + mov LOC rep3, x2 + + ; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + cmp state, (kNumStates + kNumLitStates) * PMULT + mov state, kNumLitStates * PMULT + mov t0, (kNumLitStates + 3) * PMULT + cmovae state, t0 + + ; jmp fin_OK + mov sym, 1 + jmp fin + +end_of_payload: + inc sym + jnz fin_ERROR_MATCH_DIST + + mov LOC remainLen, kMatchSpecLenStart + sub state, kNumStates * PMULT + +fin_OK: + xor sym, sym + +fin: + NORM + + mov r1, LOC lzmaPtr + + sub dicPos, LOC dic_Spec + mov GLOB dicPos_Spec, dicPos + mov GLOB buf_Spec, buf + mov GLOB range_Spec, range + mov GLOB code_Spec, cod + shr state, PSHIFT + mov GLOB state_Spec, state + mov GLOB processedPos_Spec, processedPos + + RESTORE_VAR(remainLen) + RESTORE_VAR(rep0) + RESTORE_VAR(rep1) + RESTORE_VAR(rep2) + RESTORE_VAR(rep3) + + mov x0, sym + + mov RSP, LOC Old_RSP + +MY_POP_PRESERVED_ABI_REGS +MY_ENDP + +_TEXT$LZMADECOPT ENDS + +end diff --git a/3rdparty/lzma-21.03beta/Asm/x86/Sha256Opt.asm b/3rdparty/lzma-21.03beta/Asm/x86/Sha256Opt.asm new file mode 100644 index 0000000..5d02c90 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/Sha256Opt.asm @@ -0,0 +1,263 @@ +; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions +; 2021-03-10 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +; .data +; public K + +; we can use external SHA256_K_ARRAY defined in Sha256.c +; but we must guarantee that SHA256_K_ARRAY is aligned for 16-bytes + +COMMENT @ +ifdef x64 +K_CONST equ SHA256_K_ARRAY +else +K_CONST equ _SHA256_K_ARRAY +endif +EXTRN K_CONST:xmmword +@ + +CONST SEGMENT + +align 16 +Reverse_Endian_Mask db 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 + +; COMMENT @ +align 16 +K_CONST \ +DD 0428a2f98H, 071374491H, 0b5c0fbcfH, 0e9b5dba5H +DD 03956c25bH, 059f111f1H, 0923f82a4H, 0ab1c5ed5H +DD 0d807aa98H, 012835b01H, 0243185beH, 0550c7dc3H +DD 072be5d74H, 080deb1feH, 09bdc06a7H, 0c19bf174H +DD 0e49b69c1H, 0efbe4786H, 00fc19dc6H, 0240ca1ccH +DD 02de92c6fH, 04a7484aaH, 05cb0a9dcH, 076f988daH +DD 0983e5152H, 0a831c66dH, 0b00327c8H, 0bf597fc7H +DD 0c6e00bf3H, 0d5a79147H, 006ca6351H, 014292967H +DD 027b70a85H, 02e1b2138H, 04d2c6dfcH, 053380d13H +DD 0650a7354H, 0766a0abbH, 081c2c92eH, 092722c85H +DD 0a2bfe8a1H, 0a81a664bH, 0c24b8b70H, 0c76c51a3H +DD 0d192e819H, 0d6990624H, 0f40e3585H, 0106aa070H +DD 019a4c116H, 01e376c08H, 02748774cH, 034b0bcb5H +DD 0391c0cb3H, 04ed8aa4aH, 05b9cca4fH, 0682e6ff3H +DD 0748f82eeH, 078a5636fH, 084c87814H, 08cc70208H +DD 090befffaH, 0a4506cebH, 0bef9a3f7H, 0c67178f2H +; @ + +CONST ENDS + +; _TEXT$SHA256OPT SEGMENT 'CODE' + +ifndef x64 + .686 + .xmm +endif + +ifdef x64 + rNum equ REG_ABI_PARAM_2 + if (IS_LINUX eq 0) + LOCAL_SIZE equ (16 * 2) + endif +else + rNum equ r0 + LOCAL_SIZE equ (16 * 1) +endif + +rState equ REG_ABI_PARAM_0 +rData equ REG_ABI_PARAM_1 + + + + + + +MY_SHA_INSTR macro cmd, a1, a2 + db 0fH, 038H, cmd, (0c0H + a1 * 8 + a2) +endm + +cmd_sha256rnds2 equ 0cbH +cmd_sha256msg1 equ 0ccH +cmd_sha256msg2 equ 0cdH + +MY_sha256rnds2 macro a1, a2 + MY_SHA_INSTR cmd_sha256rnds2, a1, a2 +endm + +MY_sha256msg1 macro a1, a2 + MY_SHA_INSTR cmd_sha256msg1, a1, a2 +endm + +MY_sha256msg2 macro a1, a2 + MY_SHA_INSTR cmd_sha256msg2, a1, a2 +endm + +MY_PROLOG macro + ifdef x64 + if (IS_LINUX eq 0) + movdqa [r4 + 8], xmm6 + movdqa [r4 + 8 + 16], xmm7 + sub r4, LOCAL_SIZE + 8 + movdqa [r4 ], xmm8 + movdqa [r4 + 16], xmm9 + endif + else ; x86 + if (IS_CDECL gt 0) + mov rState, [r4 + REG_SIZE * 1] + mov rData, [r4 + REG_SIZE * 2] + mov rNum, [r4 + REG_SIZE * 3] + else ; fastcall + mov rNum, [r4 + REG_SIZE * 1] + endif + push r5 + mov r5, r4 + and r4, -16 + sub r4, LOCAL_SIZE + endif +endm + +MY_EPILOG macro + ifdef x64 + if (IS_LINUX eq 0) + movdqa xmm8, [r4] + movdqa xmm9, [r4 + 16] + add r4, LOCAL_SIZE + 8 + movdqa xmm6, [r4 + 8] + movdqa xmm7, [r4 + 8 + 16] + endif + else ; x86 + mov r4, r5 + pop r5 + endif + MY_ENDP +endm + + +msg equ xmm0 +tmp equ xmm0 +state0_N equ 2 +state1_N equ 3 +w_regs equ 4 + + +state1_save equ xmm1 +state0 equ @CatStr(xmm, %state0_N) +state1 equ @CatStr(xmm, %state1_N) + + +ifdef x64 + state0_save equ xmm8 + mask2 equ xmm9 +else + state0_save equ [r4] + mask2 equ xmm0 +endif + +LOAD_MASK macro + movdqa mask2, XMMWORD PTR Reverse_Endian_Mask +endm + +LOAD_W macro k:req + movdqu @CatStr(xmm, %(w_regs + k)), [rData + (16 * (k))] + pshufb @CatStr(xmm, %(w_regs + k)), mask2 +endm + + +; pre1 <= 4 && pre2 >= 1 && pre1 > pre2 && (pre1 - pre2) <= 1 +pre1 equ 3 +pre2 equ 2 + + + +RND4 macro k + movdqa msg, xmmword ptr [K_CONST + (k) * 16] + paddd msg, @CatStr(xmm, %(w_regs + ((k + 0) mod 4))) + MY_sha256rnds2 state0_N, state1_N + pshufd msg, msg, 0eH + + if (k GE (4 - pre1)) AND (k LT (16 - pre1)) + ; w4[0] = msg1(w4[-4], w4[-3]) + MY_sha256msg1 (w_regs + ((k + pre1) mod 4)), (w_regs + ((k + pre1 - 3) mod 4)) + endif + + MY_sha256rnds2 state1_N, state0_N + + if (k GE (4 - pre2)) AND (k LT (16 - pre2)) + movdqa tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 1) mod 4))) + palignr tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 2) mod 4))), 4 + paddd @CatStr(xmm, %(w_regs + ((k + pre2) mod 4))), tmp + ; w4[0] = msg2(w4[0], w4[-1]) + MY_sha256msg2 %(w_regs + ((k + pre2) mod 4)), %(w_regs + ((k + pre2 - 1) mod 4)) + endif +endm + + + + + +REVERSE_STATE macro + ; state0 ; dcba + ; state1 ; hgfe + pshufd tmp, state0, 01bH ; abcd + pshufd state0, state1, 01bH ; efgh + movdqa state1, state0 ; efgh + punpcklqdq state0, tmp ; cdgh + punpckhqdq state1, tmp ; abef +endm + + +MY_PROC Sha256_UpdateBlocks_HW, 3 + MY_PROLOG + + cmp rNum, 0 + je end_c + + movdqu state0, [rState] ; dcba + movdqu state1, [rState + 16] ; hgfe + + REVERSE_STATE + + ifdef x64 + LOAD_MASK + endif + + align 16 + nextBlock: + movdqa state0_save, state0 + movdqa state1_save, state1 + + ifndef x64 + LOAD_MASK + endif + + LOAD_W 0 + LOAD_W 1 + LOAD_W 2 + LOAD_W 3 + + + k = 0 + rept 16 + RND4 k + k = k + 1 + endm + + paddd state0, state0_save + paddd state1, state1_save + + add rData, 64 + sub rNum, 1 + jnz nextBlock + + REVERSE_STATE + + movdqu [rState], state0 + movdqu [rState + 16], state1 + + end_c: +MY_EPILOG + +; _TEXT$SHA256OPT ENDS + +end diff --git a/3rdparty/lzma-21.03beta/Asm/x86/XzCrc64Opt.asm b/3rdparty/lzma-21.03beta/Asm/x86/XzCrc64Opt.asm new file mode 100644 index 0000000..ad22cc2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Asm/x86/XzCrc64Opt.asm @@ -0,0 +1,239 @@ +; XzCrc64Opt.asm -- CRC64 calculation : optimized version +; 2021-02-06 : Igor Pavlov : Public domain + +include 7zAsm.asm + +MY_ASM_START + +ifdef x64 + +rD equ r9 +rN equ r10 +rT equ r5 +num_VAR equ r8 + +SRCDAT4 equ dword ptr [rD + rN * 1] + +CRC_XOR macro dest:req, src:req, t:req + xor dest, QWORD PTR [rT + src * 8 + 0800h * t] +endm + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shr r0, 8 + CRC_XOR r0, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + ifdef ABI_LINUX + MY_PUSH_2_REGS + else + MY_PUSH_4_REGS + endif + mov r0, REG_ABI_PARAM_0 + mov rN, REG_ABI_PARAM_2 + mov rT, REG_ABI_PARAM_3 + mov rD, REG_ABI_PARAM_1 + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + mov num_VAR, rN + sub rN, 4 + and rN, NOT 3 + sub rD, rN + mov x1, SRCDAT4 + xor r0, r1 + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + mov x1, SRCDAT4 + xor r0, r1 + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + ifdef ABI_LINUX + MY_POP_2_REGS + else + MY_POP_4_REGS + endif +endm + +MY_PROC XzCrc64UpdateT4, 4 + MY_PROLOG crc_end_4 + align 16 + main_loop_4: + mov x1, SRCDAT4 + movzx x2, x0_L + movzx x3, x0_H + shr r0, 16 + movzx x6, x0_L + movzx x7, x0_H + shr r0, 16 + CRC_XOR r1, r2, 3 + CRC_XOR r0, r3, 2 + CRC_XOR r1, r6, 1 + CRC_XOR r0, r7, 0 + xor r0, r1 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +else +; x86 (32-bit) + +rD equ r1 +rN equ r7 +rT equ r5 + +crc_OFFS equ (REG_SIZE * 5) + +if (IS_CDECL gt 0) or (IS_LINUX gt 0) + ; cdecl or (GNU fastcall) stack: + ; (UInt32 *) table + ; size_t size + ; void * data + ; (UInt64) crc + ; ret-ip <-(r4) + data_OFFS equ (8 + crc_OFFS) + size_OFFS equ (REG_SIZE + data_OFFS) + table_OFFS equ (REG_SIZE + size_OFFS) + num_VAR equ [r4 + size_OFFS] + table_VAR equ [r4 + table_OFFS] +else + ; Windows fastcall: + ; r1 = data, r2 = size + ; stack: + ; (UInt32 *) table + ; (UInt64) crc + ; ret-ip <-(r4) + table_OFFS equ (8 + crc_OFFS) + table_VAR equ [r4 + table_OFFS] + num_VAR equ table_VAR +endif + +SRCDAT4 equ dword ptr [rD + rN * 1] + +CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req + op0 dest0, DWORD PTR [rT + src * 8 + 0800h * t] + op1 dest1, DWORD PTR [rT + src * 8 + 0800h * t + 4] +endm + +CRC_XOR macro dest0:req, dest1:req, src:req, t:req + CRC xor, xor, dest0, dest1, src, t +endm + + +CRC1b macro + movzx x6, BYTE PTR [rD] + inc rD + movzx x3, x0_L + xor x6, x3 + shrd r0, r2, 8 + shr r2, 8 + CRC_XOR r0, r2, r6, 0 + dec rN +endm + +MY_PROLOG macro crc_end:req + MY_PUSH_4_REGS + + if (IS_CDECL gt 0) or (IS_LINUX gt 0) + proc_numParams = proc_numParams + 2 ; for ABI_LINUX + mov rN, [r4 + size_OFFS] + mov rD, [r4 + data_OFFS] + else + mov rN, r2 + endif + + mov x0, [r4 + crc_OFFS] + mov x2, [r4 + crc_OFFS + 4] + mov rT, table_VAR + test rN, rN + jz crc_end + @@: + test rD, 3 + jz @F + CRC1b + jnz @B + @@: + cmp rN, 8 + jb crc_end + add rN, rD + + mov num_VAR, rN + + sub rN, 4 + and rN, NOT 3 + sub rD, rN + xor r0, SRCDAT4 + add rN, 4 +endm + +MY_EPILOG macro crc_end:req + sub rN, 4 + xor r0, SRCDAT4 + + mov rD, rN + mov rN, num_VAR + sub rN, rD + crc_end: + test rN, rN + jz @F + CRC1b + jmp crc_end + @@: + MY_POP_4_REGS +endm + +MY_PROC XzCrc64UpdateT4, 5 + MY_PROLOG crc_end_4 + movzx x6, x0_L + align 16 + main_loop_4: + mov r3, SRCDAT4 + xor r3, r2 + + CRC xor, mov, r3, r2, r6, 3 + movzx x6, x0_H + shr r0, 16 + CRC_XOR r3, r2, r6, 2 + + movzx x6, x0_L + movzx x0, x0_H + CRC_XOR r3, r2, r6, 1 + CRC_XOR r3, r2, r0, 0 + movzx x6, x3_L + mov r0, r3 + + add rD, 4 + jnz main_loop_4 + + MY_EPILOG crc_end_4 +MY_ENDP + +endif ; ! x64 + +end diff --git a/3rdparty/lzma-21.03beta/C/7z.h b/3rdparty/lzma-21.03beta/C/7z.h new file mode 100644 index 0000000..304f75f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7z.h @@ -0,0 +1,204 @@ +/* 7z.h -- 7z interface +2018-07-02 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 + +extern const Byte k7zSignature[k7zSignatureSize]; + +typedef struct +{ + const Byte *Data; + size_t Size; +} CSzData; + +/* CSzCoderInfo & CSzFolder support only default methods */ + +typedef struct +{ + size_t PropsOffset; + UInt32 MethodID; + Byte NumStreams; + Byte PropsSize; +} CSzCoderInfo; + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBond; + +#define SZ_NUM_CODERS_IN_FOLDER_MAX 4 +#define SZ_NUM_BONDS_IN_FOLDER_MAX 3 +#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 + +typedef struct +{ + UInt32 NumCoders; + UInt32 NumBonds; + UInt32 NumPackStreams; + UInt32 UnpackStream; + UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; + CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX]; + CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; +} CSzFolder; + + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + UInt32 *Vals; +} CSzBitUi32s; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + // UInt64 *Vals; + CNtfsFileTime *Vals; +} CSzBitUi64s; + +#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +typedef struct +{ + UInt32 NumPackStreams; + UInt32 NumFolders; + + UInt64 *PackPositions; // NumPackStreams + 1 + CSzBitUi32s FolderCRCs; // NumFolders + + size_t *FoCodersOffsets; // NumFolders + 1 + UInt32 *FoStartPackStreamIndex; // NumFolders + 1 + UInt32 *FoToCoderUnpackSizes; // NumFolders + 1 + Byte *FoToMainUnpackSizeIndex; // NumFolders + UInt64 *CoderUnpackSizes; // for all coders in all folders + + Byte *CodersData; + + UInt64 RangeLimit; +} CSzAr; + +UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex); + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAllocPtr allocMain); + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 NumFiles; + + UInt64 *UnpackPositions; // NumFiles + 1 + // Byte *IsEmptyFiles; + Byte *IsDirs; + CSzBitUi32s CRCs; + + CSzBitUi32s Attribs; + // CSzBitUi32s Parents; + CSzBitUi64s MTime; + CSzBitUi64s CTime; + + UInt32 *FolderToFile; // NumFolders + 1 + UInt32 *FileToFolder; // NumFiles + + size_t *FileNameOffsets; /* in 2-byte steps */ + Byte *FileNames; /* UTF-16-LE */ +} CSzArEx; + +#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) + +#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); +*/ + + + +/* + SzArEx_Extract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAllocPtr allocMain, ISzAllocPtr allocTemp); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zAlloc.c b/3rdparty/lzma-21.03beta/C/7zAlloc.c new file mode 100644 index 0000000..c924a52 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zAlloc.c @@ -0,0 +1,80 @@ +/* 7zAlloc.c -- Allocation functions +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif + +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; + +#endif + +void *SzAlloc(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p); + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10u bytes; count = %10d", (unsigned)size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p); + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(ISzAllocPtr p, size_t size) +{ + UNUSED_VAR(p); + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10u bytes; count = %10d", (unsigned)size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(ISzAllocPtr p, void *address) +{ + UNUSED_VAR(p); + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/3rdparty/lzma-21.03beta/C/7zAlloc.h b/3rdparty/lzma-21.03beta/C/7zAlloc.h new file mode 100644 index 0000000..44778f9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zAlloc.h @@ -0,0 +1,19 @@ +/* 7zAlloc.h -- Allocation functions +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *SzAlloc(ISzAllocPtr p, size_t size); +void SzFree(ISzAllocPtr p, void *address); + +void *SzAllocTemp(ISzAllocPtr p, size_t size); +void SzFreeTemp(ISzAllocPtr p, void *address); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zArcIn.c b/3rdparty/lzma-21.03beta/C/7zArcIn.c new file mode 100644 index 0000000..0d9dec4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zArcIn.c @@ -0,0 +1,1783 @@ +/* 7zArcIn.c -- 7z Input functions +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7z.h" +#include "7zBuf.h" +#include "7zCrc.h" +#include "CpuArch.h" + +#define MY_ALLOC(T, p, size, alloc) { \ + if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } + +#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } + +#define MY_ALLOC_AND_CPY(to, size, from, alloc) \ + { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); } + +#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ + { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } + +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttrib, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy + // k7zNtSecure, + // k7zParent, + // k7zIsReal +}; + +const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define SzBitUi32s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } + +static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) +{ + if (num == 0) + { + p->Defs = NULL; + p->Vals = NULL; + } + else + { + MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); + MY_ALLOC(UInt32, p->Vals, num, alloc); + } + return SZ_OK; +} + +static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; + ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; +} + +#define SzBitUi64s_Init(p) { (p)->Defs = NULL; (p)->Vals = NULL; } + +static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; + ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; +} + + +static void SzAr_Init(CSzAr *p) +{ + p->NumPackStreams = 0; + p->NumFolders = 0; + + p->PackPositions = NULL; + SzBitUi32s_Init(&p->FolderCRCs); + + p->FoCodersOffsets = NULL; + p->FoStartPackStreamIndex = NULL; + p->FoToCoderUnpackSizes = NULL; + p->FoToMainUnpackSizeIndex = NULL; + p->CoderUnpackSizes = NULL; + + p->CodersData = NULL; + + p->RangeLimit = 0; +} + +static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->PackPositions); + SzBitUi32s_Free(&p->FolderCRCs, alloc); + + ISzAlloc_Free(alloc, p->FoCodersOffsets); + ISzAlloc_Free(alloc, p->FoStartPackStreamIndex); + ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes); + ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); + ISzAlloc_Free(alloc, p->CoderUnpackSizes); + + ISzAlloc_Free(alloc, p->CodersData); + + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + + p->NumFiles = 0; + p->dataPos = 0; + + p->UnpackPositions = NULL; + p->IsDirs = NULL; + + p->FolderToFile = NULL; + p->FileToFolder = NULL; + + p->FileNameOffsets = NULL; + p->FileNames = NULL; + + SzBitUi32s_Init(&p->CRCs); + SzBitUi32s_Init(&p->Attribs); + // SzBitUi32s_Init(&p->Parents); + SzBitUi64s_Init(&p->MTime); + SzBitUi64s_Init(&p->CTime); +} + +void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->UnpackPositions); + ISzAlloc_Free(alloc, p->IsDirs); + + ISzAlloc_Free(alloc, p->FolderToFile); + ISzAlloc_Free(alloc, p->FileToFolder); + + ISzAlloc_Free(alloc, p->FileNameOffsets); + ISzAlloc_Free(alloc, p->FileNames); + + SzBitUi32s_Free(&p->CRCs, alloc); + SzBitUi32s_Free(&p->Attribs, alloc); + // SzBitUi32s_Free(&p->Parents, alloc); + SzBitUi64s_Free(&p->MTime, alloc); + SzBitUi64s_Free(&p->CTime, alloc); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + + +static int TestSignatureCandidate(const Byte *testBytes) +{ + unsigned i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +#define SzData_Clear(p) { (p)->Data = NULL; (p)->Size = 0; } + +#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; +#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) +#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; + +#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } +#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } + +#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ + dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); + +static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte, mask; + unsigned i; + UInt32 v; + + SZ_READ_BYTE(firstByte); + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + return SZ_OK; + } + SZ_READ_BYTE(v); + if ((firstByte & 0x40) == 0) + { + *value = (((UInt32)firstByte & 0x3F) << 8) | v; + return SZ_OK; + } + SZ_READ_BYTE(mask); + *value = v | ((UInt32)mask << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); + *value |= (highPart << (8 * i)); + return SZ_OK; + } + SZ_READ_BYTE(b); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + + +static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + Byte firstByte; + UInt64 value64; + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + firstByte = *sd->Data; + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + sd->Data++; + sd->Size--; + return SZ_OK; + } + RINOK(ReadNumber(sd, &value64)); + if (value64 >= (UInt32)0x80000000 - 1) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +#define ReadID(sd, value) ReadNumber(sd, value) + +static SRes SkipData(CSzData *sd) +{ + UInt64 size; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, size); + return SZ_OK; +} + +static SRes WaitId(CSzData *sd, UInt32 id) +{ + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == id) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SkipData(sd)); + } +} + +static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) +{ + UInt32 numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + *v = sd->Data; + SKIP_DATA(sd, numBytes); + return SZ_OK; +} + +static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) +{ + Byte b = 0; + unsigned m = 0; + UInt32 sum = 0; + for (; numItems != 0; numItems--) + { + if (m == 0) + { + b = *bits++; + m = 8; + } + m--; + sum += ((b >> m) & 1); + } + return sum; +} + +static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) +{ + Byte allAreDefined; + Byte *v2; + UInt32 numBytes = (numItems + 7) >> 3; + *v = NULL; + SZ_READ_BYTE(allAreDefined); + if (numBytes == 0) + return SZ_OK; + if (allAreDefined == 0) + { + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc); + SKIP_DATA(sd, numBytes); + return SZ_OK; + } + MY_ALLOC(Byte, *v, numBytes, alloc); + v2 = *v; + memset(v2, 0xFF, (size_t)numBytes); + { + unsigned numBits = (unsigned)numItems & 7; + if (numBits != 0) + v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); + } + return SZ_OK; +} + +static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +{ + UInt32 i; + CSzData sd; + UInt32 *vals; + const Byte *defs; + MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc); + sd = *sd2; + defs = crcs->Defs; + vals = crcs->Vals; + for (i = 0; i < numItems; i++) + if (SzBitArray_Check(defs, i)) + { + SZ_READ_32(vals[i]); + } + else + vals[i] = 0; + *sd2 = sd; + return SZ_OK; +} + +static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +{ + SzBitUi32s_Free(crcs, alloc); + RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); + return ReadUi32s(sd, numItems, crcs, alloc); +} + +static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) +{ + Byte allAreDefined; + UInt32 numDefined = numItems; + SZ_READ_BYTE(allAreDefined); + if (!allAreDefined) + { + size_t numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + numDefined = CountDefinedBits(sd->Data, numItems); + SKIP_DATA(sd, numBytes); + } + if (numDefined > (sd->Size >> 2)) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, (size_t)numDefined * 4); + return SZ_OK; +} + +static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) +{ + RINOK(SzReadNumber32(sd, &p->NumPackStreams)); + + RINOK(WaitId(sd, k7zIdSize)); + MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); + { + UInt64 sum = 0; + UInt32 i; + UInt32 numPackStreams = p->NumPackStreams; + for (i = 0; i < numPackStreams; i++) + { + UInt64 packSize; + p->PackPositions[i] = sum; + RINOK(ReadNumber(sd, &packSize)); + sum += packSize; + if (sum < packSize) + return SZ_ERROR_ARCHIVE; + } + p->PackPositions[i] = sum; + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + /* CRC of packed streams is unused now */ + RINOK(SkipBitUi32s(sd, p->NumPackStreams)); + continue; + } + RINOK(SkipData(sd)); + } +} + +/* +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} +*/ + +#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) +{ + UInt32 numCoders, i; + UInt32 numInStreams = 0; + const Byte *dataStart = sd->Data; + + f->NumCoders = 0; + f->NumBonds = 0; + f->NumPackStreams = 0; + f->UnpackStream = 0; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = f->Coders + i; + unsigned idSize, j; + UInt64 id; + + SZ_READ_BYTE(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + + idSize = (unsigned)(mainByte & 0xF); + if (idSize > sizeof(id)) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd->Size) + return SZ_ERROR_ARCHIVE; + id = 0; + for (j = 0; j < idSize; j++) + { + id = ((id << 8) | *sd->Data); + sd->Data++; + sd->Size--; + } + if (id > (UInt32)0xFFFFFFFF) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = (UInt32)id; + + coder->NumStreams = 1; + coder->PropsOffset = 0; + coder->PropsSize = 0; + + if ((mainByte & 0x10) != 0) + { + UInt32 numStreams; + + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > k_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumStreams = (Byte)numStreams; + + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams != 1) + return SZ_ERROR_UNSUPPORTED; + } + + numInStreams += coder->NumStreams; + + if (numInStreams > k_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize = 0; + RINOK(SzReadNumber32(sd, &propsSize)); + if (propsSize > sd->Size) + return SZ_ERROR_ARCHIVE; + if (propsSize >= 0x80) + return SZ_ERROR_UNSUPPORTED; + coder->PropsOffset = (size_t)(sd->Data - dataStart); + coder->PropsSize = (Byte)propsSize; + sd->Data += (size_t)propsSize; + sd->Size -= (size_t)propsSize; + } + } + + /* + if (numInStreams == 1 && numCoders == 1) + { + f->NumPackStreams = 1; + f->PackStreams[0] = 0; + } + else + */ + { + Byte streamUsed[k_NumCodersStreams_in_Folder_MAX]; + UInt32 numBonds, numPackStreams; + + numBonds = numCoders - 1; + if (numInStreams < numBonds) + return SZ_ERROR_ARCHIVE; + if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumBonds = numBonds; + + numPackStreams = numInStreams - numBonds; + if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumPackStreams = numPackStreams; + + for (i = 0; i < numInStreams; i++) + streamUsed[i] = False; + + if (numBonds != 0) + { + Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX]; + + for (i = 0; i < numCoders; i++) + coderUsed[i] = False; + + for (i = 0; i < numBonds; i++) + { + CSzBond *bp = f->Bonds + i; + + RINOK(SzReadNumber32(sd, &bp->InIndex)); + if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex]) + return SZ_ERROR_ARCHIVE; + streamUsed[bp->InIndex] = True; + + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex]) + return SZ_ERROR_ARCHIVE; + coderUsed[bp->OutIndex] = True; + } + + for (i = 0; i < numCoders; i++) + if (!coderUsed[i]) + { + f->UnpackStream = i; + break; + } + + if (i == numCoders) + return SZ_ERROR_ARCHIVE; + } + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (!streamUsed[i]) + break; + if (i == numInStreams) + return SZ_ERROR_ARCHIVE; + f->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + f->PackStreams[i] = index; + } + } + + f->NumCoders = numCoders; + + return SZ_OK; +} + + +static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +{ + CSzData sd; + sd = *sd2; + for (; num != 0; num--) + { + Byte firstByte, mask; + unsigned i; + SZ_READ_BYTE_2(firstByte); + if ((firstByte & 0x80) == 0) + continue; + if ((firstByte & 0x40) == 0) + { + if (sd.Size == 0) + return SZ_ERROR_ARCHIVE; + sd.Size--; + sd.Data++; + continue; + } + mask = 0x20; + for (i = 2; i < 8 && (firstByte & mask) != 0; i++) + mask >>= 1; + if (i > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, i); + } + *sd2 = sd; + return SZ_OK; +} + + +#define k_Scan_NumCoders_MAX 64 +#define k_Scan_NumCodersStreams_in_Folder_MAX 64 + + +static SRes ReadUnpackInfo(CSzAr *p, + CSzData *sd2, + UInt32 numFoldersMax, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAllocPtr alloc) +{ + CSzData sd; + + UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; + const Byte *startBufPtr; + Byte external; + + RINOK(WaitId(sd2, k7zIdFolder)); + + RINOK(SzReadNumber32(sd2, &numFolders)); + if (numFolders > numFoldersMax) + return SZ_ERROR_UNSUPPORTED; + p->NumFolders = numFolders; + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd2, &index)); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoToCoderUnpackSizes, (size_t)numFolders + 1, alloc); + MY_ALLOC_ZE(Byte, p->FoToMainUnpackSizeIndex, (size_t)numFolders, alloc); + + startBufPtr = sd.Data; + + packStreamIndex = 0; + numCodersOutStreams = 0; + + for (fo = 0; fo < numFolders; fo++) + { + UInt32 numCoders, ci, numInStreams = 0; + + p->FoCodersOffsets[fo] = (size_t)(sd.Data - startBufPtr); + + RINOK(SzReadNumber32(&sd, &numCoders)); + if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (ci = 0; ci < numCoders; ci++) + { + Byte mainByte; + unsigned idSize; + UInt32 coderInStreams; + + SZ_READ_BYTE_2(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (mainByte & 0xF); + if (idSize > 8) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, idSize); + + coderInStreams = 1; + + if ((mainByte & 0x10) != 0) + { + UInt32 coderOutStreams; + RINOK(SzReadNumber32(&sd, &coderInStreams)); + RINOK(SzReadNumber32(&sd, &coderOutStreams)); + if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1) + return SZ_ERROR_UNSUPPORTED; + } + + numInStreams += coderInStreams; + + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize; + RINOK(SzReadNumber32(&sd, &propsSize)); + if (propsSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, propsSize); + } + } + + { + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 1; + + if (numCoders != 1 || numInStreams != 1) + { + Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX]; + Byte coderUsed[k_Scan_NumCoders_MAX]; + + UInt32 i; + UInt32 numBonds = numCoders - 1; + if (numInStreams < numBonds) + return SZ_ERROR_ARCHIVE; + + if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numInStreams; i++) + streamUsed[i] = False; + for (i = 0; i < numCoders; i++) + coderUsed[i] = False; + + for (i = 0; i < numBonds; i++) + { + UInt32 index; + + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numCoders || coderUsed[index]) + return SZ_ERROR_ARCHIVE; + coderUsed[index] = True; + } + + numPackStreams = numInStreams - numBonds; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + { + UInt32 index; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || streamUsed[index]) + return SZ_ERROR_ARCHIVE; + streamUsed[index] = True; + } + + for (i = 0; i < numCoders; i++) + if (!coderUsed[i]) + { + indexOfMainStream = i; + break; + } + + if (i == numCoders) + return SZ_ERROR_ARCHIVE; + } + + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; + p->FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; + numCodersOutStreams += numCoders; + if (numCodersOutStreams < numCoders) + return SZ_ERROR_UNSUPPORTED; + if (numPackStreams > p->NumPackStreams - packStreamIndex) + return SZ_ERROR_ARCHIVE; + packStreamIndex += numPackStreams; + } + } + + p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; + + { + const size_t dataSize = (size_t)(sd.Data - startBufPtr); + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoCodersOffsets[fo] = dataSize; + MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc); + } + + if (external != 0) + { + if (sd.Size != 0) + return SZ_ERROR_ARCHIVE; + sd = *sd2; + } + + RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); + + MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); + { + UInt32 i; + for (i = 0; i < numCodersOutStreams; i++) + { + RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); + } + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(&sd, &type)); + if (type == k7zIdEnd) + { + *sd2 = sd; + return SZ_OK; + } + if (type == k7zIdCRC) + { + RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); + continue; + } + RINOK(SkipData(&sd)); + } +} + + +UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) +{ + return p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex] + p->FoToMainUnpackSizeIndex[folderIndex]]; +} + + +typedef struct +{ + UInt32 NumTotalSubStreams; + UInt32 NumSubDigests; + CSzData sdNumSubStreams; + CSzData sdSizes; + CSzData sdCRCs; +} CSubStreamInfo; + + +static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) +{ + UInt64 type = 0; + UInt32 numSubDigests = 0; + UInt32 numFolders = p->NumFolders; + UInt32 numUnpackStreams = numFolders; + UInt32 numUnpackSizesInData = 0; + + for (;;) + { + RINOK(ReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + UInt32 i; + ssi->sdNumSubStreams.Data = sd->Data; + numUnpackStreams = 0; + numSubDigests = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numUnpackStreams > numUnpackStreams + numStreams) + return SZ_ERROR_UNSUPPORTED; + numUnpackStreams += numStreams; + if (numStreams != 0) + numUnpackSizesInData += (numStreams - 1); + if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) + numSubDigests += numStreams; + } + ssi->sdNumSubStreams.Size = (size_t)(sd->Data - ssi->sdNumSubStreams.Data); + continue; + } + if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + if (!ssi->sdNumSubStreams.Data) + { + numSubDigests = numFolders; + if (p->FolderCRCs.Defs) + numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); + } + + ssi->NumTotalSubStreams = numUnpackStreams; + ssi->NumSubDigests = numSubDigests; + + if (type == k7zIdSize) + { + ssi->sdSizes.Data = sd->Data; + RINOK(SkipNumbers(sd, numUnpackSizesInData)); + ssi->sdSizes.Size = (size_t)(sd->Data - ssi->sdSizes.Data); + RINOK(ReadID(sd, &type)); + } + + for (;;) + { + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + ssi->sdCRCs.Data = sd->Data; + RINOK(SkipBitUi32s(sd, numSubDigests)); + ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); + } + else + { + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } +} + +static SRes SzReadStreamsInfo(CSzAr *p, + CSzData *sd, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + UInt64 *dataOffset, + CSubStreamInfo *ssi, + ISzAllocPtr alloc) +{ + UInt64 type; + + SzData_Clear(&ssi->sdSizes); + SzData_Clear(&ssi->sdCRCs); + SzData_Clear(&ssi->sdNumSubStreams); + + *dataOffset = 0; + RINOK(ReadID(sd, &type)); + if (type == k7zIdPackInfo) + { + RINOK(ReadNumber(sd, dataOffset)); + if (*dataOffset > p->RangeLimit) + return SZ_ERROR_ARCHIVE; + RINOK(ReadPackInfo(p, sd, alloc)); + if (p->PackPositions[p->NumPackStreams] > p->RangeLimit - *dataOffset) + return SZ_ERROR_ARCHIVE; + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdUnpackInfo) + { + RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdSubStreamsInfo) + { + RINOK(ReadSubStreamsInfo(p, sd, ssi)); + RINOK(ReadID(sd, &type)); + } + else + { + ssi->NumTotalSubStreams = p->NumFolders; + // ssi->NumSubDigests = 0; + } + + return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *tempBufs, + UInt32 numFoldersMax, + UInt64 baseOffset, + CSzAr *p, + ISzAllocPtr allocTemp) +{ + UInt64 dataStartPos; + UInt32 fo; + CSubStreamInfo ssi; + + RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders == 0) + return SZ_ERROR_ARCHIVE; + + for (fo = 0; fo < p->NumFolders; fo++) + Buf_Init(tempBufs + fo); + + for (fo = 0; fo < p->NumFolders; fo++) + { + CBuf *tempBuf = tempBufs + fo; + UInt64 unpackSize = SzAr_GetFolderUnpackSize(p, fo); + if ((size_t)unpackSize != unpackSize) + return SZ_ERROR_MEM; + if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + } + + for (fo = 0; fo < p->NumFolders; fo++) + { + const CBuf *tempBuf = tempBufs + fo; + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); + } + + return SZ_OK; +} + +static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) +{ + size_t pos = 0; + *offsets++ = 0; + if (numFiles == 0) + return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; + if (size < 2) + return SZ_ERROR_ARCHIVE; + if (data[size - 2] != 0 || data[size - 1] != 0) + return SZ_ERROR_ARCHIVE; + do + { + const Byte *p; + if (pos == size) + return SZ_ERROR_ARCHIVE; + for (p = data + pos; + #ifdef _WIN32 + *(const UInt16 *)(const void *)p != 0 + #else + p[0] != 0 || p[1] != 0 + #endif + ; p += 2); + pos = (size_t)(p - data) + 2; + *offsets++ = (pos >> 1); + } + while (--numFiles); + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, + CSzData *sd2, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAllocPtr alloc) +{ + CSzData sd; + UInt32 i; + CNtfsFileTime *vals; + Byte *defs; + Byte external; + + RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd2, &index)); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc); + vals = p->Vals; + defs = p->Defs; + for (i = 0; i < num; i++) + if (SzBitArray_Check(defs, i)) + { + if (sd.Size < 8) + return SZ_ERROR_ARCHIVE; + vals[i].Low = GetUi32(sd.Data); + vals[i].High = GetUi32(sd.Data + 4); + SKIP_DATA2(sd, 8); + } + else + vals[i].High = vals[i].Low = 0; + + if (external == 0) + *sd2 = sd; + + return SZ_OK; +} + + +#define NUM_ADDITIONAL_STREAMS_MAX 8 + + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + ILookInStream *inStream, + CBuf *tempBufs, UInt32 *numTempBufs, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp + ) +{ + CSubStreamInfo ssi; + +{ + UInt64 type; + + SzData_Clear(&ssi.sdSizes); + SzData_Clear(&ssi.sdCRCs); + SzData_Clear(&ssi.sdNumSubStreams); + + ssi.NumSubDigests = 0; + ssi.NumTotalSubStreams = 0; + + RINOK(ReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + for (;;) + { + UInt64 type2; + RINOK(ReadID(sd, &type2)); + if (type2 == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdAdditionalStreamsInfo) + { + CSzAr tempAr; + SRes res; + + SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, + p->startPosAfterHeader, &tempAr, allocTemp); + *numTempBufs = tempAr.NumFolders; + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + return res; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, + &p->dataPos, &ssi, allocMain)); + p->dataPos += p->startPosAfterHeader; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdEnd) + { + return SZ_OK; + } + + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; +} + +{ + UInt32 numFiles = 0; + UInt32 numEmptyStreams = 0; + const Byte *emptyStreams = NULL; + const Byte *emptyFiles = NULL; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->NumFiles = numFiles; + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + + if (type >= ((UInt32)1 << 8)) + { + SKIP_DATA(sd, size); + } + else switch ((unsigned)type) + { + case k7zIdName: + { + size_t namesSize; + const Byte *namesData; + Byte external; + + SZ_READ_BYTE(external); + if (external == 0) + { + namesSize = (size_t)size - 1; + namesData = sd->Data; + } + else + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + namesData = (tempBufs)[index].data; + namesSize = (tempBufs)[index].size; + } + + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain); + RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) + if (external == 0) + { + SKIP_DATA(sd, namesSize); + } + break; + } + case k7zIdEmptyStream: + { + RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); + numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); + emptyFiles = NULL; + break; + } + case k7zIdEmptyFile: + { + RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); + break; + } + case k7zIdWinAttrib: + { + Byte external; + CSzData sdSwitch; + CSzData *sdPtr; + SzBitUi32s_Free(&p->Attribs, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); + + SZ_READ_BYTE(external); + if (external == 0) + sdPtr = sd; + else + { + UInt32 index; + RINOK(SzReadNumber32(sd, &index)); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + sdSwitch.Data = (tempBufs)[index].data; + sdSwitch.Size = (tempBufs)[index].size; + sdPtr = &sdSwitch; + } + RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); + break; + } + /* + case k7zParent: + { + SzBitUi32s_Free(&p->Parents, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); + RINOK(SzReadSwitch(sd)); + RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); + break; + } + */ + case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + default: + { + SKIP_DATA(sd, size); + } + } + } + + if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + { + UInt32 i; + UInt32 emptyFileIndex = 0; + UInt32 folderIndex = 0; + UInt32 remSubStreams = 0; + UInt32 numSubStreams = 0; + UInt64 unpackPos = 0; + const Byte *digestsDefs = NULL; + const Byte *digestsVals = NULL; + UInt32 digestsValsIndex = 0; + UInt32 digestIndex; + Byte allDigestsDefined = 0; + Byte isDirMask = 0; + Byte crcMask = 0; + Byte mask = 0x80; + + MY_ALLOC(UInt32, p->FolderToFile, p->db.NumFolders + 1, allocMain); + MY_ALLOC_ZE(UInt32, p->FileToFolder, p->NumFiles, allocMain); + MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); + MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); + + RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); + + if (ssi.sdCRCs.Size != 0) + { + SZ_READ_BYTE_SD(&ssi.sdCRCs, allDigestsDefined); + if (allDigestsDefined) + digestsVals = ssi.sdCRCs.Data; + else + { + size_t numBytes = (ssi.NumSubDigests + 7) >> 3; + digestsDefs = ssi.sdCRCs.Data; + digestsVals = digestsDefs + numBytes; + } + } + + digestIndex = 0; + + for (i = 0; i < numFiles; i++, mask >>= 1) + { + if (mask == 0) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + isDirMask = 0; + crcMask = 0; + mask = 0x80; + } + + p->UnpackPositions[i] = unpackPos; + p->CRCs.Vals[i] = 0; + + if (emptyStreams && SzBitArray_Check(emptyStreams, i)) + { + if (emptyFiles) + { + if (!SzBitArray_Check(emptyFiles, emptyFileIndex)) + isDirMask |= mask; + emptyFileIndex++; + } + else + isDirMask |= mask; + if (remSubStreams == 0) + { + p->FileToFolder[i] = (UInt32)-1; + continue; + } + } + + if (remSubStreams == 0) + { + for (;;) + { + if (folderIndex >= p->db.NumFolders) + return SZ_ERROR_ARCHIVE; + p->FolderToFile[folderIndex] = i; + numSubStreams = 1; + if (ssi.sdNumSubStreams.Data) + { + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + } + remSubStreams = numSubStreams; + if (numSubStreams != 0) + break; + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + unpackPos += folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + } + + folderIndex++; + } + } + + p->FileToFolder[i] = folderIndex; + + if (emptyStreams && SzBitArray_Check(emptyStreams, i)) + continue; + + if (--remSubStreams == 0) + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + UInt64 startFolderUnpackPos = p->UnpackPositions[p->FolderToFile[folderIndex]]; + if (folderUnpackSize < unpackPos - startFolderUnpackPos) + return SZ_ERROR_ARCHIVE; + unpackPos = startFolderUnpackPos + folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + + if (numSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) + { + p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; + crcMask |= mask; + } + else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + + folderIndex++; + } + else + { + UInt64 v; + RINOK(ReadNumber(&ssi.sdSizes, &v)); + unpackPos += v; + if (unpackPos < v) + return SZ_ERROR_ARCHIVE; + if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + } + } + + if (mask != 0x80) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + } + + p->UnpackPositions[i] = unpackPos; + + if (remSubStreams != 0) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + p->FolderToFile[folderIndex] = i; + if (folderIndex >= p->db.NumFolders) + break; + if (!ssi.sdNumSubStreams.Data) + return SZ_ERROR_ARCHIVE; + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &numSubStreams)); + if (numSubStreams != 0) + return SZ_ERROR_ARCHIVE; + /* + { + UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + unpackPos += folderUnpackSize; + if (unpackPos < folderUnpackSize) + return SZ_ERROR_ARCHIVE; + } + */ + folderIndex++; + } + + if (ssi.sdNumSubStreams.Data && ssi.sdNumSubStreams.Size != 0) + return SZ_ERROR_ARCHIVE; + } +} + return SZ_OK; +} + + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ILookInStream *inStream, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + UInt32 i; + UInt32 numTempBufs = 0; + SRes res; + CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Init(tempBufs + i); + + res = SzReadHeader2(p, sd, inStream, + tempBufs, &numTempBufs, + allocMain, allocTemp); + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Free(tempBufs + i, allocTemp); + + RINOK(res); + + if (sd->Size != 0) + return SZ_ERROR_FAIL; + + return res; +} + +static SRes SzArEx_Open2( + CSzArEx *p, + ILookInStream *inStream, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + Byte header[k7zStartHeaderSize]; + Int64 startArcPos; + UInt64 nextHeaderOffset, nextHeaderSize; + size_t nextHeaderSizeT; + UInt32 nextHeaderCRC; + CBuf buf; + SRes res; + + startArcPos = 0; + RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); + + if (!TestSignatureCandidate(header)) + return SZ_ERROR_NO_ARCHIVE; + if (header[6] != k7zMajorVersion) + return SZ_ERROR_UNSUPPORTED; + + nextHeaderOffset = GetUi64(header + 12); + nextHeaderSize = GetUi64(header + 20); + nextHeaderCRC = GetUi32(header + 28); + + p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize; + + if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) + return SZ_ERROR_CRC; + + p->db.RangeLimit = nextHeaderOffset; + + nextHeaderSizeT = (size_t)nextHeaderSize; + if (nextHeaderSizeT != nextHeaderSize) + return SZ_ERROR_MEM; + if (nextHeaderSizeT == 0) + return SZ_OK; + if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || + nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) + return SZ_ERROR_NO_ARCHIVE; + + { + Int64 pos = 0; + RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)); + if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset || + (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + return SZ_ERROR_INPUT_EOF; + } + + RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + + if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); + + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buf.data; + sd.Size = buf.size; + + res = ReadID(&sd, &type); + + if (res == SZ_OK && type == k7zIdEncodedHeader) + { + CSzAr tempAr; + CBuf tempBuf; + Buf_Init(&tempBuf); + + SzAr_Init(&tempAr); + tempAr.RangeLimit = p->db.RangeLimit; + + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + { + Buf_Free(&tempBuf, allocTemp); + } + else + { + Buf_Free(&buf, allocTemp); + buf.data = tempBuf.data; + buf.size = tempBuf.size; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + } + } + + if (res == SZ_OK) + { + if (type == k7zIdHeader) + { + /* + CSzData sd2; + unsigned ttt; + for (ttt = 0; ttt < 40000; ttt++) + { + SzArEx_Free(p, allocMain); + sd2 = sd; + res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp); + if (res != SZ_OK) + break; + } + */ + res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp); + } + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + + Buf_Free(&buf, allocTemp); + return res; +} + + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAllocPtr allocMain, ISzAllocPtr allocTemp) +{ + SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); + if (res != SZ_OK) + SzArEx_Free(p, allocMain); + return res; +} + + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **tempBuf, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAllocPtr allocMain, + ISzAllocPtr allocTemp) +{ + UInt32 folderIndex = p->FileToFolder[fileIndex]; + SRes res = SZ_OK; + + *offset = 0; + *outSizeProcessed = 0; + + if (folderIndex == (UInt32)-1) + { + ISzAlloc_Free(allocMain, *tempBuf); + *blockIndex = folderIndex; + *tempBuf = NULL; + *outBufferSize = 0; + return SZ_OK; + } + + if (*tempBuf == NULL || *blockIndex != folderIndex) + { + UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + /* + UInt64 unpackSizeSpec = + p->UnpackPositions[p->FolderToFile[(size_t)folderIndex + 1]] - + p->UnpackPositions[p->FolderToFile[folderIndex]]; + */ + size_t unpackSize = (size_t)unpackSizeSpec; + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + ISzAlloc_Free(allocMain, *tempBuf); + *tempBuf = NULL; + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *tempBuf = (Byte *)ISzAlloc_Alloc(allocMain, unpackSize); + if (*tempBuf == NULL) + res = SZ_ERROR_MEM; + } + + if (res == SZ_OK) + { + res = SzAr_DecodeFolder(&p->db, folderIndex, + inStream, p->dataPos, *tempBuf, unpackSize, allocTemp); + } + } + } + + if (res == SZ_OK) + { + UInt64 unpackPos = p->UnpackPositions[fileIndex]; + *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderToFile[folderIndex]]); + *outSizeProcessed = (size_t)(p->UnpackPositions[(size_t)fileIndex + 1] - unpackPos); + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (SzBitWithVals_Check(&p->CRCs, fileIndex)) + if (CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) + res = SZ_ERROR_CRC; + } + + return res; +} + + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t offs = p->FileNameOffsets[fileIndex]; + size_t len = p->FileNameOffsets[fileIndex + 1] - offs; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames + offs * 2; + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) +{ + size_t len; + if (!p->FileNameOffsets) + return 1; + len = 0; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return len; + fileIndex = parent; + } +} + +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + BoolInt needSlash; + if (!p->FileNameOffsets) + { + *(--dest) = 0; + return dest; + } + needSlash = False; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); + if (needSlash) + *(dest - 1) = '/'; + needSlash = True; + dest -= curLen; + + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return dest; + fileIndex = parent; + } +} +*/ diff --git a/3rdparty/lzma-21.03beta/C/7zBuf.c b/3rdparty/lzma-21.03beta/C/7zBuf.c new file mode 100644 index 0000000..8865c32 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zBuf.c @@ -0,0 +1,36 @@ +/* 7zBuf.c -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zBuf.h" + +void Buf_Init(CBuf *p) +{ + p->data = 0; + p->size = 0; +} + +int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc) +{ + p->size = 0; + if (size == 0) + { + p->data = 0; + return 1; + } + p->data = (Byte *)ISzAlloc_Alloc(alloc, size); + if (p->data) + { + p->size = size; + return 1; + } + return 0; +} + +void Buf_Free(CBuf *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->data); + p->data = 0; + p->size = 0; +} diff --git a/3rdparty/lzma-21.03beta/C/7zBuf.h b/3rdparty/lzma-21.03beta/C/7zBuf.h new file mode 100644 index 0000000..81d1b5b --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zBuf.h @@ -0,0 +1,35 @@ +/* 7zBuf.h -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc); +void Buf_Free(CBuf *p, ISzAllocPtr alloc); + +typedef struct +{ + Byte *data; + size_t size; + size_t pos; +} CDynBuf; + +void DynBuf_Construct(CDynBuf *p); +void DynBuf_SeekToBeg(CDynBuf *p); +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc); +void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zBuf2.c b/3rdparty/lzma-21.03beta/C/7zBuf2.c new file mode 100644 index 0000000..2083474 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zBuf2.c @@ -0,0 +1,52 @@ +/* 7zBuf2.c -- Byte Buffer +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zBuf.h" + +void DynBuf_Construct(CDynBuf *p) +{ + p->data = 0; + p->size = 0; + p->pos = 0; +} + +void DynBuf_SeekToBeg(CDynBuf *p) +{ + p->pos = 0; +} + +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + if (size > p->size - p->pos) + { + size_t newSize = p->pos + size; + Byte *data; + newSize += newSize / 4; + data = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!data) + return 0; + p->size = newSize; + if (p->pos != 0) + memcpy(data, p->data, p->pos); + ISzAlloc_Free(alloc, p->data); + p->data = data; + } + if (size != 0) + { + memcpy(p->data + p->pos, buf, size); + p->pos += size; + } + return 1; +} + +void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->data); + p->data = 0; + p->size = 0; + p->pos = 0; +} diff --git a/3rdparty/lzma-21.03beta/C/7zCrc.c b/3rdparty/lzma-21.03beta/C/7zCrc.c new file mode 100644 index 0000000..f186324 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zCrc.c @@ -0,0 +1,322 @@ +/* 7zCrc.c -- CRC32 init +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" + +#define kCrcPoly 0xEDB88320 + +#ifdef MY_CPU_LE + #define CRC_NUM_TABLES 8 +#else + #define CRC_NUM_TABLES 9 + + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +extern +CRC_FUNC g_CrcUpdateT4; +CRC_FUNC g_CrcUpdateT4; +extern +CRC_FUNC g_CrcUpdateT8; +CRC_FUNC g_CrcUpdateT8; +extern +CRC_FUNC g_CrcUpdateT0_32; +CRC_FUNC g_CrcUpdateT0_32; +extern +CRC_FUNC g_CrcUpdateT0_64; +CRC_FUNC g_CrcUpdateT0_64; +extern +CRC_FUNC g_CrcUpdate; +CRC_FUNC g_CrcUpdate; + +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + const Byte *pEnd = p + size; + for (; p != pEnd; p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + + +/* ---------- hardware CRC ---------- */ + +#ifdef MY_CPU_LE + +#if defined(MY_CPU_ARM_OR_ARM64) + +// #pragma message("ARM*") + + #if defined(_MSC_VER) + #if defined(MY_CPU_ARM64) + #if (_MSC_VER >= 1910) + #define USE_ARM64_CRC + #endif + #endif + #elif (defined(__clang__) && (__clang_major__ >= 3)) \ + || (defined(__GNUC__) && (__GNUC__ > 4)) + #if !defined(__ARM_FEATURE_CRC32) + #define __ARM_FEATURE_CRC32 1 + #if (!defined(__clang__) || (__clang_major__ > 3)) // fix these numbers + #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) + #endif + #endif + #if defined(__ARM_FEATURE_CRC32) + #define USE_ARM64_CRC + #include + #endif + #endif + +#else + +// no hardware CRC + +// #define USE_CRC_EMU + +#ifdef USE_CRC_EMU + +#pragma message("ARM64 CRC emulation") + +MY_FORCE_INLINE +UInt32 __crc32b(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32w(UInt32 v, UInt32 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +MY_FORCE_INLINE +UInt32 __crc32d(UInt32 v, UInt64 data) +{ + const UInt32 *table = g_CrcTable; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8; + return v; +} + +#endif // USE_CRC_EMU + +#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE) + + + +#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#define T0_32_UNROLL_BYTES (4 * 4) +#define T0_64_UNROLL_BYTES (4 * 8) + +#ifndef ATTRIB_CRC +#define ATTRIB_CRC +#endif +// #pragma message("USE ARM HW CRC") + +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_32_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_32_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + v = __crc32w(v, *(const UInt32 *)(const void *)(p)); + v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); +ATTRIB_CRC +UInt32 MY_FAST_CALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + UNUSED_VAR(table); + + for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--) + v = __crc32b(v, *p++); + + if (size >= T0_64_UNROLL_BYTES) + { + const Byte *lim = p + size; + size &= (T0_64_UNROLL_BYTES - 1); + lim -= size; + do + { + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + v = __crc32d(v, *(const UInt64 *)(const void *)(p)); + v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8; + } + while (p != lim); + } + + for (; size != 0; size--) + v = __crc32b(v, *p++); + + return v; +} + +#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU) + +#endif // MY_CPU_LE + + + + +void MY_FAST_CALL CrcGenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); + g_CrcTable[i] = r; + } + for (i = 256; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[(size_t)i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + + #if CRC_NUM_TABLES < 4 + + g_CrcUpdate = CrcUpdateT1; + + #else + + #ifdef MY_CPU_LE + + g_CrcUpdateT4 = CrcUpdateT4; + g_CrcUpdate = CrcUpdateT4; + + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT8; + + #ifdef MY_CPU_X86_OR_AMD64 + if (!CPU_Is_InOrder()) + #endif + g_CrcUpdate = CrcUpdateT8; + #endif + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 0x01020304; + const Byte *p = (const Byte *)&k; + if (p[0] == 4 && p[1] == 3) + { + g_CrcUpdateT4 = CrcUpdateT4; + g_CrcUpdate = CrcUpdateT4; + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT8; + g_CrcUpdate = CrcUpdateT8; + #endif + } + else if (p[0] != 1 || p[1] != 2) + g_CrcUpdate = CrcUpdateT1; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[(size_t)i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdateT4 = CrcUpdateT1_BeT4; + g_CrcUpdate = CrcUpdateT1_BeT4; + #if CRC_NUM_TABLES >= 8 + g_CrcUpdateT8 = CrcUpdateT1_BeT8; + g_CrcUpdate = CrcUpdateT1_BeT8; + #endif + } + } + #endif + #endif + + #ifdef MY_CPU_LE + #ifdef USE_ARM64_CRC + if (CPU_IsSupported_CRC32()) + { + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = + #if defined(MY_CPU_ARM) + CrcUpdateT0_32; + #else + CrcUpdateT0_64; + #endif + } + #endif + + #ifdef USE_CRC_EMU + g_CrcUpdateT0_32 = CrcUpdateT0_32; + g_CrcUpdateT0_64 = CrcUpdateT0_64; + g_CrcUpdate = CrcUpdateT0_64; + #endif + #endif +} diff --git a/3rdparty/lzma-21.03beta/C/7zCrc.h b/3rdparty/lzma-21.03beta/C/7zCrc.h new file mode 100644 index 0000000..8fd5795 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zCrc.h @@ -0,0 +1,25 @@ +/* 7zCrc.h -- CRC32 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt32 g_CrcTable[]; + +/* Call CrcGenerateTable one time before other CRC functions */ +void MY_FAST_CALL CrcGenerateTable(void); + +#define CRC_INIT_VAL 0xFFFFFFFF +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) +#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zCrcOpt.c b/3rdparty/lzma-21.03beta/C/7zCrcOpt.c new file mode 100644 index 0000000..69fad9c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zCrcOpt.c @@ -0,0 +1,117 @@ +/* 7zCrcOpt.c -- CRC32 calculation +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifndef MY_CPU_BE + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)(const void *)p; + v = + (table + 0x300)[((v ) & 0xFF)] + ^ (table + 0x200)[((v >> 8) & 0xFF)] + ^ (table + 0x100)[((v >> 16) & 0xFF)] + ^ (table + 0x000)[((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 8; size -= 8, p += 8) + { + UInt32 d; + v ^= *(const UInt32 *)(const void *)p; + v = + (table + 0x700)[((v ) & 0xFF)] + ^ (table + 0x600)[((v >> 8) & 0xFF)] + ^ (table + 0x500)[((v >> 16) & 0xFF)] + ^ (table + 0x400)[((v >> 24))]; + d = *((const UInt32 *)(const void *)p + 1); + v ^= + (table + 0x300)[((d ) & 0xFF)] + ^ (table + 0x200)[((d >> 8) & 0xFF)] + ^ (table + 0x100)[((d >> 16) & 0xFF)] + ^ (table + 0x000)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)(const void *)p; + v = + (table + 0x000)[((v ) & 0xFF)] + ^ (table + 0x100)[((v >> 8) & 0xFF)] + ^ (table + 0x200)[((v >> 16) & 0xFF)] + ^ (table + 0x300)[((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT32_SWAP(v); +} + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 8; size -= 8, p += 8) + { + UInt32 d; + v ^= *(const UInt32 *)(const void *)p; + v = + (table + 0x400)[((v ) & 0xFF)] + ^ (table + 0x500)[((v >> 8) & 0xFF)] + ^ (table + 0x600)[((v >> 16) & 0xFF)] + ^ (table + 0x700)[((v >> 24))]; + d = *((const UInt32 *)(const void *)p + 1); + v ^= + (table + 0x000)[((d ) & 0xFF)] + ^ (table + 0x100)[((d >> 8) & 0xFF)] + ^ (table + 0x200)[((d >> 16) & 0xFF)] + ^ (table + 0x300)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT32_SWAP(v); +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zDec.c b/3rdparty/lzma-21.03beta/C/7zDec.c new file mode 100644 index 0000000..fbfd016 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zDec.c @@ -0,0 +1,600 @@ +/* 7zDec.c -- Decoding from 7z folder +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" +#include "7zCrc.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#ifndef _7Z_NO_METHOD_LZMA2 +#define k_LZMA2 0x21 +#endif +#define k_LZMA 0x30101 +#define k_BCJ2 0x303011B +#ifndef _7Z_NO_METHODS_FILTERS +#define k_Delta 3 +#define k_BCJ 0x3030103 +#define k_PPC 0x3030205 +#define k_IA64 0x3030401 +#define k_ARM 0x3030501 +#define k_ARMT 0x3030701 +#define k_SPARC 0x3030805 +#endif + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn vt; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + BoolInt extra; + SRes res; + const ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(const IByteIn *pp) +{ + CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt); + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = (size_t)(p->cur - p->begin); + p->processed += size; + p->res = ILookInStream_Skip(p->inStream, size); + size = (1 << 25); + p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.vt.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (propsSize != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = props[0]; + UInt32 memSize = GetUi32(props + 1); + if (order < PPMD7_MIN_ORDER || + order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + ppmd.rc.dec.Stream = &s.vt; + if (!Ppmd7z_RangeDec_Init(&ppmd.rc.dec)) + res = SZ_ERROR_DATA; + else if (!s.extra) + { + Byte *buf = outBuffer; + const Byte *lim = buf + outSize; + for (; buf != lim; buf++) + { + int sym = Ppmd7z_DecodeSymbol(&ppmd); + if (s.extra || sym < 0) + break; + *buf = (Byte)sym; + } + if (buf != lim) + res = SZ_ERROR_DATA; + else if (!Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) + { + /* if (Ppmd7z_DecodeSymbol(&ppmd) != PPMD7_SYM_END || !Ppmd7z_RangeDec_IsFinishedOK(&ppmd.rc.dec)) */ + res = SZ_ERROR_DATA; + } + } + if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (size_t)(s.cur - s.begin) != inSize) + res = SZ_ERROR_DATA; + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + const void *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = ILookInStream_Look(inStream, &inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (outSize != state.dicPos || inSize != 0) + res = SZ_ERROR_DATA; + break; + } + + if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + break; + + if (inProcessed == 0 && dicPos == state.dicPos) + { + res = SZ_ERROR_DATA; + break; + } + + res = ILookInStream_Skip(inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + + +#ifndef _7Z_NO_METHOD_LZMA2 + +static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (propsSize != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + const void *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = ILookInStream_Look(inStream, &inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (outSize != state.decoder.dicPos || inSize != 0) + res = SZ_ERROR_DATA; + break; + } + + if (inProcessed == 0 && dicPos == state.decoder.dicPos) + { + res = SZ_ERROR_DATA; + break; + } + + res = ILookInStream_Skip(inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + const void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(ILookInStream_Skip(inStream, curSize)); + } + return SZ_OK; +} + +static BoolInt IS_MAIN_METHOD(UInt32 m) +{ + switch (m) + { + case k_Copy: + case k_LZMA: + #ifndef _7Z_NO_METHOD_LZMA2 + case k_LZMA2: + #endif + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumStreams == 1 + /* && c->MethodID <= (UInt32)0xFFFFFFFF */ + && IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + + + #ifndef _7Z_NO_METHODS_FILTERS + + if (f->NumCoders == 2) + { + const CSzCoderInfo *c = &f->Coders[1]; + if ( + /* c->MethodID > (UInt32)0xFFFFFFFF || */ + c->NumStreams != 1 + || f->NumPackStreams != 1 + || f->PackStreams[0] != 0 + || f->NumBonds != 1 + || f->Bonds[0].InIndex != 1 + || f->Bonds[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_Delta: + case k_BCJ: + case k_PPC: + case k_IA64: + case k_SPARC: + case k_ARM: + case k_ARMT: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + + #endif + + + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) + || !IS_SUPPORTED_CODER(&f->Coders[2]) + || !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 + || f->PackStreams[0] != 2 + || f->PackStreams[1] != 6 + || f->PackStreams[2] != 1 + || f->PackStreams[3] != 0 + || f->NumBonds != 3 + || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 + || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 + || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + + return SZ_ERROR_UNSUPPORTED; +} + +#ifndef _7Z_NO_METHODS_FILTERS +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; +#endif + +static SRes SzFolder_Decode2(const CSzFolder *folder, + const Byte *propsData, + const UInt64 *unpackSizes, + const UInt64 *packPositions, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + const CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = unpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur); + if (!temp && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = packPositions[si]; + inSize = packPositions[(size_t)si + 1] - offset; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #ifndef _7Z_NO_METHOD_LZMA2 + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #endif + #ifdef _7ZIP_PPMD_SUPPPORT + else if (coder->MethodID == k_PPMD) + { + RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + #endif + else + return SZ_ERROR_UNSUPPORTED; + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = packPositions[1]; + UInt64 s3Size = packPositions[2] - offset; + + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]); + if (!tempBuf[2] && tempSizes[2] != 0) + return SZ_ERROR_MEM; + + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); + + if ((tempSizes[0] & 3) != 0 || + (tempSizes[1] & 3) != 0 || + tempSize3 + tempSizes[0] + tempSizes[1] != outSize) + return SZ_ERROR_DATA; + + { + CBcj2Dec p; + + p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; + p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; + p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; + p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; + + p.dest = outBuffer; + p.destLim = outBuffer + outSize; + + Bcj2Dec_Init(&p); + RINOK(Bcj2Dec_Decode(&p)); + + { + unsigned i; + for (i = 0; i < 4; i++) + if (p.bufs[i] != p.lims[i]) + return SZ_ERROR_DATA; + + if (!Bcj2Dec_IsFinished(&p)) + return SZ_ERROR_DATA; + + if (p.dest != p.destLim + || p.state != BCJ2_STREAM_MAIN) + return SZ_ERROR_DATA; + } + } + } + #ifndef _7Z_NO_METHODS_FILTERS + else if (ci == 1) + { + if (coder->MethodID == k_Delta) + { + if (coder->PropsSize != 1) + return SZ_ERROR_UNSUPPORTED; + { + Byte state[DELTA_STATE_SIZE]; + Delta_Init(state); + Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); + } + } + else + { + if (coder->PropsSize != 0) + return SZ_ERROR_UNSUPPORTED; + switch (coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(PPC) + CASE_BRA_CONV(IA64) + CASE_BRA_CONV(SPARC) + CASE_BRA_CONV(ARM) + CASE_BRA_CONV(ARMT) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + #endif + else + return SZ_ERROR_UNSUPPORTED; + } + + return SZ_OK; +} + + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAllocPtr allocMain) +{ + SRes res; + CSzFolder folder; + CSzData sd; + + const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; + sd.Data = data; + sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex]; + + res = SzGetNextFolderItem(&folder, &sd); + + if (res != SZ_OK) + return res; + + if (sd.Size != 0 + || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] + || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) + return SZ_ERROR_FAIL; + { + unsigned i; + Byte *tempBuf[3] = { 0, 0, 0}; + + res = SzFolder_Decode2(&folder, data, + &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], + p->PackPositions + p->FoStartPackStreamIndex[folderIndex], + inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + + for (i = 0; i < 3; i++) + ISzAlloc_Free(allocMain, tempBuf[i]); + + if (res == SZ_OK) + if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) + if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) + res = SZ_ERROR_CRC; + + return res; + } +} diff --git a/3rdparty/lzma-21.03beta/C/7zFile.c b/3rdparty/lzma-21.03beta/C/7zFile.c new file mode 100644 index 0000000..13d2efa --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zFile.c @@ -0,0 +1,442 @@ +/* 7zFile.c -- File IO +2021-04-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + + #include + + #ifndef USE_FOPEN + #include + #include + #ifdef _WIN32 + #include + typedef int ssize_t; + typedef int off_t; + #else + #include + #endif + #endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#endif + +#define kChunkSizeMax (1 << 22) + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #elif defined(USE_FOPEN) + p->file = NULL; + #else + p->fd = -1; + #endif +} + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) + +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + + #elif defined(USE_FOPEN) + + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + + #else + + int flags = (writeMode ? (O_CREAT | O_EXCL | O_WRONLY) : O_RDONLY); + #ifdef O_BINARY + flags |= O_BINARY; + #endif + p->fd = open(name, flags, 0666); + return (p->fd != -1) ? 0 : errno; + + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } + +WRes OutFile_Open(CSzFile *p, const char *name) +{ + #if defined(USE_WINDOWS_FILE) || defined(USE_FOPEN) + return File_Open(p, name, 1); + #else + p->fd = creat(name, 0666); + return (p->fd != -1) ? 0 : errno; + #endif +} + +#endif + + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + + #elif defined(USE_FOPEN) + + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + { + if (res == EOF) + return errno; + return res; + } + p->file = NULL; + } + + #else + + if (p->fd != -1) + { + if (close(p->fd) != 0) + return errno; + p->fd = -1; + } + + #endif + + return 0; +} + + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + *size = 0; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + do + { + const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + const BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + // debug : we can break here for partial reading mode + if (processed == 0) + break; + } + while (originalSize > 0); + + #elif defined(USE_FOPEN) + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const size_t processed = fread(data, 1, curSize, p->file); + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= processed; + *size += processed; + if (processed != curSize) + return ferror(p->file); + // debug : we can break here for partial reading mode + if (processed == 0) + break; + } + while (originalSize > 0); + + #else + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const ssize_t processed = read(p->fd, data, curSize); + if (processed == -1) + return errno; + if (processed == 0) + break; + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= (size_t)processed; + *size += (size_t)processed; + // debug : we can break here for partial reading mode + // break; + } + while (originalSize > 0); + + #endif + + return 0; +} + + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + *size = 0; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + do + { + const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + const BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (const void *)((const Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + + #elif defined(USE_FOPEN) + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const size_t processed = fwrite(data, 1, curSize, p->file); + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= processed; + *size += processed; + if (processed != curSize) + return ferror(p->file); + if (processed == 0) + break; + } + while (originalSize > 0); + + #else + + do + { + const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize; + const ssize_t processed = write(p->fd, data, curSize); + if (processed == -1) + return errno; + if (processed == 0) + break; + data = (void *)((Byte *)data + (size_t)processed); + originalSize -= (size_t)processed; + *size += (size_t)processed; + } + while (originalSize > 0); + + #endif + + return 0; +} + + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + DWORD moveMethod; + UInt32 low = (UInt32)*pos; + LONG high = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + low = SetFilePointer(p->handle, (LONG)low, &high, moveMethod); + if (low == (UInt32)0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)high << 32) | low; + return 0; + + #else + + int moveMethod; // = origin; + + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return EINVAL; + } + + #if defined(USE_FOPEN) + { + int res = fseek(p->file, (long)*pos, moveMethod); + if (res == -1) + return errno; + *pos = ftell(p->file); + if (*pos == -1) + return errno; + return 0; + } + #else + { + off_t res = lseek(p->fd, (off_t)*pos, moveMethod); + if (res == -1) + return errno; + *pos = res; + return 0; + } + + #endif // USE_FOPEN + #endif // USE_WINDOWS_FILE +} + + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #elif defined(USE_FOPEN) + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #else + + off_t pos; + *length = 0; + pos = lseek(p->fd, 0, SEEK_CUR); + if (pos != -1) + { + const off_t len2 = lseek(p->fd, 0, SEEK_END); + const off_t res2 = lseek(p->fd, pos, SEEK_SET); + if (len2 != -1) + { + *length = (UInt64)len2; + if (res2 != -1) + return 0; + } + } + return errno; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt); + WRes wres = File_Read(&p->file, buf, size); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->vt.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + WRes wres = File_Read(&p->file, buf, size); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + WRes wres = File_Seek(&p->file, pos, origin); + p->wres = wres; + return (wres == 0) ? SZ_OK : SZ_ERROR_READ; +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->vt.Read = FileInStream_Read; + p->vt.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt); + WRes wres = File_Write(&p->file, data, &size); + p->wres = wres; + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->vt.Write = FileOutStream_Write; +} diff --git a/3rdparty/lzma-21.03beta/C/7zFile.h b/3rdparty/lzma-21.03beta/C/7zFile.h new file mode 100644 index 0000000..788abb6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zFile.h @@ -0,0 +1,91 @@ +/* 7zFile.h -- File IO +2021-02-15 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +// #include +#endif + +#ifdef USE_WINDOWS_FILE +#include +#else +// note: USE_FOPEN mode is limited to 32-bit file size +// #define USE_FOPEN +// #include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #elif defined(USE_FOPEN) + FILE *file; + #else + int fd; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + CSzFile file; + WRes wres; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream vt; + CSzFile file; + WRes wres; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream vt; + CSzFile file; + WRes wres; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zStream.c b/3rdparty/lzma-21.03beta/C/7zStream.c new file mode 100644 index 0000000..28a1460 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zStream.c @@ -0,0 +1,176 @@ +/* 7zStream.c -- 7z Stream functions +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zTypes.h" + +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + + + +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) +{ + Int64 t = (Int64)offset; + return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(ILookInStream_Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return ILookInStream_Skip(stream, *size); +} + +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ILookInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + + + +#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt); + +static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + size2 = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + if (*size > p->bufSize) + *size = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset) +{ + GET_LookToRead2 + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) +{ + GET_LookToRead2 + size_t rem = p->size - p->pos; + if (rem == 0) + return ISeekInStream_Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin) +{ + GET_LookToRead2 + p->pos = p->size = 0; + return ISeekInStream_Seek(p->realStream, pos, origin); +} + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) +{ + p->vt.Look = lookahead ? + LookToRead2_Look_Lookahead : + LookToRead2_Look_Exact; + p->vt.Skip = LookToRead2_Skip; + p->vt.Read = LookToRead2_Read; + p->vt.Seek = LookToRead2_Seek; +} + + + +static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt); + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->vt.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt); + return ILookInStream_Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->vt.Read = SecToRead_Read; +} diff --git a/3rdparty/lzma-21.03beta/C/7zTypes.h b/3rdparty/lzma-21.03beta/C/7zTypes.h new file mode 100644 index 0000000..3f66a7b --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zTypes.h @@ -0,0 +1,524 @@ +/* 7zTypes.h -- Basic types +2021-07-13 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#else +#include +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + + +#ifdef _MSC_VER + #if _MSC_VER > 1200 + #define MY_ALIGN(n) __declspec(align(n)) + #else + #define MY_ALIGN(n) + #endif +#else + #define MY_ALIGN(n) __attribute__ ((aligned(n))) +#endif + + +#ifdef _WIN32 + +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) + +// #define MY_HRES_ERROR__INTERNAL_ERROR MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR) + +#else // _WIN32 + +// #define ENV_HAVE_LSTAT +typedef int WRes; + +// (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT +#define MY__FACILITY_ERRNO 0x800 +#define MY__FACILITY_WIN32 7 +#define MY__FACILITY__WRes MY__FACILITY_ERRNO + +#define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \ + ( (HRESULT)(x) & 0x0000FFFF) \ + | (MY__FACILITY__WRes << 16) \ + | (HRESULT)0x80000000 )) + +#define MY_SRes_HRESULT_FROM_WRes(x) \ + ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x)) + +// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno) +#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x) + +/* +#define ERROR_FILE_NOT_FOUND 2L +#define ERROR_ACCESS_DENIED 5L +#define ERROR_NO_MORE_FILES 18L +#define ERROR_LOCK_VIOLATION 33L +#define ERROR_FILE_EXISTS 80L +#define ERROR_DISK_FULL 112L +#define ERROR_NEGATIVE_SEEK 131L +#define ERROR_ALREADY_EXISTS 183L +#define ERROR_DIRECTORY 267L +#define ERROR_TOO_MANY_POSTS 298L + +#define ERROR_INTERNAL_ERROR 1359L +#define ERROR_INVALID_REPARSE_DATA 4392L +#define ERROR_REPARSE_TAG_INVALID 4393L +#define ERROR_REPARSE_TAG_MISMATCH 4394L +*/ + +// we use errno equivalents for some WIN32 errors: + +#define ERROR_INVALID_FUNCTION EINVAL +#define ERROR_ALREADY_EXISTS EEXIST +#define ERROR_FILE_EXISTS EEXIST +#define ERROR_PATH_NOT_FOUND ENOENT +#define ERROR_FILE_NOT_FOUND ENOENT +#define ERROR_DISK_FULL ENOSPC +// #define ERROR_INVALID_HANDLE EBADF + +// we use FACILITY_WIN32 for errors that has no errno equivalent +// Too many posts were made to a semaphore. +#define ERROR_TOO_MANY_POSTS ((HRESULT)0x8007012AL) +#define ERROR_INVALID_REPARSE_DATA ((HRESULT)0x80071128L) +#define ERROR_REPARSE_TAG_INVALID ((HRESULT)0x80071129L) + +// if (MY__FACILITY__WRes != FACILITY_WIN32), +// we use FACILITY_WIN32 for COM errors: +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) +#define MY__E_ERROR_NEGATIVE_SEEK ((HRESULT)0x80070083L) + +/* +// we can use FACILITY_ERRNO for some COM errors, that have errno equivalents: +#define E_OUTOFMEMORY MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM) +#define E_INVALIDARG MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) +#define MY__E_ERROR_NEGATIVE_SEEK MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL) +*/ + +// gcc / clang : (sizeof(long) == sizeof(void*)) in 32/64 bits +typedef long INT_PTR; +typedef unsigned long UINT_PTR; + +#define TEXT(quote) quote + +#define FILE_ATTRIBUTE_READONLY 0x0001 +#define FILE_ATTRIBUTE_HIDDEN 0x0002 +#define FILE_ATTRIBUTE_SYSTEM 0x0004 +#define FILE_ATTRIBUTE_DIRECTORY 0x0010 +#define FILE_ATTRIBUTE_ARCHIVE 0x0020 +#define FILE_ATTRIBUTE_DEVICE 0x0040 +#define FILE_ATTRIBUTE_NORMAL 0x0080 +#define FILE_ATTRIBUTE_TEMPORARY 0x0100 +#define FILE_ATTRIBUTE_SPARSE_FILE 0x0200 +#define FILE_ATTRIBUTE_REPARSE_POINT 0x0400 +#define FILE_ATTRIBUTE_COMPRESSED 0x0800 +#define FILE_ATTRIBUTE_OFFLINE 0x1000 +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000 +#define FILE_ATTRIBUTE_ENCRYPTED 0x4000 + +#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000 /* trick for Unix */ + +#endif + + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +#ifndef RINOK_WRes +#define RINOK_WRes(x) { WRes __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + + +#ifndef _WIN32 + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +#define VOID void + +#define HRESULT LONG + +typedef void *LPVOID; +// typedef void VOID; +// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; +// gcc / clang on Unix : sizeof(long==sizeof(void*) in 32 or 64 bits) +typedef long INT_PTR; +typedef unsigned long UINT_PTR; +typedef long LONG_PTR; +typedef unsigned long DWORD_PTR; + +typedef size_t SIZE_T; + +#endif // _WIN32 + + +#define MY_HRES_ERROR__INTERNAL_ERROR ((HRESULT)0x8007054FL) + + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int BoolInt; +/* typedef BoolInt Bool; */ +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_FORCE_INLINE __forceinline + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else // _MSC_VER + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) \ + || (defined(__clang__) && (__clang_major__ >= 4)) \ + || defined(__INTEL_COMPILER) \ + || defined(__xlC__) +#define MY_NO_INLINE __attribute__((noinline)) +// #define MY_FORCE_INLINE __attribute__((always_inline)) inline +#else +#define MY_NO_INLINE +#endif + +#define MY_FORCE_INLINE + + +#define MY_CDECL + +#if defined(_M_IX86) \ + || defined(__i386__) +// #define MY_FAST_CALL __attribute__((fastcall)) +// #define MY_FAST_CALL __attribute__((cdecl)) +#define MY_FAST_CALL +#elif defined(MY_CPU_AMD64) +// #define MY_FAST_CALL __attribute__((ms_abi)) +#define MY_FAST_CALL +#else +#define MY_FAST_CALL +#endif + +#endif // _MSC_VER + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct IByteIn IByteIn; +struct IByteIn +{ + Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ +}; +#define IByteIn_Read(p) (p)->Read(p) + + +typedef struct IByteOut IByteOut; +struct IByteOut +{ + void (*Write)(const IByteOut *p, Byte b); +}; +#define IByteOut_Write(p, b) (p)->Write(p, b) + + +typedef struct ISeqInStream ISeqInStream; +struct ISeqInStream +{ + SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +}; +#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); + + +typedef struct ISeqOutStream ISeqOutStream; +struct ISeqOutStream +{ + size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +}; +#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + + +typedef struct ISeekInStream ISeekInStream; +struct ISeekInStream +{ + SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); +}; +#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +typedef struct ILookInStream ILookInStream; +struct ILookInStream +{ + SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(const ILookInStream *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); +}; + +#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) +#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) +#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); + + + +typedef struct +{ + ILookInStream vt; + const ISeekInStream *realStream; + + size_t pos; + size_t size; /* it's data size */ + + /* the following variables must be set outside */ + Byte *buf; + size_t bufSize; +} CLookToRead2; + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); + +#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + + +typedef struct ICompressProgress ICompressProgress; + +struct ICompressProgress +{ + SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +}; +#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) + + + +typedef struct ISzAlloc ISzAlloc; +typedef const ISzAlloc * ISzAllocPtr; + +struct ISzAlloc +{ + void *(*Alloc)(ISzAllocPtr p, size_t size); + void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ +}; + +#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) +#define ISzAlloc_Free(p, a) (p)->Free(p, a) + +/* deprecated */ +#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) +#define IAlloc_Free(p, a) ISzAlloc_Free(p, a) + + + + + +#ifndef MY_offsetof + #ifdef offsetof + #define MY_offsetof(type, m) offsetof(type, m) + /* + #define MY_offsetof(type, m) FIELD_OFFSET(type, m) + */ + #else + #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) + #endif +#endif + + + +#ifndef MY_container_of + +/* +#define MY_container_of(ptr, type, m) container_of(ptr, type, m) +#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) +#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) +#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) +*/ + +/* + GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" + GCC 3.4.4 : classes with constructor + GCC 4.8.1 : classes with non-public variable members" +*/ + +#define MY_container_of(ptr, type, m) ((type *)(void *)((char *)(void *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) + +#endif + +#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr)) + +/* +#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +*/ +#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) + +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +/* +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) +*/ + + +#define MY_memset_0_ARRAY(a) memset((a), 0, sizeof(a)) + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/7zVersion.h b/3rdparty/lzma-21.03beta/C/7zVersion.h new file mode 100644 index 0000000..e7fff57 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zVersion.h @@ -0,0 +1,27 @@ +#define MY_VER_MAJOR 21 +#define MY_VER_MINOR 03 +#define MY_VER_BUILD 0 +#define MY_VERSION_NUMBERS "21.03 beta" +#define MY_VERSION MY_VERSION_NUMBERS + +#ifdef MY_CPU_NAME + #define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")" +#else + #define MY_VERSION_CPU MY_VERSION +#endif + +#define MY_DATE "2021-07-20" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE +#define MY_AUTHOR_NAME "Igor Pavlov" +#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2021 Igor Pavlov" + +#ifdef USE_COPYRIGHT_CR + #define MY_COPYRIGHT MY_COPYRIGHT_CR +#else + #define MY_COPYRIGHT MY_COPYRIGHT_PD +#endif + +#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE diff --git a/3rdparty/lzma-21.03beta/C/7zVersion.rc b/3rdparty/lzma-21.03beta/C/7zVersion.rc new file mode 100644 index 0000000..e520995 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zVersion.rc @@ -0,0 +1,55 @@ +#define MY_VS_FFI_FILEFLAGSMASK 0x0000003FL +#define MY_VOS_NT_WINDOWS32 0x00040004L +#define MY_VOS_CE_WINDOWS32 0x00050004L + +#define MY_VFT_APP 0x00000001L +#define MY_VFT_DLL 0x00000002L + +// #include + +#ifndef MY_VERSION +#include "7zVersion.h" +#endif + +#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 + +#ifdef DEBUG +#define DBG_FL VS_FF_DEBUG +#else +#define DBG_FL 0 +#endif + +#define MY_VERSION_INFO(fileType, descr, intName, origName) \ +LANGUAGE 9, 1 \ +1 VERSIONINFO \ + FILEVERSION MY_VER \ + PRODUCTVERSION MY_VER \ + FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \ + FILEFLAGS DBG_FL \ + FILEOS MY_VOS_NT_WINDOWS32 \ + FILETYPE fileType \ + FILESUBTYPE 0x0L \ +BEGIN \ + BLOCK "StringFileInfo" \ + BEGIN \ + BLOCK "040904b0" \ + BEGIN \ + VALUE "CompanyName", "Igor Pavlov" \ + VALUE "FileDescription", descr \ + VALUE "FileVersion", MY_VERSION \ + VALUE "InternalName", intName \ + VALUE "LegalCopyright", MY_COPYRIGHT \ + VALUE "OriginalFilename", origName \ + VALUE "ProductName", "7-Zip" \ + VALUE "ProductVersion", MY_VERSION \ + END \ + END \ + BLOCK "VarFileInfo" \ + BEGIN \ + VALUE "Translation", 0x409, 1200 \ + END \ +END + +#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe") + +#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll") diff --git a/3rdparty/lzma-21.03beta/C/7zip_gcc_c.mak b/3rdparty/lzma-21.03beta/C/7zip_gcc_c.mak new file mode 100644 index 0000000..e98d676 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zip_gcc_c.mak @@ -0,0 +1,301 @@ + +MY_ARCH_2 = $(MY_ARCH) + +MY_ASM = jwasm +MY_ASM = asmc + +PROGPATH = $(O)/$(PROG) + + +# for object file +CFLAGS_BASE_LIST = -c +# for ASM file +# CFLAGS_BASE_LIST = -S +CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) -Wall -Werror -Wextra $(CFLAGS_WARN) \ + -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + + +LDFLAGS_STATIC = -DNDEBUG +# -static + +ifdef SystemDrive +IS_MINGW = 1 +endif + +ifdef DEF_FILE + + +ifdef IS_MINGW +SHARED_EXT=.dll +LDFLAGS = -shared -DEF $(DEF_FILE) $(LDFLAGS_STATIC) +else +SHARED_EXT=.so +LDFLAGS = -shared -fPIC $(LDFLAGS_STATIC) +CC_SHARED=-fPIC +endif + + +else + +LDFLAGS = $(LDFLAGS_STATIC) +# -s is not required for clang, do we need it for GGC ??? +# -s + +#-static -static-libgcc -static-libstdc++ + +ifdef IS_MINGW +SHARED_EXT=.exe +else +SHARED_EXT= +endif + +endif + + +PROGPATH = $(O)/$(PROG)$(SHARED_EXT) + + +ifndef O +O=_o +endif + +ifdef IS_MINGW + +RM = del +MY_MKDIR=mkdir +LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 + + +CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE +# -Wno-delete-non-virtual-dtor + +DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll + +else + +RM = rm -f +MY_MKDIR=mkdir -p +# CFLAGS_BASE := $(CFLAGS_BASE) -D_7ZIP_ST +# CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + +# LOCAL_LIBS=-lpthread +# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl +LIB2 = -lpthread -ldl + +DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(OBJS) + +endif + + + +CFLAGS = $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(CC_SHARED) -o $@ + + +ifdef IS_X64 +AFLAGS_ABI = -elf64 -DABI_LINUX +else +AFLAGS_ABI = -elf -DABI_LINUX -DABI_CDECL +# -DABI_CDECL +# -DABI_LINUX +# -DABI_CDECL +endif +AFLAGS = $(AFLAGS_ABI) -Fo$(O)/ + + +CXX_WARN_FLAGS = +#-Wno-invalid-offsetof +#-Wno-reorder + +CXXFLAGS = $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(CXXFLAGS_EXTRA) $(CC_SHARED) -o $@ $(CXX_WARN_FLAGS) + +all: $(O) $(PROGPATH) + +$(O): + $(MY_MKDIR) $(O) + +$(PROGPATH): $(OBJS) + $(CXX) -s -o $(PROGPATH) $(MY_ARCH_2) $(LDFLAGS) $(OBJS) $(MY_LIBS) $(LIB2) + + + +ifndef NO_DEFAULT_RES +$O/resource.o: resource.rc + windres.exe $(RFLAGS) resource.rc $O/resource.o +endif + + + +$O/7zAlloc.o: ../../../C/7zAlloc.c + $(CC) $(CFLAGS) $< +$O/7zArcIn.o: ../../../C/7zArcIn.c + $(CC) $(CFLAGS) $< +$O/7zBuf.o: ../../../C/7zBuf.c + $(CC) $(CFLAGS) $< +$O/7zBuf2.o: ../../../C/7zBuf2.c + $(CC) $(CFLAGS) $< +$O/7zCrc.o: ../../../C/7zCrc.c + $(CC) $(CFLAGS) $< +$O/7zDec.o: ../../../C/7zDec.c + $(CC) $(CFLAGS) $< +$O/7zFile.o: ../../../C/7zFile.c + $(CC) $(CFLAGS) $< +$O/7zStream.o: ../../../C/7zStream.c + $(CC) $(CFLAGS) $< +$O/Aes.o: ../../../C/Aes.c + $(CC) $(CFLAGS) $< +$O/Alloc.o: ../../../C/Alloc.c + $(CC) $(CFLAGS) $< +$O/Bcj2.o: ../../../C/Bcj2.c + $(CC) $(CFLAGS) $< +$O/Bcj2Enc.o: ../../../C/Bcj2Enc.c + $(CC) $(CFLAGS) $< +$O/Blake2s.o: ../../../C/Blake2s.c + $(CC) $(CFLAGS) $< +$O/Bra.o: ../../../C/Bra.c + $(CC) $(CFLAGS) $< +$O/Bra86.o: ../../../C/Bra86.c + $(CC) $(CFLAGS) $< +$O/BraIA64.o: ../../../C/BraIA64.c + $(CC) $(CFLAGS) $< +$O/BwtSort.o: ../../../C/BwtSort.c + $(CC) $(CFLAGS) $< + +$O/CpuArch.o: ../../../C/CpuArch.c + $(CC) $(CFLAGS) $< +$O/Delta.o: ../../../C/Delta.c + $(CC) $(CFLAGS) $< +$O/DllSecur.o: ../../../C/DllSecur.c + $(CC) $(CFLAGS) $< +$O/HuffEnc.o: ../../../C/HuffEnc.c + $(CC) $(CFLAGS) $< +$O/LzFind.o: ../../../C/LzFind.c + $(CC) $(CFLAGS) $< + +# ifdef MT_FILES +$O/LzFindMt.o: ../../../C/LzFindMt.c + $(CC) $(CFLAGS) $< + +$O/Threads.o: ../../../C/Threads.c + $(CC) $(CFLAGS) $< +# endif + +$O/LzmaEnc.o: ../../../C/LzmaEnc.c + $(CC) $(CFLAGS) $< +$O/Lzma86Dec.o: ../../../C/Lzma86Dec.c + $(CC) $(CFLAGS) $< +$O/Lzma86Enc.o: ../../../C/Lzma86Enc.c + $(CC) $(CFLAGS) $< +$O/Lzma2Dec.o: ../../../C/Lzma2Dec.c + $(CC) $(CFLAGS) $< +$O/Lzma2DecMt.o: ../../../C/Lzma2DecMt.c + $(CC) $(CFLAGS) $< +$O/Lzma2Enc.o: ../../../C/Lzma2Enc.c + $(CC) $(CFLAGS) $< +$O/LzmaLib.o: ../../../C/LzmaLib.c + $(CC) $(CFLAGS) $< +$O/MtCoder.o: ../../../C/MtCoder.c + $(CC) $(CFLAGS) $< +$O/MtDec.o: ../../../C/MtDec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7.o: ../../../C/Ppmd7.c + $(CC) $(CFLAGS) $< +$O/Ppmd7aDec.o: ../../../C/Ppmd7aDec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7Dec.o: ../../../C/Ppmd7Dec.c + $(CC) $(CFLAGS) $< +$O/Ppmd7Enc.o: ../../../C/Ppmd7Enc.c + $(CC) $(CFLAGS) $< +$O/Ppmd8.o: ../../../C/Ppmd8.c + $(CC) $(CFLAGS) $< +$O/Ppmd8Dec.o: ../../../C/Ppmd8Dec.c + $(CC) $(CFLAGS) $< +$O/Ppmd8Enc.o: ../../../C/Ppmd8Enc.c + $(CC) $(CFLAGS) $< +$O/Sha1.o: ../../../C/Sha1.c + $(CC) $(CFLAGS) $< +$O/Sha256.o: ../../../C/Sha256.c + $(CC) $(CFLAGS) $< +$O/Sort.o: ../../../C/Sort.c + $(CC) $(CFLAGS) $< +$O/Xz.o: ../../../C/Xz.c + $(CC) $(CFLAGS) $< +$O/XzCrc64.o: ../../../C/XzCrc64.c + $(CC) $(CFLAGS) $< + + +ifdef USE_ASM +ifdef IS_X64 +USE_X86_ASM=1 +else +ifdef IS_X86 +USE_X86_ASM=1 +endif +endif +endif + +ifdef USE_X86_ASM +$O/7zCrcOpt.o: ../../../Asm/x86/7zCrcOpt.asm + $(MY_ASM) $(AFLAGS) $< +$O/XzCrc64Opt.o: ../../../Asm/x86/XzCrc64Opt.asm + $(MY_ASM) $(AFLAGS) $< +$O/AesOpt.o: ../../../Asm/x86/AesOpt.asm + $(MY_ASM) $(AFLAGS) $< +$O/Sha1Opt.o: ../../../Asm/x86/Sha1Opt.asm + $(MY_ASM) $(AFLAGS) $< +$O/Sha256Opt.o: ../../../Asm/x86/Sha256Opt.asm + $(MY_ASM) $(AFLAGS) $< +else +$O/7zCrcOpt.o: ../../7zCrcOpt.c + $(CC) $(CFLAGS) $< +$O/XzCrc64Opt.o: ../../XzCrc64Opt.c + $(CC) $(CFLAGS) $< +$O/Sha1Opt.o: ../../Sha1Opt.c + $(CC) $(CFLAGS) $< +$O/Sha256Opt.o: ../../Sha256Opt.c + $(CC) $(CFLAGS) $< +$O/AesOpt.o: ../../AesOpt.c + $(CC) $(CFLAGS) $< +endif + + +ifdef USE_LZMA_DEC_ASM + +ifdef IS_X64 +$O/LzmaDecOpt.o: ../../../Asm/x86/LzmaDecOpt.asm + $(MY_ASM) $(AFLAGS) $< +endif + +ifdef IS_ARM64 +$O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S + $(CC) $(CFLAGS) $< +endif + +$O/LzmaDec.o: ../../LzmaDec.c + $(CC) $(CFLAGS) -D_LZMA_DEC_OPT $< + +else + +$O/LzmaDec.o: ../../LzmaDec.c + $(CC) $(CFLAGS) $< + +endif + + + +$O/XzDec.o: ../../../C/XzDec.c + $(CC) $(CFLAGS) $< +$O/XzEnc.o: ../../../C/XzEnc.c + $(CC) $(CFLAGS) $< +$O/XzIn.o: ../../../C/XzIn.c + $(CC) $(CFLAGS) $< + + +$O/7zMain.o: ../../../C/Util/7z/7zMain.c + $(CC) $(CFLAGS) $< +$O/LzmaUtil.o: ../../../C/Util/Lzma/LzmaUtil.c + $(CC) $(CFLAGS) $< + + + +clean: + -$(DEL_OBJ_EXE) diff --git a/3rdparty/lzma-21.03beta/C/Aes.c b/3rdparty/lzma-21.03beta/C/Aes.c new file mode 100644 index 0000000..27e32e6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Aes.c @@ -0,0 +1,375 @@ +/* Aes.c -- AES encryption / decryption +2021-05-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "Aes.h" + +AES_CODE_FUNC g_AesCbc_Decode; +#ifndef _SFX +AES_CODE_FUNC g_AesCbc_Encode; +AES_CODE_FUNC g_AesCtr_Code; +UInt32 g_Aes_SupportedFunctions_Flags; +#endif + +static UInt32 T[256 * 4]; +static const Byte Sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; + + +static UInt32 D[256 * 4]; +static Byte InvS[256]; + +#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) + +#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24)) + +#define gb0(x) ( (x) & 0xFF) +#define gb1(x) (((x) >> ( 8)) & 0xFF) +#define gb2(x) (((x) >> (16)) & 0xFF) +#define gb3(x) (((x) >> (24))) + +#define gb(n, x) gb ## n(x) + +#define TT(x) (T + (x << 8)) +#define DD(x) (D + (x << 8)) + + +// #define _SHOW_AES_STATUS + +#ifdef MY_CPU_X86_OR_AMD64 + #define USE_HW_AES +#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_AES + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_AES + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_AES + #endif + #endif +#endif + +#ifdef USE_HW_AES +#ifdef _SHOW_AES_STATUS +#include +#define _PRF(x) x +#else +#define _PRF(x) +#endif +#endif + + +void AesGenTables(void) +{ + unsigned i; + for (i = 0; i < 256; i++) + InvS[Sbox[i]] = (Byte)i; + + for (i = 0; i < 256; i++) + { + { + UInt32 a1 = Sbox[i]; + UInt32 a2 = xtime(a1); + UInt32 a3 = a2 ^ a1; + TT(0)[i] = Ui32(a2, a1, a1, a3); + TT(1)[i] = Ui32(a3, a2, a1, a1); + TT(2)[i] = Ui32(a1, a3, a2, a1); + TT(3)[i] = Ui32(a1, a1, a3, a2); + } + { + UInt32 a1 = InvS[i]; + UInt32 a2 = xtime(a1); + UInt32 a4 = xtime(a2); + UInt32 a8 = xtime(a4); + UInt32 a9 = a8 ^ a1; + UInt32 aB = a8 ^ a2 ^ a1; + UInt32 aD = a8 ^ a4 ^ a1; + UInt32 aE = a8 ^ a4 ^ a2; + DD(0)[i] = Ui32(aE, a9, aD, aB); + DD(1)[i] = Ui32(aB, aE, a9, aD); + DD(2)[i] = Ui32(aD, aB, aE, a9); + DD(3)[i] = Ui32(a9, aD, aB, aE); + } + } + + { + AES_CODE_FUNC d = AesCbc_Decode; + #ifndef _SFX + AES_CODE_FUNC e = AesCbc_Encode; + AES_CODE_FUNC c = AesCtr_Code; + UInt32 flags = 0; + #endif + + #ifdef USE_HW_AES + if (CPU_IsSupported_AES()) + { + // #pragma message ("AES HW") + _PRF(printf("\n===AES HW\n")); + d = AesCbc_Decode_HW; + + #ifndef _SFX + e = AesCbc_Encode_HW; + c = AesCtr_Code_HW; + flags = k_Aes_SupportedFunctions_HW; + #endif + + #ifdef MY_CPU_X86_OR_AMD64 + if (CPU_IsSupported_VAES_AVX2()) + { + _PRF(printf("\n===vaes avx2\n")); + d = AesCbc_Decode_HW_256; + #ifndef _SFX + c = AesCtr_Code_HW_256; + flags |= k_Aes_SupportedFunctions_HW_256; + #endif + } + #endif + } + #endif + + g_AesCbc_Decode = d; + #ifndef _SFX + g_AesCbc_Encode = e; + g_AesCtr_Code = c; + g_Aes_SupportedFunctions_Flags = flags; + #endif + } +} + + +#define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])] + +#define HT4(m, i, s, p) m[i] = \ + HT(i, 0, s) ^ \ + HT(i, 1, s) ^ \ + HT(i, 2, s) ^ \ + HT(i, 3, s) ^ w[p + i] + +#define HT16(m, s, p) \ + HT4(m, 0, s, p); \ + HT4(m, 1, s, p); \ + HT4(m, 2, s, p); \ + HT4(m, 3, s, p); \ + +#define FT(i, x) Sbox[gb(x, m[(i + x) & 3])] +#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; + + +#define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])] + +#define HD4(m, i, s, p) m[i] = \ + HD(i, 0, s) ^ \ + HD(i, 1, s) ^ \ + HD(i, 2, s) ^ \ + HD(i, 3, s) ^ w[p + i]; + +#define HD16(m, s, p) \ + HD4(m, 0, s, p); \ + HD4(m, 1, s, p); \ + HD4(m, 2, s, p); \ + HD4(m, 3, s, p); \ + +#define FD(i, x) InvS[gb(x, m[(i - x) & 3])] +#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; + +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, m; + const UInt32 *wLim; + UInt32 t; + UInt32 rcon = 1; + + keySize /= 4; + w[0] = ((UInt32)keySize / 2) + 3; + w += 4; + + for (i = 0; i < keySize; i++, key += 4) + w[i] = GetUi32(key); + + t = w[(size_t)keySize - 1]; + wLim = w + (size_t)keySize * 3 + 28; + m = 0; + do + { + if (m == 0) + { + t = Ui32(Sbox[gb1(t)] ^ rcon, Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); + rcon <<= 1; + if (rcon & 0x100) + rcon = 0x1b; + m = keySize; + } + else if (m == 4 && keySize > 6) + t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]); + m--; + t ^= w[0]; + w[keySize] = t; + } + while (++w != wLim); +} + +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, num; + Aes_SetKey_Enc(w, key, keySize); + num = keySize + 20; + w += 8; + for (i = 0; i < num; i++) + { + UInt32 r = w[i]; + w[i] = + DD(0)[Sbox[gb0(r)]] ^ + DD(1)[Sbox[gb1(r)]] ^ + DD(2)[Sbox[gb2(r)]] ^ + DD(3)[Sbox[gb3(r)]]; + } +} + +/* Aes_Encode and Aes_Decode functions work with little-endian words. + src and dest are pointers to 4 UInt32 words. + src and dest can point to same block */ + +// MY_FORCE_INLINE +static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + w += 4; + for (;;) + { + HT16(m, s, 0); + if (--numRounds2 == 0) + break; + HT16(s, m, 4); + w += 8; + } + w += 4; + FT4(0); FT4(1); FT4(2); FT4(3); +} + +MY_FORCE_INLINE +static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4 + numRounds2 * 8; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + for (;;) + { + w -= 8; + HD16(m, s, 4); + if (--numRounds2 == 0) + break; + HD16(s, m, 0); + } + FD4(0); FD4(1); FD4(2); FD4(3); +} + +void AesCbc_Init(UInt32 *p, const Byte *iv) +{ + unsigned i; + for (i = 0; i < 4; i++) + p[i] = GetUi32(iv + i * 4); +} + +void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + p[0] ^= GetUi32(data); + p[1] ^= GetUi32(data + 4); + p[2] ^= GetUi32(data + 8); + p[3] ^= GetUi32(data + 12); + + Aes_Encode(p + 4, p, p); + + SetUi32(data, p[0]); + SetUi32(data + 4, p[1]); + SetUi32(data + 8, p[2]); + SetUi32(data + 12, p[3]); + } +} + +void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks) +{ + UInt32 in[4], out[4]; + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + in[0] = GetUi32(data); + in[1] = GetUi32(data + 4); + in[2] = GetUi32(data + 8); + in[3] = GetUi32(data + 12); + + Aes_Decode(p + 4, out, in); + + SetUi32(data, p[0] ^ out[0]); + SetUi32(data + 4, p[1] ^ out[1]); + SetUi32(data + 8, p[2] ^ out[2]); + SetUi32(data + 12, p[3] ^ out[3]); + + p[0] = in[0]; + p[1] = in[1]; + p[2] = in[2]; + p[3] = in[3]; + } +} + +void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--) + { + UInt32 temp[4]; + unsigned i; + + if (++p[0] == 0) + p[1]++; + + Aes_Encode(p + 4, temp, p); + + for (i = 0; i < 4; i++, data += 4) + { + UInt32 t = temp[i]; + + #ifdef MY_CPU_LE_UNALIGN + *((UInt32 *)(void *)data) ^= t; + #else + data[0] = (Byte)(data[0] ^ (t & 0xFF)); + data[1] = (Byte)(data[1] ^ ((t >> 8) & 0xFF)); + data[2] = (Byte)(data[2] ^ ((t >> 16) & 0xFF)); + data[3] = (Byte)(data[3] ^ ((t >> 24))); + #endif + } + } +} diff --git a/3rdparty/lzma-21.03beta/C/Aes.h b/3rdparty/lzma-21.03beta/C/Aes.h new file mode 100644 index 0000000..2aa2256 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Aes.h @@ -0,0 +1,60 @@ +/* Aes.h -- AES encryption / decryption +2018-04-28 : Igor Pavlov : Public domain */ + +#ifndef __AES_H +#define __AES_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define AES_BLOCK_SIZE 16 + +/* Call AesGenTables one time before other AES functions */ +void AesGenTables(void); + +/* UInt32 pointers must be 16-byte aligned */ + +/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */ +#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4) + +/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */ +/* keySize = 16 or 24 or 32 (bytes) */ +typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize); + +/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */ +void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */ + +/* data - 16-byte aligned pointer to data */ +/* numBlocks - the number of 16-byte blocks in data array */ +typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks); + +extern AES_CODE_FUNC g_AesCbc_Decode; +#ifndef _SFX +extern AES_CODE_FUNC g_AesCbc_Encode; +extern AES_CODE_FUNC g_AesCtr_Code; +#define k_Aes_SupportedFunctions_HW (1 << 2) +#define k_Aes_SupportedFunctions_HW_256 (1 << 3) +extern UInt32 g_Aes_SupportedFunctions_Flags; +#endif + + +#define DECLARE__AES_CODE_FUNC(funcName) \ + void MY_FAST_CALL funcName(UInt32 *ivAes, Byte *data, size_t numBlocks); + +DECLARE__AES_CODE_FUNC (AesCbc_Encode) +DECLARE__AES_CODE_FUNC (AesCbc_Decode) +DECLARE__AES_CODE_FUNC (AesCtr_Code) + +DECLARE__AES_CODE_FUNC (AesCbc_Encode_HW) +DECLARE__AES_CODE_FUNC (AesCbc_Decode_HW) +DECLARE__AES_CODE_FUNC (AesCtr_Code_HW) + +DECLARE__AES_CODE_FUNC (AesCbc_Decode_HW_256) +DECLARE__AES_CODE_FUNC (AesCtr_Code_HW_256) + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/AesOpt.c b/3rdparty/lzma-21.03beta/C/AesOpt.c new file mode 100644 index 0000000..8be8ff6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/AesOpt.c @@ -0,0 +1,776 @@ +/* AesOpt.c -- AES optimized code for x86 AES hardware instructions +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + + #if defined(__clang__) + #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8) + #define USE_INTEL_AES + #define ATTRIB_AES __attribute__((__target__("aes"))) + #if (__clang_major__ >= 8) + #define USE_INTEL_VAES + #define ATTRIB_VAES __attribute__((__target__("aes,vaes,avx2"))) + #endif + #endif + #elif defined(__GNUC__) + #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) + #define USE_INTEL_AES + #ifndef __AES__ + #define ATTRIB_AES __attribute__((__target__("aes"))) + #endif + #if (__GNUC__ >= 8) + #define USE_INTEL_VAES + #define ATTRIB_VAES __attribute__((__target__("aes,vaes,avx2"))) + #endif + #endif + #elif defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1110) + #define USE_INTEL_AES + #if (__INTEL_COMPILER >= 1900) + #define USE_INTEL_VAES + #endif + #endif + #elif defined(_MSC_VER) + #if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729) + #define USE_INTEL_AES + #if (_MSC_VER >= 1910) + #define USE_INTEL_VAES + #endif + #endif + #endif + +#ifndef ATTRIB_AES + #define ATTRIB_AES +#endif +#ifndef ATTRIB_VAES + #define ATTRIB_VAES +#endif + + +#ifdef USE_INTEL_AES + +#include + +#ifndef USE_INTEL_VAES +#define AES_TYPE_keys __m128i +#define AES_TYPE_data __m128i +#endif + +#define AES_FUNC_START(name) \ + void MY_FAST_CALL name(__m128i *p, __m128i *data, size_t numBlocks) + +#define AES_FUNC_START2(name) \ +AES_FUNC_START (name); \ +ATTRIB_AES \ +AES_FUNC_START (name) + +#define MM_OP(op, dest, src) dest = op(dest, src); +#define MM_OP_m(op, src) MM_OP(op, m, src); + +#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src); +#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src); + + +AES_FUNC_START2 (AesCbc_Encode_HW) +{ + __m128i m = *p; + const __m128i k0 = p[2]; + const __m128i k1 = p[3]; + const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 r = numRounds2; + const __m128i *w = p + 4; + __m128i temp = *data; + MM_XOR (temp, k0); + MM_XOR (m, temp); + MM_OP_m (_mm_aesenc_si128, k1); + do + { + MM_OP_m (_mm_aesenc_si128, w[0]); + MM_OP_m (_mm_aesenc_si128, w[1]); + w += 2; + } + while (--r); + MM_OP_m (_mm_aesenclast_si128, w[0]); + *data = m; + } + *p = m; +} + + +#define WOP_1(op) +#define WOP_2(op) WOP_1 (op) op (m1, 1); +#define WOP_3(op) WOP_2 (op) op (m2, 2); +#define WOP_4(op) WOP_3 (op) op (m3, 3); +#ifdef MY_CPU_AMD64 +#define WOP_5(op) WOP_4 (op) op (m4, 4); +#define WOP_6(op) WOP_5 (op) op (m5, 5); +#define WOP_7(op) WOP_6 (op) op (m6, 6); +#define WOP_8(op) WOP_7 (op) op (m7, 7); +#endif +/* +#define WOP_9(op) WOP_8 (op) op (m8, 8); +#define WOP_10(op) WOP_9 (op) op (m9, 9); +#define WOP_11(op) WOP_10(op) op (m10, 10); +#define WOP_12(op) WOP_11(op) op (m11, 11); +#define WOP_13(op) WOP_12(op) op (m12, 12); +#define WOP_14(op) WOP_13(op) op (m13, 13); +*/ + +#ifdef MY_CPU_AMD64 + #define NUM_WAYS 8 + #define WOP_M1 WOP_8 +#else + #define NUM_WAYS 4 + #define WOP_M1 WOP_4 +#endif + +#define WOP(op) op (m0, 0); WOP_M1(op) + + +#define DECLARE_VAR(reg, ii) __m128i reg +#define LOAD_data( reg, ii) reg = data[ii]; +#define STORE_data( reg, ii) data[ii] = reg; +#if (NUM_WAYS > 1) +#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]); +#endif + +#define AVX__DECLARE_VAR(reg, ii) __m256i reg +#define AVX__LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii]; +#define AVX__STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg; +#define AVX__XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii])); + +#define MM_OP_key(op, reg) MM_OP(op, reg, key); + +#define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg) +#define AES_DEC_LAST( reg, ii) MM_OP_key (_mm_aesdeclast_si128, reg) +#define AES_ENC( reg, ii) MM_OP_key (_mm_aesenc_si128, reg) +#define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg) +#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) + + +#define AVX__AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg) +#define AVX__AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg) +#define AVX__AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg) +#define AVX__AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg) +#define AVX__AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg) + +#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one); reg = ctr; +#define CTR_END( reg, ii) MM_XOR (data[ii], reg); + +#define AVX__CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two); reg = _mm256_xor_si256(ctr2, key); +#define AVX__CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg); + +#define WOP_KEY(op, n) { \ + const __m128i key = w[n]; \ + WOP(op); } + +#define AVX__WOP_KEY(op, n) { \ + const __m256i key = w[n]; \ + WOP(op); } + + +#define WIDE_LOOP_START \ + dataEnd = data + numBlocks; \ + if (numBlocks >= NUM_WAYS) \ + { dataEnd -= NUM_WAYS; do { \ + + +#define WIDE_LOOP_END \ + data += NUM_WAYS; \ + } while (data <= dataEnd); \ + dataEnd += NUM_WAYS; } \ + + +#define SINGLE_LOOP \ + for (; data < dataEnd; data++) + + +#define NUM_AES_KEYS_MAX 15 + +#define WIDE_LOOP_START_AVX(OP) \ + dataEnd = data + numBlocks; \ + if (numBlocks >= NUM_WAYS * 2) \ + { __m256i keys[NUM_AES_KEYS_MAX]; \ + UInt32 ii; \ + OP \ + for (ii = 0; ii < numRounds; ii++) \ + keys[ii] = _mm256_broadcastsi128_si256(p[ii]); \ + dataEnd -= NUM_WAYS * 2; do { \ + + +#define WIDE_LOOP_END_AVX(OP) \ + data += NUM_WAYS * 2; \ + } while (data <= dataEnd); \ + dataEnd += NUM_WAYS * 2; \ + OP \ + _mm256_zeroupper(); \ + } \ + +/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, + MSVC still can insert vzeroupper instruction. */ + + +AES_FUNC_START2 (AesCbc_Decode_HW) +{ + __m128i iv = *p; + const __m128i *wStart = p + *(const UInt32 *)(p + 1) * 2 + 2 - 1; + const __m128i *dataEnd; + p += 2; + + WIDE_LOOP_START + { + const __m128i *w = wStart; + + WOP (DECLARE_VAR) + WOP (LOAD_data); + WOP_KEY (AES_XOR, 1) + + do + { + WOP_KEY (AES_DEC, 0) + w--; + } + while (w != p); + WOP_KEY (AES_DEC_LAST, 0) + + MM_XOR (m0, iv); + WOP_M1 (XOR_data_M1) + iv = data[NUM_WAYS - 1]; + WOP (STORE_data); + } + WIDE_LOOP_END + + SINGLE_LOOP + { + const __m128i *w = wStart - 1; + __m128i m = _mm_xor_si128 (w[2], *data); + do + { + MM_OP_m (_mm_aesdec_si128, w[1]); + MM_OP_m (_mm_aesdec_si128, w[0]); + w -= 2; + } + while (w != p); + MM_OP_m (_mm_aesdec_si128, w[1]); + MM_OP_m (_mm_aesdeclast_si128, w[0]); + + MM_XOR (m, iv); + iv = *data; + *data = m; + } + + p[-2] = iv; +} + + +AES_FUNC_START2 (AesCtr_Code_HW) +{ + __m128i ctr = *p; + UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1; + const __m128i *dataEnd; + __m128i one = _mm_cvtsi32_si128(1); + + p += 2; + + WIDE_LOOP_START + { + const __m128i *w = p; + UInt32 r = numRoundsMinus2; + WOP (DECLARE_VAR) + WOP (CTR_START); + WOP_KEY (AES_XOR, 0) + w += 1; + do + { + WOP_KEY (AES_ENC, 0) + w += 1; + } + while (--r); + WOP_KEY (AES_ENC_LAST, 0) + + WOP (CTR_END); + } + WIDE_LOOP_END + + SINGLE_LOOP + { + UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1; + const __m128i *w = p; + __m128i m; + MM_OP (_mm_add_epi64, ctr, one); + m = _mm_xor_si128 (ctr, p[0]); + w += 1; + do + { + MM_OP_m (_mm_aesenc_si128, w[0]); + MM_OP_m (_mm_aesenc_si128, w[1]); + w += 2; + } + while (--numRounds2); + MM_OP_m (_mm_aesenc_si128, w[0]); + MM_OP_m (_mm_aesenclast_si128, w[1]); + MM_XOR (*data, m); + } + + p[-2] = ctr; +} + + + +#ifdef USE_INTEL_VAES + +#if defined(__clang__) && defined(_MSC_VER) +#define __SSE4_2__ +#define __AES__ +#define __AVX__ +#define __AVX2__ +#define __VAES__ +#define __AVX512F__ +#define __AVX512VL__ +#endif + +#include + +#define VAES_FUNC_START2(name) \ +AES_FUNC_START (name); \ +ATTRIB_VAES \ +AES_FUNC_START (name) + +VAES_FUNC_START2 (AesCbc_Decode_HW_256) +{ + __m128i iv = *p; + const __m128i *dataEnd; + UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; + p += 2; + + WIDE_LOOP_START_AVX(;) + { + const __m256i *w = keys + numRounds - 2; + + WOP (AVX__DECLARE_VAR) + WOP (AVX__LOAD_data); + AVX__WOP_KEY (AVX__AES_XOR, 1) + + do + { + AVX__WOP_KEY (AVX__AES_DEC, 0) + w--; + } + while (w != keys); + AVX__WOP_KEY (AVX__AES_DEC_LAST, 0) + + AVX_XOR (m0, _mm256_setr_m128i(iv, data[0])); + WOP_M1 (AVX__XOR_data_M1) + iv = data[NUM_WAYS * 2 - 1]; + WOP (AVX__STORE_data); + } + WIDE_LOOP_END_AVX(;) + + SINGLE_LOOP + { + const __m128i *w = p + *(const UInt32 *)(p + 1 - 2) * 2 + 1 - 3; + __m128i m = _mm_xor_si128 (w[2], *data); + do + { + MM_OP_m (_mm_aesdec_si128, w[1]); + MM_OP_m (_mm_aesdec_si128, w[0]); + w -= 2; + } + while (w != p); + MM_OP_m (_mm_aesdec_si128, w[1]); + MM_OP_m (_mm_aesdeclast_si128, w[0]); + + MM_XOR (m, iv); + iv = *data; + *data = m; + } + + p[-2] = iv; +} + + +/* +SSE2: _mm_cvtsi32_si128 : movd +AVX: _mm256_setr_m128i : vinsertf128 +AVX2: _mm256_add_epi64 : vpaddq ymm, ymm, ymm + _mm256_extracti128_si256 : vextracti128 + _mm256_broadcastsi128_si256 : vbroadcasti128 +*/ + +#define AVX__CTR_LOOP_START \ + ctr2 = _mm256_setr_m128i(_mm_sub_epi64(ctr, one), ctr); \ + two = _mm256_setr_m128i(one, one); \ + two = _mm256_add_epi64(two, two); \ + +// two = _mm256_setr_epi64x(2, 0, 2, 0); + +#define AVX__CTR_LOOP_ENC \ + ctr = _mm256_extracti128_si256 (ctr2, 1); \ + +VAES_FUNC_START2 (AesCtr_Code_HW_256) +{ + __m128i ctr = *p; + UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1; + const __m128i *dataEnd; + __m128i one = _mm_cvtsi32_si128(1); + __m256i ctr2, two; + p += 2; + + WIDE_LOOP_START_AVX (AVX__CTR_LOOP_START) + { + const __m256i *w = keys; + UInt32 r = numRounds - 2; + WOP (AVX__DECLARE_VAR) + AVX__WOP_KEY (AVX__CTR_START, 0); + + w += 1; + do + { + AVX__WOP_KEY (AVX__AES_ENC, 0) + w += 1; + } + while (--r); + AVX__WOP_KEY (AVX__AES_ENC_LAST, 0) + + WOP (AVX__CTR_END); + } + WIDE_LOOP_END_AVX (AVX__CTR_LOOP_ENC) + + SINGLE_LOOP + { + UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1; + const __m128i *w = p; + __m128i m; + MM_OP (_mm_add_epi64, ctr, one); + m = _mm_xor_si128 (ctr, p[0]); + w += 1; + do + { + MM_OP_m (_mm_aesenc_si128, w[0]); + MM_OP_m (_mm_aesenc_si128, w[1]); + w += 2; + } + while (--numRounds2); + MM_OP_m (_mm_aesenc_si128, w[0]); + MM_OP_m (_mm_aesenclast_si128, w[1]); + MM_XOR (*data, m); + } + + p[-2] = ctr; +} + +#endif // USE_INTEL_VAES + +#else // USE_INTEL_AES + +/* no USE_INTEL_AES */ + +#pragma message("AES HW_SW stub was used") + +#define AES_TYPE_keys UInt32 +#define AES_TYPE_data Byte + +#define AES_FUNC_START(name) \ + void MY_FAST_CALL name(UInt32 *p, Byte *data, size_t numBlocks) \ + +#define AES_COMPAT_STUB(name) \ + AES_FUNC_START(name); \ + AES_FUNC_START(name ## _HW) \ + { name(p, data, numBlocks); } + +AES_COMPAT_STUB (AesCbc_Encode) +AES_COMPAT_STUB (AesCbc_Decode) +AES_COMPAT_STUB (AesCtr_Code) + +#endif // USE_INTEL_AES + + +#ifndef USE_INTEL_VAES + +#pragma message("VAES HW_SW stub was used") + +#define VAES_COMPAT_STUB(name) \ + void MY_FAST_CALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \ + void MY_FAST_CALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks) \ + { name((AES_TYPE_keys *)(void *)p, (AES_TYPE_data *)(void *)data, numBlocks); } + +VAES_COMPAT_STUB (AesCbc_Decode_HW) +VAES_COMPAT_STUB (AesCtr_Code_HW) + +#endif // ! USE_INTEL_VAES + + +#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) + + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_AES + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_AES + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_AES + #endif + #endif + +#ifdef USE_HW_AES + +// #pragma message("=== AES HW === ") + +#if defined(__clang__) || defined(__GNUC__) + #ifdef MY_CPU_ARM64 + #define ATTRIB_AES __attribute__((__target__("+crypto"))) + #else + #define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif +#else + // _MSC_VER + // for arm32 + #define _ARM_USE_NEW_NEON_INTRINSICS +#endif + +#ifndef ATTRIB_AES + #define ATTRIB_AES +#endif + +#if defined(_MSC_VER) && defined(MY_CPU_ARM64) +#include +#else +#include +#endif + +typedef uint8x16_t v128; + +#define AES_FUNC_START(name) \ + void MY_FAST_CALL name(v128 *p, v128 *data, size_t numBlocks) + +#define AES_FUNC_START2(name) \ +AES_FUNC_START (name); \ +ATTRIB_AES \ +AES_FUNC_START (name) + +#define MM_OP(op, dest, src) dest = op(dest, src); +#define MM_OP_m(op, src) MM_OP(op, m, src); +#define MM_OP1_m(op) m = op(m); + +#define MM_XOR( dest, src) MM_OP(veorq_u8, dest, src); +#define MM_XOR_m( src) MM_XOR(m, src); + +#define AES_E_m(k) MM_OP_m (vaeseq_u8, k); +#define AES_E_MC_m(k) AES_E_m (k); MM_OP1_m(vaesmcq_u8); + + +AES_FUNC_START2 (AesCbc_Encode_HW) +{ + v128 m = *p; + const v128 k0 = p[2]; + const v128 k1 = p[3]; + const v128 k2 = p[4]; + const v128 k3 = p[5]; + const v128 k4 = p[6]; + const v128 k5 = p[7]; + const v128 k6 = p[8]; + const v128 k7 = p[9]; + const v128 k8 = p[10]; + const v128 k9 = p[11]; + const UInt32 numRounds2 = *(const UInt32 *)(p + 1); + const v128 *w = p + ((size_t)numRounds2 * 2); + const v128 k_z1 = w[1]; + const v128 k_z0 = w[2]; + for (; numBlocks != 0; numBlocks--, data++) + { + MM_XOR_m (*data); + AES_E_MC_m (k0) + AES_E_MC_m (k1) + AES_E_MC_m (k2) + AES_E_MC_m (k3) + AES_E_MC_m (k4) + AES_E_MC_m (k5) + AES_E_MC_m (k6) + AES_E_MC_m (k7) + AES_E_MC_m (k8) + if (numRounds2 >= 6) + { + AES_E_MC_m (k9) + AES_E_MC_m (p[12]) + if (numRounds2 != 6) + { + AES_E_MC_m (p[13]) + AES_E_MC_m (p[14]) + } + } + AES_E_m (k_z1); + MM_XOR_m (k_z0); + *data = m; + } + *p = m; +} + + +#define WOP_1(op) +#define WOP_2(op) WOP_1 (op) op (m1, 1); +#define WOP_3(op) WOP_2 (op) op (m2, 2); +#define WOP_4(op) WOP_3 (op) op (m3, 3); +#define WOP_5(op) WOP_4 (op) op (m4, 4); +#define WOP_6(op) WOP_5 (op) op (m5, 5); +#define WOP_7(op) WOP_6 (op) op (m6, 6); +#define WOP_8(op) WOP_7 (op) op (m7, 7); + + #define NUM_WAYS 8 + #define WOP_M1 WOP_8 + +#define WOP(op) op (m0, 0); WOP_M1(op) + +#define DECLARE_VAR(reg, ii) v128 reg +#define LOAD_data( reg, ii) reg = data[ii]; +#define STORE_data( reg, ii) data[ii] = reg; +#if (NUM_WAYS > 1) +#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]); +#endif + +#define MM_OP_key(op, reg) MM_OP (op, reg, key); + +#define AES_D_m(k) MM_OP_m (vaesdq_u8, k); +#define AES_D_IMC_m(k) AES_D_m (k); MM_OP1_m (vaesimcq_u8); + +#define AES_XOR( reg, ii) MM_OP_key (veorq_u8, reg) +#define AES_D( reg, ii) MM_OP_key (vaesdq_u8, reg) +#define AES_E( reg, ii) MM_OP_key (vaeseq_u8, reg) + +#define AES_D_IMC( reg, ii) AES_D (reg, ii); reg = vaesimcq_u8(reg) +#define AES_E_MC( reg, ii) AES_E (reg, ii); reg = vaesmcq_u8(reg) + +#define CTR_START(reg, ii) MM_OP (vaddq_u64, ctr, one); reg = vreinterpretq_u8_u64(ctr); +#define CTR_END( reg, ii) MM_XOR (data[ii], reg); + +#define WOP_KEY(op, n) { \ + const v128 key = w[n]; \ + WOP(op); } + +#define WIDE_LOOP_START \ + dataEnd = data + numBlocks; \ + if (numBlocks >= NUM_WAYS) \ + { dataEnd -= NUM_WAYS; do { \ + +#define WIDE_LOOP_END \ + data += NUM_WAYS; \ + } while (data <= dataEnd); \ + dataEnd += NUM_WAYS; } \ + +#define SINGLE_LOOP \ + for (; data < dataEnd; data++) + + +AES_FUNC_START2 (AesCbc_Decode_HW) +{ + v128 iv = *p; + const v128 *wStart = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; + const v128 *dataEnd; + p += 2; + + WIDE_LOOP_START + { + const v128 *w = wStart; + WOP (DECLARE_VAR) + WOP (LOAD_data); + WOP_KEY (AES_D_IMC, 2) + do + { + WOP_KEY (AES_D_IMC, 1) + WOP_KEY (AES_D_IMC, 0) + w -= 2; + } + while (w != p); + WOP_KEY (AES_D, 1) + WOP_KEY (AES_XOR, 0) + MM_XOR (m0, iv); + WOP_M1 (XOR_data_M1) + iv = data[NUM_WAYS - 1]; + WOP (STORE_data); + } + WIDE_LOOP_END + + SINGLE_LOOP + { + const v128 *w = wStart; + v128 m = *data; + AES_D_IMC_m (w[2]) + do + { + AES_D_IMC_m (w[1]); + AES_D_IMC_m (w[0]); + w -= 2; + } + while (w != p); + AES_D_m (w[1]); + MM_XOR_m (w[0]); + MM_XOR_m (iv); + iv = *data; + *data = m; + } + + p[-2] = iv; +} + + +AES_FUNC_START2 (AesCtr_Code_HW) +{ + uint64x2_t ctr = vreinterpretq_u64_u8(*p); + const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; + const v128 *dataEnd; + uint64x2_t one = vdupq_n_u64(0); + one = vsetq_lane_u64(1, one, 0); + p += 2; + + WIDE_LOOP_START + { + const v128 *w = p; + WOP (DECLARE_VAR) + WOP (CTR_START); + do + { + WOP_KEY (AES_E_MC, 0) + WOP_KEY (AES_E_MC, 1) + w += 2; + } + while (w != wEnd); + WOP_KEY (AES_E_MC, 0) + WOP_KEY (AES_E, 1) + WOP_KEY (AES_XOR, 2) + WOP (CTR_END); + } + WIDE_LOOP_END + + SINGLE_LOOP + { + const v128 *w = p; + v128 m; + CTR_START (m, 0); + do + { + AES_E_MC_m (w[0]); + AES_E_MC_m (w[1]); + w += 2; + } + while (w != wEnd); + AES_E_MC_m (w[0]); + AES_E_m (w[1]); + MM_XOR_m (w[2]); + CTR_END (m, 0); + } + + p[-2] = vreinterpretq_u8_u64(ctr); +} + +#endif // USE_HW_AES + +#endif // MY_CPU_ARM_OR_ARM64 diff --git a/3rdparty/lzma-21.03beta/C/Alloc.c b/3rdparty/lzma-21.03beta/C/Alloc.c new file mode 100644 index 0000000..d1af76c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Alloc.c @@ -0,0 +1,463 @@ +/* Alloc.c -- Memory allocation functions +2021-07-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG + +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; + + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +static void ConvertUInt64ToString(UInt64 val, char *s) +{ + CONVERT_INT_TO_STR(char, 24); +} + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static void ConvertUInt64ToHex(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +#define DEBUG_OUT_STREAM stderr + +static void Print(const char *s) +{ + fputs(s, DEBUG_OUT_STREAM); +} + +static void PrintAligned(const char *s, size_t align) +{ + size_t len = strlen(s); + for(;;) + { + fputc(' ', DEBUG_OUT_STREAM); + if (len >= align) + break; + ++len; + } + Print(s); +} + +static void PrintLn() +{ + Print("\n"); +} + +static void PrintHex(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToHex(v, s); + PrintAligned(s, align); +} + +static void PrintDec(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToString(v, s); + PrintAligned(s, align); +} + +static void PrintAddr(void *p) +{ + PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12); +} + + +#define PRINT_ALLOC(name, cnt, size, ptr) \ + Print(name " "); \ + PrintDec(cnt++, 10); \ + PrintHex(size, 10); \ + PrintAddr(ptr); \ + PrintLn(); + +#define PRINT_FREE(name, cnt, ptr) if (ptr) { \ + Print(name " "); \ + PrintDec(--cnt, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#else + +#define PRINT_ALLOC(name, cnt, size, ptr) +#define PRINT_FREE(name, cnt, ptr) +#define Print(s) +#define PrintLn() +#define PrintHex(v, align) +#define PrintAddr(p) + +#endif + + + +void *MyAlloc(size_t size) +{ + if (size == 0) + return NULL; + PRINT_ALLOC("Alloc ", g_allocCount, size, NULL); + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + // PRINT_ALLOC("Alloc ", g_allocCount, size, p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + PRINT_FREE("Free ", g_allocCount, address); + + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL); + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + PRINT_FREE("Free-Mid", g_allocCountMid, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifdef _7ZIP_LARGE_PAGES + +#ifdef MEM_LARGE_PAGES + #define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES +#else + #define MY__MEM_LARGE_PAGES 0x20000000 +#endif + +extern +SIZE_T g_LargePageSize; +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(VOID); + +#endif // _7ZIP_LARGE_PAGES + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (!largePageMinimum) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL); + + #ifdef _7ZIP_LARGE_PAGES + { + SIZE_T ps = g_LargePageSize; + if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) + { + size_t size2; + ps--; + size2 = (size + ps) & ~ps; + if (size2 >= size) + { + void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); + if (res) + return res; + } + } + } + #endif + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + PRINT_FREE("Free-Big", g_allocCountBig, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif + + +static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } +static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } +const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +#ifdef _WIN32 +static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); } +static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); } +static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } +static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } +const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; +const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; +#endif + +/* + uintptr_t : C99 (optional) + : unsupported in VS6 +*/ + +#ifdef _WIN32 + typedef UINT_PTR UIntPtr; +#else + /* + typedef uintptr_t UIntPtr; + */ + typedef ptrdiff_t UIntPtr; +#endif + + +#define ADJUST_ALLOC_SIZE 0 +/* +#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1) +*/ +/* + Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if + MyAlloc() can return address that is NOT multiple of sizeof(void *). +*/ + + +/* +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) +*/ +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) + + +#if !defined(_WIN32) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) + #define USE_posix_memalign +#endif + +#ifndef USE_posix_memalign +#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align) +#endif + +/* + This posix_memalign() is for test purposes only. + We also need special Free() function instead of free(), + if this posix_memalign() is used. +*/ + +/* +static int posix_memalign(void **ptr, size_t align, size_t size) +{ + size_t newSize = size + align; + void *p; + void *pAligned; + *ptr = NULL; + if (newSize < size) + return 12; // ENOMEM + p = MyAlloc(newSize); + if (!p) + return 12; // ENOMEM + pAligned = MY_ALIGN_PTR_UP_PLUS(p, align); + ((void **)pAligned)[-1] = p; + *ptr = pAligned; + return 0; +} +*/ + +/* + ALLOC_ALIGN_SIZE >= sizeof(void *) + ALLOC_ALIGN_SIZE >= cache_line_size +*/ + +#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) + +static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) +{ + #ifndef USE_posix_memalign + + void *p; + void *pAligned; + size_t newSize; + UNUSED_VAR(pp); + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + + newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + p = MyAlloc(newSize); + + if (!p) + return NULL; + pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE); + + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(p); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + ((void **)pAligned)[-1] = p; + + return pAligned; + + #else + + void *p; + UNUSED_VAR(pp); + if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) + return NULL; + + Print(" posix_memalign="); PrintAddr(p); + PrintLn(); + + return p; + + #endif +} + + +static void SzAlignedFree(ISzAllocPtr pp, void *address) +{ + UNUSED_VAR(pp); + #ifndef USE_posix_memalign + if (address) + MyFree(((void **)address)[-1]); + #else + free(address); + #endif +} + + +const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; + + + +#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) + +/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ +#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] +/* +#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] +*/ + +static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) +{ + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + void *adr; + void *pAligned; + size_t newSize; + size_t extra; + size_t alignSize = (size_t)1 << p->numAlignBits; + + if (alignSize < sizeof(void *)) + alignSize = sizeof(void *); + + if (p->offset >= alignSize) + return NULL; + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + extra = p->offset & (sizeof(void *) - 1); + newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + adr = ISzAlloc_Alloc(p->baseAlloc, newSize); + + if (!adr) + return NULL; + + pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + + alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; + + PrintLn(); + Print("- Aligned: "); + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(adr); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + REAL_BLOCK_PTR_VAR(pAligned) = adr; + + return pAligned; +} + + +static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) +{ + if (address) + { + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + PrintLn(); + Print("- Aligned Free: "); + PrintLn(); + ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); + } +} + + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p) +{ + p->vt.Alloc = AlignOffsetAlloc_Alloc; + p->vt.Free = AlignOffsetAlloc_Free; +} diff --git a/3rdparty/lzma-21.03beta/C/Alloc.h b/3rdparty/lzma-21.03beta/C/Alloc.h new file mode 100644 index 0000000..3be2041 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Alloc.h @@ -0,0 +1,58 @@ +/* Alloc.h -- Memory allocation functions +2021-07-13 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(void); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +extern const ISzAlloc g_Alloc; + +#ifdef _WIN32 +extern const ISzAlloc g_BigAlloc; +extern const ISzAlloc g_MidAlloc; +#else +#define g_BigAlloc g_AlignedAlloc +#define g_MidAlloc g_AlignedAlloc +#endif + +extern const ISzAlloc g_AlignedAlloc; + + +typedef struct +{ + ISzAlloc vt; + ISzAllocPtr baseAlloc; + unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */ + size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */ +} CAlignOffsetAlloc; + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p); + + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Bcj2.c b/3rdparty/lzma-21.03beta/C/Bcj2.c new file mode 100644 index 0000000..c7b9567 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bcj2.c @@ -0,0 +1,257 @@ +/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bcj2.h" +#include "CpuArch.h" + +#define CProb UInt16 + +#define kTopValue ((UInt32)1 << 24) +#define kNumModelBits 11 +#define kBitModelTotal (1 << kNumModelBits) +#define kNumMoveBits 5 + +#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) +#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); + +void Bcj2Dec_Init(CBcj2Dec *p) +{ + unsigned i; + + p->state = BCJ2_DEC_STATE_OK; + p->ip = 0; + p->temp[3] = 0; + p->range = 0; + p->code = 0; + for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) + p->probs[i] = kBitModelTotal >> 1; +} + +SRes Bcj2Dec_Decode(CBcj2Dec *p) +{ + if (p->range <= 5) + { + p->state = BCJ2_DEC_STATE_OK; + for (; p->range != 5; p->range++) + { + if (p->range == 1 && p->code != 0) + return SZ_ERROR_DATA; + + if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + return SZ_OK; + } + + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + if (p->code == 0xFFFFFFFF) + return SZ_ERROR_DATA; + + p->range = 0xFFFFFFFF; + } + else if (p->state >= BCJ2_DEC_STATE_ORIG_0) + { + while (p->state <= BCJ2_DEC_STATE_ORIG_3) + { + Byte *dest = p->dest; + if (dest == p->destLim) + return SZ_OK; + *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0]; + p->state++; + p->dest = dest + 1; + } + } + + /* + if (BCJ2_IS_32BIT_STREAM(p->state)) + { + const Byte *cur = p->bufs[p->state]; + if (cur == p->lims[p->state]) + return SZ_OK; + p->bufs[p->state] = cur + 4; + + { + UInt32 val; + Byte *dest; + SizeT rem; + + p->ip += 4; + val = GetBe32(cur) - p->ip; + dest = p->dest; + rem = p->destLim - dest; + if (rem < 4) + { + SizeT i; + SetUi32(p->temp, val); + for (i = 0; i < rem; i++) + dest[i] = p->temp[i]; + p->dest = dest + rem; + p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; + return SZ_OK; + } + SetUi32(dest, val); + p->temp[3] = (Byte)(val >> 24); + p->dest = dest + 4; + p->state = BCJ2_DEC_STATE_OK; + } + } + */ + + for (;;) + { + if (BCJ2_IS_32BIT_STREAM(p->state)) + p->state = BCJ2_DEC_STATE_OK; + else + { + if (p->range < kTopValue) + { + if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + return SZ_OK; + } + p->range <<= 8; + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + { + const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; + const Byte *srcLim; + Byte *dest; + SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); + + if (num == 0) + { + p->state = BCJ2_STREAM_MAIN; + return SZ_OK; + } + + dest = p->dest; + if (num > (SizeT)(p->destLim - dest)) + { + num = (SizeT)(p->destLim - dest); + if (num == 0) + { + p->state = BCJ2_DEC_STATE_ORIG; + return SZ_OK; + } + } + + srcLim = src + num; + + if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) + *dest = src[0]; + else for (;;) + { + Byte b = *src; + *dest = b; + if (b != 0x0F) + { + if ((b & 0xFE) == 0xE8) + break; + dest++; + if (++src != srcLim) + continue; + break; + } + dest++; + if (++src == srcLim) + break; + if ((*src & 0xF0) != 0x80) + continue; + *dest = *src; + break; + } + + num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); + + if (src == srcLim) + { + p->temp[3] = src[-1]; + p->bufs[BCJ2_STREAM_MAIN] = src; + p->ip += (UInt32)num; + p->dest += num; + p->state = + p->bufs[BCJ2_STREAM_MAIN] == + p->lims[BCJ2_STREAM_MAIN] ? + (unsigned)BCJ2_STREAM_MAIN : + (unsigned)BCJ2_DEC_STATE_ORIG; + return SZ_OK; + } + + { + UInt32 bound, ttt; + CProb *prob; + Byte b = src[0]; + Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); + + p->temp[3] = b; + p->bufs[BCJ2_STREAM_MAIN] = src + 1; + num++; + p->ip += (UInt32)num; + p->dest += num; + + prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); + + _IF_BIT_0 + { + _UPDATE_0 + continue; + } + _UPDATE_1 + + } + } + } + + { + UInt32 val; + unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + const Byte *cur = p->bufs[cj]; + Byte *dest; + SizeT rem; + + if (cur == p->lims[cj]) + { + p->state = cj; + break; + } + + val = GetBe32(cur); + p->bufs[cj] = cur + 4; + + p->ip += 4; + val -= p->ip; + dest = p->dest; + rem = (SizeT)(p->destLim - dest); + + if (rem < 4) + { + p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8; + p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8; + p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8; + p->temp[3] = (Byte)val; + p->dest = dest + rem; + p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; + break; + } + + SetUi32(dest, val); + p->temp[3] = (Byte)(val >> 24); + p->dest = dest + 4; + } + } + + if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) + { + p->range <<= 8; + p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; + } + + return SZ_OK; +} diff --git a/3rdparty/lzma-21.03beta/C/Bcj2.h b/3rdparty/lzma-21.03beta/C/Bcj2.h new file mode 100644 index 0000000..8824080 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bcj2.h @@ -0,0 +1,146 @@ +/* Bcj2.h -- BCJ2 Converter for x86 code +2014-11-10 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define BCJ2_NUM_STREAMS 4 + +enum +{ + BCJ2_STREAM_MAIN, + BCJ2_STREAM_CALL, + BCJ2_STREAM_JUMP, + BCJ2_STREAM_RC +}; + +enum +{ + BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, + BCJ2_DEC_STATE_ORIG_1, + BCJ2_DEC_STATE_ORIG_2, + BCJ2_DEC_STATE_ORIG_3, + + BCJ2_DEC_STATE_ORIG, + BCJ2_DEC_STATE_OK +}; + +enum +{ + BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, + BCJ2_ENC_STATE_OK +}; + + +#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) + +/* +CBcj2Dec / CBcj2Enc +bufs sizes: + BUF_SIZE(n) = lims[n] - bufs[n] +bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: + (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 + (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 +*/ + +/* +CBcj2Dec: +dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: + bufs[BCJ2_STREAM_MAIN] >= dest && + bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + + BUF_SIZE(BCJ2_STREAM_CALL) + + BUF_SIZE(BCJ2_STREAM_JUMP) + tempReserv = 0 : for first call of Bcj2Dec_Decode + tempReserv = 4 : for any other calls of Bcj2Dec_Decode + overlap with offset = 1 is not allowed +*/ + +typedef struct +{ + const Byte *bufs[BCJ2_NUM_STREAMS]; + const Byte *lims[BCJ2_NUM_STREAMS]; + Byte *dest; + const Byte *destLim; + + unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ + + UInt32 ip; + Byte temp[4]; + UInt32 range; + UInt32 code; + UInt16 probs[2 + 256]; +} CBcj2Dec; + +void Bcj2Dec_Init(CBcj2Dec *p); + +/* Returns: SZ_OK or SZ_ERROR_DATA */ +SRes Bcj2Dec_Decode(CBcj2Dec *p); + +#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) + + + +typedef enum +{ + BCJ2_ENC_FINISH_MODE_CONTINUE, + BCJ2_ENC_FINISH_MODE_END_BLOCK, + BCJ2_ENC_FINISH_MODE_END_STREAM +} EBcj2Enc_FinishMode; + +typedef struct +{ + Byte *bufs[BCJ2_NUM_STREAMS]; + const Byte *lims[BCJ2_NUM_STREAMS]; + const Byte *src; + const Byte *srcLim; + + unsigned state; + EBcj2Enc_FinishMode finishMode; + + Byte prevByte; + + Byte cache; + UInt32 range; + UInt64 low; + UInt64 cacheSize; + + UInt32 ip; + + /* 32-bit ralative offset in JUMP/CALL commands is + - (mod 4 GB) in 32-bit mode + - signed Int32 in 64-bit mode + We use (mod 4 GB) check for fileSize. + Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ + UInt32 fileIp; + UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ + UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ + + UInt32 tempTarget; + unsigned tempPos; + Byte temp[4 * 2]; + + unsigned flushPos; + + UInt16 probs[2 + 256]; +} CBcj2Enc; + +void Bcj2Enc_Init(CBcj2Enc *p); +void Bcj2Enc_Encode(CBcj2Enc *p); + +#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) +#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) + + +#define BCJ2_RELAT_LIMIT_NUM_BITS 26 +#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) + +/* limit for CBcj2Enc::fileSize variable */ +#define BCJ2_FileSize_MAX ((UInt32)1 << 31) + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Bcj2Enc.c b/3rdparty/lzma-21.03beta/C/Bcj2Enc.c new file mode 100644 index 0000000..682362a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bcj2Enc.c @@ -0,0 +1,311 @@ +/* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code) +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #define SHOW_STAT */ + +#ifdef SHOW_STAT +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +#include + +#include "Bcj2.h" +#include "CpuArch.h" + +#define CProb UInt16 + +#define kTopValue ((UInt32)1 << 24) +#define kNumModelBits 11 +#define kBitModelTotal (1 << kNumModelBits) +#define kNumMoveBits 5 + +void Bcj2Enc_Init(CBcj2Enc *p) +{ + unsigned i; + + p->state = BCJ2_ENC_STATE_OK; + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + p->prevByte = 0; + + p->cache = 0; + p->range = 0xFFFFFFFF; + p->low = 0; + p->cacheSize = 1; + + p->ip = 0; + + p->fileIp = 0; + p->fileSize = 0; + p->relatLimit = BCJ2_RELAT_LIMIT; + + p->tempPos = 0; + + p->flushPos = 0; + + for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) + p->probs[i] = kBitModelTotal >> 1; +} + +static BoolInt MY_FAST_CALL RangeEnc_ShiftLow(CBcj2Enc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (UInt32)(p->low >> 32) != 0) + { + Byte *buf = p->bufs[BCJ2_STREAM_RC]; + do + { + if (buf == p->lims[BCJ2_STREAM_RC]) + { + p->state = BCJ2_STREAM_RC; + p->bufs[BCJ2_STREAM_RC] = buf; + return True; + } + *buf++ = (Byte)(p->cache + (Byte)(p->low >> 32)); + p->cache = 0xFF; + } + while (--p->cacheSize); + p->bufs[BCJ2_STREAM_RC] = buf; + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; + return False; +} + +static void Bcj2Enc_Encode_2(CBcj2Enc *p) +{ + if (BCJ2_IS_32BIT_STREAM(p->state)) + { + Byte *cur = p->bufs[p->state]; + if (cur == p->lims[p->state]) + return; + SetBe32(cur, p->tempTarget); + p->bufs[p->state] = cur + 4; + } + + p->state = BCJ2_ENC_STATE_ORIG; + + for (;;) + { + if (p->range < kTopValue) + { + if (RangeEnc_ShiftLow(p)) + return; + p->range <<= 8; + } + + { + { + const Byte *src = p->src; + const Byte *srcLim; + Byte *dest; + SizeT num = (SizeT)(p->srcLim - src); + + if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE) + { + if (num <= 4) + return; + num -= 4; + } + else if (num == 0) + break; + + dest = p->bufs[BCJ2_STREAM_MAIN]; + if (num > (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest)) + { + num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest); + if (num == 0) + { + p->state = BCJ2_STREAM_MAIN; + return; + } + } + + srcLim = src + num; + + if (p->prevByte == 0x0F && (src[0] & 0xF0) == 0x80) + *dest = src[0]; + else for (;;) + { + Byte b = *src; + *dest = b; + if (b != 0x0F) + { + if ((b & 0xFE) == 0xE8) + break; + dest++; + if (++src != srcLim) + continue; + break; + } + dest++; + if (++src == srcLim) + break; + if ((*src & 0xF0) != 0x80) + continue; + *dest = *src; + break; + } + + num = (SizeT)(src - p->src); + + if (src == srcLim) + { + p->prevByte = src[-1]; + p->bufs[BCJ2_STREAM_MAIN] = dest; + p->src = src; + p->ip += (UInt32)num; + continue; + } + + { + Byte context = (Byte)(num == 0 ? p->prevByte : src[-1]); + BoolInt needConvert; + + p->bufs[BCJ2_STREAM_MAIN] = dest + 1; + p->ip += (UInt32)num + 1; + src++; + + needConvert = False; + + if ((SizeT)(p->srcLim - src) >= 4) + { + UInt32 relatVal = GetUi32(src); + if ((p->fileSize == 0 || (UInt32)(p->ip + 4 + relatVal - p->fileIp) < p->fileSize) + && ((relatVal + p->relatLimit) >> 1) < p->relatLimit) + needConvert = True; + } + + { + UInt32 bound; + unsigned ttt; + Byte b = src[-1]; + CProb *prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)context : (b == 0xE9 ? 1 : 0)); + + ttt = *prob; + bound = (p->range >> kNumModelBits) * ttt; + + if (!needConvert) + { + p->range = bound; + *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + p->src = src; + p->prevByte = b; + continue; + } + + p->low += bound; + p->range -= bound; + *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); + + { + UInt32 relatVal = GetUi32(src); + UInt32 absVal; + p->ip += 4; + absVal = p->ip + relatVal; + p->prevByte = src[3]; + src += 4; + p->src = src; + { + unsigned cj = (b == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; + Byte *cur = p->bufs[cj]; + if (cur == p->lims[cj]) + { + p->state = cj; + p->tempTarget = absVal; + return; + } + SetBe32(cur, absVal); + p->bufs[cj] = cur + 4; + } + } + } + } + } + } + } + + if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM) + return; + + for (; p->flushPos < 5; p->flushPos++) + if (RangeEnc_ShiftLow(p)) + return; + p->state = BCJ2_ENC_STATE_OK; +} + + +void Bcj2Enc_Encode(CBcj2Enc *p) +{ + PRF(printf("\n")); + PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + if (p->tempPos != 0) + { + unsigned extra = 0; + + for (;;) + { + const Byte *src = p->src; + const Byte *srcLim = p->srcLim; + EBcj2Enc_FinishMode finishMode = p->finishMode; + + p->src = p->temp; + p->srcLim = p->temp + p->tempPos; + if (src != srcLim) + p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + Bcj2Enc_Encode_2(p); + + { + unsigned num = (unsigned)(p->src - p->temp); + unsigned tempPos = p->tempPos - num; + unsigned i; + p->tempPos = tempPos; + for (i = 0; i < tempPos; i++) + p->temp[i] = p->temp[(size_t)i + num]; + + p->src = src; + p->srcLim = srcLim; + p->finishMode = finishMode; + + if (p->state != BCJ2_ENC_STATE_ORIG || src == srcLim) + return; + + if (extra >= tempPos) + { + p->src = src - tempPos; + p->tempPos = 0; + break; + } + + p->temp[tempPos] = src[0]; + p->tempPos = tempPos + 1; + p->src = src + 1; + extra++; + } + } + } + + PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p->ip, p->tempPos, p->srcLim - p->src)); + + Bcj2Enc_Encode_2(p); + + if (p->state == BCJ2_ENC_STATE_ORIG) + { + const Byte *src = p->src; + unsigned rem = (unsigned)(p->srcLim - src); + unsigned i; + for (i = 0; i < rem; i++) + p->temp[i] = src[i]; + p->tempPos = rem; + p->src = src + rem; + } +} diff --git a/3rdparty/lzma-21.03beta/C/Bra.c b/3rdparty/lzma-21.03beta/C/Bra.c new file mode 100644 index 0000000..3b854d9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bra.c @@ -0,0 +1,230 @@ +/* Bra.c -- Converters for RISC code +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip += 4; + p = data; + lim = data + size; + + if (encoding) + + for (;;) + { + for (;;) + { + if (p >= lim) + return (SizeT)(p - data); + p += 4; + if (p[-1] == 0xEB) + break; + } + { + UInt32 v = GetUi32(p - 4); + v <<= 2; + v += ip + (UInt32)(p - data); + v >>= 2; + v &= 0x00FFFFFF; + v |= 0xEB000000; + SetUi32(p - 4, v); + } + } + + for (;;) + { + for (;;) + { + if (p >= lim) + return (SizeT)(p - data); + p += 4; + if (p[-1] == 0xEB) + break; + } + { + UInt32 v = GetUi32(p - 4); + v <<= 2; + v -= ip + (UInt32)(p - data); + v >>= 2; + v &= 0x00FFFFFF; + v |= 0xEB000000; + SetUi32(p - 4, v); + } + } +} + + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)1; + p = data; + lim = data + size - 4; + + if (encoding) + + for (;;) + { + UInt32 b1; + for (;;) + { + UInt32 b3; + if (p > lim) + return (SizeT)(p - data); + b1 = p[1]; + b3 = p[3]; + p += 2; + b1 ^= 8; + if ((b3 & b1) >= 0xF8) + break; + } + { + UInt32 v = + ((UInt32)b1 << 19) + + (((UInt32)p[1] & 0x7) << 8) + + (((UInt32)p[-2] << 11)) + + (p[0]); + + p += 2; + { + UInt32 cur = (ip + (UInt32)(p - data)) >> 1; + v += cur; + } + + p[-4] = (Byte)(v >> 11); + p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); + p[-2] = (Byte)v; + p[-1] = (Byte)(0xF8 | (v >> 8)); + } + } + + for (;;) + { + UInt32 b1; + for (;;) + { + UInt32 b3; + if (p > lim) + return (SizeT)(p - data); + b1 = p[1]; + b3 = p[3]; + p += 2; + b1 ^= 8; + if ((b3 & b1) >= 0xF8) + break; + } + { + UInt32 v = + ((UInt32)b1 << 19) + + (((UInt32)p[1] & 0x7) << 8) + + (((UInt32)p[-2] << 11)) + + (p[0]); + + p += 2; + { + UInt32 cur = (ip + (UInt32)(p - data)) >> 1; + v -= cur; + } + + /* + SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000)); + SetUi16(p - 2, (UInt16)(v | 0xF800)); + */ + + p[-4] = (Byte)(v >> 11); + p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7)); + p[-2] = (Byte)v; + p[-1] = (Byte)(0xF8 | (v >> 8)); + } + } +} + + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip -= 4; + p = data; + lim = data + size; + + for (;;) + { + for (;;) + { + if (p >= lim) + return (SizeT)(p - data); + p += 4; + /* if ((v & 0xFC000003) == 0x48000001) */ + if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) + break; + } + { + UInt32 v = GetBe32(p - 4); + if (encoding) + v += ip + (UInt32)(p - data); + else + v -= ip + (UInt32)(p - data); + v &= 0x03FFFFFF; + v |= 0x48000000; + SetBe32(p - 4, v); + } + } +} + + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + Byte *p; + const Byte *lim; + size &= ~(size_t)3; + ip -= 4; + p = data; + lim = data + size; + + for (;;) + { + for (;;) + { + if (p >= lim) + return (SizeT)(p - data); + /* + v = GetBe32(p); + p += 4; + m = v + ((UInt32)5 << 29); + m ^= (UInt32)7 << 29; + m += (UInt32)1 << 22; + if ((m & ((UInt32)0x1FF << 23)) == 0) + break; + */ + p += 4; + if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) || + (p[-4] == 0x7F && (p[-3] >= 0xC0))) + break; + } + { + UInt32 v = GetBe32(p - 4); + v <<= 2; + if (encoding) + v += ip + (UInt32)(p - data); + else + v -= ip + (UInt32)(p - data); + + v &= 0x01FFFFFF; + v -= (UInt32)1 << 24; + v ^= 0xFF000000; + v >>= 2; + v |= 0x40000000; + SetBe32(p - 4, v); + } + } +} diff --git a/3rdparty/lzma-21.03beta/C/Bra.h b/3rdparty/lzma-21.03beta/C/Bra.h new file mode 100644 index 0000000..855e37a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bra.h @@ -0,0 +1,64 @@ +/* Bra.h -- Branch converters for executables +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Bra86.c b/3rdparty/lzma-21.03beta/C/Bra86.c new file mode 100644 index 0000000..10a0fbd --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Bra86.c @@ -0,0 +1,82 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT pos = 0; + UInt32 mask = *state & 7; + if (size < 5) + return 0; + size -= 4; + ip += 5; + + for (;;) + { + Byte *p = data + pos; + const Byte *limit = data + size; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + + { + SizeT d = (SizeT)(p - data) - pos; + pos = (SizeT)(p - data); + if (p >= limit) + { + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1]))) + { + mask = (mask >> 1) | 4; + pos++; + continue; + } + } + } + + if (Test86MSByte(p[4])) + { + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) + { + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; + } + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); + } + else + { + mask = (mask >> 1) | 4; + pos++; + } + } +} diff --git a/3rdparty/lzma-21.03beta/C/BraIA64.c b/3rdparty/lzma-21.03beta/C/BraIA64.c new file mode 100644 index 0000000..d1dbc62 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/BraIA64.c @@ -0,0 +1,53 @@ +/* BraIA64.c -- Converter for IA-64 code +2017-01-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" +#include "Bra.h" + +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 16) + return 0; + size -= 16; + i = 0; + do + { + unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3; + if (m) + { + m++; + do + { + Byte *p = data + (i + (size_t)m * 5 - 8); + if (((p[3] >> m) & 15) == 5 + && (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0) + { + unsigned raw = GetUi32(p); + unsigned v = raw >> m; + v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3); + + v <<= 4; + if (encoding) + v += ip + (UInt32)i; + else + v -= ip + (UInt32)i; + v >>= 4; + + v &= 0x1FFFFF; + v += 0x700000; + v &= 0x8FFFFF; + raw &= ~((UInt32)0x8FFFFF << m); + raw |= (v << m); + SetUi32(p, raw); + } + } + while (++m <= 4); + } + i += 16; + } + while (i <= size); + return i; +} diff --git a/3rdparty/lzma-21.03beta/C/Compiler.h b/3rdparty/lzma-21.03beta/C/Compiler.h new file mode 100644 index 0000000..a9816fa --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Compiler.h @@ -0,0 +1,43 @@ +/* Compiler.h +2021-01-05 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wunused-private-field" + #endif + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4514) // unreferenced inline function has been removed + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4714) // function marked as __forceinline not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + + #ifdef __clang__ + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma clang diagnostic ignored "-Wmicrosoft-exception-spec" + // #pragma clang diagnostic ignored "-Wreserved-id-macro" + #endif + +#endif + +#define UNUSED_VAR(x) (void)x; +/* #define UNUSED_VAR(x) x=x; */ + +#endif diff --git a/3rdparty/lzma-21.03beta/C/CpuArch.c b/3rdparty/lzma-21.03beta/C/CpuArch.c new file mode 100644 index 0000000..fa9afe3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/CpuArch.c @@ -0,0 +1,478 @@ +/* CpuArch.c -- CPU specific code +2021-07-13 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if !defined(USE_ASM) && _MSC_VER >= 1500 +#include +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag) : + "%eax", "%edx"); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +#ifndef USE_ASM + #ifdef _MSC_VER + #if _MSC_VER >= 1600 + #define MY__cpuidex __cpuidex + #else + +/* + __cpuid (function == 4) requires subfunction number in ECX. + MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction. + __cpuid() in new MSVC clears ECX. + __cpuid() in old MSVC (14.00) doesn't clear ECX + We still can use __cpuid for low (function) values that don't require ECX, + but __cpuid() in old MSVC will be incorrect for some function values: (function == 4). + So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction, + where ECX value is first parameter for FAST_CALL / NO_INLINE function, + So the caller of MY__cpuidex_HACK() sets ECX as subFunction, and + old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value. + + DON'T remove MY_NO_INLINE and MY_FAST_CALL for MY__cpuidex_HACK() !!! +*/ + +static +MY_NO_INLINE +void MY_FAST_CALL MY__cpuidex_HACK(UInt32 subFunction, int *CPUInfo, UInt32 function) +{ + UNUSED_VAR(subFunction); + __cpuid(CPUInfo, function); +} + + #define MY__cpuidex(info, func, func2) MY__cpuidex_HACK(func2, info, func) + #pragma message("======== MY__cpuidex_HACK WAS USED ========") + #endif + #else + #define MY__cpuidex(info, func, func2) __cpuid(info, func) + #pragma message("======== (INCORRECT ?) cpuid WAS USED ========") + #endif +#endif + + + + +void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #else + + __asm__ __volatile__ ( + #if defined(MY_CPU_AMD64) && defined(__PIC__) + "mov %%rbx, %%rdi;" + "cpuid;" + "xchg %%rbx, %%rdi;" + : "=a" (*a) , + "=D" (*b) , + #elif defined(MY_CPU_X86) && defined(__PIC__) + "mov %%ebx, %%edi;" + "cpuid;" + "xchgl %%ebx, %%edi;" + : "=a" (*a) , + "=D" (*b) , + #else + "cpuid" + : "=a" (*a) , + "=b" (*b) , + #endif + "=c" (*c) , + "=d" (*d) + : "0" (function), "c"(0) ) ; + + #endif + + #else + + int CPUInfo[4]; + + MY__cpuidex(CPUInfo, (int)function, 0); + + *a = (UInt32)CPUInfo[0]; + *b = (UInt32)CPUInfo[1]; + *c = (UInt32)CPUInfo[2]; + *d = (UInt32)CPUInfo[3]; + + #endif +} + +BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static const UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +BoolInt CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + + family = x86cpuid_GetFamily(p.ver); + model = x86cpuid_GetModel(p.ver); + + firm = x86cpuid_GetFirm(&p); + + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( + /* In-Order Atom CPU */ + model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ + || model == 0x26 /* 45 nm, Z6xx */ + || model == 0x27 /* 32 nm, Z2460 */ + || model == 0x35 /* 32 nm, Z2760 */ + || model == 0x36 /* 32 nm, N2xxx, D2xxx */ + ))); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +#include +static BoolInt CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + + +static UInt32 X86_CPUID_ECX_Get_Flags() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return 0; + return p.c; +} + +BoolInt CPU_IsSupported_AES() +{ + return (X86_CPUID_ECX_Get_Flags() >> 25) & 1; +} + +BoolInt CPU_IsSupported_SSSE3() +{ + return (X86_CPUID_ECX_Get_Flags() >> 9) & 1; +} + +BoolInt CPU_IsSupported_SSE41() +{ + return (X86_CPUID_ECX_Get_Flags() >> 19) & 1; +} + +BoolInt CPU_IsSupported_SHA() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + return (d[1] >> 29) & 1; + } +} + +// #include + +#ifdef _WIN32 +#include +#endif + +BoolInt CPU_IsSupported_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5); // avx2 + } +} + +BoolInt CPU_IsSupported_VAES_AVX2() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + + #ifdef _WIN32 + #define MY__PF_XSAVE_ENABLED 17 + if (!IsProcessorFeaturePresent(MY__PF_XSAVE_ENABLED)) + return False; + #endif + + if (!x86cpuid_CheckAndRead(&p)) + return False; + if (p.maxFunc < 7) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(7, &d[0], &d[1], &d[2], &d[3]); + // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); + return 1 + & (d[1] >> 5) // avx2 + // & (d[1] >> 31) // avx512vl + & (d[2] >> 9); // vaes // VEX-256/EVEX + } +} + +BoolInt CPU_IsSupported_PageGB() +{ + Cx86cpuid cpuid; + if (!x86cpuid_CheckAndRead(&cpuid)) + return False; + { + UInt32 d[4] = { 0 }; + MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]); + if (d[0] < 0x80000001) + return False; + } + { + UInt32 d[4] = { 0 }; + MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]); + return (d[3] >> 26) & 1; + } +} + + +#elif defined(MY_CPU_ARM_OR_ARM64) + +#ifdef _WIN32 + +#include + +BoolInt CPU_IsSupported_CRC32() { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_CRYPTO() { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } +BoolInt CPU_IsSupported_NEON() { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } + +#else + +#if defined(__APPLE__) + +/* +#include +#include +static void Print_sysctlbyname(const char *name) +{ + size_t bufSize = 256; + char buf[256]; + int res = sysctlbyname(name, &buf, &bufSize, NULL, 0); + { + int i; + printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize); + for (i = 0; i < 20; i++) + printf(" %2x", (unsigned)(Byte)buf[i]); + + } +} +*/ + +static BoolInt My_sysctlbyname_Get_BoolInt(const char *name) +{ + UInt32 val = 0; + if (My_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1) + return 1; + return 0; +} + + /* + Print_sysctlbyname("hw.pagesize"); + Print_sysctlbyname("machdep.cpu.brand_string"); + */ + +BoolInt CPU_IsSupported_CRC32(void) +{ + return My_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32"); +} + +BoolInt CPU_IsSupported_NEON(void) +{ + return My_sysctlbyname_Get_BoolInt("hw.optional.neon"); +} + +#ifdef MY_CPU_ARM64 +#define APPLE_CRYPTO_SUPPORT_VAL 1 +#else +#define APPLE_CRYPTO_SUPPORT_VAL 0 +#endif + +BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; } +BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } + + +#else // __APPLE__ + +#include + +#define USE_HWCAP + +#ifdef USE_HWCAP + +#include + + #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ + BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; } + +#ifdef MY_CPU_ARM64 + #define MY_HWCAP_CHECK_FUNC(name) \ + MY_HWCAP_CHECK_FUNC_2(name, name) + MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) +// MY_HWCAP_CHECK_FUNC (ASIMD) +#elif defined(MY_CPU_ARM) + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; } + MY_HWCAP_CHECK_FUNC_2(NEON, NEON) +#endif + +#else // USE_HWCAP + + #define MY_HWCAP_CHECK_FUNC(name) \ + BoolInt CPU_IsSupported_ ## name() { return 0; } + MY_HWCAP_CHECK_FUNC(NEON) + +#endif // USE_HWCAP + +MY_HWCAP_CHECK_FUNC (CRC32) +MY_HWCAP_CHECK_FUNC (SHA1) +MY_HWCAP_CHECK_FUNC (SHA2) +MY_HWCAP_CHECK_FUNC (AES) + +#endif // __APPLE__ +#endif // _WIN32 + +#endif // MY_CPU_ARM_OR_ARM64 + + + +#ifdef __APPLE__ + +#include + +int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize) +{ + return sysctlbyname(name, buf, bufSize, NULL, 0); +} + +int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val) +{ + size_t bufSize = sizeof(*val); + int res = My_sysctlbyname_Get(name, val, &bufSize); + if (res == 0 && bufSize != sizeof(*val)) + return EFAULT; + return res; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/CpuArch.h b/3rdparty/lzma-21.03beta/C/CpuArch.h new file mode 100644 index 0000000..529d3a5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/CpuArch.h @@ -0,0 +1,442 @@ +/* CpuArch.h -- CPU specific code +2021-07-13 : Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +MY_CPU_BE means that CPU is BIG ENDIAN. +If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. + +MY_CPU_64BIT means that processor can work with 64-bit registers. + MY_CPU_64BIT can be used to select fast code branch + MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) +*/ + +#if defined(_M_X64) \ + || defined(_M_AMD64) \ + || defined(__x86_64__) \ + || defined(__AMD64__) \ + || defined(__amd64__) + #define MY_CPU_AMD64 + #ifdef __ILP32__ + #define MY_CPU_NAME "x32" + #define MY_CPU_SIZEOF_POINTER 4 + #else + #define MY_CPU_NAME "x64" + #define MY_CPU_SIZEOF_POINTER 8 + #endif + #define MY_CPU_64BIT +#endif + + +#if defined(_M_IX86) \ + || defined(__i386__) + #define MY_CPU_X86 + #define MY_CPU_NAME "x86" + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 +#endif + + +#if defined(_M_ARM64) \ + || defined(__AARCH64EL__) \ + || defined(__AARCH64EB__) \ + || defined(__aarch64__) + #define MY_CPU_ARM64 + #define MY_CPU_NAME "arm64" + #define MY_CPU_64BIT +#endif + + +#if defined(_M_ARM) \ + || defined(_M_ARM_NT) \ + || defined(_M_ARMT) \ + || defined(__arm__) \ + || defined(__thumb__) \ + || defined(__ARMEL__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEL__) \ + || defined(__THUMBEB__) + #define MY_CPU_ARM + + #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT) + #define MY_CPU_NAME "armt" + #else + #define MY_CPU_NAME "arm" + #endif + /* #define MY_CPU_32BIT */ + #define MY_CPU_SIZEOF_POINTER 4 +#endif + + +#if defined(_M_IA64) \ + || defined(__ia64__) + #define MY_CPU_IA64 + #define MY_CPU_NAME "ia64" + #define MY_CPU_64BIT +#endif + + +#if defined(__mips64) \ + || defined(__mips64__) \ + || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) + #define MY_CPU_NAME "mips64" + #define MY_CPU_64BIT +#elif defined(__mips__) + #define MY_CPU_NAME "mips" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(__ppc64__) \ + || defined(__powerpc64__) \ + || defined(__ppc__) \ + || defined(__powerpc__) \ + || defined(__PPC__) \ + || defined(_POWER) + +#if defined(__ppc64__) \ + || defined(__powerpc64__) \ + || defined(_LP64) \ + || defined(__64BIT__) + #ifdef __ILP32__ + #define MY_CPU_NAME "ppc64-32" + #define MY_CPU_SIZEOF_POINTER 4 + #else + #define MY_CPU_NAME "ppc64" + #define MY_CPU_SIZEOF_POINTER 8 + #endif + #define MY_CPU_64BIT +#else + #define MY_CPU_NAME "ppc" + #define MY_CPU_SIZEOF_POINTER 4 + /* #define MY_CPU_32BIT */ +#endif +#endif + + +#if defined(__sparc64__) + #define MY_CPU_NAME "sparc64" + #define MY_CPU_64BIT +#elif defined(__sparc__) + #define MY_CPU_NAME "sparc" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64) +#define MY_CPU_ARM_OR_ARM64 +#endif + + +#ifdef _WIN32 + + #ifdef MY_CPU_ARM + #define MY_CPU_ARM_LE + #endif + + #ifdef MY_CPU_ARM64 + #define MY_CPU_ARM64_LE + #endif + + #ifdef _M_IA64 + #define MY_CPU_IA64_LE + #endif + +#endif + + +#if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM_LE) \ + || defined(MY_CPU_ARM64_LE) \ + || defined(MY_CPU_IA64_LE) \ + || defined(__LITTLE_ENDIAN__) \ + || defined(__ARMEL__) \ + || defined(__THUMBEL__) \ + || defined(__AARCH64EL__) \ + || defined(__MIPSEL__) \ + || defined(__MIPSEL) \ + || defined(_MIPSEL) \ + || defined(__BFIN__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + #define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEB__) \ + || defined(__AARCH64EB__) \ + || defined(__MIPSEB__) \ + || defined(__MIPSEB) \ + || defined(_MIPSEB) \ + || defined(__m68k__) \ + || defined(__s390__) \ + || defined(__s390x__) \ + || defined(__zarch__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + #define MY_CPU_BE +#endif + + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) + #error Stop_Compiling_Bad_Endian +#endif + + +#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) + #error Stop_Compiling_Bad_32_64_BIT +#endif + +#ifdef __SIZEOF_POINTER__ + #ifdef MY_CPU_SIZEOF_POINTER + #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__ + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE + #endif + #else + #define MY_CPU_SIZEOF_POINTER __SIZEOF_POINTER__ + #endif +#endif + +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +#if defined (_LP64) + #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE +#endif +#endif + +#ifdef _MSC_VER + #if _MSC_VER >= 1300 + #define MY_CPU_pragma_pack_push_1 __pragma(pack(push, 1)) + #define MY_CPU_pragma_pop __pragma(pack(pop)) + #else + #define MY_CPU_pragma_pack_push_1 + #define MY_CPU_pragma_pop + #endif +#else + #ifdef __xlC__ + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(1)") + #define MY_CPU_pragma_pop _Pragma("pack()") + #else + #define MY_CPU_pragma_pack_push_1 _Pragma("pack(push, 1)") + #define MY_CPU_pragma_pop _Pragma("pack(pop)") + #endif +#endif + + +#ifndef MY_CPU_NAME + #ifdef MY_CPU_LE + #define MY_CPU_NAME "LE" + #elif defined(MY_CPU_BE) + #define MY_CPU_NAME "BE" + #else + /* + #define MY_CPU_NAME "" + */ + #endif +#endif + + + + + +#ifdef MY_CPU_LE + #if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM64) + #define MY_CPU_LE_UNALIGN + #define MY_CPU_LE_UNALIGN_64 + #elif defined(__ARM_FEATURE_UNALIGNED) + /* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. + So we can't use unaligned 64-bit operations. */ + #define MY_CPU_LE_UNALIGN + #endif +#endif + + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#ifdef MY_CPU_LE_UNALIGN_64 +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) +#endif + +#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); } +#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); } +#ifdef MY_CPU_LE_UNALIGN_64 +#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); } +#endif + +#else + +#define GetUi16(p) ( (UInt16) ( \ + ((const Byte *)(p))[0] | \ + ((UInt16)((const Byte *)(p))[1] << 8) )) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); } + +#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); \ + _ppp_[2] = (Byte)(_vvv_ >> 16); \ + _ppp_[3] = (Byte)(_vvv_ >> 24); } + +#endif + + +#ifndef MY_CPU_LE_UNALIGN_64 + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ + SetUi32(_ppp2_ , (UInt32)_vvv2_); \ + SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } + +#endif + + + + +#ifdef __has_builtin + #define MY__has_builtin(x) __has_builtin(x) +#else + #define MY__has_builtin(x) 0 +#endif + +#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ defined(_MSC_VER) && (_MSC_VER >= 1300) + +/* Note: we use bswap instruction, that is unsupported in 386 cpu */ + +#include + +#pragma intrinsic(_byteswap_ushort) +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) + +/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ +#define GetBe32(p) _byteswap_ulong (*(const UInt32 *)(const void *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const void *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) + +#elif defined(MY_CPU_LE_UNALIGN) && ( \ + (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ + || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) + +/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const void *)(p)) */ +#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const void *)(p)) +#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const void *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)(_vvv_ >> 24); \ + _ppp_[1] = (Byte)(_vvv_ >> 16); \ + _ppp_[2] = (Byte)(_vvv_ >> 8); \ + _ppp_[3] = (Byte)_vvv_; } + +#endif + + +#ifndef GetBe16 + +#define GetBe16(p) ( (UInt16) ( \ + ((UInt16)((const Byte *)(p))[0] << 8) | \ + ((const Byte *)(p))[1] )) + +#endif + + + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); + +BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) +#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) +#define x86cpuid_GetStepping(ver) (ver & 0xF) + +BoolInt CPU_Is_InOrder(void); + +BoolInt CPU_IsSupported_AES(void); +BoolInt CPU_IsSupported_AVX2(void); +BoolInt CPU_IsSupported_VAES_AVX2(void); +BoolInt CPU_IsSupported_SSSE3(void); +BoolInt CPU_IsSupported_SSE41(void); +BoolInt CPU_IsSupported_SHA(void); +BoolInt CPU_IsSupported_PageGB(void); + +#elif defined(MY_CPU_ARM_OR_ARM64) + +BoolInt CPU_IsSupported_CRC32(void); +BoolInt CPU_IsSupported_NEON(void); + +#if defined(_WIN32) +BoolInt CPU_IsSupported_CRYPTO(void); +#define CPU_IsSupported_SHA1 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_SHA2 CPU_IsSupported_CRYPTO +#define CPU_IsSupported_AES CPU_IsSupported_CRYPTO +#else +BoolInt CPU_IsSupported_SHA1(void); +BoolInt CPU_IsSupported_SHA2(void); +BoolInt CPU_IsSupported_AES(void); +#endif + +#endif + +#if defined(__APPLE__) +int My_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize); +int My_sysctlbyname_Get_UInt32(const char *name, UInt32 *val); +#endif + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Delta.c b/3rdparty/lzma-21.03beta/C/Delta.c new file mode 100644 index 0000000..c4a4499 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Delta.c @@ -0,0 +1,169 @@ +/* Delta.c -- Delta converter +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Delta.h" + +void Delta_Init(Byte *state) +{ + unsigned i; + for (i = 0; i < DELTA_STATE_SIZE; i++) + state[i] = 0; +} + + +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + Byte temp[DELTA_STATE_SIZE]; + + if (size == 0) + return; + + { + unsigned i = 0; + do + temp[i] = state[i]; + while (++i != delta); + } + + if (size <= delta) + { + unsigned i = 0, k; + do + { + Byte b = *data; + *data++ = (Byte)(b - temp[i]); + temp[i] = b; + } + while (++i != size); + + k = 0; + + do + { + if (i == delta) + i = 0; + state[k] = temp[i++]; + } + while (++k != delta); + + return; + } + + { + Byte *p = data + size - delta; + { + unsigned i = 0; + do + state[i] = *p++; + while (++i != delta); + } + { + const Byte *lim = data + delta; + ptrdiff_t dif = -(ptrdiff_t)delta; + + if (((ptrdiff_t)size + dif) & 1) + { + --p; *p = (Byte)(*p - p[dif]); + } + + while (p != lim) + { + --p; *p = (Byte)(*p - p[dif]); + --p; *p = (Byte)(*p - p[dif]); + } + + dif = -dif; + + do + { + --p; *p = (Byte)(*p - temp[--dif]); + } + while (dif != 0); + } + } +} + + +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + unsigned i; + const Byte *lim; + + if (size == 0) + return; + + i = 0; + lim = data + size; + + if (size <= delta) + { + do + *data = (Byte)(*data + state[i++]); + while (++data != lim); + + for (; delta != i; state++, delta--) + *state = state[i]; + data -= i; + } + else + { + /* + #define B(n) b ## n + #define I(n) Byte B(n) = state[n]; + #define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); } + #define F(n) if (data != lim) { U(n) } + + if (delta == 1) + { + I(0) + if ((lim - data) & 1) { U(0) } + while (data != lim) { U(0) U(0) } + data -= 1; + } + else if (delta == 2) + { + I(0) I(1) + lim -= 1; while (data < lim) { U(0) U(1) } + lim += 1; F(0) + data -= 2; + } + else if (delta == 3) + { + I(0) I(1) I(2) + lim -= 2; while (data < lim) { U(0) U(1) U(2) } + lim += 2; F(0) F(1) + data -= 3; + } + else if (delta == 4) + { + I(0) I(1) I(2) I(3) + lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) } + lim += 3; F(0) F(1) F(2) + data -= 4; + } + else + */ + { + do + { + *data = (Byte)(*data + state[i++]); + data++; + } + while (i != delta); + + { + ptrdiff_t dif = -(ptrdiff_t)delta; + do + *data = (Byte)(*data + data[dif]); + while (++data != lim); + data += dif; + } + } + } + + do + *state++ = *data; + while (++data != lim); +} diff --git a/3rdparty/lzma-21.03beta/C/Delta.h b/3rdparty/lzma-21.03beta/C/Delta.h new file mode 100644 index 0000000..2fa54ad --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Delta.h @@ -0,0 +1,19 @@ +/* Delta.h -- Delta converter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __DELTA_H +#define __DELTA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define DELTA_STATE_SIZE 256 + +void Delta_Init(Byte *state); +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/DllSecur.c b/3rdparty/lzma-21.03beta/C/DllSecur.c new file mode 100644 index 0000000..4b2c521 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/DllSecur.c @@ -0,0 +1,108 @@ +/* DllSecur.c -- DLL loading security +2018-02-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 + +#include + +#include "DllSecur.h" + +#ifndef UNDER_CE + +typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); + +#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 +#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32 0x800 + +static const char * const g_Dlls = + #ifndef _CONSOLE + "UXTHEME\0" + #endif + "USERENV\0" + "SETUPAPI\0" + "APPHELP\0" + "PROPSYS\0" + "DWMAPI\0" + "CRYPTBASE\0" + "OLEACC\0" + "CLBCATQ\0" + "VERSION\0" + ; + +#endif + +void My_SetDefaultDllDirectories() +{ + #ifndef UNDER_CE + + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + GetVersionEx(&vi); + if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0) + { + Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); + if (setDllDirs) + if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) + return; + } + + #endif +} + + +void LoadSecurityDlls() +{ + #ifndef UNDER_CE + + wchar_t buf[MAX_PATH + 100]; + + { + // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ??? + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0) + { + Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); + if (setDllDirs) + if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) + return; + } + } + + { + unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2); + if (len == 0 || len > MAX_PATH) + return; + } + { + const char *dll; + unsigned pos = (unsigned)lstrlenW(buf); + + if (buf[pos - 1] != '\\') + buf[pos++] = '\\'; + + for (dll = g_Dlls; dll[0] != 0;) + { + unsigned k = 0; + for (;;) + { + char c = *dll++; + buf[pos + k] = (Byte)c; + k++; + if (c == 0) + break; + } + + lstrcatW(buf, L".dll"); + LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + + #endif +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/DllSecur.h b/3rdparty/lzma-21.03beta/C/DllSecur.h new file mode 100644 index 0000000..64ff26c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/DllSecur.h @@ -0,0 +1,20 @@ +/* DllSecur.h -- DLL loading for security +2018-02-19 : Igor Pavlov : Public domain */ + +#ifndef __DLL_SECUR_H +#define __DLL_SECUR_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#ifdef _WIN32 + +void My_SetDefaultDllDirectories(void); +void LoadSecurityDlls(void); + +#endif + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/LzFind.c b/3rdparty/lzma-21.03beta/C/LzFind.c new file mode 100644 index 0000000..3b32eae --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzFind.c @@ -0,0 +1,1621 @@ +/* LzFind.c -- Match finder for LZ algorithms +2021-07-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +// #include + +#include "CpuArch.h" +#include "LzFind.h" +#include "LzHash.h" + +#define kBlockMoveAlign (1 << 7) // alignment for memmove() +#define kBlockSizeAlign (1 << 16) // alignment for block allocation +#define kBlockSizeReserveMin (1 << 24) // it's 1/256 from 4 GB dictinary + +#define kEmptyHashValue 0 + +#define kMaxValForNormalize ((UInt32)0) +// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xFFF) // for debug + +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#define GET_AVAIL_BYTES(p) \ + Inline_MatchFinder_GetNumAvailableBytes(p) + + +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) +#define kFix5HashSize kFix4HashSize + +/* + HASH2_CALC: + if (hv) match, then cur[0] and cur[1] also match +*/ +#define HASH2_CALC hv = GetUi16(cur); + +// (crc[0 ... 255] & 0xFF) provides one-to-one correspondence to [0 ... 255] + +/* + HASH3_CALC: + if (cur[0]) and (h2) match, then cur[1] also match + if (cur[0]) and (hv) match, then cur[1] and cur[2] also match +*/ +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + hv = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + temp ^= (p->crc[cur[3]] << kLzHash_CrcShift_1); \ + /* h4 = temp & p->hash4Mask; */ /* (kHash4Size - 1); */ \ + hv = (temp ^ (p->crc[cur[4]] << kLzHash_CrcShift_2)) & p->hashMask; } + +#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + if (!p->directInput) + { + ISzAlloc_Free(alloc, p->bufferBase); + p->bufferBase = NULL; + } +} + + +static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr alloc) +{ + if (blockSize == 0) + return 0; + if (!p->bufferBase || p->blockSize != blockSize) + { + // size_t blockSizeT; + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + // blockSizeT = blockSize; + + // printf("\nblockSize = 0x%x\n", blockSize); + /* + #if defined _WIN64 + // we can allocate 4GiB, but still use UInt32 for (p->blockSize) + // we use UInt32 type for (p->blockSize), because + // we don't want to wrap over 4 GiB, + // when we use (p->streamPos - p->pos) that is UInt32. + if (blockSize >= (UInt32)0 - (UInt32)kBlockSizeAlign) + { + blockSizeT = ((size_t)1 << 32); + printf("\nchanged to blockSizeT = 4GiB\n"); + } + #endif + */ + + p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize); + // printf("\nbufferBase = %p\n", p->bufferBase); + // return 0; // for debug + } + return (p->bufferBase != NULL); +} + +static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } + +static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } + + +MY_NO_INLINE +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + + /* We use (p->streamPos - p->pos) value. + (p->streamPos < p->pos) is allowed. */ + + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p); + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } + + for (;;) + { + Byte *dest = p->buffer + GET_AVAIL_BYTES(p); + size_t size = (size_t)(p->bufferBase + p->blockSize - dest); + if (size == 0) + { + /* we call ReadBlock() after NeedMove() and MoveBlock(). + NeedMove() and MoveBlock() povide more than (keepSizeAfter) + to the end of (blockSize). + So we don't execute this branch in normal code flow. + We can go here, if we will call ReadBlock() before NeedMove(), MoveBlock(). + */ + // p->result = SZ_ERROR_FAIL; // we can show error here + return; + } + + // #define kRead 3 + // if (size > kRead) size = kRead; // for debug + + p->result = ISeqInStream_Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (GET_AVAIL_BYTES(p) > p->keepSizeAfter) + return; + /* here and in another (p->keepSizeAfter) checks we keep on 1 byte more than was requested by Create() function + (GET_AVAIL_BYTES(p) >= p->keepSizeAfter) - minimal required size */ + } + + // on exit: (p->result != SZ_OK || p->streamEndWasReached || GET_AVAIL_BYTES(p) > p->keepSizeAfter) +} + + + +MY_NO_INLINE +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + const size_t offset = (size_t)(p->buffer - p->bufferBase) - p->keepSizeBefore; + const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore; + p->buffer = p->bufferBase + keepBefore; + memmove(p->bufferBase, + p->bufferBase + (offset & ~((size_t)kBlockMoveAlign - 1)), + keepBefore + (size_t)GET_AVAIL_BYTES(p)); +} + +/* We call MoveBlock() before ReadBlock(). + So MoveBlock() can be wasteful operation, if the whole input data + can fit in current block even without calling MoveBlock(). + in important case where (dataSize <= historySize) + condition (p->blockSize > dataSize + p->keepSizeAfter) is met + So there is no MoveBlock() in that case case. +*/ + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + if (p->directInput) + return 0; + if (p->streamEndWasReached || p->result != SZ_OK) + return 0; + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->keepSizeAfter >= GET_AVAIL_BYTES(p)) + MatchFinder_ReadBlock(p); +} + + + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + unsigned i; + p->bufferBase = NULL; + p->directInput = 0; + p->hash = NULL; + p->expectedDataSize = (UInt64)(Int64)-1; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = (UInt32)i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hash); + p->hash = NULL; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return NULL; + return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); +} + +#if (kBlockSizeReserveMin < kBlockSizeAlign * 2) + #error Stop_Compiling_Bad_Reserve +#endif + + + +static UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize) +{ + UInt32 blockSize = (p->keepSizeBefore + p->keepSizeAfter); + /* + if (historySize > kMaxHistorySize) + return 0; + */ + // printf("\nhistorySize == 0x%x\n", historySize); + + if (p->keepSizeBefore < historySize || blockSize < p->keepSizeBefore) // if 32-bit overflow + return 0; + + { + const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)kBlockSizeAlign; + const UInt32 rem = kBlockSizeMax - blockSize; + const UInt32 reserve = (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)) + + (1 << 12) + kBlockMoveAlign + kBlockSizeAlign; // do not overflow 32-bit here + if (blockSize >= kBlockSizeMax + || rem < kBlockSizeReserveMin) // we reject settings that will be slow + return 0; + if (reserve >= rem) + blockSize = kBlockSizeMax; + else + { + blockSize += reserve; + blockSize &= ~(UInt32)(kBlockSizeAlign - 1); + } + } + // printf("\n LzFind_blockSize = %x\n", blockSize); + // printf("\n LzFind_blockSize = %d\n", blockSize >> 20); + return blockSize; +} + + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc) +{ + /* we need one additional byte in (p->keepSizeBefore), + since we use MoveBlock() after (p->pos++) and before dictionary using */ + // keepAddBufferBefore = (UInt32)0xFFFFFFFF - (1 << 22); // for debug + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + + keepAddBufferAfter += matchMaxLen; + /* we need (p->keepSizeAfter >= p->numHashBytes) */ + if (keepAddBufferAfter < p->numHashBytes) + keepAddBufferAfter = p->numHashBytes; + // keepAddBufferAfter -= 2; // for debug + p->keepSizeAfter = keepAddBufferAfter; + + if (p->directInput) + p->blockSize = 0; + if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc)) + { + const UInt32 newCyclicBufferSize = historySize + 1; // do not change it + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + // UInt32 hs4; + p->fixedHashSize = 0; + hs = (1 << 16) - 1; + if (p->numHashBytes != 2) + { + hs = historySize; + if (hs > p->expectedDataSize) + hs = (UInt32)p->expectedDataSize; + if (hs != 0) + hs--; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + // we propagated 16 bits in (hs). Low 16 bits must be set later + hs >>= 1; + if (hs >= (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ + } + + // hs = ((UInt32)1 << 25) - 1; // for test + + // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2) + hs |= (1 << 16) - 1; /* don't change it! */ + + // bt5: we adjust the size with recommended minimum size + if (p->numHashBytes >= 5) + hs |= (256 << kLzHash_CrcShift_2) - 1; + } + p->hashMask = hs; + hs++; + + /* + hs4 = (1 << 20); + if (hs4 > hs) + hs4 = hs; + // hs4 = (1 << 16); // for test + p->hash4Mask = hs4 - 1; + */ + + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size; + hs += p->fixedHashSize; + } + + { + size_t newSize; + size_t numSons; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1) + + numSons = newCyclicBufferSize; + if (p->btMode) + numSons <<= 1; + newSize = hs + numSons; + + // aligned size is not required here, but it can be better for some loops + #define NUM_REFS_ALIGN_MASK 0xF + newSize = (newSize + NUM_REFS_ALIGN_MASK) & ~(size_t)NUM_REFS_ALIGN_MASK; + + if (p->hash && p->numRefs == newSize) + return 1; + + MatchFinder_FreeThisClassMemory(p, alloc); + p->numRefs = newSize; + p->hash = AllocRefs(newSize, alloc); + + if (p->hash) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + + MatchFinder_Free(p, alloc); + return 0; +} + + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 k; + UInt32 n = kMaxValForNormalize - p->pos; + if (n == 0) + n = (UInt32)(Int32)-1; // we allow (pos == 0) at start even with (kMaxValForNormalize == 0) + + k = p->cyclicBufferSize - p->cyclicBufferPos; + if (k < n) + n = k; + + k = GET_AVAIL_BYTES(p); + { + const UInt32 ksa = p->keepSizeAfter; + UInt32 mm = p->matchMaxLen; + if (k > ksa) + k -= ksa; // we must limit exactly to keepSizeAfter for ReadBlock + else if (k >= mm) + { + // the limitation for (p->lenLimit) update + k -= mm; // optimization : to reduce the number of checks + k++; + // k = 1; // non-optimized version : for debug + } + else + { + mm = k; + if (k != 0) + k = 1; + } + p->lenLimit = mm; + } + if (k < n) + n = k; + + p->posLimit = p->pos + n; +} + + +void MatchFinder_Init_LowHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash; + const size_t numItems = p->fixedHashSize; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_HighHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash + p->fixedHashSize; + const size_t numItems = (size_t)p->hashMask + 1; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_4(CMatchFinder *p) +{ + p->buffer = p->bufferBase; + { + /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker. + the code in CMatchFinderMt expects (pos = 1) */ + p->pos = + p->streamPos = + 1; // it's smallest optimal value. do not change it + // 0; // for debug + } + p->result = SZ_OK; + p->streamEndWasReached = 0; +} + + +// (CYC_TO_POS_OFFSET == 0) is expected by some optimized code +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug + +void MatchFinder_Init(CMatchFinder *p) +{ + MatchFinder_Init_HighHash(p); + MatchFinder_Init_LowHash(p); + MatchFinder_Init_4(p); + // if (readData) + MatchFinder_ReadBlock(p); + + /* if we init (cyclicBufferPos = pos), then we can use one variable + instead of both (cyclicBufferPos) and (pos) : only before (cyclicBufferPos) wrapping */ + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); // init with relation to (pos) + // p->cyclicBufferPos = 0; // smallest value + // p->son[0] = p->son[1] = 0; // unused: we can init skipped record for speculated accesses. + MatchFinder_SetLimits(p); +} + + + +#ifdef MY_CPU_X86_OR_AMD64 + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) \ + || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) + #define USE_SATUR_SUB_128 + #define USE_AVX2 + #define ATTRIB_SSE41 __attribute__((__target__("sse4.1"))) + #define ATTRIB_AVX2 __attribute__((__target__("avx2"))) + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1600) + #define USE_SATUR_SUB_128 + #if (_MSC_VER >= 1900) + #define USE_AVX2 + #include // avx + #endif + #endif + #endif + +// #elif defined(MY_CPU_ARM_OR_ARM64) +#elif defined(MY_CPU_ARM64) + + #if defined(__clang__) && (__clang_major__ >= 8) \ + || defined(__GNUC__) && (__GNUC__ >= 8) + #define USE_SATUR_SUB_128 + #ifdef MY_CPU_ARM64 + // #define ATTRIB_SSE41 __attribute__((__target__(""))) + #else + // #define ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif + + #elif defined(_MSC_VER) + #if (_MSC_VER >= 1910) + #define USE_SATUR_SUB_128 + #endif + #endif + + #if defined(_MSC_VER) && defined(MY_CPU_ARM64) + #include + #else + #include + #endif + +#endif + +/* +#ifndef ATTRIB_SSE41 + #define ATTRIB_SSE41 +#endif +#ifndef ATTRIB_AVX2 + #define ATTRIB_AVX2 +#endif +*/ + +#ifdef USE_SATUR_SUB_128 + +// #define _SHOW_HW_STATUS + +#ifdef _SHOW_HW_STATUS +#include +#define _PRF(x) x +_PRF(;) +#else +#define _PRF(x) +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +#ifdef MY_CPU_ARM64 +// #define FORCE_SATUR_SUB_128 +#endif + +typedef uint32x4_t v128; +#define SASUB_128(i) \ + *(v128 *)(void *)(items + (i) * 4) = \ + vsubq_u32(vmaxq_u32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); + +#else + +#include // sse4.1 + +typedef __m128i v128; +#define SASUB_128(i) \ + *(v128 *)(void *)(items + (i) * 4) = \ + _mm_sub_epi32(_mm_max_epu32(*(const v128 *)(const void *)(items + (i) * 4), sub2), sub2); // SSE 4.1 + +#endif + + + +MY_NO_INLINE +static +#ifdef ATTRIB_SSE41 +ATTRIB_SSE41 +#endif +void LzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + v128 sub2 = + #ifdef MY_CPU_ARM_OR_ARM64 + vdupq_n_u32(subValue); + #else + _mm_set_epi32((Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + #endif + do + { + SASUB_128(0) + SASUB_128(1) + SASUB_128(2) + SASUB_128(3) + items += 4 * 4; + } + while (items != lim); +} + + + +#ifdef USE_AVX2 + +#include // avx + +#define SASUB_256(i) *(__m256i *)(void *)(items + (i) * 8) = _mm256_sub_epi32(_mm256_max_epu32(*(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2); // AVX2 + +MY_NO_INLINE +static +#ifdef ATTRIB_AVX2 +ATTRIB_AVX2 +#endif +void LzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + __m256i sub2 = _mm256_set_epi32( + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue, + (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue); + do + { + SASUB_256(0) + SASUB_256(1) + items += 2 * 8; + } + while (items != lim); +} +#endif // USE_AVX2 + +#ifndef FORCE_SATUR_SUB_128 +typedef void (MY_FAST_CALL *LZFIND_SATUR_SUB_CODE_FUNC)( + UInt32 subValue, CLzRef *items, const CLzRef *lim); +static LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub; +#endif // FORCE_SATUR_SUB_128 + +#endif // USE_SATUR_SUB_128 + + +// kEmptyHashValue must be zero +// #define SASUB_32(i) v = items[i]; m = v - subValue; if (v < subValue) m = kEmptyHashValue; items[i] = m; +#define SASUB_32(i) v = items[i]; if (v < subValue) v = subValue; items[i] = v - subValue; + +#ifdef FORCE_SATUR_SUB_128 + +#define DEFAULT_SaturSub LzFind_SaturSub_128 + +#else + +#define DEFAULT_SaturSub LzFind_SaturSub_32 + +MY_NO_INLINE +static void LzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim) +{ + do + { + UInt32 v; + SASUB_32(0) + SASUB_32(1) + SASUB_32(2) + SASUB_32(3) + SASUB_32(4) + SASUB_32(5) + SASUB_32(6) + SASUB_32(7) + items += 8; + } + while (items != lim); +} + +#endif + + +MY_NO_INLINE +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) +{ + #define K_NORM_ALIGN_BLOCK_SIZE (1 << 6) + + CLzRef *lim; + + for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (K_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--) + { + UInt32 v; + SASUB_32(0); + items++; + } + + { + #define K_NORM_ALIGN_MASK (K_NORM_ALIGN_BLOCK_SIZE / 4 - 1) + lim = items + (numItems & ~(size_t)K_NORM_ALIGN_MASK); + numItems &= K_NORM_ALIGN_MASK; + if (items != lim) + { + #if defined(USE_SATUR_SUB_128) && !defined(FORCE_SATUR_SUB_128) + if (g_LzFind_SaturSub) + g_LzFind_SaturSub(subValue, items, lim); + else + #endif + DEFAULT_SaturSub(subValue, items, lim); + } + items = lim; + } + + + for (; numItems != 0; numItems--) + { + UInt32 v; + SASUB_32(0); + items++; + } +} + + + +// call MatchFinder_CheckLimits() only after (p->pos++) update + +MY_NO_INLINE +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (// !p->streamEndWasReached && p->result == SZ_OK && + p->keepSizeAfter == GET_AVAIL_BYTES(p)) + { + // we try to read only in exact state (p->keepSizeAfter == GET_AVAIL_BYTES(p)) + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); + } + + if (p->pos == kMaxValForNormalize) + if (GET_AVAIL_BYTES(p) >= p->numHashBytes) // optional optimization for last bytes of data. + /* + if we disable normalization for last bytes of data, and + if (data_size == 4 GiB), we don't call wastfull normalization, + but (pos) will be wrapped over Zero (0) in that case. + And we cannot resume later to normal operation + */ + { + // MatchFinder_Normalize(p); + /* after normalization we need (p->pos >= p->historySize + 1); */ + /* we can reduce subValue to aligned value, if want to keep alignment + of (p->pos) and (p->buffer) for speculated accesses. */ + const UInt32 subValue = (p->pos - p->historySize - 1) /* & ~(UInt32)(kNormalizeAlign - 1) */; + // const UInt32 subValue = (1 << 15); // for debug + // printf("\nMatchFinder_Normalize() subValue == 0x%x\n", subValue); + size_t numSonRefs = p->cyclicBufferSize; + if (p->btMode) + numSonRefs <<= 1; + Inline_MatchFinder_ReduceOffsets(p, subValue); + MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashSizeSum + numSonRefs); + } + + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + + MatchFinder_SetLimits(p); +} + + +/* + (lenLimit > maxLen) +*/ +MY_FORCE_INLINE +static UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *d, unsigned maxLen) +{ + /* + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return d; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = len; + *d++ = len; + *d++ = delta - 1; + if (len == lenLimit) + return d; + } + } + } + } + */ + + const Byte *lim = cur + lenLimit; + son[_cyclicBufferPos] = curMatch; + + do + { + UInt32 delta; + + if (curMatch == 0) + break; + // if (curMatch2 >= curMatch) return NULL; + delta = pos - curMatch; + if (delta >= _cyclicBufferSize) + break; + { + ptrdiff_t diff; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + diff = (ptrdiff_t)0 - (ptrdiff_t)delta; + if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff]) + { + const Byte *c = cur; + while (*c == c[diff]) + { + if (++c == lim) + { + d[0] = (UInt32)(lim - cur); + d[1] = delta - 1; + return d + 2; + } + } + { + const unsigned len = (unsigned)(c - cur); + if (maxLen < len) + { + maxLen = len; + d[0] = (UInt32)len; + d[1] = delta - 1; + d += 2; + } + } + } + } + } + while (--cutValue); + + return d; +} + + +MY_FORCE_INLINE +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *d, UInt32 maxLen) +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + unsigned len0 = 0, len1 = 0; + + UInt32 cmCheck; + + // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (cmCheck < curMatch) + do + { + const UInt32 delta = pos - curMatch; + { + CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + unsigned len = (len0 < len1 ? len0 : len1); + const UInt32 pair0 = pair[0]; + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = (UInt32)len; + *d++ = (UInt32)len; + *d++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair0; + *ptr0 = pair[1]; + return d; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + // const UInt32 curMatch2 = pair[1]; + // if (curMatch2 >= curMatch) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; } + // curMatch = curMatch2; + curMatch = pair[1]; + ptr1 = pair + 1; + len1 = len; + } + else + { + *ptr0 = curMatch; + curMatch = pair[0]; + ptr0 = pair; + len0 = len; + } + } + } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return d; +} + + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + unsigned len0 = 0, len1 = 0; + + UInt32 cmCheck; + + cmCheck = (UInt32)(pos - _cyclicBufferSize); + if ((UInt32)pos <= _cyclicBufferSize) + cmCheck = 0; + + if (// curMatch >= pos || // failure + cmCheck < curMatch) + do + { + const UInt32 delta = pos - curMatch; + { + CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + unsigned len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + curMatch = pair[1]; + ptr1 = pair + 1; + len1 = len; + } + else + { + *ptr0 = curMatch; + curMatch = pair[0]; + ptr0 = pair; + len0 = len; + } + } + } + while(--cutValue && cmCheck < curMatch); + + *ptr0 = *ptr1 = kEmptyHashValue; + return; +} + + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + { const UInt32 pos1 = p->pos + 1; p->pos = pos1; if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } + +#define MOVE_POS_RET MOVE_POS return distances; + +MY_NO_INLINE +static void MatchFinder_MovePos(CMatchFinder *p) +{ + /* we go here at the end of stream data, when (avail < num_hash_bytes) + We don't update sons[cyclicBufferPos << btMode]. + So (sons) record will contain junk. And we cannot resume match searching + to normal operation, even if we will provide more input data in buffer. + p->sons[p->cyclicBufferPos << p->btMode] = 0; // kEmptyHashValue + if (p->btMode) + p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0; // kEmptyHashValue + */ + MOVE_POS; +} + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + unsigned lenLimit; UInt32 hv; Byte *cur; UInt32 curMatch; \ + lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) +#define SKIP_HEADER(minLen) do { GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS; } while (--num); + +#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ + distances = func(MF_PARAMS(p), \ + distances, (UInt32)_maxLen_); MOVE_POS_RET; + +#define GET_MATCHES_FOOTER_BT(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) + +#define GET_MATCHES_FOOTER_HC(_maxLen_) \ + GET_MATCHES_FOOTER_BASE(_maxLen_, Hc_GetMatchesSpec) + + + +#define UPDATE_maxLen { \ + const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)d2; \ + const Byte *c = cur + maxLen; \ + const Byte *lim = cur + lenLimit; \ + for (; c != lim; c++) if (*(c + diff) != *c) break; \ + maxLen = (unsigned)(c - cur); } + +static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + GET_MATCHES_FOOTER_BT(1) +} + +UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + GET_MATCHES_FOOTER_BT(2) +} + + +#define SET_mmm \ + mmm = p->cyclicBufferSize; \ + if (pos < mmm) \ + mmm = pos; + + +static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 mmm; + UInt32 h2, d2, pos; + unsigned maxLen; + UInt32 *hash; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[h2]; + + curMatch = (hash + kFix3HashSize)[hv]; + + hash[h2] = pos; + (hash + kFix3HashSize)[hv] = pos; + + SET_mmm + + maxLen = 2; + + if (d2 < mmm && *(cur - d2) == *cur) + { + UPDATE_maxLen + distances[0] = (UInt32)maxLen; + distances[1] = d2 - 1; + distances += 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + GET_MATCHES_FOOTER_BT(maxLen) +} + + +static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 mmm; + UInt32 h2, h3, d2, d3, pos; + unsigned maxLen; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + curMatch = (hash + kFix4HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + SET_mmm + + maxLen = 3; + + for (;;) + { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + + UPDATE_maxLen + distances[-2] = (UInt32)maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(MF_PARAMS(p)); + MOVE_POS_RET + } + break; + } + + GET_MATCHES_FOOTER_BT(maxLen) +} + + +static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + // d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + // (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + SET_mmm + + maxLen = 4; + + for (;;) + { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; + UPDATE_maxLen + distances[-2] = (UInt32)maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(MF_PARAMS(p)); + MOVE_POS_RET; + } + break; + } + + GET_MATCHES_FOOTER_BT(maxLen) +} + + +static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 mmm; + UInt32 h2, h3, d2, d3, pos; + unsigned maxLen; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + curMatch = (hash + kFix4HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + SET_mmm + + maxLen = 3; + + for (;;) + { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + // distances[-2] = 3; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + d2 = d3; + distances[1] = d3 - 1; + distances += 2; + } + else + break; + + UPDATE_maxLen + distances[-2] = (UInt32)maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + break; + } + + GET_MATCHES_FOOTER_HC(maxLen); +} + + +static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 mmm; + UInt32 h2, h3, d2, d3, maxLen, pos; + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + // d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + // (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + SET_mmm + + maxLen = 4; + + for (;;) + { + if (d2 < mmm && *(cur - d2) == *cur) + { + distances[0] = 2; + distances[1] = d2 - 1; + distances += 2; + if (*(cur - d2 + 2) == cur[2]) + { + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + } + else if (d3 < mmm && *(cur - d3) == *cur) + { + distances[1] = d3 - 1; + distances += 2; + d2 = d3; + } + else + break; + + distances[-2] = 3; + if (*(cur - d2 + 3) != cur[3]) + break; + UPDATE_maxLen + distances[-2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + break; + } + + GET_MATCHES_FOOTER_HC(maxLen); +} + + +UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + GET_MATCHES_FOOTER_HC(2) +} + + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + SKIP_HEADER(2) + { + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + } + SKIP_FOOTER +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + SKIP_HEADER(3) + { + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + } + SKIP_FOOTER +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + SKIP_HEADER(3) + { + UInt32 h2; + UInt32 *hash; + HASH3_CALC; + hash = p->hash; + curMatch = (hash + kFix3HashSize)[hv]; + hash[h2] = + (hash + kFix3HashSize)[hv] = p->pos; + } + SKIP_FOOTER +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + SKIP_HEADER(4) + { + UInt32 h2, h3; + UInt32 *hash; + HASH4_CALC; + hash = p->hash; + curMatch = (hash + kFix4HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = p->pos; + } + SKIP_FOOTER +} + +static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + SKIP_HEADER(5) + { + UInt32 h2, h3; + UInt32 *hash; + HASH5_CALC; + hash = p->hash; + curMatch = (hash + kFix5HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + // (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = p->pos; + } + SKIP_FOOTER +} + + +#define HC_SKIP_HEADER(minLen) \ + do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \ + Byte *cur; \ + UInt32 *hash; \ + UInt32 *son; \ + UInt32 pos = p->pos; \ + UInt32 num2 = num; \ + /* (p->pos == p->posLimit) is not allowed here !!! */ \ + { const UInt32 rem = p->posLimit - pos; if (num2 > rem) num2 = rem; } \ + num -= num2; \ + { const UInt32 cycPos = p->cyclicBufferPos; \ + son = p->son + cycPos; \ + p->cyclicBufferPos = cycPos + num2; } \ + cur = p->buffer; \ + hash = p->hash; \ + do { \ + UInt32 curMatch; \ + UInt32 hv; + + +#define HC_SKIP_FOOTER \ + cur++; pos++; *son++ = curMatch; \ + } while (--num2); \ + p->buffer = cur; \ + p->pos = pos; \ + if (pos == p->posLimit) MatchFinder_CheckLimits(p); \ + }} while(num); \ + + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + HC_SKIP_HEADER(4) + + UInt32 h2, h3; + HASH4_CALC; + curMatch = (hash + kFix4HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = pos; + + HC_SKIP_FOOTER +} + + +static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + HC_SKIP_HEADER(5) + + UInt32 h2, h3; + HASH5_CALC + curMatch = (hash + kFix5HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + // (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = pos; + + HC_SKIP_FOOTER +} + + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + HC_SKIP_HEADER(3) + + HASH_ZIP_CALC; + curMatch = hash[hv]; + hash[hv] = pos; + + HC_SKIP_FOOTER +} + + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + if (p->numHashBytes <= 4) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; + } + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else if (p->numHashBytes == 4) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; + } +} + + + +void LzFindPrepare() +{ + #ifndef FORCE_SATUR_SUB_128 + #ifdef USE_SATUR_SUB_128 + LZFIND_SATUR_SUB_CODE_FUNC f = NULL; + #ifdef MY_CPU_ARM_OR_ARM64 + { + if (CPU_IsSupported_NEON()) + { + #pragma message ("=== LzFind NEON") + _PRF(printf("\n=== LzFind NEON\n")); + f = LzFind_SaturSub_128; + } + // f = 0; // for debug + } + #else // MY_CPU_ARM_OR_ARM64 + if (CPU_IsSupported_SSE41()) + { + #pragma message ("=== LzFind SSE41") + _PRF(printf("\n=== LzFind SSE41\n")); + f = LzFind_SaturSub_128; + + #ifdef USE_AVX2 + if (CPU_IsSupported_AVX2()) + { + #pragma message ("=== LzFind AVX2") + _PRF(printf("\n=== LzFind AVX2\n")); + f = LzFind_SaturSub_256; + } + #endif + } + #endif // MY_CPU_ARM_OR_ARM64 + g_LzFind_SaturSub = f; + #endif // USE_SATUR_SUB_128 + #endif // FORCE_SATUR_SUB_128 +} diff --git a/3rdparty/lzma-21.03beta/C/LzFind.h b/3rdparty/lzma-21.03beta/C/LzFind.h new file mode 100644 index 0000000..eea873f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzFind.h @@ -0,0 +1,136 @@ +/* LzFind.h -- Match finder for LZ algorithms +2021-07-13 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_H +#define __LZ_FIND_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */ + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + Byte streamEndWasReached; + Byte btMode; + Byte bigHash; + Byte directInput; + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + size_t directInputRem; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + SRes result; + UInt32 crc[256]; + size_t numRefs; + + UInt64 expectedDataSize; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((p)->streamPos - (p)->pos)) + +/* +#define Inline_MatchFinder_IsFinishedOK(p) \ + ((p)->streamEndWasReached \ + && (p)->streamPos == (p)->pos \ + && (!(p)->directInput || (p)->directInputRem == 0)) +*/ + +int MatchFinder_NeedMove(CMatchFinder *p); +/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */ +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); +// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +/* +#define Inline_MatchFinder_InitPos(p, val) \ + (p)->pos = (val); \ + (p)->streamPos = (val); +*/ + +#define Inline_MatchFinder_ReduceOffsets(p, subValue) \ + (p)->pos -= (subValue); \ + (p)->streamPos -= (subValue); + + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder2; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable); + +void MatchFinder_Init_LowHash(CMatchFinder *p); +void MatchFinder_Init_HighHash(CMatchFinder *p); +void MatchFinder_Init_4(CMatchFinder *p); +void MatchFinder_Init(CMatchFinder *p); + +UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +void LzFindPrepare(void); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/LzFindMt.c b/3rdparty/lzma-21.03beta/C/LzFindMt.c new file mode 100644 index 0000000..da339eb --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzFindMt.c @@ -0,0 +1,1400 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2021-07-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #include + +#include "CpuArch.h" + +#include "LzHash.h" +#include "LzFindMt.h" + +// #define LOG_ITERS + +// #define LOG_THREAD + +#ifdef LOG_THREAD +#include +#define PRF(x) x +#else +#define PRF(x) +#endif + +#ifdef LOG_ITERS +#include +extern UInt64 g_NumIters_Tree; +extern UInt64 g_NumIters_Loop; +extern UInt64 g_NumIters_Bytes; +#define LOG_ITER(x) x +#else +#define LOG_ITER(x) +#endif + +#define kMtHashBlockSize ((UInt32)1 << 17) +#define kMtHashNumBlocks (1 << 1) + +#define GET_HASH_BLOCK_OFFSET(i) (((i) & (kMtHashNumBlocks - 1)) * kMtHashBlockSize) + +#define kMtBtBlockSize ((UInt32)1 << 16) +#define kMtBtNumBlocks (1 << 4) + +#define GET_BT_BLOCK_OFFSET(i) (((i) & (kMtBtNumBlocks - 1)) * (size_t)kMtBtBlockSize) + +/* + HASH functions: + We use raw 8/16 bits from a[1] and a[2], + xored with crc(a[0]) and crc(a[3]). + We check a[0], a[3] only. We don't need to compare a[1] and a[2] in matches. + our crc() function provides one-to-one correspondence for low 8-bit values: + (crc[0...0xFF] & 0xFF) <-> [0...0xFF] +*/ + +#define MF(mt) ((mt)->MatchFinder) +#define MF_CRC (p->crc) + +// #define MF(mt) (&(mt)->MatchFinder) +// #define MF_CRC (p->MatchFinder.crc) + +#define MT_HASH2_CALC \ + h2 = (MF_CRC[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = MF_CRC[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +/* +#define MT_HASH3_CALC__NO_2 { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define __MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + h4 = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hash4Mask; } + // (kHash4Size - 1); +*/ + + +MY_NO_INLINE +static void MtSync_Construct(CMtSync *p) +{ + p->affinity = 0; + p->wasCreated = False; + p->csWasInitialized = False; + p->csWasEntered = False; + Thread_Construct(&p->thread); + Event_Construct(&p->canStart); + Event_Construct(&p->wasStopped); + Semaphore_Construct(&p->freeSemaphore); + Semaphore_Construct(&p->filledSemaphore); +} + + +#define DEBUG_BUFFER_LOCK // define it to debug lock state + +#ifdef DEBUG_BUFFER_LOCK +#include +#define BUFFER_MUST_BE_LOCKED(p) if (!(p)->csWasEntered) exit(1); +#define BUFFER_MUST_BE_UNLOCKED(p) if ( (p)->csWasEntered) exit(1); +#else +#define BUFFER_MUST_BE_LOCKED(p) +#define BUFFER_MUST_BE_UNLOCKED(p) +#endif + +#define LOCK_BUFFER(p) { \ + BUFFER_MUST_BE_UNLOCKED(p); \ + CriticalSection_Enter(&(p)->cs); \ + (p)->csWasEntered = True; } + +#define UNLOCK_BUFFER(p) { \ + BUFFER_MUST_BE_LOCKED(p); \ + CriticalSection_Leave(&(p)->cs); \ + (p)->csWasEntered = False; } + + +MY_NO_INLINE +static UInt32 MtSync_GetNextBlock(CMtSync *p) +{ + UInt32 numBlocks = 0; + if (p->needStart) + { + BUFFER_MUST_BE_UNLOCKED(p) + p->numProcessedBlocks = 1; + p->needStart = False; + p->stopWriting = False; + p->exit = False; + Event_Reset(&p->wasStopped); + Event_Set(&p->canStart); + } + else + { + UNLOCK_BUFFER(p) + // we free current block + numBlocks = p->numProcessedBlocks++; + Semaphore_Release1(&p->freeSemaphore); + } + + // buffer is UNLOCKED here + Semaphore_Wait(&p->filledSemaphore); + LOCK_BUFFER(p); + return numBlocks; +} + + +/* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */ + +MY_NO_INLINE +static void MtSync_StopWriting(CMtSync *p) +{ + if (!Thread_WasCreated(&p->thread) || p->needStart) + return; + + PRF(printf("\nMtSync_StopWriting %p\n", p)); + + if (p->csWasEntered) + { + /* we don't use buffer in this thread after StopWriting(). + So we UNLOCK buffer. + And we restore default UNLOCKED state for stopped thread */ + UNLOCK_BUFFER(p) + } + + /* We send (p->stopWriting) message and release freeSemaphore + to free current block. + So the thread will see (p->stopWriting) at some + iteration after Wait(freeSemaphore). + The thread doesn't need to fill all avail free blocks, + so we can get fast thread stop. + */ + + p->stopWriting = True; + Semaphore_Release1(&p->freeSemaphore); // check semaphore count !!! + + PRF(printf("\nMtSync_StopWriting %p : Event_Wait(&p->wasStopped)\n", p)); + Event_Wait(&p->wasStopped); + PRF(printf("\nMtSync_StopWriting %p : Event_Wait() finsihed\n", p)); + + /* 21.03 : we don't restore samaphore counters here. + We will recreate and reinit samaphores in next start */ + + p->needStart = True; +} + + +MY_NO_INLINE +static void MtSync_Destruct(CMtSync *p) +{ + PRF(printf("\nMtSync_Destruct %p\n", p)); + + if (Thread_WasCreated(&p->thread)) + { + /* we want thread to be in Stopped state before sending EXIT command. + note: stop(btSync) will stop (htSync) also */ + MtSync_StopWriting(p); + /* thread in Stopped state here : (p->needStart == true) */ + p->exit = True; + // if (p->needStart) // it's (true) + Event_Set(&p->canStart); // we send EXIT command to thread + Thread_Wait_Close(&p->thread); // we wait thread finishing + } + + if (p->csWasInitialized) + { + CriticalSection_Delete(&p->cs); + p->csWasInitialized = False; + } + p->csWasEntered = False; + + Event_Close(&p->canStart); + Event_Close(&p->wasStopped); + Semaphore_Close(&p->freeSemaphore); + Semaphore_Close(&p->filledSemaphore); + + p->wasCreated = False; +} + + +// #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } +// we want to get real system error codes here instead of SZ_ERROR_THREAD +#define RINOK_THREAD(x) RINOK(x) + + +// call it before each new file (when new starting is required): +MY_NO_INLINE +static SRes MtSync_Init(CMtSync *p, UInt32 numBlocks) +{ + WRes wres; + // BUFFER_MUST_BE_UNLOCKED(p) + if (!p->needStart || p->csWasEntered) + return SZ_ERROR_FAIL; + wres = Semaphore_OptCreateInit(&p->freeSemaphore, numBlocks, numBlocks); + if (wres == 0) + wres = Semaphore_OptCreateInit(&p->filledSemaphore, 0, numBlocks); + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) +{ + WRes wres; + + if (p->wasCreated) + return SZ_OK; + + RINOK_THREAD(CriticalSection_Init(&p->cs)); + p->csWasInitialized = True; + p->csWasEntered = False; + + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + + p->needStart = True; + p->exit = True; /* p->exit is unused before (canStart) Event. + But in case of some unexpected code failure we will get fast exit from thread */ + + // return ERROR_TOO_MANY_POSTS; // for debug + // return EINVAL; // for debug + + if (p->affinity != 0) + wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity); + else + wres = Thread_Create(&p->thread, startAddress, obj); + + RINOK_THREAD(wres); + p->wasCreated = True; + return SZ_OK; +} + + +MY_NO_INLINE +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj) +{ + const WRes wres = MtSync_Create_WRes(p, startAddress, obj); + if (wres == 0) + return 0; + MtSync_Destruct(p); + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +// ---------- HASH THREAD ---------- + +#define kMtMaxValForNormalize 0xFFFFFFFF +// #define kMtMaxValForNormalize ((1 << 21)) // for debug +// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses + +#ifdef MY_CPU_LE_UNALIGN + #define GetUi24hi_from32(p) ((UInt32)GetUi32(p) >> 8) +#else + #define GetUi24hi_from32(p) ((p)[1] ^ ((UInt32)(p)[2] << 8) ^ ((UInt32)(p)[3] << 16)) +#endif + +#define GetHeads_DECL(name) \ + static void GetHeads ## name(const Byte *p, UInt32 pos, \ + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) + +#define GetHeads_LOOP(v) \ + for (; numHeads != 0; numHeads--) { \ + const UInt32 value = (v); \ + p++; \ + *heads++ = pos - hash[value]; \ + hash[value] = pos++; } + +#define DEF_GetHeads2(name, v, action) \ + GetHeads_DECL(name) { action \ + GetHeads_LOOP(v) } + +#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) + +DEF_GetHeads2(2, GetUi16(p), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +DEF_GetHeads(3, (crc[p[0]] ^ GetUi16(p + 1)) & hashMask) +DEF_GetHeads2(3b, GetUi16(p) ^ ((UInt32)(p)[2] << 16), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +// BT3 is not good for crc collisions for big hashMask values. + +/* +GetHeads_DECL(3b) +{ + UNUSED_VAR(hashMask); + UNUSED_VAR(crc); + { + const Byte *pLim = p + numHeads; + if (numHeads == 0) + return; + pLim--; + while (p < pLim) + { + UInt32 v1 = GetUi32(p); + UInt32 v0 = v1 & 0xFFFFFF; + UInt32 h0, h1; + p += 2; + v1 >>= 8; + h0 = hash[v0]; hash[v0] = pos; heads[0] = pos - h0; pos++; + h1 = hash[v1]; hash[v1] = pos; heads[1] = pos - h1; pos++; + heads += 2; + } + if (p == pLim) + { + UInt32 v0 = GetUi16(p) ^ ((UInt32)(p)[2] << 16); + *heads = pos - hash[v0]; + hash[v0] = pos; + } + } +} +*/ + +/* +GetHeads_DECL(4) +{ + unsigned sh = 0; + UNUSED_VAR(crc) + while ((hashMask & 0x80000000) == 0) + { + hashMask <<= 1; + sh++; + } + GetHeads_LOOP((GetUi32(p) * 0xa54a1) >> sh) +} +#define GetHeads4b GetHeads4 +*/ + +#define USE_GetHeads_LOCAL_CRC + +#ifdef USE_GetHeads_LOCAL_CRC + +GetHeads_DECL(4) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + // crc1[i] = rotlFixed(v, 8) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(4b) +{ + UInt32 crc0[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + crc0[i] = crc[i] & hashMask; + } + GetHeads_LOOP(crc0[p[0]] ^ GetUi24hi_from32(p)) +} + +GetHeads_DECL(5) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + UInt32 crc2[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + crc2[i] = (v << kLzHash_CrcShift_2) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ crc2[p[4]] ^ (UInt32)GetUi16(p+1)) +} + +GetHeads_DECL(5b) +{ + UInt32 crc0[256]; + UInt32 crc1[256]; + { + unsigned i; + for (i = 0; i < 256; i++) + { + UInt32 v = crc[i]; + crc0[i] = v & hashMask; + crc1[i] = (v << kLzHash_CrcShift_1) & hashMask; + } + } + GetHeads_LOOP(crc0[p[0]] ^ crc1[p[4]] ^ GetUi24hi_from32(p)) +} + +#else + +DEF_GetHeads(4, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (UInt32)GetUi16(p+1)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ GetUi24hi_from32(p)) & hashMask) +DEF_GetHeads(5, (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (crc[p[4]] << kLzHash_CrcShift_2) ^ (UInt32)GetUi16(p + 1)) & hashMask) +DEF_GetHeads(5b, (crc[p[0]] ^ (crc[p[4]] << kLzHash_CrcShift_1) ^ GetUi24hi_from32(p)) & hashMask) + +#endif + + +static void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + PRF(printf("\nHashThreadFunc\n")); + + for (;;) + { + UInt32 blockIndex = 0; + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart)\n")); + Event_Wait(&p->canStart); + PRF(printf("\nHashThreadFunc : Event_Wait(&p->canStart) : after \n")); + if (p->exit) + { + PRF(printf("\nHashThreadFunc : exit \n")); + return; + } + + MatchFinder_Init_HighHash(MF(mt)); + + for (;;) + { + PRF(printf("Hash thread block = %d pos = %d\n", (unsigned)blockIndex, mt->MatchFinder->pos)); + + { + CMatchFinder *mf = MF(mt); + if (MatchFinder_NeedMove(mf)) + { + CriticalSection_Enter(&mt->btSync.cs); + CriticalSection_Enter(&mt->hashSync.cs); + { + const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf); + ptrdiff_t offset; + MatchFinder_MoveBlock(mf); + offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= offset; + mt->buffer -= offset; + } + CriticalSection_Leave(&mt->hashSync.cs); + CriticalSection_Leave(&mt->btSync.cs); + continue; + } + + Semaphore_Wait(&p->freeSemaphore); + + if (p->exit) // exit is unexpected here. But we check it here for some failure case + return; + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + + MatchFinder_ReadIfRequired(mf); + { + UInt32 *heads = mt->hashBuf + GET_HASH_BLOCK_OFFSET(blockIndex++); + UInt32 num = Inline_MatchFinder_GetNumAvailableBytes(mf); + heads[0] = 2; + heads[1] = num; + + /* heads[1] contains the number of avail bytes: + if (avail < mf->numHashBytes) : + { + it means that stream was finished + HASH_THREAD and BT_TREAD must move position for heads[1] (avail) bytes. + HASH_THREAD doesn't stop, + HASH_THREAD fills only the header (2 numbers) for all next blocks: + {2, NumHashBytes - 1}, {2,0}, {2,0}, ... , {2,0} + } + else + { + HASH_THREAD and BT_TREAD must move position for (heads[0] - 2) bytes; + } + */ + + if (num >= mf->numHashBytes) + { + num = num - mf->numHashBytes + 1; + if (num > kMtHashBlockSize - 2) + num = kMtHashBlockSize - 2; + + if (mf->pos > (UInt32)kMtMaxValForNormalize - num) + { + const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + Inline_MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); + } + + heads[0] = 2 + num; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + } + + mf->pos += num; // wrap over zero is allowed at the end of stream + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } // for() processing end + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); + } // for() thread end +} + + + + +// ---------- BT THREAD ---------- + +/* we use one variable instead of two (cyclicBufferPos == pos) before CyclicBuf wrap. + here we define fixed offset of (p->pos) from (p->cyclicBufferPos) */ +#define CYC_TO_POS_OFFSET 0 +// #define CYC_TO_POS_OFFSET 1 // for debug + +#define MFMT_GM_INLINE + +#ifdef MFMT_GM_INLINE + +/* + we use size_t for (pos) instead of UInt32 + to eliminate "movsx" BUG in old MSVC x64 compiler. +*/ + + +UInt32 * MY_FAST_CALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son, + UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, + UInt32 *posRes); + +#endif + + +static void BtGetMatches(CMatchFinderMt *p, UInt32 *d) +{ + UInt32 numProcessed = 0; + UInt32 curPos = 2; + + /* GetMatchesSpec() functions don't create (len = 1) + in [len, dist] match pairs, if (p->numHashBytes >= 2) + Also we suppose here that (matchMaxLen >= 2). + So the following code for (reserve) is not required + UInt32 reserve = (p->matchMaxLen * 2); + const UInt32 kNumHashBytes_Max = 5; // BT_HASH_BYTES_MAX + if (reserve < kNumHashBytes_Max - 1) + reserve = kNumHashBytes_Max - 1; + const UInt32 limit = kMtBtBlockSize - (reserve); + */ + + const UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + + d[1] = p->hashNumAvail; + + if (p->failure_BT) + { + // printf("\n == 1 BtGetMatches() p->failure_BT\n"); + d[0] = 0; + // d[1] = 0; + return; + } + + while (curPos < limit) + { + if (p->hashBufPos == p->hashBufPosLimit) + { + // MatchFinderMt_GetNextBlock_Hash(p); + UInt32 avail; + { + const UInt32 bi = MtSync_GetNextBlock(&p->hashSync); + const UInt32 k = GET_HASH_BLOCK_OFFSET(bi); + const UInt32 *h = p->hashBuf + k; + avail = h[1]; + p->hashBufPosLimit = k + h[0]; + p->hashNumAvail = avail; + p->hashBufPos = k + 2; + } + + { + /* we must prevent UInt32 overflow for avail total value, + if avail was increased with new hash block */ + UInt32 availSum = numProcessed + avail; + if (availSum < numProcessed) + availSum = (UInt32)(Int32)-1; + d[1] = availSum; + } + + if (avail >= p->numHashBytes) + continue; + + // if (p->hashBufPos != p->hashBufPosLimit) exit(1); + + /* (avail < p->numHashBytes) + It means that stream was finished. + And (avail) - is a number of remaining bytes, + we fill (d) for (avail) bytes for LZ_THREAD (receiver). + but we don't update (p->pos) and (p->cyclicBufferPos) here in BT_THREAD */ + + /* here we suppose that we have space enough: + (kMtBtBlockSize - curPos >= p->hashNumAvail) */ + p->hashNumAvail = 0; + d[0] = curPos + avail; + d += curPos; + for (; avail != 0; avail--) + *d++ = 0; + return; + } + { + UInt32 size = p->hashBufPosLimit - p->hashBufPos; + UInt32 pos = p->pos; + UInt32 cyclicBufferPos = p->cyclicBufferPos; + UInt32 lenLimit = p->matchMaxLen; + if (lenLimit >= p->hashNumAvail) + lenLimit = p->hashNumAvail; + { + UInt32 size2 = p->hashNumAvail - lenLimit + 1; + if (size2 < size) + size = size2; + size2 = p->cyclicBufferSize - cyclicBufferPos; + if (size2 < size) + size = size2; + } + + if (pos > (UInt32)kMtMaxValForNormalize - size) + { + const UInt32 subValue = (pos - p->cyclicBufferSize); // & ~(UInt32)(kNormalizeAlign - 1); + pos -= subValue; + p->pos = pos; + MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); + } + + #ifndef MFMT_GM_INLINE + while (curPos < limit && size-- != 0) + { + UInt32 *startDistances = d + curPos; + UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], + pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + startDistances + 1, p->numHashBytes - 1) - startDistances); + *startDistances = num - 1; + curPos += num; + cyclicBufferPos++; + pos++; + p->buffer++; + } + #else + { + UInt32 posRes = pos; + const UInt32 *d_end; + { + d_end = GetMatchesSpecN_2( + p->buffer + lenLimit - 1, + pos, p->buffer, p->son, p->cutValue, d + curPos, + p->numHashBytes - 1, p->hashBuf + p->hashBufPos, + d + limit, p->hashBuf + p->hashBufPos + size, + cyclicBufferPos, p->cyclicBufferSize, + &posRes); + } + { + if (!d_end) + { + // printf("\n == 2 BtGetMatches() p->failure_BT\n"); + // internal data failure + p->failure_BT = True; + d[0] = 0; + // d[1] = 0; + return; + } + } + curPos = (UInt32)(d_end - d); + { + const UInt32 processed = posRes - pos; + pos = posRes; + p->hashBufPos += processed; + cyclicBufferPos += processed; + p->buffer += processed; + } + } + #endif + + { + const UInt32 processed = pos - p->pos; + numProcessed += processed; + p->hashNumAvail -= processed; + p->pos = pos; + } + if (cyclicBufferPos == p->cyclicBufferSize) + cyclicBufferPos = 0; + p->cyclicBufferPos = cyclicBufferPos; + } + } + + d[0] = curPos; +} + + +static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) +{ + CMtSync *sync = &p->hashSync; + + BUFFER_MUST_BE_UNLOCKED(sync) + + if (!sync->needStart) + { + LOCK_BUFFER(sync) + } + + BtGetMatches(p, p->btBuf + GET_BT_BLOCK_OFFSET(globalBlockIndex)); + + /* We suppose that we have called GetNextBlock() from start. + So buffer is LOCKED */ + + UNLOCK_BUFFER(sync) +} + + +MY_NO_INLINE +static void BtThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->btSync; + for (;;) + { + UInt32 blockIndex = 0; + Event_Wait(&p->canStart); + + for (;;) + { + PRF(printf(" BT thread block = %d pos = %d\n", (unsigned)blockIndex, mt->pos)); + /* (p->exit == true) is possible after (p->canStart) at first loop iteration + and is unexpected after more Wait(freeSemaphore) iterations */ + if (p->exit) + return; + + Semaphore_Wait(&p->freeSemaphore); + + // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore) + if (p->stopWriting) + break; + + BtFillBlock(mt, blockIndex++); + + Semaphore_Release1(&p->filledSemaphore); + } + + // we stop HASH_THREAD here + MtSync_StopWriting(&mt->hashSync); + + // p->numBlocks_Sent = blockIndex; + Event_Set(&p->wasStopped); + } +} + + +void MatchFinderMt_Construct(CMatchFinderMt *p) +{ + p->hashBuf = NULL; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hashBuf); + p->hashBuf = NULL; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + /* + HASH_THREAD can use CriticalSection(s) btSync.cs and hashSync.cs. + So we must be sure that HASH_THREAD will not use CriticalSection(s) + after deleting CriticalSection here. + + we call ReleaseStream(p) + that calls StopWriting(btSync) + that calls StopWriting(hashSync), if it's required to stop HASH_THREAD. + after StopWriting() it's safe to destruct MtSync(s) in any order */ + + MatchFinderMt_ReleaseStream(p); + + MtSync_Destruct(&p->btSync); + MtSync_Destruct(&p->hashSync); + + LOG_ITER( + printf("\nTree %9d * %7d iter = %9d = sum : bytes = %9d\n", + (UInt32)(g_NumIters_Tree / 1000), + (UInt32)(((UInt64)g_NumIters_Loop * 1000) / (g_NumIters_Tree + 1)), + (UInt32)(g_NumIters_Loop / 1000), + (UInt32)(g_NumIters_Bytes / 1000) + )); + + MatchFinderMt_FreeMem(p, alloc); +} + + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + unsigned i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)0; + if (allocaDummy[0] == 0) + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) +{ + CMatchFinder *mf = MF(p); + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (!p->hashBuf) + { + p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, ((size_t)kHashBufferSize + (size_t)kBtBufferSize) * sizeof(UInt32)); + if (!p->hashBuf) + return SZ_ERROR_MEM; + p->btBuf = p->hashBuf + kHashBufferSize; + } + keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); + keepAddBufferAfter += kMtHashBlockSize; + if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) + return SZ_ERROR_MEM; + + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p)); + return SZ_OK; +} + + +SRes MatchFinderMt_InitMt(CMatchFinderMt *p) +{ + RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks)); + return MtSync_Init(&p->btSync, kMtBtNumBlocks); +} + + +static void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = MF(p); + + p->btBufPos = + p->btBufPosLimit = NULL; + p->hashBufPos = + p->hashBufPosLimit = 0; + p->hashNumAvail = 0; // 21.03 + + p->failure_BT = False; + + /* Init without data reading. We don't want to read data in this thread */ + MatchFinder_Init_4(mf); + + MatchFinder_Init_LowHash(mf); + + p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); + p->btNumAvailBytes = 0; + p->failure_LZ_BT = False; + // p->failure_LZ_LZ = False; + + p->lzPos = + 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug + + p->hash = mf->hash; + p->fixedHashSize = mf->fixedHashSize; + // p->hash4Mask = mf->hash4Mask; + p->crc = mf->crc; + // memcpy(p->crc, mf->crc, sizeof(mf->crc)); + + p->son = mf->son; + p->matchMaxLen = mf->matchMaxLen; + p->numHashBytes = mf->numHashBytes; + + /* (mf->pos) and (mf->streamPos) were already initialized to 1 in MatchFinder_Init_4() */ + // mf->streamPos = mf->pos = 1; // optimal smallest value + // 0; // for debug: ignores match to start + // kNormalizeAlign; // for debug + + /* we must init (p->pos = mf->pos) for BT, because + BT code needs (p->pos == delta_value_for_empty_hash_record == mf->pos) */ + p->pos = mf->pos; // do not change it + + p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); + p->cyclicBufferSize = mf->cyclicBufferSize; + p->buffer = mf->buffer; + p->cutValue = mf->cutValue; + // p->son[0] = p->son[1] = 0; // unused: to init skipped record for speculated accesses. +} + + +/* ReleaseStream is required to finish multithreading */ +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) +{ + // Sleep(1); // for debug + MtSync_StopWriting(&p->btSync); + // Sleep(200); // for debug + /* p->MatchFinder->ReleaseStream(); */ +} + + +MY_NO_INLINE +static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + if (p->failure_LZ_BT) + p->btBufPos = p->failureBuf; + else + { + const UInt32 bi = MtSync_GetNextBlock(&p->btSync); + const UInt32 *bt = p->btBuf + GET_BT_BLOCK_OFFSET(bi); + { + const UInt32 numItems = bt[0]; + p->btBufPosLimit = bt + numItems; + p->btNumAvailBytes = bt[1]; + p->btBufPos = bt + 2; + if (numItems < 2 || numItems > kMtBtBlockSize) + { + p->failureBuf[0] = 0; + p->btBufPos = p->failureBuf; + p->btBufPosLimit = p->failureBuf + 1; + p->failure_LZ_BT = True; + // p->btNumAvailBytes = 0; + /* we don't want to decrease AvailBytes, that was load before. + that can be unxepected for the code that have loaded anopther value before */ + } + } + + if (p->lzPos >= (UInt32)kMtMaxValForNormalize - (UInt32)kMtBtBlockSize) + { + /* we don't check (lzPos) over exact avail bytes in (btBuf). + (fixedHashSize) is small, so normalization is fast */ + const UInt32 subValue = (p->lzPos - p->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1); + p->lzPos -= subValue; + MatchFinder_Normalize3(subValue, p->hash, p->fixedHashSize); + } + } + return p->btNumAvailBytes; +} + + + +static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + + +static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + if (p->btBufPos != p->btBufPosLimit) + return p->btNumAvailBytes; + return MatchFinderMt_GetNextBlock_Bt(p); +} + + +// #define CHECK_FAILURE_LZ(_match_, _pos_) if (_match_ >= _pos_) { p->failure_LZ_LZ = True; return d; } +#define CHECK_FAILURE_LZ(_match_, _pos_) + +static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +{ + UInt32 h2, c2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + const UInt32 m = p->lzPos; + MT_HASH2_CALC + + c2 = hash[h2]; + hash[h2] = m; + + if (c2 >= matchMinPos) + { + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 2; + *d++ = m - c2 - 1; + } + } + + return d; +} + +static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +{ + UInt32 h2, h3, c2, c3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + const UInt32 m = p->lzPos; + MT_HASH3_CALC + + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + + if (c2 >= matchMinPos) + { + CHECK_FAILURE_LZ(c2, m) + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + return d + 2; + } + d[0] = 2; + d += 2; + } + } + + if (c3 >= matchMinPos) + { + CHECK_FAILURE_LZ(c3, m) + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } + } + + return d; +} + + +#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; + +/* +static +UInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + UInt32 matchMinPos; + UInt32 avail = p->btNumAvailBytes - 1; + p->btBufPos = btLim; + + { + p->btNumAvailBytes = avail; + + #define BT_HASH_BYTES_MAX 5 + + matchMinPos = p->lzPos; + + if (len != 0) + matchMinPos -= bt[1]; + else if (avail < (BT_HASH_BYTES_MAX - 1) - 1) + { + INCREASE_LZ_POS + return d; + } + else + { + const UInt32 hs = p->historySize; + if (matchMinPos > hs) + matchMinPos -= hs; + else + matchMinPos = 1; + } + } + + for (;;) + { + + UInt32 h2, h3, c2, c3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 m = p->lzPos; + MT_HASH3_CALC + + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + d[0] = 3; + d += 2; + break; + } + // else + { + d[0] = 2; + d += 2; + } + } + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + *d++ = 3; + *d++ = m - c3 - 1; + } + break; + } + + if (len != 0) + { + do + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + while (bt != btLim); + } + INCREASE_LZ_POS + return d; +} +*/ + + +static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d) +{ + UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + const UInt32 m = p->lzPos; + MT_HASH3_CALC + // MT_HASH4_CALC + c2 = hash[h2]; + c3 = (hash + kFix3HashSize)[h3]; + // c4 = (hash + kFix4HashSize)[h4]; + + hash[h2] = m; + (hash + kFix3HashSize)[h3] = m; + // (hash + kFix4HashSize)[h4] = m; + + #define _USE_H2 + + #ifdef _USE_H2 + if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c2 - 1; + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2]) + { + // d[0] = (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) ? 4 : 3; + // return d + 2; + + if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + return d; + } + d[0] = 2; + d += 2; + } + #endif + + if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0]) + { + d[1] = m - c3 - 1; + if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m + 3] == cur[3]) + { + d[0] = 4; + return d + 2; + } + d[0] = 3; + d += 2; + } + + #ifdef _USE_H4 + if (c4 >= matchMinPos) + if ( + cur[(ptrdiff_t)c4 - (ptrdiff_t)m] == cur[0] && + cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3] + ) + { + *d++ = 4; + *d++ = m - c4 - 1; + } + #endif + + return d; +} + + +static UInt32* MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + const UInt32 len = *bt++; + const UInt32 *btLim = bt + len; + p->btBufPos = btLim; + p->btNumAvailBytes--; + INCREASE_LZ_POS + { + while (bt != btLim) + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + } + return d; +} + + + +static UInt32* MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) +{ + const UInt32 *bt = p->btBufPos; + UInt32 len = *bt++; + const UInt32 avail = p->btNumAvailBytes - 1; + p->btNumAvailBytes = avail; + p->btBufPos = bt + len; + if (len == 0) + { + #define BT_HASH_BYTES_MAX 5 + if (avail >= (BT_HASH_BYTES_MAX - 1) - 1) + { + UInt32 m = p->lzPos; + if (m > p->historySize) + m -= p->historySize; + else + m = 1; + d = p->MixMatchesFunc(p, m, d); + } + } + else + { + /* + first match pair from BinTree: (match_len, match_dist), + (match_len >= numHashBytes). + MixMatchesFunc() inserts only hash matches that are nearer than (match_dist) + */ + d = p->MixMatchesFunc(p, p->lzPos - bt[1], d); + // if (d) // check for failure + do + { + const UInt32 v0 = bt[0]; + const UInt32 v1 = bt[1]; + bt += 2; + d[0] = v0; + d[1] = v1; + d += 2; + } + while (len -= 2); + } + INCREASE_LZ_POS + return d; +} + +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); + +static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT +} + +static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(2) + UInt32 h2; + MT_HASH2_CALC + hash[h2] = p->lzPos; + SKIP_FOOTER_MT +} + +static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(3) + UInt32 h2, h3; + MT_HASH3_CALC + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} + +/* +// MatchFinderMt4_Skip() is similar to MatchFinderMt3_Skip(). +// The difference is that MatchFinderMt3_Skip() updates hash for last 3 bytes of stream. + +static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(4) + UInt32 h2, h3; // h4 + MT_HASH3_CALC + // MT_HASH4_CALC + // (hash + kFix4HashSize)[h4] = + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + + switch (MF(p)->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)NULL; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; + break; + case 3: + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; + break; + case 4: + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; + + // it's fast inline version of GetMatches() + // vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches_Bt4; + + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; + break; + default: + p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; + vTable->Skip = + (Mf_Skip_Func)MatchFinderMt3_Skip; + // (Mf_Skip_Func)MatchFinderMt4_Skip; + break; + } +} diff --git a/3rdparty/lzma-21.03beta/C/LzFindMt.h b/3rdparty/lzma-21.03beta/C/LzFindMt.h new file mode 100644 index 0000000..660b724 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzFindMt.h @@ -0,0 +1,109 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2021-07-12 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H + +#include "LzFind.h" +#include "Threads.h" + +EXTERN_C_BEGIN + +typedef struct _CMtSync +{ + UInt32 numProcessedBlocks; + CThread thread; + UInt64 affinity; + + BoolInt wasCreated; + BoolInt needStart; + BoolInt csWasInitialized; + BoolInt csWasEntered; + + BoolInt exit; + BoolInt stopWriting; + + CAutoResetEvent canStart; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + CCriticalSection cs; + // UInt32 numBlocks_Sent; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + const UInt32 *btBufPos; + const UInt32 *btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + // UInt32 hash4Mask; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + UInt32 failure_LZ_BT; // failure in BT transfered to LZ + // UInt32 failure_LZ_LZ; // failure in LZ tables + UInt32 failureBuf[1]; + // UInt32 crc[256]; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + UInt32 failure_BT; + + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + const Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; + // CMatchFinder MatchFinder; +} CMatchFinderMt; + +// only for Mt part +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable); + +/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */ +SRes MatchFinderMt_InitMt(CMatchFinderMt *p); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/LzHash.h b/3rdparty/lzma-21.03beta/C/LzHash.h new file mode 100644 index 0000000..77b898c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzHash.h @@ -0,0 +1,34 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2019-10-30 : Igor Pavlov : Public domain */ + +#ifndef __LZ_HASH_H +#define __LZ_HASH_H + +/* + (kHash2Size >= (1 << 8)) : Required + (kHash3Size >= (1 << 16)) : Required +*/ + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +// #define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +/* + We use up to 3 crc values for hash: + crc0 + crc1 << Shift_1 + crc2 << Shift_2 + (Shift_1 = 5) and (Shift_2 = 10) is good tradeoff. + Small values for Shift are not good for collision rate. + Big value for Shift_2 increases the minimum size + of hash table, that will be slow for small files. +*/ + +#define kLzHash_CrcShift_1 5 +#define kLzHash_CrcShift_2 10 + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Lzma2Dec.c b/3rdparty/lzma-21.03beta/C/Lzma2Dec.c new file mode 100644 index 0000000..ac970a8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2Dec.c @@ -0,0 +1,489 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2021-02-09 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#include "Precomp.h" + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - End of data +00000001 U U - Uncompressed, reset dic, need reset state and set new prop +00000010 U U - Uncompressed, no reset +100uuuuu U U P P - LZMA, no reset +101uuuuu U U P P - LZMA, reset state +110uuuuu U U P P S - LZMA, reset state + set new prop +111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#define LZMA2_CONTROL_COPY_RESET_DIC 1 + +#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0) + +#define LZMA2_LCLP_MAX 4 +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +typedef enum +{ + LZMA2_STATE_CONTROL, + LZMA2_STATE_UNPACK0, + LZMA2_STATE_UNPACK1, + LZMA2_STATE_PACK0, + LZMA2_STATE_PACK1, + LZMA2_STATE_PROP, + LZMA2_STATE_DATA, + LZMA2_STATE_DATA_CONT, + LZMA2_STATE_FINISHED, + LZMA2_STATE_ERROR +} ELzma2State; + +static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) +{ + UInt32 dicSize; + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); + props[0] = (Byte)LZMA2_LCLP_MAX; + props[1] = (Byte)(dicSize); + props[2] = (Byte)(dicSize >> 8); + props[3] = (Byte)(dicSize >> 16); + props[4] = (Byte)(dicSize >> 24); + return SZ_OK; +} + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +void Lzma2Dec_Init(CLzma2Dec *p) +{ + p->state = LZMA2_STATE_CONTROL; + p->needInitLevel = 0xE0; + p->isExtraMode = False; + p->unpackSize = 0; + + // p->decoder.dicPos = 0; // we can use it instead of full init + LzmaDec_Init(&p->decoder); +} + +// ELzma2State +static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch (p->state) + { + case LZMA2_STATE_CONTROL: + p->isExtraMode = False; + p->control = b; + PRF(printf("\n %8X", (unsigned)p->decoder.dicPos)); + PRF(printf(" %02X", (unsigned)b)); + if (b == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (b == LZMA2_CONTROL_COPY_RESET_DIC) + p->needInitLevel = 0xC0; + else if (b > 2 || p->needInitLevel == 0xE0) + return LZMA2_STATE_ERROR; + } + else + { + if (b < p->needInitLevel) + return LZMA2_STATE_ERROR; + p->needInitLevel = 0; + p->unpackSize = (UInt32)(b & 0x1F) << 16; + } + return LZMA2_STATE_UNPACK0; + + case LZMA2_STATE_UNPACK0: + p->unpackSize |= (UInt32)b << 8; + return LZMA2_STATE_UNPACK1; + + case LZMA2_STATE_UNPACK1: + p->unpackSize |= (UInt32)b; + p->unpackSize++; + PRF(printf(" %7u", (unsigned)p->unpackSize)); + return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; + + case LZMA2_STATE_PACK0: + p->packSize = (UInt32)b << 8; + return LZMA2_STATE_PACK1; + + case LZMA2_STATE_PACK1: + p->packSize |= (UInt32)b; + p->packSize++; + // if (p->packSize < 5) return LZMA2_STATE_ERROR; + PRF(printf(" %5u", (unsigned)p->packSize)); + return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA; + + case LZMA2_STATE_PROP: + { + unsigned lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = (Byte)(b / 5); + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = (Byte)lc; + p->decoder.prop.lp = (Byte)lp; + return LZMA2_STATE_DATA; + } + } + return LZMA2_STATE_ERROR; +} + +static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) +{ + memcpy(p->dic + p->dicPos, src, size); + p->dicPos += size; + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) + p->checkDicSize = p->prop.dicSize; + p->processedPos += (UInt32)size; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); + + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->state != LZMA2_STATE_ERROR) + { + SizeT dicPos; + + if (p->state == LZMA2_STATE_FINISHED) + { + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + + dicPos = p->decoder.dicPos; + + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) + break; + continue; + } + + { + SizeT inCur = inSize - *srcLen; + SizeT outCur = dicLimit - dicPos; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (outCur >= p->unpackSize) + { + outCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (inCur == 0) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (inCur > outCur) + inCur = outCur; + if (inCur == 0) + break; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); + + src += inCur; + *srcLen += inCur; + p->unpackSize -= (UInt32)inCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + BoolInt initDic = (p->control >= 0xE0); + BoolInt initState = (p->control >= 0xA0); + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->state = LZMA2_STATE_DATA_CONT; + } + + if (inCur > p->packSize) + inCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); + + src += inCur; + *srcLen += inCur; + p->packSize -= (UInt32)inCur; + outCur = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outCur; + + if (res != 0) + break; + + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (p->packSize == 0) + break; + return SZ_OK; + } + + if (inCur == 0 && outCur == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + || p->unpackSize != 0 + || p->packSize != 0) + break; + p->state = LZMA2_STATE_CONTROL; + } + + *status = LZMA_STATUS_NOT_SPECIFIED; + } + } + } + + *status = LZMA_STATUS_NOT_SPECIFIED; + p->state = LZMA2_STATE_ERROR; + return SZ_ERROR_DATA; +} + + + + +ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, + SizeT outSize, + const Byte *src, SizeT *srcLen, + int checkFinishBlock) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + + while (p->state != LZMA2_STATE_ERROR) + { + if (p->state == LZMA2_STATE_FINISHED) + return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK; + + if (outSize == 0 && !checkFinishBlock) + return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; + + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; + (*srcLen)++; + + p->state = Lzma2Dec_UpdateState(p, *src++); + + if (p->state == LZMA2_STATE_UNPACK0) + { + // if (p->decoder.dicPos != 0) + if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0) + return LZMA2_PARSE_STATUS_NEW_BLOCK; + // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; + } + + // The following code can be commented. + // It's not big problem, if we read additional input bytes. + // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. + + if (outSize == 0 && p->state != LZMA2_STATE_FINISHED) + { + // checkFinishBlock is true. So we expect that block must be finished, + // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here + // break; + return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; + } + + if (p->state == LZMA2_STATE_DATA) + return LZMA2_PARSE_STATUS_NEW_CHUNK; + + continue; + } + + if (outSize == 0) + return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; + + { + SizeT inCur = inSize - *srcLen; + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (inCur == 0) + return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; + if (inCur > p->unpackSize) + inCur = p->unpackSize; + if (inCur > outSize) + inCur = outSize; + p->decoder.dicPos += inCur; + src += inCur; + *srcLen += inCur; + outSize -= inCur; + p->unpackSize -= (UInt32)inCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + p->isExtraMode = True; + + if (inCur == 0) + { + if (p->packSize != 0) + return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; + } + else if (p->state == LZMA2_STATE_DATA) + { + p->state = LZMA2_STATE_DATA_CONT; + if (*src != 0) + { + // first byte of lzma chunk must be Zero + *srcLen += 1; + p->packSize--; + break; + } + } + + if (inCur > p->packSize) + inCur = (SizeT)p->packSize; + + src += inCur; + *srcLen += inCur; + p->packSize -= (UInt32)inCur; + + if (p->packSize == 0) + { + SizeT rem = outSize; + if (rem > p->unpackSize) + rem = p->unpackSize; + p->decoder.dicPos += rem; + p->unpackSize -= (UInt32)rem; + outSize -= rem; + if (p->unpackSize == 0) + p->state = LZMA2_STATE_CONTROL; + } + } + } + } + + p->state = LZMA2_STATE_ERROR; + return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; +} + + + + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen, inSize = *srcLen; + *srcLen = *destLen = 0; + + for (;;) + { + SizeT inCur = inSize, outCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + curFinishMode = LZMA_FINISH_ANY; + outCur = p->decoder.dicBufSize - dicPos; + + if (outCur >= outSize) + { + outCur = outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); + + src += inCur; + inSize -= inCur; + *srcLen += inCur; + outCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outCur); + dest += outCur; + outSize -= outCur; + *destLen += outCur; + if (res != 0) + return res; + if (outCur == 0 || outSize == 0) + return SZ_OK; + } +} + + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) +{ + CLzma2Dec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + Lzma2Dec_FreeProbs(&p, alloc); + return res; +} diff --git a/3rdparty/lzma-21.03beta/C/Lzma2Dec.h b/3rdparty/lzma-21.03beta/C/Lzma2Dec.h new file mode 100644 index 0000000..b8ddeac --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2Dec.h @@ -0,0 +1,120 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2018-02-19 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +EXTERN_C_BEGIN + +/* ---------- State Interface ---------- */ + +typedef struct +{ + unsigned state; + Byte control; + Byte needInitLevel; + Byte isExtraMode; + Byte _pad_; + UInt32 packSize; + UInt32 unpackSize; + CLzmaDec decoder; +} CLzma2Dec; + +#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc) +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc) + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc); +void Lzma2Dec_Init(CLzma2Dec *p); + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen or dicLimit). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + SZ_ERROR_DATA - Data error +*/ + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- LZMA2 block and chunk parsing ---------- */ + +/* +Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data. +It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code: + - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input. + - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read. + CLzma2Dec::unpackSize contains unpack size of that chunk +*/ + +typedef enum +{ +/* + LZMA_STATUS_NOT_SPECIFIED // data error + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED // + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused +*/ + LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1, + LZMA2_PARSE_STATUS_NEW_CHUNK +} ELzma2ParseStatus; + +ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, + SizeT outSize, // output size + const Byte *src, SizeT *srcLen, + int checkFinishBlock // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. + ); + +/* +LZMA2 parser doesn't decode LZMA chunks, so we must read + full input LZMA chunk to decode some part of LZMA chunk. + +Lzma2Dec_GetUnpackExtra() returns the value that shows + max possible number of output bytes that can be output by decoder + at current input positon. +*/ + +#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0); + + +/* ---------- One Call Interface ---------- */ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Lzma2DecMt.c b/3rdparty/lzma-21.03beta/C/Lzma2DecMt.c new file mode 100644 index 0000000..9f1dc52 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2DecMt.c @@ -0,0 +1,1090 @@ +/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO + +// #define _7ZIP_ST + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifndef _7ZIP_ST +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif +#define PRF_STR(s) PRF(printf("\n" s "\n")) +#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2)) +#endif + +#include "Alloc.h" + +#include "Lzma2Dec.h" +#include "Lzma2DecMt.h" + +#ifndef _7ZIP_ST +#include "MtDec.h" + +#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28) +#endif + + +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p) +{ + p->inBufSize_ST = 1 << 20; + p->outStep_ST = 1 << 20; + + #ifndef _7ZIP_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT; + p->inBlockMax = p->outBlockMax + p->outBlockMax / 16; + #endif +} + + + +#ifndef _7ZIP_ST + +/* ---------- CLzma2DecMtThread ---------- */ + +typedef struct +{ + CLzma2Dec dec; + Byte dec_created; + Byte needInit; + + Byte *outBuf; + size_t outBufSize; + + EMtDecParseState state; + ELzma2ParseStatus parseStatus; + + size_t inPreSize; + size_t outPreSize; + + size_t inCodeSize; + size_t outCodeSize; + SRes codeRes; + + CAlignOffsetAlloc alloc; + + Byte mtPad[1 << 7]; +} CLzma2DecMtThread; + +#endif + + +/* ---------- CLzma2DecMt ---------- */ + +typedef struct +{ + // ISzAllocPtr alloc; + ISzAllocPtr allocMid; + + CAlignOffsetAlloc alignOffsetAlloc; + CLzma2DecMtProps props; + Byte prop; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + + BoolInt finishMode; + BoolInt outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + BoolInt readWasFinished; + SRes readRes; + + Byte *inBuf; + size_t inBufSize; + Byte dec_created; + CLzma2Dec dec; + + size_t inPos; + size_t inLim; + + #ifndef _7ZIP_ST + UInt64 outProcessed_Parse; + BoolInt mtc_WasConstructed; + CMtDec mtc; + CLzma2DecMtThread coders[MTDEC__THREADS_MAX]; + #endif + +} CLzma2DecMt; + + + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt)); + if (!p) + return NULL; + + // p->alloc = alloc; + p->allocMid = allocMid; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + p->alignOffsetAlloc.baseAlloc = alloc; + + p->inBuf = NULL; + p->inBufSize = 0; + p->dec_created = False; + + // Lzma2DecMtProps_Init(&p->props); + + #ifndef _7ZIP_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + t->dec_created = False; + t->outBuf = NULL; + t->outBufSize = 0; + } + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->outBuf) + { + ISzAlloc_Free(p->allocMid, t->outBuf); + t->outBuf = NULL; + t->outBufSize = 0; + } + } +} + +#endif + + +static void Lzma2DecMt_FreeSt(CLzma2DecMt *p) +{ + if (p->dec_created) + { + Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt); + p->dec_created = False; + } + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + + Lzma2DecMt_FreeSt(p); + + #ifndef _7ZIP_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CLzma2DecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!! + t->dec_created = False; + } + } + } + Lzma2DecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); +} + + + +#ifndef _7ZIP_ST + +static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CLzma2DecMt *me = (CLzma2DecMt *)obj; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + PRF_STR_INT_2("Parse", coderIndex, cc->srcSize); + + cc->state = MTDEC_PARSE_CONTINUE; + + if (cc->startCall) + { + if (!t->dec_created) + { + Lzma2Dec_Construct(&t->dec); + t->dec_created = True; + AlignOffsetAlloc_CreateVTable(&t->alloc); + { + /* (1 << 12) is expected size of one way in data cache. + We optimize alignment for cache line size of 128 bytes and smaller */ + const unsigned kNumAlignBits = 12; + const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */ + t->alloc.numAlignBits = kNumAlignBits; + t->alloc.offset = ((UInt32)coderIndex * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits)); + t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc; + } + } + Lzma2Dec_Init(&t->dec); + + t->inPreSize = 0; + t->outPreSize = 0; + // t->blockWasFinished = False; + // t->finishedWithMark = False; + t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; + t->state = MTDEC_PARSE_CONTINUE; + + t->inCodeSize = 0; + t->outCodeSize = 0; + t->codeRes = SZ_OK; + + // (cc->srcSize == 0) is allowed + } + + { + ELzma2ParseStatus status; + BoolInt overflow; + UInt32 unpackRem = 0; + + int checkFinishBlock = True; + size_t limit = me->props.outBlockMax; + if (me->outSize_Defined) + { + UInt64 rem = me->outSize - me->outProcessed_Parse; + if (limit >= rem) + { + limit = (size_t)rem; + if (!me->finishMode) + checkFinishBlock = False; + } + } + + // checkFinishBlock = False, if we want to decode partial data + // that must be finished at position <= outBlockMax. + + { + const SizeT srcOrig = cc->srcSize; + SizeT srcSize_Point = 0; + SizeT dicPos_Point = 0; + + cc->srcSize = 0; + overflow = False; + + for (;;) + { + SizeT srcCur = srcOrig - cc->srcSize; + + status = Lzma2Dec_Parse(&t->dec, + limit - t->dec.decoder.dicPos, + cc->src + cc->srcSize, &srcCur, + checkFinishBlock); + + cc->srcSize += srcCur; + + if (status == LZMA2_PARSE_STATUS_NEW_CHUNK) + { + if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos) + { + overflow = True; + break; + } + continue; + } + + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + if (t->dec.decoder.dicPos == 0) + continue; + // we decode small blocks in one thread + if (t->dec.decoder.dicPos >= (1 << 14)) + break; + dicPos_Point = t->dec.decoder.dicPos; + srcSize_Point = cc->srcSize; + continue; + } + + if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock + // && limit == t->dec.decoder.dicPos + // && limit == me->props.outBlockMax + ) + { + overflow = True; + break; + } + + unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec); + break; + } + + if (dicPos_Point != 0 + && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK + && (int)status != LZMA_STATUS_FINISHED_WITH_MARK + && (int)status != LZMA_STATUS_NOT_SPECIFIED) + { + // we revert to latest newBlock state + status = LZMA2_PARSE_STATUS_NEW_BLOCK; + unpackRem = 0; + t->dec.decoder.dicPos = dicPos_Point; + cc->srcSize = srcSize_Point; + overflow = False; + } + } + + t->inPreSize += cc->srcSize; + t->parseStatus = status; + + if (overflow) + cc->state = MTDEC_PARSE_OVERFLOW; + else + { + size_t dicPos = t->dec.decoder.dicPos; + + if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (status == LZMA2_PARSE_STATUS_NEW_BLOCK) + { + cc->state = MTDEC_PARSE_NEW; + cc->srcSize--; // we don't need control byte of next block + t->inPreSize--; + } + else + { + cc->state = MTDEC_PARSE_END; + if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK) + { + // (status == LZMA_STATUS_NOT_SPECIFIED) + // (status == LZMA_STATUS_NOT_FINISHED) + if (unpackRem != 0) + { + /* we also reserve space for max possible number of output bytes of current LZMA chunk */ + SizeT rem = limit - dicPos; + if (rem > unpackRem) + rem = unpackRem; + dicPos += rem; + } + } + } + + me->outProcessed_Parse += dicPos; + } + + cc->outPos = dicPos; + t->outPreSize = (size_t)dicPos; + } + + t->state = cc->state; + return; + } +} + + +static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + Byte *dest = t->outBuf; + + if (t->inPreSize == 0) + { + t->codeRes = SZ_ERROR_DATA; + return t->codeRes; + } + + if (!dest || t->outBufSize < t->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + t->outBuf = NULL; + t->outBufSize = 0; + } + + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize + // + (1 << 28) + ); + // Sleep(200); + if (!dest) + return SZ_ERROR_MEM; + t->outBuf = dest; + t->outBufSize = t->outPreSize; + } + + t->dec.decoder.dic = dest; + t->dec.decoder.dicBufSize = t->outPreSize; + + t->needInit = True; + + return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt +} + + +static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + CLzma2DecMtThread *t = &me->coders[coderIndex]; + + UNUSED_VAR(srcFinished) + + PRF_STR_INT_2("Code", coderIndex, srcSize); + + *inCodePos = t->inCodeSize; + *outCodePos = 0; + *stop = True; + + if (t->needInit) + { + Lzma2Dec_Init(&t->dec); + t->needInit = False; + } + + { + ELzmaStatus status; + size_t srcProcessed = srcSize; + BoolInt blockWasFinished = + ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK); + + SRes res = Lzma2Dec_DecodeToDic(&t->dec, + t->outPreSize, + src, &srcProcessed, + blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY, + &status); + + t->codeRes = res; + + t->inCodeSize += srcProcessed; + *inCodePos = t->inCodeSize; + t->outCodeSize = t->dec.decoder.dicPos; + *outCodePos = t->dec.decoder.dicPos; + + if (res != SZ_OK) + return res; + + if (srcProcessed == srcSize) + *stop = False; + + if (blockWasFinished) + { + if (srcSize != srcProcessed) + return SZ_ERROR_FAIL; + + if (t->inPreSize == t->inCodeSize) + { + if (t->outPreSize != t->outCodeSize) + return SZ_ERROR_FAIL; + *stop = True; + } + } + else + { + if (t->outPreSize == t->outCodeSize) + *stop = True; + } + + return SZ_OK; + } +} + + +#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + BoolInt *needContinue, BoolInt *canRecode) +{ + CLzma2DecMt *me = (CLzma2DecMt *)pp; + const CLzma2DecMtThread *t = &me->coders[coderIndex]; + size_t size = t->outCodeSize; + const Byte *data = t->outBuf; + BoolInt needContinue2 = True; + + UNUSED_VAR(src) + UNUSED_VAR(srcSize) + UNUSED_VAR(isCross) + + PRF_STR_INT_2("Write", coderIndex, srcSize); + + *needContinue = False; + *canRecode = True; + + if ( + // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + t->state == MTDEC_PARSE_OVERFLOW + || t->state == MTDEC_PARSE_END) + needContinue2 = False; + + + if (!needWriteToStream) + return SZ_OK; + + me->mtc.inProcessed += t->inCodeSize; + + if (t->codeRes == SZ_OK) + if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK + || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK) + if (t->outPreSize != t->outCodeSize + || t->inPreSize != t->inCodeSize) + return SZ_ERROR_FAIL; + + *canRecode = False; + + if (me->outStream) + { + for (;;) + { + size_t cur = size; + size_t written; + if (cur > LZMA2DECMT_STREAM_WRITE_STEP) + cur = LZMA2DECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + me->outProcessed += written; + // me->mtc.writtenTotal += written; + if (written != cur) + return SZ_ERROR_WRITE; + data += cur; + size -= cur; + if (size == 0) + { + *needContinue = needContinue2; + return SZ_OK; + } + RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0)); + } + } + + return SZ_ERROR_FAIL; + /* + if (size > me->outBufSize) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBufSize -= size; + me->outBuf += size; + *needContinue = needContinue2; + return SZ_OK; + */ +} + +#endif + + +static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p) +{ + if (!p->dec_created) + { + Lzma2Dec_Construct(&p->dec); + p->dec_created = True; + } + + RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt)); + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + Lzma2Dec_Init(&p->dec); + + return SZ_OK; +} + + +static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p + #ifndef _7ZIP_ST + , BoolInt tMode + #endif + ) +{ + SizeT wrPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CLzma2Dec *dec; + + #ifndef _7ZIP_ST + if (tMode) + { + Lzma2DecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + RINOK(Lzma2Dec_Prepare_ST(p)); + + dec = &p->dec; + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + wrPos = dec->decoder.dicPos; + + for (;;) + { + SizeT dicPos; + SizeT size; + ELzmaFinishMode finishMode; + SizeT inProcessed; + ELzmaStatus status; + SRes res; + + SizeT outProcessed; + BoolInt outFinished; + BoolInt needStop; + + if (inPos == inLim) + { + #ifndef _7ZIP_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim); + // p->readProcessed += inLim; + // inLim -= 5; p->readWasFinished = True; // for test + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + dicPos = dec->decoder.dicPos; + { + SizeT next = dec->decoder.dicBufSize; + if (next - wrPos > p->props.outStep_ST) + next = wrPos + p->props.outStep_ST; + size = next - dicPos; + } + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (SizeT)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + inProcessed = inLim - inPos; + + res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status); + + inPos += inProcessed; + p->inProcessed += inProcessed; + outProcessed = dec->decoder.dicPos - dicPos; + p->outProcessed += outProcessed; + + outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed); + + needStop = (res != SZ_OK + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (!p->finishMode && outFinished)); + + if (needStop || outProcessed >= size) + { + SRes res2; + { + size_t writeSize = dec->decoder.dicPos - wrPos; + size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize); + res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE; + } + + if (dec->decoder.dicPos == dec->decoder.dicBufSize) + dec->decoder.dicPos = 0; + wrPos = dec->decoder.dicPos; + + RINOK(res2); + + if (needStop) + { + if (res != SZ_OK) + return res; + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (p->finishMode) + { + if (p->outSize_Defined && p->outSize != p->outProcessed) + return SZ_ERROR_DATA; + } + return SZ_OK; + } + + if (!p->finishMode && outFinished) + return SZ_OK; + + if (status == LZMA_STATUS_NEEDS_MORE_INPUT) + return SZ_ERROR_INPUT_EOF; + + return SZ_ERROR_DATA; + } + } + + if (p->progress) + { + UInt64 inDelta = p->inProcessed - inPrev; + UInt64 outDelta = p->outProcessed - outPrev; + if (inDelta >= (1 << 22) || outDelta >= (1 << 22)) + { + RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed)); + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + } +} + + + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + UInt64 *inProcessed, + // UInt64 *outProcessed, + int *isMT, + ICompressProgress *progress) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + #ifndef _7ZIP_ST + BoolInt tMode; + #endif + + *inProcessed = 0; + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->readWasFinished = False; + p->readRes = SZ_OK; + + *isMT = False; + + + #ifndef _7ZIP_ST + + tMode = False; + + // p->mtc.parseRes = SZ_OK; + + // p->mtc.numFilledThreads = 0; + // p->mtc.crossStart = 0; + // p->mtc.crossEnd = 0; + // p->mtc.allocError_for_Read_BlockIndex = 0; + // p->mtc.isAllocError = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback2 vt; + + Lzma2DecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + + // p->outBuf = NULL; + // p->outBufSize = 0; + /* + if (!outStream) + { + // p->outBuf = outBuf; + // p->outBufSize = *outBufSize; + // *outBufSize = 0; + return SZ_ERROR_PARAM; + } + */ + + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->alignOffsetAlloc.baseAlloc; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.inBufSize = p->props.inBufSize_MT; + + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = Lzma2DecMt_MtCallback_Parse; + vt.PreCode = Lzma2DecMt_MtCallback_PreCode; + vt.Code = Lzma2DecMt_MtCallback_Code; + vt.Write = Lzma2DecMt_MtCallback_Write; + + { + BoolInt needContinue = False; + + SRes res = MtDec_Code(&p->mtc); + + /* + if (!outStream) + *outBufSize = p->outBuf - outBuf; + */ + + *inProcessed = p->mtc.inProcessed; + + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + res = p->mtc.mtProgress.res; + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + if (res == SZ_OK) + return p->mtc.readRes; + return res; + } + + tMode = True; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->inProcessed = p->mtc.inProcessed; + + PRF_STR("----- decoding ST -----"); + } + } + + #endif + + + *isMT = False; + + { + SRes res = Lzma2Dec_Decode_ST(p + #ifndef _7ZIP_ST + , tMode + #endif + ); + + *inProcessed = p->inProcessed; + + // res = SZ_OK; // for test + if (res == SZ_ERROR_INPUT_EOF) + { + if (p->readRes != SZ_OK) + res = p->readRes; + } + else if (res == SZ_OK && p->readRes != SZ_OK) + res = p->readRes; + + /* + #ifndef _7ZIP_ST + if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK) + res = p->mtc.parseRes; + #endif + */ + + return res; + } +} + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStream *inStream) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + + p->prop = prop; + p->props = *props; + + p->inStream = inStream; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + p->finishMode = finishMode; + + p->outProcessed = 0; + p->inProcessed = 0; + + p->inPos = 0; + p->inLim = 0; + + return Lzma2Dec_Prepare_ST(p); +} + + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed) +{ + CLzma2DecMt *p = (CLzma2DecMt *)pp; + ELzmaFinishMode finishMode; + SRes readRes; + size_t size = *outSize; + + *outSize = 0; + *inStreamProcessed = 0; + + finishMode = LZMA_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (size >= rem) + { + size = (size_t)rem; + if (p->finishMode) + finishMode = LZMA_FINISH_END; + } + } + + readRes = SZ_OK; + + for (;;) + { + SizeT inCur; + SizeT outCur; + ELzmaStatus status; + SRes res; + + if (p->inPos == p->inLim && readRes == SZ_OK) + { + p->inPos = 0; + p->inLim = p->props.inBufSize_ST; + readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim); + } + + inCur = p->inLim - p->inPos; + outCur = size; + + res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur, + p->inBuf + p->inPos, &inCur, finishMode, &status); + + p->inPos += inCur; + p->inProcessed += inCur; + *inStreamProcessed += inCur; + p->outProcessed += outCur; + *outSize += outCur; + size -= outCur; + data += outCur; + + if (res != 0) + return res; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; + + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize) + return SZ_ERROR_DATA; + return readRes; + } + */ + + if (inCur == 0 && outCur == 0) + return readRes; + } +} diff --git a/3rdparty/lzma-21.03beta/C/Lzma2DecMt.h b/3rdparty/lzma-21.03beta/C/Lzma2DecMt.h new file mode 100644 index 0000000..7791c31 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2DecMt.h @@ -0,0 +1,79 @@ +/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread +2018-02-17 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_MT_H +#define __LZMA2_DEC_MT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + size_t inBufSize_ST; + size_t outStep_ST; + + #ifndef _7ZIP_ST + unsigned numThreads; + size_t inBufSize_MT; + size_t outBlockMax; + size_t inBlockMax; + #endif +} CLzma2DecMtProps; + +/* init to single-thread mode */ +void Lzma2DecMtProps_Init(CLzma2DecMtProps *p); + + +/* ---------- CLzma2DecMtHandle Interface ---------- */ + +/* Lzma2DecMt_ * functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + // SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2DecMtHandle; + +CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void Lzma2DecMt_Destroy(CLzma2DecMtHandle p); + +SRes Lzma2DecMt_Decode(CLzma2DecMtHandle p, + Byte prop, + const CLzma2DecMtProps *props, + ISeqOutStream *outStream, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + + // out variables: + UInt64 *inProcessed, + int *isMT, /* out: (*isMT == 0), if single thread decoding was used */ + + // UInt64 *outProcessed, + ICompressProgress *progress); + + +/* ---------- Read from CLzma2DecMtHandle Interface ---------- */ + +SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp, + Byte prop, + const CLzma2DecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqInStream *inStream); + +SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp, + Byte *data, size_t *outSize, + UInt64 *inStreamProcessed); + + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Lzma2Enc.c b/3rdparty/lzma-21.03beta/C/Lzma2Enc.c new file mode 100644 index 0000000..e61a5df --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2Enc.c @@ -0,0 +1,803 @@ +/* Lzma2Enc.c -- LZMA2 Encoder +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define _7ZIP_ST */ + +#include "Lzma2Enc.h" + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define MTCODER__THREADS_MAX 1 +#endif + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_LCLP_MAX 4 + +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#define LZMA2_PACK_SIZE_MAX (1 << 16) +#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX +#define LZMA2_UNPACK_SIZE_MAX (1 << 21) +#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX + +#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) + + +#define PRF(x) /* x */ + + +/* ---------- CLimitedSeqInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *realStream; + UInt64 limit; + UInt64 processed; + int finished; +} CLimitedSeqInStream; + +static void LimitedSeqInStream_Init(CLimitedSeqInStream *p) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->finished = 0; +} + +static SRes LimitedSeqInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CLimitedSeqInStream *p = CONTAINER_FROM_VTBL(pp, CLimitedSeqInStream, vt); + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->finished = (size2 == 0 ? 1 : 0); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + Byte propsAreSet; + Byte propsByte; + Byte needInitState; + Byte needInitProp; + UInt64 srcPos; +} CLzma2EncInt; + + +static SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + if (!p->propsAreSet) + { + SizeT propsSize = LZMA_PROPS_SIZE; + Byte propsEncoded[LZMA_PROPS_SIZE]; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); + p->propsByte = propsEncoded[0]; + p->propsAreSet = True; + } + return SZ_OK; +} + +static void Lzma2EncInt_InitBlock(CLzma2EncInt *p) +{ + p->srcPos = 0; + p->needInitState = True; + p->needInitProp = True; +} + + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + +/* +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp); +*/ + +static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, + size_t *packSizeRes, ISeqOutStream *outStream) +{ + size_t packSizeLimit = *packSizeRes; + size_t packSize = packSizeLimit; + UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; + unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); + BoolInt useCopyBlock; + SRes res; + + *packSizeRes = 0; + if (packSize < lzHeaderSize) + return SZ_ERROR_OUTPUT_EOF; + packSize -= lzHeaderSize; + + LzmaEnc_SaveState(p->enc); + res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, + outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); + + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); + + if (unpackSize == 0) + return res; + + if (res == SZ_OK) + useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); + else + { + if (res != SZ_ERROR_OUTPUT_EOF) + return res; + res = SZ_OK; + useCopyBlock = True; + } + + if (useCopyBlock) + { + size_t destPos = 0; + PRF(printf("################# COPY ")); + + while (unpackSize > 0) + { + UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; + if (packSizeLimit - destPos < u + 3) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); + outBuf[destPos++] = (Byte)((u - 1) >> 8); + outBuf[destPos++] = (Byte)(u - 1); + memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); + unpackSize -= u; + destPos += u; + p->srcPos += u; + + if (outStream) + { + *packSizeRes += destPos; + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + destPos = 0; + } + else + *packSizeRes = destPos; + /* needInitState = True; */ + } + + LzmaEnc_RestoreState(p->enc); + return SZ_OK; + } + + { + size_t destPos = 0; + UInt32 u = unpackSize - 1; + UInt32 pm = (UInt32)(packSize - 1); + unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); + + PRF(printf(" ")); + + outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); + outBuf[destPos++] = (Byte)(u >> 8); + outBuf[destPos++] = (Byte)u; + outBuf[destPos++] = (Byte)(pm >> 8); + outBuf[destPos++] = (Byte)pm; + + if (p->needInitProp) + outBuf[destPos++] = p->propsByte; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + + *packSizeRes = destPos; + return SZ_OK; + } +} + + +/* ---------- Lzma2 Props ---------- */ + +void Lzma2EncProps_Init(CLzma2EncProps *p) +{ + LzmaEncProps_Init(&p->lzmaProps); + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + + t2r = t2; + + fileSize = p->lzmaProps.reduceSize; + + if ( p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && p->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO + && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzmaProps.reduceSize = p->blockSize; + + LzmaEncProps_Normalize(&p->lzmaProps); + + p->lzmaProps.reduceSize = fileSize; + + t1 = p->lzmaProps.numThreads; + + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + { + t2r = t2 = 1; + t3 = t1; + } + else if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO && t2 <= 1) + { + /* if there is no block multi-threading, we use SOLID block */ + p->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + } + else + { + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + { + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + const UInt32 dictSize = p->lzmaProps.dictSize; + UInt64 blockSize = (UInt64)dictSize << 2; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + blockSize += (kMinSize - 1); + blockSize &= ~(UInt64)(kMinSize - 1); + p->blockSize = blockSize; + } + + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (int)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + Byte propEncoded; + CLzma2EncProps props; + UInt64 expectedDataSize; + + Byte *tempBufLzma; + + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CLzma2EncInt coders[MTCODER__THREADS_MAX]; + + #ifndef _7ZIP_ST + + ISeqOutStream *outStream; + Byte *outBuf; + size_t outBuf_Rem; /* remainder in outBuf */ + + size_t outBufSize; /* size of allocated outBufs[i] */ + size_t outBufsDataSizes[MTCODER__BLOCKS_MAX]; + BoolInt mtCoder_WasConstructed; + CMtCoder mtCoder; + Byte *outBufs[MTCODER__BLOCKS_MAX]; + + #endif + +} CLzma2Enc; + + + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc)); + if (!p) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->expectedDataSize = (UInt64)(Int64)-1; + p->tempBufLzma = NULL; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].enc = NULL; + } + + #ifndef _7ZIP_ST + p->mtCoder_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void Lzma2Enc_FreeOutBufs(CLzma2Enc *p) +{ + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + +#endif + + +void Lzma2Enc_Destroy(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = NULL; + } + } + + + #ifndef _7ZIP_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + Lzma2Enc_FreeOutBufs(p); + #endif + + ISzAlloc_Free(p->alloc, p->tempBufLzma); + p->tempBufLzma = NULL; + + ISzAlloc_Free(p->alloc, pp); +} + + +SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + CLzmaEncProps lzmaProps = props->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) + return SZ_ERROR_PARAM; + p->props = *props; + Lzma2EncProps_Normalize(&p->props); + return SZ_OK; +} + + +void Lzma2Enc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + p->expectedDataSize = expectedDataSiize; +} + + +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); + for (i = 0; i < 40; i++) + if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) + break; + return (Byte)i; +} + + +static SRes Lzma2Enc_EncodeMt1( + CLzma2Enc *me, + CLzma2EncInt *p, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + int finished, + ICompressProgress *progress) +{ + UInt64 unpackTotal = 0; + UInt64 packTotal = 0; + size_t outLim = 0; + CLimitedSeqInStream limitedInStream; + + if (outBuf) + { + outLim = *outBufSize; + *outBufSize = 0; + } + + if (!p->enc) + { + p->propsAreSet = False; + p->enc = LzmaEnc_Create(me->alloc); + if (!p->enc) + return SZ_ERROR_MEM; + } + + limitedInStream.realStream = inStream; + if (inStream) + { + limitedInStream.vt.Read = LimitedSeqInStream_Read; + } + + if (!outBuf) + { + // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma + if (!me->tempBufLzma) + { + me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (!me->tempBufLzma) + return SZ_ERROR_MEM; + } + } + + RINOK(Lzma2EncInt_InitStream(p, &me->props)); + + for (;;) + { + SRes res = SZ_OK; + size_t inSizeCur = 0; + + Lzma2EncInt_InitBlock(p); + + LimitedSeqInStream_Init(&limitedInStream); + limitedInStream.limit = me->props.blockSize; + + if (inStream) + { + UInt64 expected = (UInt64)(Int64)-1; + // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize + if (me->expectedDataSize != (UInt64)(Int64)-1 + && me->expectedDataSize >= unpackTotal) + expected = me->expectedDataSize - unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && expected > me->props.blockSize) + expected = (size_t)me->props.blockSize; + + LzmaEnc_SetDataSize(p->enc, expected); + + RINOK(LzmaEnc_PrepareForLzma2(p->enc, + &limitedInStream.vt, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + else + { + inSizeCur = inDataSize - (size_t)unpackTotal; + if (me->props.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + && inSizeCur > me->props.blockSize) + inSizeCur = (size_t)me->props.blockSize; + + // LzmaEnc_SetDataSize(p->enc, inSizeCur); + + RINOK(LzmaEnc_MemPrepare(p->enc, + inData + (size_t)unpackTotal, inSizeCur, + LZMA2_KEEP_WINDOW_SIZE, + me->alloc, + me->allocBig)); + } + + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + if (outBuf) + packSize = outLim - (size_t)packTotal; + + res = Lzma2EncInt_EncodeSubblock(p, + outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize, + outBuf ? NULL : outStream); + + if (res != SZ_OK) + break; + + packTotal += packSize; + if (outBuf) + *outBufSize = (size_t)packTotal; + + res = Progress(progress, unpackTotal + p->srcPos, packTotal); + if (res != SZ_OK) + break; + + /* + if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0) + break; + */ + + if (packSize == 0) + break; + } + + LzmaEnc_Finish(p->enc); + + unpackTotal += p->srcPos; + + RINOK(res); + + if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur)) + return SZ_ERROR_FAIL; + + if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize)) + { + if (finished) + { + if (outBuf) + { + const size_t destPos = *outBufSize; + if (destPos >= outLim) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos] = LZMA2_CONTROL_EOF; // 0 + *outBufSize = destPos + 1; + } + else + { + const Byte b = LZMA2_CONTROL_EOF; // 0; + if (ISeqOutStream_Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + } + return SZ_OK; + } + } +} + + + +#ifndef _7ZIP_ST + +static SRes Lzma2Enc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t destSize = me->outBufSize; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + me->outBufsDataSizes[outBufIndex] = 0; + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + progressThunk.inSize = 0; + progressThunk.outSize = 0; + + res = Lzma2Enc_EncodeMt1(me, + &me->coders[coderIndex], + NULL, dest, &destSize, + NULL, src, srcSize, + finished, + &progressThunk.vt); + + me->outBufsDataSizes[outBufIndex] = destSize; + + return res; +} + + +static SRes Lzma2Enc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CLzma2Enc *me = (CLzma2Enc *)pp; + size_t size = me->outBufsDataSizes[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + if (me->outStream) + return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE; + + if (size > me->outBuf_Rem) + return SZ_ERROR_OUTPUT_EOF; + memcpy(me->outBuf, data, size); + me->outBuf_Rem -= size; + me->outBuf += size; + return SZ_OK; +} + +#endif + + + +SRes Lzma2Enc_Encode2(CLzma2EncHandle pp, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + ICompressProgress *progress) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + + if (inStream && inData) + return SZ_ERROR_PARAM; + + if (outStream && outBuf) + return SZ_ERROR_PARAM; + + { + unsigned i; + for (i = 0; i < MTCODER__THREADS_MAX; i++) + p->coders[i].propsAreSet = False; + } + + #ifndef _7ZIP_ST + + if (p->props.numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = Lzma2Enc_MtCallback_Code; + vt.Write = Lzma2Enc_MtCallback_Write; + + p->outStream = outStream; + p->outBuf = NULL; + p->outBuf_Rem = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBuf_Rem = *outBufSize; + *outBufSize = 0; + } + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = inData; + p->mtCoder.inDataSize = inDataSize; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + p->mtCoder.blockSize = (size_t)p->props.blockSize; + if (p->mtCoder.blockSize != p->props.blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16; + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + Lzma2Enc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + { + SRes res = MtCoder_Code(&p->mtCoder); + if (!outStream) + *outBufSize = (size_t)(p->outBuf - outBuf); + return res; + } + } + + #endif + + + return Lzma2Enc_EncodeMt1(p, + &p->coders[0], + outStream, outBuf, outBufSize, + inStream, inData, inDataSize, + True, /* finished */ + progress); +} diff --git a/3rdparty/lzma-21.03beta/C/Lzma2Enc.h b/3rdparty/lzma-21.03beta/C/Lzma2Enc.h new file mode 100644 index 0000000..6a6110f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma2Enc.h @@ -0,0 +1,55 @@ +/* Lzma2Enc.h -- LZMA2 Encoder +2017-07-27 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_ENC_H +#define __LZMA2_ENC_H + +#include "LzmaEnc.h" + +EXTERN_C_BEGIN + +#define LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO 0 +#define LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID ((UInt64)(Int64)-1) + +typedef struct +{ + CLzmaEncProps lzmaProps; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; +} CLzma2EncProps; + +void Lzma2EncProps_Init(CLzma2EncProps *p); +void Lzma2EncProps_Normalize(CLzma2EncProps *p); + +/* ---------- CLzmaEnc2Handle Interface ---------- */ + +/* Lzma2Enc_* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2EncHandle; + +CLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void Lzma2Enc_Destroy(CLzma2EncHandle p); +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); +void Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize); +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); +SRes Lzma2Enc_Encode2(CLzma2EncHandle p, + ISeqOutStream *outStream, + Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + const Byte *inData, size_t inDataSize, + ICompressProgress *progress); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Lzma86.h b/3rdparty/lzma-21.03beta/C/Lzma86.h new file mode 100644 index 0000000..bebed5c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma86.h @@ -0,0 +1,111 @@ +/* Lzma86.h -- LZMA + x86 (BCJ) Filter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA86_H +#define __LZMA86_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA86_SIZE_OFFSET (1 + 5) +#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) + +/* +It's an example for LZMA + x86 Filter use. +You can use .lzma86 extension, if you write that stream to file. +.lzma86 header adds one additional byte to standard .lzma header. +.lzma86 header (14 bytes): + Offset Size Description + 0 1 = 0 - no filter, pure LZMA + = 1 - x86 filter + LZMA + 1 1 lc, lp and pb in encoded form + 2 4 dictSize (little endian) + 6 8 uncompressed size (little endian) + + +Lzma86_Encode +------------- +level - compression level: 0 <= level <= 9, the default value for "level" is 5. + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes, for level = 5. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + For better compression ratio dictSize must be >= inSize. + +filterMode: + SZ_FILTER_NO - no Filter + SZ_FILTER_YES - x86 Filter + SZ_FILTER_AUTO - it tries both alternatives to select best. + Encoder will use 2 or 3 passes: + 2 passes when FILTER_NO provides better compression. + 3 passes when FILTER_YES provides better compression. + +Lzma86Encode allocates Data with MyAlloc functions. +RAM Requirements for compressing: + RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize + filterMode FilterBlockSize + SZ_FILTER_NO 0 + SZ_FILTER_YES inSize + SZ_FILTER_AUTO inSize + + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +enum ESzFilterMode +{ + SZ_FILTER_NO, + SZ_FILTER_YES, + SZ_FILTER_AUTO +}; + +SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode); + + +/* +Lzma86_GetUnpackSize: + In: + src - input data + srcLen - input data size + Out: + unpackSize - size of uncompressed stream + Return code: + SZ_OK - OK + SZ_ERROR_INPUT_EOF - Error in headers +*/ + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); + +/* +Lzma86_Decode: + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + Out: + destLen - processed output size + srcLen - processed input size + Return code: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - unsupported file + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer +*/ + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Lzma86Dec.c b/3rdparty/lzma-21.03beta/C/Lzma86Dec.c new file mode 100644 index 0000000..2103174 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma86Dec.c @@ -0,0 +1,54 @@ +/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder +2016-05-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaDec.h" + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) +{ + unsigned i; + if (srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + *unpackSize = 0; + for (i = 0; i < sizeof(UInt64); i++) + *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); + return SZ_OK; +} + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) +{ + SRes res; + int useFilter; + SizeT inSizePure; + ELzmaStatus status; + + if (*srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + + useFilter = src[0]; + + if (useFilter > 1) + { + *destLen = 0; + return SZ_ERROR_UNSUPPORTED; + } + + inSizePure = *srcLen - LZMA86_HEADER_SIZE; + res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, + src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); + *srcLen = inSizePure + LZMA86_HEADER_SIZE; + if (res != SZ_OK) + return res; + if (useFilter == 1) + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(dest, *destLen, 0, &x86State, 0); + } + return SZ_OK; +} diff --git a/3rdparty/lzma-21.03beta/C/Lzma86Enc.c b/3rdparty/lzma-21.03beta/C/Lzma86Enc.c new file mode 100644 index 0000000..14fcd65 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Lzma86Enc.c @@ -0,0 +1,104 @@ +/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder +2018-07-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaEnc.h" + +int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode) +{ + size_t outSize2 = *destLen; + Byte *filteredStream; + BoolInt useFilter; + int mainResult = SZ_ERROR_OUTPUT_EOF; + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + + *destLen = 0; + if (outSize2 < LZMA86_HEADER_SIZE) + return SZ_ERROR_OUTPUT_EOF; + + { + int i; + UInt64 t = srcLen; + for (i = 0; i < 8; i++, t >>= 8) + dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; + } + + filteredStream = 0; + useFilter = (filterMode != SZ_FILTER_NO); + if (useFilter) + { + if (srcLen != 0) + { + filteredStream = (Byte *)MyAlloc(srcLen); + if (filteredStream == 0) + return SZ_ERROR_MEM; + memcpy(filteredStream, src, srcLen); + } + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(filteredStream, srcLen, 0, &x86State, 1); + } + } + + { + size_t minSize = 0; + BoolInt bestIsFiltered = False; + + /* passes for SZ_FILTER_AUTO: + 0 - BCJ + LZMA + 1 - LZMA + 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. + */ + int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; + + int i; + for (i = 0; i < numPasses; i++) + { + size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; + size_t outPropsSize = 5; + SRes curRes; + BoolInt curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); + if (curModeIsFiltered && !bestIsFiltered) + break; + if (useFilter && i == 0) + curModeIsFiltered = True; + + curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, + curModeIsFiltered ? filteredStream : src, srcLen, + &props, dest + 1, &outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); + + if (curRes != SZ_ERROR_OUTPUT_EOF) + { + if (curRes != SZ_OK) + { + mainResult = curRes; + break; + } + if (outSizeProcessed <= minSize || mainResult != SZ_OK) + { + minSize = outSizeProcessed; + bestIsFiltered = curModeIsFiltered; + mainResult = SZ_OK; + } + } + } + dest[0] = (Byte)(bestIsFiltered ? 1 : 0); + *destLen = LZMA86_HEADER_SIZE + minSize; + } + if (useFilter) + MyFree(filteredStream); + return mainResult; +} diff --git a/3rdparty/lzma-21.03beta/C/LzmaDec.c b/3rdparty/lzma-21.03beta/C/LzmaDec.c new file mode 100644 index 0000000..d6742e5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaDec.c @@ -0,0 +1,1363 @@ +/* LzmaDec.c -- LZMA Decoder +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #include "CpuArch.h" */ +#include "LzmaDec.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) + +#define RC_INIT_SIZE 5 + +#ifndef _LZMA_DEC_OPT + +#define kNumMoveBits 5 +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } + +#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); } + +#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \ + { UPDATE_0(p + i); A0; } else \ + { UPDATE_1(p + i); A1; } +#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; ) +#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; ) +#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; ) + +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol) +#define MATCHED_LITER_DEC \ + matchByte += matchByte; \ + bit = offs; \ + offs &= matchByte; \ + probLit = prob + (offs + bit + symbol); \ + GET_BIT2(probLit, symbol, offs ^= bit; , ;) + +#endif // _LZMA_DEC_OPT + + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \ + { UPDATE_0_CHECK; i += m; m += m; } else \ + { UPDATE_1_CHECK; m += m; i += m; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenLow 0 +#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +#define LenChoice LenLow +#define LenChoice2 (LenLow + (1 << kLenNumLowBits)) + +#define kNumStates 12 +#define kNumStates2 16 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +#define kMatchSpecLen_Error_Data (1 << 9) +#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1) + +/* External ASM code needs same CLzmaProb array layout. So don't change it. */ + +/* (probs_1664) is faster and better for code size at some platforms */ +/* +#ifdef MY_CPU_X86_OR_AMD64 +*/ +#define kStartOffset 1664 +#define GET_PROBS p->probs_1664 +/* +#define GET_PROBS p->probs + kStartOffset +#else +#define kStartOffset 0 +#define GET_PROBS p->probs +#endif +*/ + +#define SpecPos (-kStartOffset) +#define IsRep0Long (SpecPos + kNumFullDistances) +#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) +#define LenCoder (RepLenCoder + kNumLenProbs) +#define IsMatch (LenCoder + kNumLenProbs) +#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax)) +#define IsRep (Align + kAlignTableSize) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define PosSlot (IsRepG2 + kNumStates) +#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define NUM_BASE_PROBS (Literal + kStartOffset) + +#if Align != 0 && kStartOffset != 0 + #error Stop_Compiling_Bad_LZMA_kAlign +#endif + +#if NUM_BASE_PROBS != 1984 + #error Stop_Compiling_Bad_LZMA_PROBS +#endif + + +#define LZMA_LIT_SIZE 0x300 + +#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + + +#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4) +#define COMBINED_PS_STATE (posState + state) +#define GET_LEN_STATE (posState) + +#define LZMA_DIC_MIN (1 << 12) + +/* +p->remainLen : shows status of LZMA decoder: + < kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + = kMatchSpecLenStart + 1 : need init range coder + = kMatchSpecLenStart + 2 : need init range coder and state + = kMatchSpecLen_Error_Fail : Internal Code Failure + = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error +*/ + +/* ---------- LZMA_DECODE_REAL ---------- */ +/* +LzmaDec_DecodeReal_3() can be implemented in external ASM file. +3 - is the code compatibility version of that function for check at link time. +*/ + +#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3 + +/* +LZMA_DECODE_REAL() +In: + RangeCoder is normalized + if (p->dicPos == limit) + { + LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. + So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol + is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary, + the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later. + } + +Processing: + The first LZMA symbol will be decoded in any case. + All main checks for limits are at the end of main loop, + It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit), + RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. + But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for + next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX), + that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit. + So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte. + +Out: + RangeCoder is normalized + Result: + SZ_OK - OK + p->remainLen: + < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset + = kMatchSpecLenStart : the LZMA stream was finished with end mark + + SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary + p->remainLen : undefined + p->reps[*] : undefined +*/ + + +#ifdef _LZMA_DEC_OPT + +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); + +#else + +static +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lc = p->prop.lc; + unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(processedPos, pbMask); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (processedPos != 0 || checkDicSize != 0) + prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); + processedPos++; + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif + } + else + { + unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + } + while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif + } + + dic[dicPos++] = (Byte)symbol; + continue; + } + + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + UPDATE_0(prob); + + // that case was checked before with kBadRepCode + // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; } + // The caller doesn't allow (dicPos == limit) case here + // so we don't need the following check: + // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; } + + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + + #ifdef _LZMA_SIZE_OPT + { + unsigned lim, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + lim = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, lim, len); + len += offset; + } + #else + { + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + len -= 8; + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + TREE_DECODE(probLen, (1 << kLenNumHighBits), len); + len += kLenNumLowSymbols * 2; + } + } + } + #endif + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos; + { + UInt32 m = 1; + distance++; + do + { + REV_BIT_VAR(prob, distance, m); + } + while (--numDirectBits); + distance -= m; + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + REV_BIT_CONST(prob, i, 1); + REV_BIT_CONST(prob, i, 2); + REV_BIT_CONST(prob, i, 4); + REV_BIT_LAST (prob, i, 8); + distance |= i; + } + if (distance == (UInt32)0xFFFFFFFF) + { + len = kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + { + len += kMatchSpecLen_Error_Data + kMatchMinLen; + // len = kMatchSpecLen_Error_Data; + // len += kMatchMinLen; + break; + } + } + + len += kMatchMinLen; + + { + SizeT rem; + unsigned curLen; + SizeT pos; + + if ((rem = limit - dicPos) == 0) + { + /* + We stop decoding and return SZ_OK, and we can resume decoding later. + Any error conditions can be tested later in caller code. + For more strict mode we can stop decoding with error + // len += kMatchSpecLen_Error_Data; + */ + break; + } + + curLen = ((rem < len) ? (unsigned)rem : len); + pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + + processedPos += (UInt32)curLen; + + len -= curLen; + if (curLen <= dicBufSize - pos) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += (SizeT)curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + + NORMALIZE; + + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too. + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = (UInt32)state; + if (len >= kMatchSpecLen_Error_Data) + return SZ_ERROR_DATA; + return SZ_OK; +} +#endif + + + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + unsigned len = (unsigned)p->remainLen; + if (len == 0 /* || len >= kMatchSpecLenStart */) + return; + { + SizeT dicPos = p->dicPos; + Byte *dic; + SizeT dicBufSize; + SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ + { + SizeT rem = limit - dicPos; + if (rem < len) + { + len = (unsigned)(rem); + if (len == 0) + return; + } + } + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += (UInt32)len; + p->remainLen -= (UInt32)len; + dic = p->dic; + rep0 = p->reps[0]; + dicBufSize = p->dicBufSize; + do + { + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + } + while (--len); + p->dicPos = dicPos; + } +} + + +/* +At staring of new stream we have one of the following symbols: + - Literal - is allowed + - Non-Rep-Match - is allowed only if it's end marker symbol + - Rep-Match - is not allowed +We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code +*/ + +#define kRange0 0xFFFFFFFF +#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) +#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) +#if kBadRepCode != (0xC0000000 - 0x400) + #error Stop_Compiling_Bad_LZMA_Check +#endif + + +/* +LzmaDec_DecodeReal2(): + It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize). + +We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(), +and we support the following state of (p->checkDicSize): + if (total_processed < p->prop.dicSize) then + { + (total_processed == p->processedPos) + (p->checkDicSize == 0) + } + else + (p->checkDicSize == p->prop.dicSize) +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit = p->dicPos + rem; + } + { + int res = LZMA_DECODE_REAL(p, limit, bufLimit); + if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + return res; + } +} + + + +typedef enum +{ + DUMMY_INPUT_EOF, /* need more input data */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + + +#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH) + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = *bufOut; + const CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + ELzmaDummy res; + + for (;;) + { + const CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += ((UInt32)LZMA_LIT_SIZE * + ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) + + ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + (p->dicPos < p->reps[0] ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + const CLzmaProb *probLit; + matchByte += matchByte; + bit = offs; + offs &= matchByte; + probLit = prob + (offs + bit + symbol); + GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; ) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + break; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + const CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + unsigned numDirectBits = ((posSlot >> 1) - 1); + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + unsigned m = 1; + do + { + REV_BIT_CHECK(prob, i, m); + } + while (--numDirectBits); + } + } + } + } + break; + } + NORMALIZE_CHECK; + + *bufOut = buf; + return res; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState) +{ + p->remainLen = kMatchSpecLenStart + 1; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->remainLen = kMatchSpecLenStart + 2; + } + if (initState) + p->remainLen = kMatchSpecLenStart + 2; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + + +/* +LZMA supports optional end_marker. +So the decoder can lookahead for one additional LZMA-Symbol to check end_marker. +That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream. +When the decoder reaches dicLimit, it looks (finishMode) parameter: + if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead + if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position + +When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways: + 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA. + 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller + must check (status) value. The caller can show the error, + if the end of stream is expected, and the (status) is noit + LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK. +*/ + + +#define RETURN__NOT_FINISHED__FOR_FINISH \ + *status = LZMA_STATUS_NOT_FINISHED; \ + return SZ_ERROR_DATA; // for strict mode + // return SZ_OK; // for relaxed mode + + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + if (p->remainLen > kMatchSpecLenStart) + { + if (p->remainLen > kMatchSpecLenStart + 2) + return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA; + + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize != 0 && p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + p->code = + ((UInt32)p->tempBuf[1] << 24) + | ((UInt32)p->tempBuf[2] << 16) + | ((UInt32)p->tempBuf[3] << 8) + | ((UInt32)p->tempBuf[4]); + + if (p->checkDicSize == 0 + && p->processedPos == 0 + && p->code >= kBadRepCode) + return SZ_ERROR_DATA; + + p->range = 0xFFFFFFFF; + p->tempBufSize = 0; + + if (p->remainLen > kMatchSpecLenStart + 1) + { + SizeT numProbs = LzmaProps_GetNumProbs(&p->prop); + SizeT i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + } + + p->remainLen = 0; + } + + for (;;) + { + if (p->remainLen == kMatchSpecLenStart) + { + if (p->code != 0) + return SZ_ERROR_DATA; + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + + LzmaDec_WriteRem(p, dicLimit); + + { + // (p->remainLen == 0 || p->dicPos == dicLimit) + + int checkEndMarkNow = 0; + + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + RETURN__NOT_FINISHED__FOR_FINISH; + } + checkEndMarkNow = 1; + } + + // (p->remainLen == 0) + + if (p->tempBufSize == 0) + { + const Byte *bufLimit; + int dummyProcessed = -1; + + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + const Byte *bufOut = src + inSize; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) + { + size_t i; + if (inSize >= LZMA_REQUIRED_INPUT_MAX) + break; + (*srcLen) += inSize; + p->tempBufSize = (unsigned)inSize; + for (i = 0; i < inSize; i++) + p->tempBuf[i] = src[i]; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + dummyProcessed = (int)(bufOut - src); + if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) + { + unsigned i; + (*srcLen) += (unsigned)dummyProcessed; + p->tempBufSize = (unsigned)dummyProcessed; + for (i = 0; i < (unsigned)dummyProcessed; i++) + p->tempBuf[i] = src[i]; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; + } + + bufLimit = src; + // we will decode only one iteration + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + + p->buf = src; + + { + int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit); + + SizeT processed = (SizeT)(p->buf - src); + + if (dummyProcessed < 0) + { + if (processed > inSize) + break; + } + else if ((unsigned)dummyProcessed != processed) + break; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + + if (res != SZ_OK) + { + p->remainLen = kMatchSpecLen_Error_Data; + return SZ_ERROR_DATA; + } + } + continue; + } + + { + // we have some data in (p->tempBuf) + // in strict mode: tempBufSize is not enough for one Symbol decoding. + // in relaxed mode: tempBufSize not larger than required for one Symbol decoding. + + unsigned rem = p->tempBufSize; + unsigned ahead = 0; + int dummyProcessed = -1; + + while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize) + p->tempBuf[rem++] = src[ahead++]; + + // ahead - the size of new data copied from (src) to (p->tempBuf) + // rem - the size of temp buffer including new data from (src) + + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + const Byte *bufOut = p->tempBuf + rem; + + ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut); + + if (dummyRes == DUMMY_INPUT_EOF) + { + if (rem >= LZMA_REQUIRED_INPUT_MAX) + break; + p->tempBufSize = rem; + (*srcLen) += (SizeT)ahead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + dummyProcessed = (int)(bufOut - p->tempBuf); + + if ((unsigned)dummyProcessed < p->tempBufSize) + break; + + if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes)) + { + (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize; + p->tempBufSize = (unsigned)dummyProcessed; + // p->remainLen = kMatchSpecLen_Error_Data; + RETURN__NOT_FINISHED__FOR_FINISH; + } + } + + p->buf = p->tempBuf; + + { + // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf) + int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf); + + SizeT processed = (SizeT)(p->buf - p->tempBuf); + rem = p->tempBufSize; + + if (dummyProcessed < 0) + { + if (processed > LZMA_REQUIRED_INPUT_MAX) + break; + if (processed < rem) + break; + } + else if ((unsigned)dummyProcessed != processed) + break; + + processed -= rem; + + src += processed; + inSize -= processed; + (*srcLen) += processed; + p->tempBufSize = 0; + + if (res != SZ_OK) + { + p->remainLen = kMatchSpecLen_Error_Data; + return SZ_ERROR_DATA; + } + } + } + } + } + + /* Some unexpected error: internal error of code, memory corruption or hardware failure */ + p->remainLen = kMatchSpecLen_Error_Fail; + return SZ_ERROR_FAIL; +} + + + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->probs); + p->probs = NULL; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->dic); + p->dic = NULL; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = (Byte)(d % 9); + d /= 9; + p->pb = (Byte)(d / 5); + p->lp = (Byte)(d % 5); + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (!p->probs || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb)); + if (!p->probs) + return SZ_ERROR_MEM; + p->probs_1664 = p->probs + 1664; + p->numProbs = numProbs; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + + { + UInt32 dictSize = propNew.dicSize; + SizeT mask = ((UInt32)1 << 12) - 1; + if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1; + else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;; + dicBufSize = ((SizeT)dictSize + mask) & ~mask; + if (dicBufSize < dictSize) + dicBufSize = dictSize; + } + + if (!p->dic || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize); + if (!p->dic) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc) +{ + CLzmaDec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + LzmaDec_Construct(&p); + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); + p.dic = dest; + p.dicBufSize = outSize; + LzmaDec_Init(&p); + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/3rdparty/lzma-21.03beta/C/LzmaDec.h b/3rdparty/lzma-21.03beta/C/LzmaDec.h new file mode 100644 index 0000000..6f12962 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaDec.h @@ -0,0 +1,236 @@ +/* LzmaDec.h -- LZMA Decoder +2020-03-19 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + Byte lc; + Byte lp; + Byte pb; + Byte _pad_; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + /* Don't change this structure. ASM code can use it. */ + CLzmaProps prop; + CLzmaProb *probs; + CLzmaProb *probs_1664; + Byte *dic; + SizeT dicBufSize; + SizeT dicPos; + const Byte *buf; + UInt32 range; + UInt32 code; + UInt32 processedPos; + UInt32 checkDicSize; + UInt32 reps[4]; + UInt32 state; + UInt32 remainLen; + + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + - Stream with end mark. That end mark adds about 6 bytes to compressed size. + - Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Construct() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/LzmaEnc.c b/3rdparty/lzma-21.03beta/C/LzmaEnc.c new file mode 100644 index 0000000..832e414 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaEnc.c @@ -0,0 +1,3163 @@ +/* LzmaEnc.c -- LZMA Encoder +2021-07-10: Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "CpuArch.h" +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifndef _7ZIP_ST +#include "LzFindMt.h" +#endif + +/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */ + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + +#ifdef SHOW_STAT +static unsigned g_STAT_OFFSET = 0; +#endif + +/* for good normalization speed we still reserve 256 MB before 4 GB range */ +#define kLzmaMaxHistorySize ((UInt32)15 << 28) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +// #define kBitPrice (1 << kNumBitPriceShiftBits) + +#define REP_LEN_COUNT 64 + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->reduceSize = (UInt64)(Int64)-1; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; + p->affinity = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + + if (p->dictSize == 0) + p->dictSize = + ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : + ( level <= 6 ? ((UInt32)1 << (level + 19)) : + ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) + ))); + + if (p->dictSize > p->reduceSize) + { + UInt32 v = (UInt32)p->reduceSize; + const UInt32 kReduceMin = ((UInt32)1 << 12); + if (v < kReduceMin) + v = kReduceMin; + if (p->dictSize > v) + p->dictSize = v; + } + + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5); + if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1); + + if (p->numThreads < 0) + p->numThreads = + #ifndef _7ZIP_ST + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + + +/* +x86/x64: + +BSR: + IF (SRC == 0) ZF = 1, DEST is undefined; + AMD : DEST is unchanged; + IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit + BSR is slow in some processors + +LZCNT: + IF (SRC == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64) + IF (SRC != 0) CF = 0, DEST = num_lead_zero_bits + IF (DEST == 0) ZF = 1; + +LZCNT works only in new processors starting from Haswell. +if LZCNT is not supported by processor, then it's executed as BSR. +LZCNT can be faster than BSR, if supported. +*/ + +// #define LZMA_LOG_BSR + +#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */ + + #if (defined(__clang__) && (__clang_major__ >= 6)) \ + || (defined(__GNUC__) && (__GNUC__ >= 6)) + #define LZMA_LOG_BSR + #elif defined(_MSC_VER) && (_MSC_VER >= 1300) + // #if defined(MY_CPU_ARM_OR_ARM64) + #define LZMA_LOG_BSR + // #endif + #endif +#endif + +// #include + +#ifdef LZMA_LOG_BSR + +#if defined(__clang__) \ + || defined(__GNUC__) + +/* + C code: : (30 - __builtin_clz(x)) + gcc9/gcc10 for x64 /x86 : 30 - (bsr(x) xor 31) + clang10 for x64 : 31 + (bsr(x) xor -32) +*/ + + #define MY_clz(x) ((unsigned)__builtin_clz(x)) + // __lzcnt32 + // __builtin_ia32_lzcnt_u32 + +#else // #if defined(_MSC_VER) + + #ifdef MY_CPU_ARM_OR_ARM64 + + #define MY_clz _CountLeadingZeros + + #else // if defined(MY_CPU_X86_OR_AMD64) + + // #define MY_clz __lzcnt // we can use lzcnt (unsupported by old CPU) + // _BitScanReverse code is not optimal for some MSVC compilers + #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \ + res = (zz + zz) + (pos >> zz); } + + #endif // MY_CPU_X86_OR_AMD64 + +#endif // _MSC_VER + + +#ifndef BSR2_RET + + #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \ + res = (zz + zz) + (pos >> zz); } + +#endif + + +unsigned GetPosSlot1(UInt32 pos); +unsigned GetPosSlot1(UInt32 pos) +{ + unsigned res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + + +#else // ! LZMA_LOG_BSR + +#define kNumLogBits (11 + sizeof(size_t) / 8 * 3) + +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +static void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + unsigned slot; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + g_FastPos += 2; + + for (slot = 2; slot < kNumLogBits * 2; slot++) + { + size_t k = ((size_t)1 << ((slot >> 1) - 1)); + size_t j; + for (j = 0; j < k; j++) + g_FastPos[j] = (Byte)slot; + g_FastPos += k; + } +} + +/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */ +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } + +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } + +#endif // LZMA_LOG_BSR + + +#define LZMA_NUM_REPS 4 + +typedef UInt16 CState; +typedef UInt16 CExtra; + +typedef struct +{ + UInt32 price; + CState state; + CExtra extra; + // 0 : normal + // 1 : LIT : MATCH + // > 1 : MATCH (extra-1) : LIT : REP0 (len) + UInt32 len; + UInt32 dist; + UInt32 reps[LZMA_NUM_REPS]; +} COptimal; + + +// 18.06 +#define kNumOpts (1 << 11) +#define kPackReserve (kNumOpts * 8) +// #define kNumOpts (1 << 12) +// #define kPackReserve (1 + kNumOpts * 2) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +// #define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) +#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + + +typedef struct +{ + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + + +typedef struct +{ + unsigned tableSize; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2]; + // UInt32 prices2[kLenNumSymbolsTotal]; +} CLenPriceEnc; + +#define GET_PRICE_LEN(p, posState, len) \ + ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN]) + +/* +#define GET_PRICE_LEN(p, posState, len) \ + ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9))) +*/ + +typedef struct +{ + UInt32 range; + unsigned cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + + +typedef struct +{ + CLzmaProb *litProbs; + + unsigned state; + UInt32 reps[LZMA_NUM_REPS]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + +} CSaveState; + + +typedef UInt32 CProbPrice; + + +typedef struct +{ + void *matchFinderObj; + IMatchFinder2 matchFinder; + + unsigned optCur; + unsigned optEnd; + + unsigned longestMatchLen; + unsigned numPairs; + UInt32 numAvail; + + unsigned state; + unsigned numFastBytes; + unsigned additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + unsigned lpMask, pbMask; + CLzmaProb *litProbs; + CRangeEnc rc; + + UInt32 backRes; + + unsigned lc, lp, pb; + unsigned lclp; + + BoolInt fastMode; + BoolInt writeEndMark; + BoolInt finished; + BoolInt multiThread; + BoolInt needInit; + // BoolInt _maxMode; + + UInt64 nowPos64; + + unsigned matchPriceCount; + // unsigned alignPriceCount; + int repLenEncCounter; + + unsigned distTableSize; + + UInt32 dictSize; + SRes result; + + #ifndef _7ZIP_ST + BoolInt mtMode; + // begin of CMatchFinderMt is used in LZ thread + CMatchFinderMt matchFinderMt; + // end of CMatchFinderMt is used in BT and HASH threads + // #else + // CMatchFinder matchFinderBase; + #endif + CMatchFinder matchFinderBase; + + + // we suppose that we have 8-bytes alignment after CMatchFinder + + #ifndef _7ZIP_ST + Byte pad[128]; + #endif + + // LZ thread + CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + + // we want {len , dist} pairs to be 8-bytes aligned in matches array + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2]; + + // we want 8-bytes alignment here + UInt32 alignPrices[kAlignTableSize]; + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + COptimal opt[kNumOpts]; + + CSaveState saveState; + + // BoolInt mf_Failure; + #ifndef _7ZIP_ST + Byte pad2[128]; + #endif +} CLzmaEnc; + + +#define MFB (p->matchFinderBase) +/* +#ifndef _7ZIP_ST +#define MFB (p->matchFinderMt.MatchFinder) +#endif +*/ + +#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb)); +} + + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + + + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX + || props.lp > LZMA_LP_MAX + || props.pb > LZMA_PB_MAX) + return SZ_ERROR_PARAM; + + + if (props.dictSize > kLzmaMaxHistorySize) + props.dictSize = kLzmaMaxHistorySize; + + #ifndef LZMA_LOG_BSR + { + const UInt64 dict64 = props.dictSize; + if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress)) + return SZ_ERROR_PARAM; + } + #endif + + p->dictSize = props.dictSize; + { + unsigned fb = (unsigned)props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = (unsigned)props.lc; + p->lp = (unsigned)props.lp; + p->pb = (unsigned)props.pb; + p->fastMode = (props.algo == 0); + // p->_maxMode = True; + MFB.btMode = (Byte)(props.btMode ? 1 : 0); + { + unsigned numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) numHashBytes = 2; + else if (props.numHashBytes < 4) numHashBytes = (unsigned)props.numHashBytes; + } + if (props.numHashBytes >= 5) numHashBytes = 5; + + MFB.numHashBytes = numHashBytes; + } + + MFB.cutValue = props.mc; + + p->writeEndMark = (BoolInt)props.writeEndMark; + + #ifndef _7ZIP_ST + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + p->matchFinderMt.btSync.affinity = + p->matchFinderMt.hashSync.affinity = props.affinity; + #endif + + return SZ_OK; +} + + +void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + MFB.expectedDataSize = expectedDataSiize; +} + + +#define kState_Start 0 +#define kState_LitAfterMatch 4 +#define kState_LitAfterRep 5 +#define kState_MatchAfterLit 7 +#define kState_RepAfterLit 8 + +static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsLitState(s) ((s) < 7) +#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1) +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = NULL; + p->bufBase = NULL; +} + +#define RangeEnc_GetProcessed(p) ( (p)->processed + (size_t)((p)->buf - (p)->bufBase) + (p)->cacheSize) +#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) + +static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) +{ + if (!p->bufBase) + { + p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE); + if (!p->bufBase) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->range = 0xFFFFFFFF; + p->cache = 0; + p->low = 0; + p->cacheSize = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = (size_t)(p->buf - p->bufBase); + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + UInt32 low = (UInt32)p->low; + unsigned high = (unsigned)(p->low >> 32); + p->low = (UInt32)(low << 8); + if (low < (UInt32)0xFF000000 || high != 0) + { + { + Byte *buf = p->buf; + *buf++ = (Byte)(p->cache + high); + p->cache = (unsigned)(low >> 24); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (p->cacheSize == 0) + return; + } + high += 0xFF; + for (;;) + { + Byte *buf = p->buf; + *buf++ = (Byte)(high); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (--p->cacheSize == 0) + return; + } + } + p->cacheSize++; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); } + +#define RC_BIT_PRE(p, prob) \ + ttt = *(prob); \ + newBound = (range >> kNumBitModelTotalBits) * ttt; + +// #define _LZMA_ENC_USE_BRANCH + +#ifdef _LZMA_ENC_USE_BRANCH + +#define RC_BIT(p, prob, bit) { \ + RC_BIT_PRE(p, prob) \ + if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \ + else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#else + +#define RC_BIT(p, prob, bit) { \ + UInt32 mask; \ + RC_BIT_PRE(p, prob) \ + mask = 0 - (UInt32)bit; \ + range &= mask; \ + mask &= newBound; \ + range -= mask; \ + (p)->low += mask; \ + mask = (UInt32)bit - 1; \ + range += newBound & mask; \ + mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ + mask += ((1 << kNumMoveBits) - 1); \ + ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#endif + + + + +#define RC_BIT_0_BASE(p, prob) \ + range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + +#define RC_BIT_1_BASE(p, prob) \ + range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \ + +#define RC_BIT_0(p, prob) \ + RC_BIT_0_BASE(p, prob) \ + RC_NORM(p) + +#define RC_BIT_1(p, prob) \ + RC_BIT_1_BASE(p, prob) \ + RC_NORM(p) + +static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob) +{ + UInt32 range, ttt, newBound; + range = p->range; + RC_BIT_PRE(p, prob) + RC_BIT_0(p, prob) + p->range = range; +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym) +{ + UInt32 range = p->range; + sym |= 0x100; + do + { + UInt32 ttt, newBound; + // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1); + CLzmaProb *prob = probs + (sym >> 8); + UInt32 bit = (sym >> 7) & 1; + sym <<= 1; + RC_BIT(p, prob, bit); + } + while (sym < 0x10000); + p->range = range; +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte) +{ + UInt32 range = p->range; + UInt32 offs = 0x100; + sym |= 0x100; + do + { + UInt32 ttt, newBound; + CLzmaProb *prob; + UInt32 bit; + matchByte <<= 1; + // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1); + prob = probs + (offs + (matchByte & offs) + (sym >> 8)); + bit = (sym >> 7) & 1; + sym <<= 1; + offs &= ~(matchByte ^ sym); + RC_BIT(p, prob, bit); + } + while (sym < 0x10000); + p->range = range; +} + + + +static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) +{ + UInt32 i; + for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++) + { + const unsigned kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1)); + unsigned bitCount = 0; + unsigned j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + // printf("\n%3d: %5d", i, ProbPrices[i]); + } +} + + +#define GET_PRICE(prob, bit) \ + p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, bit) \ + ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + sym |= 0x100; + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[sym], bit); + } + while (sym >= 2); + return price; +} + + +static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + sym |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1); + sym <<= 1; + offs &= ~(matchByte ^ sym); + } + while (sym < 0x10000); + return price; +} + + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym) +{ + UInt32 range = rc->range; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + unsigned bit = sym & 1; + // RangeEnc_EncodeBit(rc, probs + m, bit); + sym >>= 1; + RC_BIT(rc, probs + m, bit); + m = (m << 1) | bit; + } + while (--numBits); + rc->range = range; +} + + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState) +{ + UInt32 range, ttt, newBound; + CLzmaProb *probs = p->low; + range = rc->range; + RC_BIT_PRE(rc, probs); + if (sym >= kLenNumLowSymbols) + { + RC_BIT_1(rc, probs); + probs += kLenNumLowSymbols; + RC_BIT_PRE(rc, probs); + if (sym >= kLenNumLowSymbols * 2) + { + RC_BIT_1(rc, probs); + rc->range = range; + // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2); + LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2); + return; + } + sym -= kLenNumLowSymbols; + } + + // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym); + { + unsigned m; + unsigned bit; + RC_BIT_0(rc, probs); + probs += (posState << (1 + kLenNumLowBits)); + bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit; + bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit; + bit = sym & 1; RC_BIT(rc, probs + m, bit); + rc->range = range; + } +} + +static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices) +{ + unsigned i; + for (i = 0; i < 8; i += 2) + { + UInt32 price = startPrice; + UInt32 prob; + price += GET_PRICEa(probs[1 ], (i >> 2)); + price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1); + prob = probs[4 + (i >> 1)]; + prices[i ] = price + GET_PRICEa_0(prob); + prices[i + 1] = price + GET_PRICEa_1(prob); + } +} + + +MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables( + CLenPriceEnc *p, + unsigned numPosStates, + const CLenEnc *enc, + const CProbPrice *ProbPrices) +{ + UInt32 b; + + { + unsigned prob = enc->low[0]; + UInt32 a, c; + unsigned posState; + b = GET_PRICEa_1(prob); + a = GET_PRICEa_0(prob); + c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); + for (posState = 0; posState < numPosStates; posState++) + { + UInt32 *prices = p->prices[posState]; + const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits)); + SetPrices_3(probs, a, prices, ProbPrices); + SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices); + } + } + + /* + { + unsigned i; + UInt32 b; + a = GET_PRICEa_0(enc->low[0]); + for (i = 0; i < kLenNumLowSymbols; i++) + p->prices2[i] = a; + a = GET_PRICEa_1(enc->low[0]); + b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); + for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++) + p->prices2[i] = b; + a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); + } + */ + + // p->counter = numSymbols; + // p->counter = 64; + + { + unsigned i = p->tableSize; + + if (i > kLenNumLowSymbols * 2) + { + const CLzmaProb *probs = enc->high; + UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2; + i -= kLenNumLowSymbols * 2 - 1; + i >>= 1; + b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); + do + { + /* + p->prices2[i] = a + + // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices); + LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices); + */ + // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices); + unsigned sym = --i + (1 << (kLenNumHighBits - 1)); + UInt32 price = b; + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[sym], bit); + } + while (sym >= 2); + + { + unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))]; + prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob); + prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob); + } + } + while (i); + + { + unsigned posState; + size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]); + for (posState = 1; posState < numPosStates; posState++) + memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num); + } + } + } +} + +/* + #ifdef SHOW_STAT + g_STAT_OFFSET += num; + printf("\n MovePos %u", num); + #endif +*/ + +#define MOVE_POS(p, num) { \ + p->additionalOffset += (num); \ + p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); } + + +static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) +{ + unsigned numPairs; + + p->additionalOffset++; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + { + const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + // if (!d) { p->mf_Failure = True; *numPairsRes = 0; return 0; } + numPairs = (unsigned)(d - p->matches); + } + *numPairsRes = numPairs; + + #ifdef SHOW_STAT + printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2); + g_STAT_OFFSET++; + { + unsigned i; + for (i = 0; i < numPairs; i += 2) + printf("%2u %6u | ", p->matches[i], p->matches[i + 1]); + } + #endif + + if (numPairs == 0) + return 0; + { + const unsigned len = p->matches[(size_t)numPairs - 2]; + if (len != p->numFastBytes) + return len; + { + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + const Byte *p2 = p1 + len; + const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1]; + const Byte *lim = p1 + numAvail; + for (; p2 != lim && *p2 == p2[dif]; p2++) + {} + return (unsigned)(p2 - p1); + } + } + } +} + +#define MARK_LIT ((UInt32)(Int32)-1) + +#define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; } +#define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; } +#define IsShortRep(p) ((p)->dist == 0) + + +#define GetPrice_ShortRep(p, state, posState) \ + ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState])) + +#define GetPrice_Rep_0(p, state, posState) ( \ + GET_PRICE_1(p->isMatch[state][posState]) \ + + GET_PRICE_1(p->isRep0Long[state][posState])) \ + + GET_PRICE_1(p->isRep[state]) \ + + GET_PRICE_0(p->isRepG0[state]) + +MY_FORCE_INLINE +static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState) +{ + UInt32 price; + UInt32 prob = p->isRepG0[state]; + if (repIndex == 0) + { + price = GET_PRICE_0(prob); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(prob); + prob = p->isRepG1[state]; + if (repIndex == 1) + price += GET_PRICE_0(prob); + else + { + price += GET_PRICE_1(prob); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + + +static unsigned Backward(CLzmaEnc *p, unsigned cur) +{ + unsigned wr = cur + 1; + p->optEnd = wr; + + for (;;) + { + UInt32 dist = p->opt[cur].dist; + unsigned len = (unsigned)p->opt[cur].len; + unsigned extra = (unsigned)p->opt[cur].extra; + cur -= len; + + if (extra) + { + wr--; + p->opt[wr].len = (UInt32)len; + cur -= extra; + len = extra; + if (extra == 1) + { + p->opt[wr].dist = dist; + dist = MARK_LIT; + } + else + { + p->opt[wr].dist = 0; + len--; + wr--; + p->opt[wr].dist = MARK_LIT; + p->opt[wr].len = 1; + } + } + + if (cur == 0) + { + p->backRes = dist; + p->optCur = wr; + return len; + } + + wr--; + p->opt[wr].dist = dist; + p->opt[wr].len = (UInt32)len; + } +} + + + +#define LIT_PROBS(pos, prevByte) \ + (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc)) + + +static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) +{ + unsigned last, cur; + UInt32 reps[LZMA_NUM_REPS]; + unsigned repLens[LZMA_NUM_REPS]; + UInt32 *matches; + + { + UInt32 numAvail; + unsigned numPairs, mainLen, repMaxIndex, i, posState; + UInt32 matchPrice, repMatchPrice; + const Byte *data; + Byte curByte, matchByte; + + p->optCur = p->optEnd = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + p->backRes = MARK_LIT; + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization + break; + } + + if (repLens[repMaxIndex] >= p->numFastBytes) + { + unsigned len; + p->backRes = (UInt32)repMaxIndex; + len = repLens[repMaxIndex]; + MOVE_POS(p, len - 1) + return len; + } + + matches = p->matches; + #define MATCHES matches + // #define MATCHES p->matches + + if (mainLen >= p->numFastBytes) + { + p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + curByte = *data; + matchByte = *(data - reps[0]); + + last = repLens[repMaxIndex]; + if (last <= mainLen) + last = mainLen; + + if (last < 2 && curByte != matchByte) + { + p->backRes = MARK_LIT; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsLitState(p->state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAs_Lit(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + // 18.06 + if (matchByte == curByte && repLens[0] == 0) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAs_ShortRep(&p->opt[1]); + } + if (last < 2) + { + p->backRes = p->opt[1].dist; + return 1; + } + } + + p->opt[1].len = 1; + + p->opt[0].reps[0] = reps[0]; + p->opt[0].reps[1] = reps[1]; + p->opt[0].reps[2] = reps[2]; + p->opt[0].reps[3] = reps[3]; + + // ---------- REP ---------- + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState); + do + { + UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen); + COptimal *opt = &p->opt[repLen]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)repLen; + opt->dist = (UInt32)i; + opt->extra = 0; + } + } + while (--repLen >= 2); + } + + + // ---------- MATCH ---------- + { + unsigned len = repLens[0] + 1; + if (len <= mainLen) + { + unsigned offs = 0; + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + if (len < 2) + len = 2; + else + while (len > MATCHES[offs]) + offs += 2; + + for (; ; len++) + { + COptimal *opt; + UInt32 dist = MATCHES[(size_t)offs + 1]; + UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); + unsigned lenToPosState = GetLenToPosState(len); + + if (dist < kNumFullDistances) + price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)]; + else + { + unsigned slot; + GetPosSlot2(dist, slot); + price += p->alignPrices[dist & kAlignMask]; + price += p->posSlotPrices[lenToPosState][slot]; + } + + opt = &p->opt[len]; + + if (price < opt->price) + { + opt->price = price; + opt->len = (UInt32)len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + + if (len == MATCHES[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + } + + + cur = 0; + + #ifdef SHOW_STAT2 + /* if (position >= 0) */ + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= last; i++) + printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price); + } + #endif + } + + + + // ---------- Optimal Parsing ---------- + + for (;;) + { + unsigned numAvail; + UInt32 numAvailFull; + unsigned newLen, numPairs, prev, state, posState, startLen; + UInt32 litPrice, matchPrice, repMatchPrice; + BoolInt nextIsLit; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt, *nextOpt; + + if (++cur == last) + break; + + // 18.06 + if (cur >= kNumOpts - 64) + { + unsigned j, best; + UInt32 price = p->opt[cur].price; + best = cur; + for (j = cur + 1; j <= last; j++) + { + UInt32 price2 = p->opt[j].price; + if (price >= price2) + { + price = price2; + best = j; + } + } + { + unsigned delta = best - cur; + if (delta != 0) + { + MOVE_POS(p, delta); + } + } + cur = best; + break; + } + + newLen = ReadMatchDistances(p, &numPairs); + + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLen = newLen; + break; + } + + curOpt = &p->opt[cur]; + + position++; + + // we need that check here, if skip_items in p->opt are possible + /* + if (curOpt->price >= kInfinityPrice) + continue; + */ + + prev = cur - curOpt->len; + + if (curOpt->len == 1) + { + state = (unsigned)p->opt[prev].state; + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + const COptimal *prevOpt; + UInt32 b0; + UInt32 dist = curOpt->dist; + + if (curOpt->extra) + { + prev -= (unsigned)curOpt->extra; + state = kState_RepAfterLit; + if (curOpt->extra == 1) + state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit); + } + else + { + state = (unsigned)p->opt[prev].state; + if (dist < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + + prevOpt = &p->opt[prev]; + b0 = prevOpt->reps[0]; + + if (dist < LZMA_NUM_REPS) + { + if (dist == 0) + { + reps[0] = b0; + reps[1] = prevOpt->reps[1]; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[1] = b0; + b0 = prevOpt->reps[1]; + if (dist == 1) + { + reps[0] = b0; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[2] = b0; + reps[0] = prevOpt->reps[dist]; + reps[3] = prevOpt->reps[dist ^ 1]; + } + } + } + else + { + reps[0] = (dist - LZMA_NUM_REPS + 1); + reps[1] = b0; + reps[2] = prevOpt->reps[1]; + reps[3] = prevOpt->reps[2]; + } + } + + curOpt->state = (CState)state; + curOpt->reps[0] = reps[0]; + curOpt->reps[1] = reps[1]; + curOpt->reps[2] = reps[2]; + curOpt->reps[3] = reps[3]; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - reps[0]); + + posState = (position & p->pbMask); + + /* + The order of Price checks: + < LIT + <= SHORT_REP + < LIT : REP_0 + < REP [ : LIT : REP_0 ] + < MATCH [ : LIT : REP_0 ] + */ + + { + UInt32 curPrice = curOpt->price; + unsigned prob = p->isMatch[state][posState]; + matchPrice = curPrice + GET_PRICE_1(prob); + litPrice = curPrice + GET_PRICE_0(prob); + } + + nextOpt = &p->opt[(size_t)cur + 1]; + nextIsLit = False; + + // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice) + // 18.new.06 + if ((nextOpt->price < kInfinityPrice + // && !IsLitState(state) + && matchByte == curByte) + || litPrice > nextOpt->price + ) + litPrice = 0; + else + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + litPrice += (!IsLitState(state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + + if (litPrice < nextOpt->price) + { + nextOpt->price = litPrice; + nextOpt->len = 1; + MakeAs_Lit(nextOpt); + nextIsLit = True; + } + } + + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + numAvailFull = p->numAvail; + { + unsigned temp = kNumOpts - 1 - cur; + if (numAvailFull > temp) + numAvailFull = (UInt32)temp; + } + + // 18.06 + // ---------- SHORT_REP ---------- + if (IsLitState(state)) // 18.new + if (matchByte == curByte) + if (repMatchPrice < nextOpt->price) // 18.new + // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1)) + if ( + // nextOpt->price >= kInfinityPrice || + nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt + || (nextOpt->dist != 0 + // && nextOpt->extra <= 1 // 17.old + ) + ) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState); + // if (shortRepPrice <= nextOpt->price) // 17.old + if (shortRepPrice < nextOpt->price) // 18.new + { + nextOpt->price = shortRepPrice; + nextOpt->len = 1; + MakeAs_ShortRep(nextOpt); + nextIsLit = False; + } + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + // numAvail <= p->numFastBytes + + // ---------- LIT : REP_0 ---------- + + if (!nextIsLit + && litPrice != 0 // 18.new + && matchByte != curByte + && numAvailFull > 2) + { + const Byte *data2 = data - reps[0]; + if (data[1] == data2[1] && data[2] == data2[2]) + { + unsigned len; + unsigned limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + for (len = 3; len < limit && data[len] == data2[len]; len++) + {} + + { + unsigned state2 = kLiteralNextStates[state]; + unsigned posState2 = (position + 1) & p->pbMask; + UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2); + { + unsigned offset = cur + len; + + if (last < offset) + last = offset; + + // do + { + UInt32 price2; + COptimal *opt; + len--; + // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len); + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len; + opt->dist = 0; + opt->extra = 1; + } + } + // while (len >= 3); + } + } + } + } + + startLen = 2; /* speed optimization */ + + { + // ---------- REP ---------- + unsigned repIndex = 0; // 17.old + // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused + for (; repIndex < LZMA_NUM_REPS; repIndex++) + { + unsigned len; + UInt32 price; + const Byte *data2 = data - reps[repIndex]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + + // if (len < startLen) continue; // 18.new: speed optimization + + { + unsigned offset = cur + len; + if (last < offset) + last = offset; + } + { + unsigned len2 = len; + price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState); + do + { + UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2); + COptimal *opt = &p->opt[cur + len2]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->dist = (UInt32)repIndex; + opt->extra = 0; + } + } + while (--len2 >= 2); + } + + if (repIndex == 0) startLen = len + 1; // 17.old + // startLen = len + 1; // 18.new + + /* if (_maxMode) */ + { + // ---------- REP : LIT : REP_0 ---------- + // numFastBytes + 1 + numFastBytes + + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + len2 += 2; + if (len2 <= limit) + if (data[len2 - 2] == data2[len2 - 2]) + if (data[len2 - 1] == data2[len2 - 1]) + { + unsigned state2 = kRepNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + price += GET_PRICE_LEN(&p->repLenEnc, posState, len) + + GET_PRICE_0(p->isMatch[state2][posState2]) + + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterRep; + posState2 = (posState2 + 1) & p->pbMask; + + + price += GetPrice_Rep_0(p, state2, posState2); + + for (; len2 < limit && data[len2] == data2[len2]; len2++) + {} + + len2 -= len; + // if (len2 >= 3) + { + { + unsigned offset = cur + len + len2; + + if (last < offset) + last = offset; + // do + { + UInt32 price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->extra = (CExtra)(len + 1); + opt->dist = (UInt32)repIndex; + } + } + // while (len2 >= 3); + } + } + } + } + } + } + + + // ---------- MATCH ---------- + /* for (unsigned len = 2; len <= newLen; len++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2); + MATCHES[numPairs] = (UInt32)newLen; + numPairs += 2; + } + + // startLen = 2; /* speed optimization */ + + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 dist; + unsigned offs, posSlot, len; + + { + unsigned offset = cur + newLen; + if (last < offset) + last = offset; + } + + offs = 0; + while (startLen > MATCHES[offs]) + offs += 2; + dist = MATCHES[(size_t)offs + 1]; + + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + + for (len = /*2*/ startLen; ; len++) + { + UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); + { + COptimal *opt; + unsigned lenNorm = len - 2; + lenNorm = GetLenToPosState2(lenNorm); + if (dist < kNumFullDistances) + price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)]; + else + price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask]; + + opt = &p->opt[cur + len]; + if (price < opt->price) + { + opt->price = price; + opt->len = (UInt32)len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + } + + if (len == MATCHES[offs]) + { + // if (p->_maxMode) { + // MATCH : LIT : REP_0 + + const Byte *data2 = data - dist - 1; + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + len2 += 2; + if (len2 <= limit) + if (data[len2 - 2] == data2[len2 - 2]) + if (data[len2 - 1] == data2[len2 - 1]) + { + for (; len2 < limit && data[len2] == data2[len2]; len2++) + {} + + len2 -= len; + + // if (len2 >= 3) + { + unsigned state2 = kMatchNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + unsigned offset; + price += GET_PRICE_0(p->isMatch[state2][posState2]); + price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterMatch; + + posState2 = (posState2 + 1) & p->pbMask; + price += GetPrice_Rep_0(p, state2, posState2); + + offset = cur + len + len2; + + if (last < offset) + last = offset; + // do + { + UInt32 price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->extra = (CExtra)(len + 1); + opt->dist = dist + LZMA_NUM_REPS; + } + } + // while (len2 >= 3); + } + + } + + offs += 2; + if (offs == numPairs) + break; + dist = MATCHES[(size_t)offs + 1]; + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + } + } + } + } + + do + p->opt[last].price = kInfinityPrice; + while (--last); + + return Backward(p, cur); +} + + + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + + + +static unsigned GetOptimumFast(CLzmaEnc *p) +{ + UInt32 numAvail, mainDist; + unsigned mainLen, numPairs, repIndex, repLen, i; + const Byte *data; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + p->backRes = MARK_LIT; + if (numAvail < 2) + return 1; + // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repLen = repIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + if (len >= p->numFastBytes) + { + p->backRes = (UInt32)i; + MOVE_POS(p, len - 1) + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + if (mainLen >= p->numFastBytes) + { + p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + mainDist = 0; /* for GCC */ + + if (mainLen >= 2) + { + mainDist = p->matches[(size_t)numPairs - 1]; + while (numPairs > 2) + { + UInt32 dist2; + if (mainLen != p->matches[(size_t)numPairs - 4] + 1) + break; + dist2 = p->matches[(size_t)numPairs - 3]; + if (!ChangePair(dist2, mainDist)) + break; + numPairs -= 2; + mainLen--; + mainDist = dist2; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2) + if ( repLen + 1 >= mainLen + || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) + || (repLen + 3 >= mainLen && mainDist >= (1 << 15))) + { + p->backRes = (UInt32)repIndex; + MOVE_POS(p, repLen - 1) + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + { + unsigned len1 = ReadMatchDistances(p, &p->numPairs); + p->longestMatchLen = len1; + + if (len1 >= 2) + { + UInt32 newDist = p->matches[(size_t)p->numPairs - 1]; + if ( (len1 >= mainLen && newDist < mainDist) + || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist)) + || (len1 > mainLen + 1) + || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist))) + return 1; + } + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len, limit; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2;; len++) + { + if (len >= limit) + return 1; + if (data[len] != data2[len]) + break; + } + } + + p->backRes = mainDist + LZMA_NUM_REPS; + if (mainLen != 2) + { + MOVE_POS(p, mainLen - 2) + } + return mainLen; +} + + + + +static void WriteEndMarker(CLzmaEnc *p, unsigned posState) +{ + UInt32 range; + range = p->rc.range; + { + UInt32 ttt, newBound; + CLzmaProb *prob = &p->isMatch[p->state][posState]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_1(&p->rc, prob) + prob = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_0(&p->rc, prob) + } + p->state = kMatchNextStates[p->state]; + + p->rc.range = range; + LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState); + range = p->rc.range; + + { + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1); + CLzmaProb *probs = p->posSlotEncoder[0]; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < (1 << kNumPosSlotBits)); + } + { + // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range; + unsigned numBits = 30 - kNumAlignBits; + do + { + range >>= 1; + p->rc.low += range; + RC_NORM(&p->rc) + } + while (--numBits); + } + + { + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); + CLzmaProb *probs = p->posAlignEncoder; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < kAlignTableSize); + } + p->rc.range = range; +} + + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + + #ifndef _7ZIP_ST + if ( + // p->mf_Failure || + (p->mtMode && + ( // p->matchFinderMt.failure_LZ_LZ || + p->matchFinderMt.failure_LZ_BT)) + ) + { + p->result = MY_HRES_ERROR__INTERNAL_ERROR; + // printf("\nCheckErrors p->matchFinderMt.failureLZ\n"); + } + #endif + + if (MFB.result != SZ_OK) + p->result = SZ_ERROR_READ; + + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + + +MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + + +MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) +{ + unsigned i; + const CProbPrice *ProbPrices = p->ProbPrices; + const CLzmaProb *probs = p->posAlignEncoder; + // p->alignPriceCount = 0; + for (i = 0; i < kAlignTableSize / 2; i++) + { + UInt32 price = 0; + unsigned sym = i; + unsigned m = 1; + unsigned bit; + UInt32 prob; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + prob = probs[m]; + p->alignPrices[i ] = price + GET_PRICEa_0(prob); + p->alignPrices[i + 8] = price + GET_PRICEa_1(prob); + // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + } +} + + +MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) +{ + // int y; for (y = 0; y < 100; y++) { + + UInt32 tempPrices[kNumFullDistances]; + unsigned i, lps; + + const CProbPrice *ProbPrices = p->ProbPrices; + p->matchPriceCount = 0; + + for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++) + { + unsigned posSlot = GetPosSlot1(i); + unsigned footerBits = (posSlot >> 1) - 1; + unsigned base = ((2 | (posSlot & 1)) << footerBits); + const CLzmaProb *probs = p->posEncoders + (size_t)base * 2; + // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices); + UInt32 price = 0; + unsigned m = 1; + unsigned sym = i; + unsigned offset = (unsigned)1 << footerBits; + base += i; + + if (footerBits) + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) + bit; + } + while (--footerBits); + + { + unsigned prob = probs[m]; + tempPrices[base ] = price + GET_PRICEa_0(prob); + tempPrices[base + offset] = price + GET_PRICEa_1(prob); + } + } + + for (lps = 0; lps < kNumLenToPosStates; lps++) + { + unsigned slot; + unsigned distTableSize2 = (p->distTableSize + 1) >> 1; + UInt32 *posSlotPrices = p->posSlotPrices[lps]; + const CLzmaProb *probs = p->posSlotEncoder[lps]; + + for (slot = 0; slot < distTableSize2; slot++) + { + // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices); + UInt32 price; + unsigned bit; + unsigned sym = slot + (1 << (kNumPosSlotBits - 1)); + unsigned prob; + bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))]; + posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob); + posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob); + } + + { + UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++) + { + posSlotPrices[(size_t)slot * 2 ] += delta; + posSlotPrices[(size_t)slot * 2 + 1] += delta; + delta += ((UInt32)1 << kNumBitPriceShiftBits); + } + } + + { + UInt32 *dp = p->distancesPrices[lps]; + + dp[0] = posSlotPrices[0]; + dp[1] = posSlotPrices[1]; + dp[2] = posSlotPrices[2]; + dp[3] = posSlotPrices[3]; + + for (i = 4; i < kNumFullDistances; i += 2) + { + UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)]; + dp[i ] = slotPrice + tempPrices[i]; + dp[i + 1] = slotPrice + tempPrices[i + 1]; + } + } + } + // } +} + + + +static void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&MFB); + + #ifndef _7ZIP_ST + p->matchFinderMt.MatchFinder = &MFB; + MatchFinderMt_Construct(&p->matchFinderMt); + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = NULL; + p->saveState.litProbs = NULL; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) +{ + void *p; + p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); + if (p) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->litProbs); + ISzAlloc_Free(alloc, p->saveState.litProbs); + p->litProbs = NULL; + p->saveState.litProbs = NULL; +} + +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + + MatchFinder_Free(&MFB, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + ISzAlloc_Free(alloc, p); +} + + +MY_NO_INLINE +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->needInit) + { + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_InitMt(&p->matchFinderMt)); + } + #endif + p->matchFinder.Init(p->matchFinderObj); + p->needInit = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + unsigned numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]); + // p->state = kLiteralNextStates[p->state]; + curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + + for (;;) + { + UInt32 dist; + unsigned len, posState; + UInt32 range, ttt, newBound; + CLzmaProb *probs; + + if (p->fastMode) + len = GetOptimumFast(p); + else + { + unsigned oci = p->optCur; + if (p->optEnd == oci) + len = GetOptimum(p, nowPos32); + else + { + const COptimal *opt = &p->opt[oci]; + len = opt->len; + p->backRes = opt->dist; + p->optCur = oci + 1; + } + } + + posState = (unsigned)nowPos32 & p->pbMask; + range = p->rc.range; + probs = &p->isMatch[p->state][posState]; + + RC_BIT_PRE(&p->rc, probs) + + dist = p->backRes; + + #ifdef SHOW_STAT2 + printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist); + #endif + + if (dist == MARK_LIT) + { + Byte curByte; + const Byte *data; + unsigned state; + + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + probs = LIT_PROBS(nowPos32, *(data - 1)); + curByte = *data; + state = p->state; + p->state = kLiteralNextStates[state]; + if (IsLitState(state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0])); + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, probs) + + if (dist < LZMA_NUM_REPS) + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG0[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 0) + { + RC_BIT_0(&p->rc, probs); + probs = &p->isRep0Long[p->state][posState]; + RC_BIT_PRE(&p->rc, probs) + if (len != 1) + { + RC_BIT_1_BASE(&p->rc, probs); + } + else + { + RC_BIT_0_BASE(&p->rc, probs); + p->state = kShortRepNextStates[p->state]; + } + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG1[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 1) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[1]; + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG2[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 2) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[2]; + } + else + { + RC_BIT_1_BASE(&p->rc, probs); + dist = p->reps[3]; + p->reps[3] = p->reps[2]; + } + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = dist; + } + + RC_NORM(&p->rc) + + p->rc.range = range; + + if (len != 1) + { + LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + --p->repLenEncCounter; + p->state = kRepNextStates[p->state]; + } + } + else + { + unsigned posSlot; + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + p->state = kMatchNextStates[p->state]; + + LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + // --p->lenEnc.counter; + + dist -= LZMA_NUM_REPS; + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = dist + 1; + + p->matchPriceCount++; + GetPosSlot(dist, posSlot); + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot); + { + UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits); + range = p->rc.range; + probs = p->posSlotEncoder[GetLenToPosState(len)]; + do + { + CLzmaProb *prob = probs + (sym >> kNumPosSlotBits); + UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1; + sym <<= 1; + RC_BIT(&p->rc, prob, bit); + } + while (sym < (1 << kNumPosSlotBits * 2)); + p->rc.range = range; + } + + if (dist >= kStartPosModelIndex) + { + unsigned footerBits = ((posSlot >> 1) - 1); + + if (dist < kNumFullDistances) + { + unsigned base = ((2 | (posSlot & 1)) << footerBits); + RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */)); + } + else + { + UInt32 pos2 = (dist | 0xF) << (32 - footerBits); + range = p->rc.range; + // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + /* + do + { + range >>= 1; + p->rc.low += range & (0 - ((dist >> --footerBits) & 1)); + RC_NORM(&p->rc) + } + while (footerBits > kNumAlignBits); + */ + do + { + range >>= 1; + p->rc.low += range & (0 - (pos2 >> 31)); + pos2 += pos2; + RC_NORM(&p->rc) + } + while (pos2 != 0xF0000000); + + + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + + { + unsigned m = 1; + unsigned bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); + p->rc.range = range; + // p->alignPriceCount++; + } + } + } + } + } + + nowPos32 += (UInt32)len; + p->additionalOffset -= len; + + if (p->additionalOffset == 0) + { + UInt32 processed; + + if (!p->fastMode) + { + /* + if (p->alignPriceCount >= 16) // kAlignTableSize + FillAlignPrices(p); + if (p->matchPriceCount >= 128) + FillDistancesPrices(p); + if (p->lenEnc.counter <= 0) + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + */ + if (p->matchPriceCount >= 64) + { + FillAlignPrices(p); + // { int y; for (y = 0; y < 100; y++) { + FillDistancesPrices(p); + // }} + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); + } + if (p->repLenEncCounter <= 0) + { + p->repLenEncCounter = REP_LEN_COUNT; + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); + } + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + + if (maxPackSize) + { + if (processed + kNumOpts + 300 >= maxUnpackSize + || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize) + break; + } + else if (processed >= (1 << 17)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + + + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + UInt32 beforeSize = kNumOpts; + UInt32 dictSize; + + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + + #ifndef _7ZIP_ST + p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0)); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + if (!p->litProbs || !p->saveState.litProbs) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); + + + dictSize = p->dictSize; + if (dictSize == ((UInt32)2 << 30) || + dictSize == ((UInt32)3 << 30)) + { + /* 21.03 : here we reduce the dictionary for 2 reasons: + 1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary. + 2) we want to elimate useless last MatchFinder_Normalize3() for corner cases, + where data size is aligned for 1 GB: 5/6/8 GB. + That reducing must be >= 1 for such corner cases. */ + dictSize -= 1; + } + + if (beforeSize + dictSize < keepWindowSize) + beforeSize = keepWindowSize - dictSize; + + /* in worst case we can look ahead for + max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes. + we send larger value for (keepAfter) to MantchFinder_Create(): + (numFastBytes + LZMA_MATCH_LEN_MAX + 1) + */ + + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */ + , allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MFB.bigHash = (Byte)( + (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0); + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&MFB, dictSize, beforeSize, + p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */ + , allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &MFB; + MatchFinder_CreateVTable(&MFB, &p->matchFinder); + } + + return SZ_OK; +} + +static void LzmaEnc_Init(CLzmaEnc *p) +{ + unsigned i; + p->state = 0; + p->reps[0] = + p->reps[1] = + p->reps[2] = + p->reps[3] = 1; + + RangeEnc_Init(&p->rc); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + for (i = 0; i < kNumStates; i++) + { + unsigned j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + unsigned j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances; i++) + p->posEncoders[i] = kProbInitValue; + } + + { + UInt32 num = (UInt32)0x300 << (p->lp + p->lc); + UInt32 k; + CLzmaProb *probs = p->litProbs; + for (k = 0; k < num; k++) + probs[k] = kProbInitValue; + } + + + LenEnc_Init(&p->lenProbs); + LenEnc_Init(&p->repLenProbs); + + p->optEnd = 0; + p->optCur = 0; + + { + for (i = 0; i < kNumOpts; i++) + p->opt[i].price = kInfinityPrice; + } + + p->additionalOffset = 0; + + p->pbMask = ((unsigned)1 << p->pb) - 1; + p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); + + // p->mf_Failure = False; +} + + +static void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + + p->repLenEncCounter = REP_LEN_COUNT; + + LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + unsigned i; + for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + MFB.stream = inStream; + p->needInit = 1; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + MFB.stream = inStream; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + MFB.directInput = 1; + MFB.bufferBase = (Byte *)src; + MFB.directInputRem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->needInit = 1; + + LzmaEnc_SetDataSize(pp, srcLen); + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifndef _7ZIP_ST + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + UNUSED_VAR(pp); + #endif +} + + +typedef struct +{ + ISeqOutStream vt; + Byte *data; + SizeT rem; + BoolInt overflow; +} CLzmaEnc_SeqOutStreamBuf; + +static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt); + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +/* +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} +*/ + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.vt; + + if (desiredPackSize == 0) + return SZ_ERROR_OUTPUT_EOF; + + res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + + +MY_NO_INLINE +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +{ + SRes res = SZ_OK; + + #ifndef _7ZIP_ST + Byte allocaDummy[0x300]; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; + #endif + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, 0, 0); + if (res != SZ_OK || p->finished) + break; + if (progress) + { + res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + + LzmaEnc_Finish(p); + + /* + if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB)) + res = SZ_ERROR_FAIL; + } + */ + + return res; +} + + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + { + const CLzmaEnc *p = (const CLzmaEnc *)pp; + const UInt32 dictSize = p->dictSize; + UInt32 v; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + // we write aligned dictionary value to properties for lzma decoder + if (dictSize >= ((UInt32)1 << 21)) + { + const UInt32 kDictMask = ((UInt32)1 << 20) - 1; + v = (dictSize + kDictMask) & ~kDictMask; + if (v < dictSize) + v = dictSize; + } + else + { + unsigned i = 11 * 2; + do + { + v = (UInt32)(2 + (i & 1)) << (i >> 1); + i++; + } + while (v < dictSize); + } + + SetUi32(props + 1, v); + return SZ_OK; + } +} + + +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) +{ + return (unsigned)((CLzmaEnc *)pp)->writeEndMark; +} + + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + p->rc.outStream = &outStream.vt; + + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + + if (res == SZ_OK) + { + res = LzmaEnc_Encode2(p, progress); + if (res == SZ_OK && p->nowPos64 != srcLen) + res = SZ_ERROR_FAIL; + } + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (!p) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} + + +/* +#ifndef _7ZIP_ST +void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + lz_threads[0] = p->matchFinderMt.hashSync.thread; + lz_threads[1] = p->matchFinderMt.btSync.thread; +} +#endif +*/ diff --git a/3rdparty/lzma-21.03beta/C/LzmaEnc.h b/3rdparty/lzma-21.03beta/C/LzmaEnc.h new file mode 100644 index 0000000..bc2ed50 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaEnc.h @@ -0,0 +1,78 @@ +/* LzmaEnc.h -- LZMA Encoder +2019-10-30 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (3 << 29) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ + + UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. + Encoder uses this value to reduce dictionary size */ + + UInt64 affinity; +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p); + +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + + +/* ---------- One Call Interface ---------- */ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/LzmaLib.c b/3rdparty/lzma-21.03beta/C/LzmaLib.c new file mode 100644 index 0000000..706e9e5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaLib.c @@ -0,0 +1,40 @@ +/* LzmaLib.c -- LZMA library wrapper +2015-06-13 : Igor Pavlov : Public domain */ + +#include "Alloc.h" +#include "LzmaDec.h" +#include "LzmaEnc.h" +#include "LzmaLib.h" + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ +) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + props.lc = lc; + props.lp = lp; + props.pb = pb; + props.fb = fb; + props.numThreads = numThreads; + + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); +} + + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + const unsigned char *props, size_t propsSize) +{ + ELzmaStatus status; + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); +} diff --git a/3rdparty/lzma-21.03beta/C/LzmaLib.h b/3rdparty/lzma-21.03beta/C/LzmaLib.h new file mode 100644 index 0000000..c343a85 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/LzmaLib.h @@ -0,0 +1,138 @@ +/* LzmaLib.h -- LZMA library interface +2021-04-03 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_LIB_H +#define __LZMA_LIB_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define MY_STDAPI int MY_STD_CALL + +#define LZMA_PROPS_SIZE 5 + +/* +RAM requirements for LZMA: + for compression: (dictSize * 11.5 + 6 MB) + state_size + for decompression: dictSize + state_size + state_size = (4 + (1.5 << (lc + lp))) KB + by default (lc=3, lp=0), state_size = 16 KB. + +LZMA properties (5 bytes) format + Offset Size Description + 0 1 lc, lp and pb in encoded form. + 1 4 dictSize (little endian). +*/ + +/* +LzmaCompress +------------ + +outPropsSize - + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + + LZMA Encoder will use defult values for any parameter, if it is + -1 for any from: level, loc, lp, pb, fb, numThreads + 0 for dictSize + +level - compression level: 0 <= level <= 9; + + level dictSize algo fb + 0: 64 KB 0 32 + 1: 256 KB 0 32 + 2: 1 MB 0 32 + 3: 4 MB 0 32 + 4: 16 MB 0 32 + 5: 16 MB 1 32 + 6: 32 MB 1 32 + 7: 32 MB 1 64 + 8: 64 MB 1 64 + 9: 64 MB 1 64 + + The default value for "level" is 5. + + algo = 0 means fast method + algo = 1 means normal method + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + +lc - The number of literal context bits (high bits of previous literal). + It can be in the range from 0 to 8. The default value is 3. + Sometimes lc=4 gives the gain for big files. + +lp - The number of literal pos bits (low bits of current position for literals). + It can be in the range from 0 to 4. The default value is 0. + The lp switch is intended for periodical data when the period is equal to 2^lp. + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's + better to set lc=0, if you change lp switch. + +pb - The number of pos bits (low bits of current position). + It can be in the range from 0 to 4. The default value is 2. + The pb switch is intended for periodical data when the period is equal 2^pb. + +fb - Word size (the number of fast bytes). + It can be in the range from 5 to 273. The default value is 32. + Usually, a big number gives a little bit better compression ratio and + slower compression process. + +numThreads - The number of thereads. 1 or 2. The default value is 2. + Fast mode (algo = 0) can use only 1 thread. + +In: + dest - output data buffer + destLen - output data buffer size + src - input data + srcLen - input data size +Out: + destLen - processed output size +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* default = (1 << 24) */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ + ); + +/* +LzmaUncompress +-------------- +In: + dest - output data buffer + destLen - output data buffer size + src - input data + srcLen - input data size +Out: + destLen - processed output size + srcLen - processed input size +Returns: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation arror + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) +*/ + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, + const unsigned char *props, size_t propsSize); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/MtCoder.c b/3rdparty/lzma-21.03beta/C/MtCoder.c new file mode 100644 index 0000000..7936c41 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/MtCoder.c @@ -0,0 +1,595 @@ +/* MtCoder.c -- Multi-thread Coder +2021-07-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "MtCoder.h" + +#ifndef _7ZIP_ST + +static SRes MtProgressThunk_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) +{ + CMtProgressThunk *thunk = CONTAINER_FROM_VTBL(pp, CMtProgressThunk, vt); + UInt64 inSize2 = 0; + UInt64 outSize2 = 0; + if (inSize != (UInt64)(Int64)-1) + { + inSize2 = inSize - thunk->inSize; + thunk->inSize = inSize; + } + if (outSize != (UInt64)(Int64)-1) + { + outSize2 = outSize - thunk->outSize; + thunk->outSize = outSize; + } + return MtProgress_ProgressAdd(thunk->mtProgress, inSize2, outSize2); +} + + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p) +{ + p->vt.Progress = MtProgressThunk_Progress; +} + + + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + + +static WRes ArEvent_OptCreate_And_Reset(CEvent *p) +{ + if (Event_IsCreated(p)) + return Event_Reset(p); + return AutoResetEvent_CreateNotSignaled(p); +} + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp); + + +static SRes MtCoderThread_CreateAndStart(CMtCoderThread *t) +{ + WRes wres = ArEvent_OptCreate_And_Reset(&t->startEvent); + if (wres == 0) + { + t->stop = False; + if (!Thread_WasCreated(&t->thread)) + wres = Thread_Create(&t->thread, ThreadFunc, t); + if (wres == 0) + wres = Event_Set(&t->startEvent); + } + if (wres == 0) + return SZ_OK; + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +static void MtCoderThread_Destruct(CMtCoderThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + t->stop = 1; + Event_Set(&t->startEvent); + Thread_Wait_Close(&t->thread); + } + + Event_Close(&t->startEvent); + + if (t->inBuf) + { + ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf); + t->inBuf = NULL; + } +} + + + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t cur = size; + SRes res = ISeqInStream_Read(stream, data, &cur); + *processedSize += cur; + data += cur; + size -= cur; + RINOK(res); + if (cur == 0) + return SZ_OK; + } + return SZ_OK; +} + + +/* + ThreadFunc2() returns: + SZ_OK - in all normal cases (even for stream error or memory allocation error) + SZ_ERROR_THREAD - in case of failure in system synch function +*/ + +static SRes ThreadFunc2(CMtCoderThread *t) +{ + CMtCoder *mtc = t->mtCoder; + + for (;;) + { + unsigned bi; + SRes res; + SRes res2; + BoolInt finished; + unsigned bufIndex; + size_t size; + const Byte *inData; + UInt64 readProcessed = 0; + + RINOK_THREAD(Event_Wait(&mtc->readEvent)) + + /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */ + + if (mtc->stopReading) + { + return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } + + res = MtProgress_GetError(&mtc->mtProgress); + + size = 0; + inData = NULL; + finished = True; + + if (res == SZ_OK) + { + size = mtc->blockSize; + if (mtc->inStream) + { + if (!t->inBuf) + { + t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize); + if (!t->inBuf) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = FullRead(mtc->inStream, t->inBuf, &size); + readProcessed = mtc->readProcessed + size; + mtc->readProcessed = readProcessed; + } + if (res != SZ_OK) + { + mtc->readRes = res; + /* after reading error - we can stop encoding of previous blocks */ + MtProgress_SetError(&mtc->mtProgress, res); + } + else + finished = (size != mtc->blockSize); + } + else + { + size_t rem; + readProcessed = mtc->readProcessed; + rem = mtc->inDataSize - (size_t)readProcessed; + if (size > rem) + size = rem; + inData = mtc->inData + (size_t)readProcessed; + readProcessed += size; + mtc->readProcessed = readProcessed; + finished = (mtc->inDataSize == (size_t)readProcessed); + } + } + + /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */ + + res2 = SZ_OK; + + if (Semaphore_Wait(&mtc->blocksSemaphore) != 0) + { + res2 = SZ_ERROR_THREAD; + if (res == SZ_OK) + { + res = res2; + // MtProgress_SetError(&mtc->mtProgress, res); + } + } + + bi = mtc->blockIndex; + + if (++mtc->blockIndex >= mtc->numBlocksMax) + mtc->blockIndex = 0; + + bufIndex = (unsigned)(int)-1; + + if (res == SZ_OK) + res = MtProgress_GetError(&mtc->mtProgress); + + if (res != SZ_OK) + finished = True; + + if (!finished) + { + if (mtc->numStartedThreads < mtc->numStartedThreadsLimit + && mtc->expectedDataSize != readProcessed) + { + res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]); + if (res == SZ_OK) + mtc->numStartedThreads++; + else + { + MtProgress_SetError(&mtc->mtProgress, res); + finished = True; + } + } + } + + if (finished) + mtc->stopReading = True; + + RINOK_THREAD(Event_Set(&mtc->readEvent)) + + if (res2 != SZ_OK) + return res2; + + if (res == SZ_OK) + { + CriticalSection_Enter(&mtc->cs); + bufIndex = mtc->freeBlockHead; + mtc->freeBlockHead = mtc->freeBlockList[bufIndex]; + CriticalSection_Leave(&mtc->cs); + + res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex, + mtc->inStream ? t->inBuf : inData, size, finished); + + // MtProgress_Reinit(&mtc->mtProgress, t->index); + + if (res != SZ_OK) + MtProgress_SetError(&mtc->mtProgress, res); + } + + { + CMtCoderBlock *block = &mtc->blocks[bi]; + block->res = res; + block->bufIndex = bufIndex; + block->finished = finished; + } + + #ifdef MTCODER__USE_WRITE_THREAD + RINOK_THREAD(Event_Set(&mtc->writeEvents[bi])) + #else + { + unsigned wi; + { + CriticalSection_Enter(&mtc->cs); + wi = mtc->writeIndex; + if (wi == bi) + mtc->writeIndex = (unsigned)(int)-1; + else + mtc->ReadyBlocks[bi] = True; + CriticalSection_Leave(&mtc->cs); + } + + if (wi != bi) + { + if (res != SZ_OK || finished) + return 0; + continue; + } + + if (mtc->writeRes != SZ_OK) + res = mtc->writeRes; + + for (;;) + { + if (res == SZ_OK && bufIndex != (unsigned)(int)-1) + { + res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex); + if (res != SZ_OK) + { + mtc->writeRes = res; + MtProgress_SetError(&mtc->mtProgress, res); + } + } + + if (++wi >= mtc->numBlocksMax) + wi = 0; + { + BoolInt isReady; + + CriticalSection_Enter(&mtc->cs); + + if (bufIndex != (unsigned)(int)-1) + { + mtc->freeBlockList[bufIndex] = mtc->freeBlockHead; + mtc->freeBlockHead = bufIndex; + } + + isReady = mtc->ReadyBlocks[wi]; + + if (isReady) + mtc->ReadyBlocks[wi] = False; + else + mtc->writeIndex = wi; + + CriticalSection_Leave(&mtc->cs); + + RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore)) + + if (!isReady) + break; + } + + { + CMtCoderBlock *block = &mtc->blocks[wi]; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + bufIndex = block->bufIndex; + finished = block->finished; + } + } + } + #endif + + if (finished || res != SZ_OK) + return 0; + } +} + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + CMtCoderThread *t = (CMtCoderThread *)pp; + for (;;) + { + if (Event_Wait(&t->startEvent) != 0) + return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; + if (t->stop) + return 0; + { + SRes res = ThreadFunc2(t); + CMtCoder *mtc = t->mtCoder; + if (res != SZ_OK) + { + MtProgress_SetError(&mtc->mtProgress, res); + } + + #ifndef MTCODER__USE_WRITE_THREAD + { + unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads); + if (numFinished == mtc->numStartedThreads) + if (Event_Set(&mtc->finishedEvent) != 0) + return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD; + } + #endif + } + } +} + + + +void MtCoder_Construct(CMtCoder *p) +{ + unsigned i; + + p->blockSize = 0; + p->numThreadsMax = 0; + p->expectedDataSize = (UInt64)(Int64)-1; + + p->inStream = NULL; + p->inData = NULL; + p->inDataSize = 0; + + p->progress = NULL; + p->allocBig = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + Event_Construct(&p->readEvent); + Semaphore_Construct(&p->blocksSemaphore); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + t->mtCoder = p; + t->index = i; + t->inBuf = NULL; + t->stop = False; + Event_Construct(&t->startEvent); + Thread_Construct(&t->thread); + } + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + Event_Construct(&p->writeEvents[i]); + #else + Event_Construct(&p->finishedEvent); + #endif + + CriticalSection_Init(&p->cs); + CriticalSection_Init(&p->mtProgress.cs); +} + + + + +static void MtCoder_Free(CMtCoder *p) +{ + unsigned i; + + /* + p->stopReading = True; + if (Event_IsCreated(&p->readEvent)) + Event_Set(&p->readEvent); + */ + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + MtCoderThread_Destruct(&p->threads[i]); + + Event_Close(&p->readEvent); + Semaphore_Close(&p->blocksSemaphore); + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + Event_Close(&p->writeEvents[i]); + #else + Event_Close(&p->finishedEvent); + #endif +} + + +void MtCoder_Destruct(CMtCoder *p) +{ + MtCoder_Free(p); + + CriticalSection_Delete(&p->cs); + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtCoder_Code(CMtCoder *p) +{ + unsigned numThreads = p->numThreadsMax; + unsigned numBlocksMax; + unsigned i; + SRes res = SZ_OK; + + if (numThreads > MTCODER__THREADS_MAX) + numThreads = MTCODER__THREADS_MAX; + numBlocksMax = MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads); + + if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++; + if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; + + if (numBlocksMax > MTCODER__BLOCKS_MAX) + numBlocksMax = MTCODER__BLOCKS_MAX; + + if (p->blockSize != p->allocatedBufsSize) + { + for (i = 0; i < MTCODER__THREADS_MAX; i++) + { + CMtCoderThread *t = &p->threads[i]; + if (t->inBuf) + { + ISzAlloc_Free(p->allocBig, t->inBuf); + t->inBuf = NULL; + } + } + p->allocatedBufsSize = p->blockSize; + } + + p->readRes = SZ_OK; + + MtProgress_Init(&p->mtProgress, p->progress); + + #ifdef MTCODER__USE_WRITE_THREAD + for (i = 0; i < numBlocksMax; i++) + { + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->writeEvents[i])); + } + #else + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent)); + #endif + + { + RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->readEvent)); + RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, numBlocksMax, numBlocksMax)); + } + + for (i = 0; i < MTCODER__BLOCKS_MAX - 1; i++) + p->freeBlockList[i] = i + 1; + p->freeBlockList[MTCODER__BLOCKS_MAX - 1] = (unsigned)(int)-1; + p->freeBlockHead = 0; + + p->readProcessed = 0; + p->blockIndex = 0; + p->numBlocksMax = numBlocksMax; + p->stopReading = False; + + #ifndef MTCODER__USE_WRITE_THREAD + p->writeIndex = 0; + p->writeRes = SZ_OK; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->ReadyBlocks[i] = False; + p->numFinishedThreads = 0; + #endif + + p->numStartedThreadsLimit = numThreads; + p->numStartedThreads = 0; + + // for (i = 0; i < numThreads; i++) + { + CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++]; + RINOK(MtCoderThread_CreateAndStart(nextThread)); + } + + RINOK_THREAD(Event_Set(&p->readEvent)) + + #ifdef MTCODER__USE_WRITE_THREAD + { + unsigned bi = 0; + + for (;; bi++) + { + if (bi >= numBlocksMax) + bi = 0; + + RINOK_THREAD(Event_Wait(&p->writeEvents[bi])) + + { + const CMtCoderBlock *block = &p->blocks[bi]; + unsigned bufIndex = block->bufIndex; + BoolInt finished = block->finished; + if (res == SZ_OK && block->res != SZ_OK) + res = block->res; + + if (bufIndex != (unsigned)(int)-1) + { + if (res == SZ_OK) + { + res = p->mtCallback->Write(p->mtCallbackObject, bufIndex); + if (res != SZ_OK) + MtProgress_SetError(&p->mtProgress, res); + } + + CriticalSection_Enter(&p->cs); + { + p->freeBlockList[bufIndex] = p->freeBlockHead; + p->freeBlockHead = bufIndex; + } + CriticalSection_Leave(&p->cs); + } + + RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore)) + + if (finished) + break; + } + } + } + #else + { + WRes wres = Event_Wait(&p->finishedEvent); + res = MY_SRes_HRESULT_FROM_WRes(wres); + } + #endif + + if (res == SZ_OK) + res = p->readRes; + + if (res == SZ_OK) + res = p->mtProgress.res; + + #ifndef MTCODER__USE_WRITE_THREAD + if (res == SZ_OK) + res = p->writeRes; + #endif + + if (res != SZ_OK) + MtCoder_Free(p); + return res; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/MtCoder.h b/3rdparty/lzma-21.03beta/C/MtCoder.h new file mode 100644 index 0000000..5a5f4d1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/MtCoder.h @@ -0,0 +1,141 @@ +/* MtCoder.h -- Multi-thread Coder +2018-07-04 : Igor Pavlov : Public domain */ + +#ifndef __MT_CODER_H +#define __MT_CODER_H + +#include "MtDec.h" + +EXTERN_C_BEGIN + +/* + if ( defined MTCODER__USE_WRITE_THREAD) : main thread writes all data blocks to output stream + if (not defined MTCODER__USE_WRITE_THREAD) : any coder thread can write data blocks to output stream +*/ +/* #define MTCODER__USE_WRITE_THREAD */ + +#ifndef _7ZIP_ST + #define MTCODER__GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1) + #define MTCODER__THREADS_MAX 64 + #define MTCODER__BLOCKS_MAX (MTCODER__GET_NUM_BLOCKS_FROM_THREADS(MTCODER__THREADS_MAX) + 3) +#else + #define MTCODER__THREADS_MAX 1 + #define MTCODER__BLOCKS_MAX 1 +#endif + + +#ifndef _7ZIP_ST + + +typedef struct +{ + ICompressProgress vt; + CMtProgress *mtProgress; + UInt64 inSize; + UInt64 outSize; +} CMtProgressThunk; + +void MtProgressThunk_CreateVTable(CMtProgressThunk *p); + +#define MtProgressThunk_Init(p) { (p)->inSize = 0; (p)->outSize = 0; } + + +struct _CMtCoder; + + +typedef struct +{ + struct _CMtCoder *mtCoder; + unsigned index; + int stop; + Byte *inBuf; + + CAutoResetEvent startEvent; + CThread thread; +} CMtCoderThread; + + +typedef struct +{ + SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished); + SRes (*Write)(void *p, unsigned outBufIndex); +} IMtCoderCallback2; + + +typedef struct +{ + SRes res; + unsigned bufIndex; + BoolInt finished; +} CMtCoderBlock; + + +typedef struct _CMtCoder +{ + /* input variables */ + + size_t blockSize; /* size of input block */ + unsigned numThreadsMax; + UInt64 expectedDataSize; + + ISeqInStream *inStream; + const Byte *inData; + size_t inDataSize; + + ICompressProgress *progress; + ISzAllocPtr allocBig; + + IMtCoderCallback2 *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + CAutoResetEvent readEvent; + CSemaphore blocksSemaphore; + + BoolInt stopReading; + SRes readRes; + + #ifdef MTCODER__USE_WRITE_THREAD + CAutoResetEvent writeEvents[MTCODER__BLOCKS_MAX]; + #else + CAutoResetEvent finishedEvent; + SRes writeRes; + unsigned writeIndex; + Byte ReadyBlocks[MTCODER__BLOCKS_MAX]; + LONG numFinishedThreads; + #endif + + unsigned numStartedThreadsLimit; + unsigned numStartedThreads; + + unsigned numBlocksMax; + unsigned blockIndex; + UInt64 readProcessed; + + CCriticalSection cs; + + unsigned freeBlockHead; + unsigned freeBlockList[MTCODER__BLOCKS_MAX]; + + CMtProgress mtProgress; + CMtCoderBlock blocks[MTCODER__BLOCKS_MAX]; + CMtCoderThread threads[MTCODER__THREADS_MAX]; +} CMtCoder; + + +void MtCoder_Construct(CMtCoder *p); +void MtCoder_Destruct(CMtCoder *p); +SRes MtCoder_Code(CMtCoder *p); + + +#endif + + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/MtDec.c b/3rdparty/lzma-21.03beta/C/MtDec.c new file mode 100644 index 0000000..fa533d2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/MtDec.c @@ -0,0 +1,1139 @@ +/* MtDec.c -- Multi-thread Decoder +2021-02-27 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #define SHOW_DEBUG_INFO + +// #include +#include + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "MtDec.h" + +#ifndef _7ZIP_ST + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +void MtProgress_Init(CMtProgress *p, ICompressProgress *progress) +{ + p->progress = progress; + p->res = SZ_OK; + p->totalInSize = 0; + p->totalOutSize = 0; +} + + +SRes MtProgress_Progress_ST(CMtProgress *p) +{ + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + return p->res; +} + + +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize) +{ + SRes res; + CriticalSection_Enter(&p->cs); + + p->totalInSize += inSize; + p->totalOutSize += outSize; + if (p->res == SZ_OK && p->progress) + if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) + p->res = SZ_ERROR_PROGRESS; + res = p->res; + + CriticalSection_Leave(&p->cs); + return res; +} + + +SRes MtProgress_GetError(CMtProgress *p) +{ + SRes res; + CriticalSection_Enter(&p->cs); + res = p->res; + CriticalSection_Leave(&p->cs); + return res; +} + + +void MtProgress_SetError(CMtProgress *p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + + +#define RINOK_THREAD(x) RINOK_WRes(x) + + +static WRes ArEvent_OptCreate_And_Reset(CEvent *p) +{ + if (Event_IsCreated(p)) + return Event_Reset(p); + return AutoResetEvent_CreateNotSignaled(p); +} + + +struct __CMtDecBufLink +{ + struct __CMtDecBufLink *next; + void *pad[3]; +}; + +typedef struct __CMtDecBufLink CMtDecBufLink; + +#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink) +#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET) + + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp); + + +static WRes MtDecThread_CreateEvents(CMtDecThread *t) +{ + WRes wres = ArEvent_OptCreate_And_Reset(&t->canWrite); + if (wres == 0) + { + wres = ArEvent_OptCreate_And_Reset(&t->canRead); + if (wres == 0) + return SZ_OK; + } + return wres; +} + + +static SRes MtDecThread_CreateAndStart(CMtDecThread *t) +{ + WRes wres = MtDecThread_CreateEvents(t); + // wres = 17; // for test + if (wres == 0) + { + if (Thread_WasCreated(&t->thread)) + return SZ_OK; + wres = Thread_Create(&t->thread, ThreadFunc, t); + if (wres == 0) + return SZ_OK; + } + return MY_SRes_HRESULT_FROM_WRes(wres); +} + + +void MtDecThread_FreeInBufs(CMtDecThread *t) +{ + if (t->inBuf) + { + void *link = t->inBuf; + t->inBuf = NULL; + do + { + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(t->mtDec->alloc, link); + link = next; + } + while (link); + } +} + + +static void MtDecThread_CloseThread(CMtDecThread *t) +{ + if (Thread_WasCreated(&t->thread)) + { + Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */ + Event_Set(&t->canRead); + Thread_Wait_Close(&t->thread); + } + + Event_Close(&t->canRead); + Event_Close(&t->canWrite); +} + +static void MtDec_CloseThreads(CMtDec *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + MtDecThread_CloseThread(&p->threads[i]); +} + +static void MtDecThread_Destruct(CMtDecThread *t) +{ + MtDecThread_CloseThread(t); + MtDecThread_FreeInBufs(t); +} + + + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t cur = size; + SRes res = ISeqInStream_Read(stream, data, &cur); + *processedSize += cur; + data += cur; + size -= cur; + RINOK(res); + if (cur == 0) + return SZ_OK; + } + return SZ_OK; +} + + +static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + CriticalSection_Leave(&p->mtProgress.cs); + return res; +} + +static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted) +{ + SRes res; + CriticalSection_Enter(&p->mtProgress.cs); + + p->mtProgress.totalInSize += inSize; + p->mtProgress.totalOutSize += outSize; + if (p->mtProgress.res == SZ_OK && p->mtProgress.progress) + if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK) + p->mtProgress.res = SZ_ERROR_PROGRESS; + + *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); + res = p->mtProgress.res; + + CriticalSection_Leave(&p->mtProgress.cs); + + return res; +} + +static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex) +{ + CriticalSection_Enter(&p->mtProgress.cs); + if (!p->needInterrupt || interruptIndex < p->interruptIndex) + { + p->interruptIndex = interruptIndex; + p->needInterrupt = True; + } + CriticalSection_Leave(&p->mtProgress.cs); +} + +Byte *MtDec_GetCrossBuff(CMtDec *p) +{ + Byte *cr = p->crossBlock; + if (!cr) + { + cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!cr) + return NULL; + p->crossBlock = cr; + } + return MTDEC__DATA_PTR_FROM_LINK(cr); +} + + +/* + ThreadFunc2() returns: + 0 - in all normal cases (even for stream error or memory allocation error) + (!= 0) - WRes error return by system threading function +*/ + +// #define MTDEC_ProgessStep (1 << 22) +#define MTDEC_ProgessStep (1 << 0) + +static WRes ThreadFunc2(CMtDecThread *t) +{ + CMtDec *p = t->mtDec; + + PRF_STR_INT("ThreadFunc2", t->index); + + // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index); + + for (;;) + { + SRes res, codeRes; + BoolInt wasInterrupted, isAllocError, overflow, finish; + SRes threadingErrorSRes; + BoolInt needCode, needWrite, needContinue; + + size_t inDataSize_Start; + UInt64 inDataSize; + // UInt64 inDataSize_Full; + + UInt64 blockIndex; + + UInt64 inPrev = 0; + UInt64 outPrev = 0; + UInt64 inCodePos; + UInt64 outCodePos; + + Byte *afterEndData = NULL; + size_t afterEndData_Size = 0; + BoolInt afterEndData_IsCross = False; + + BoolInt canCreateNewThread = False; + // CMtDecCallbackInfo parse; + CMtDecThread *nextThread; + + PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index); + + RINOK_THREAD(Event_Wait(&t->canRead)); + if (p->exitThread) + return 0; + + PRF_STR_INT("after Event_Wait(&t->canRead)", t->index); + + // if (t->index == 3) return 19; // for test + + blockIndex = p->blockIndex++; + + // PRF(printf("\ncanRead\n")) + + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + + finish = p->readWasFinished; + needCode = False; + needWrite = False; + isAllocError = False; + overflow = False; + + inDataSize_Start = 0; + inDataSize = 0; + // inDataSize_Full = 0; + + if (res == SZ_OK && !wasInterrupted) + { + // if (p->inStream) + { + CMtDecBufLink *prev = NULL; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + size_t crossSize = p->crossEnd - p->crossStart; + + PRF(printf("\ncrossSize = %d\n", crossSize)); + + for (;;) + { + if (!link) + { + link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); + if (!link) + { + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + link->next = NULL; + if (prev) + { + // static unsigned g_num = 0; + // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev)); + prev->next = link; + } + else + t->inBuf = (void *)link; + } + + { + Byte *data = MTDEC__DATA_PTR_FROM_LINK(link); + Byte *parseData = data; + size_t size; + + if (crossSize != 0) + { + inDataSize = crossSize; + // inDataSize_Full = inDataSize; + inDataSize_Start = crossSize; + size = crossSize; + parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d", + (int)p->crossStart, (int)p->crossEnd, (int)finish)); + } + else + { + size = p->inBufSize; + + res = FullRead(p->inStream, data, &size); + + // size = 10; // test + + inDataSize += size; + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = size; + + p->readProcessed += size; + finish = (size != p->inBufSize); + if (finish) + p->readWasFinished = True; + + // res = E_INVALIDARG; // test + + if (res != SZ_OK) + { + // PRF(printf("\nRead error = %d\n", res)) + // we want to decode all data before error + p->readRes = res; + // p->readError_BlockIndex = blockIndex; + p->readWasFinished = True; + finish = True; + res = SZ_OK; + // break; + } + + if (inDataSize - inPrev >= MTDEC_ProgessStep) + { + res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inDataSize; + } + } + + { + CMtDecCallbackInfo parse; + + parse.startCall = (prev == NULL); + parse.src = parseData; + parse.srcSize = size; + parse.srcFinished = finish; + parse.canCreateNewThread = True; + + PRF(printf("\nParse size = %d\n", (unsigned)size)); + + p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse); + + PRF(printf(" Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state)); + + needWrite = True; + canCreateNewThread = parse.canCreateNewThread; + + // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize); + + if ( + // parseRes != SZ_OK || + // inDataSize - (size - parse.srcSize) > p->inBlockMax + // || + parse.state == MTDEC_PARSE_OVERFLOW + // || wasInterrupted + ) + { + // Overflow or Parse error - switch from MT decoding to ST decoding + finish = True; + overflow = True; + + { + PRF(printf("\n Overflow")); + // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished)); + PRF(printf("\n inDataSize = %d", (unsigned)inDataSize)); + } + + if (crossSize != 0) + memcpy(data, parseData, size); + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (crossSize != 0) + { + memcpy(data, parseData, parse.srcSize); + p->crossStart += parse.srcSize; + } + + if (parse.state != MTDEC_PARSE_CONTINUE || finish) + { + // we don't need to parse in current thread anymore + + if (parse.state == MTDEC_PARSE_END) + finish = True; + + needCode = True; + // p->crossFinished = finish; + + if (parse.srcSize == size) + { + // full parsed - no cross transfer + p->crossStart = 0; + p->crossEnd = 0; + break; + } + + if (parse.state == MTDEC_PARSE_END) + { + afterEndData = parseData + parse.srcSize; + afterEndData_Size = size - parse.srcSize; + if (crossSize != 0) + afterEndData_IsCross = True; + // we reduce data size to required bytes (parsed only) + inDataSize -= afterEndData_Size; + if (!prev) + inDataSize_Start = parse.srcSize; + break; + } + + { + // partial parsed - need cross transfer + if (crossSize != 0) + inDataSize = parse.srcSize; // it's only parsed now + else + { + // partial parsed - is not in initial cross block - we need to copy new data to cross block + Byte *cr = MtDec_GetCrossBuff(p); + if (!cr) + { + { + PRF(printf("\ncross alloc error error\n")); + // res = SZ_ERROR_MEM; + finish = True; + // p->allocError_for_Read_BlockIndex = blockIndex; + isAllocError = True; + break; + } + } + + { + size_t crSize = size - parse.srcSize; + inDataSize -= crSize; + p->crossEnd = crSize; + p->crossStart = 0; + memcpy(cr, parseData + parse.srcSize, crSize); + } + } + + // inDataSize_Full = inDataSize; + if (!prev) + inDataSize_Start = parse.srcSize; // it's partial size (parsed only) + + finish = False; + break; + } + } + + if (parse.srcSize != size) + { + res = SZ_ERROR_FAIL; + PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res)); + break; + } + } + } + + prev = link; + link = link->next; + + if (crossSize != 0) + { + crossSize = 0; + p->crossStart = 0; + p->crossEnd = 0; + } + } + } + + if (res == SZ_OK) + res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted); + } + + codeRes = SZ_OK; + + if (res == SZ_OK && needCode && !wasInterrupted) + { + codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index); + if (codeRes != SZ_OK) + { + needCode = False; + finish = True; + // SZ_ERROR_MEM is expected error here. + // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later. + // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding. + } + } + + if (res != SZ_OK || wasInterrupted) + finish = True; + + nextThread = NULL; + threadingErrorSRes = SZ_OK; + + if (!finish) + { + if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread) + { + SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]); + if (res2 == SZ_OK) + { + // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads)); + p->numStartedThreads++; + } + else + { + PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads)); + if (p->numStartedThreads == 1) + { + // if only one thread is possible, we leave muti-threading code + finish = True; + needCode = False; + threadingErrorSRes = res2; + } + else + p->numStartedThreads_Limit = p->numStartedThreads; + } + } + + if (!finish) + { + unsigned nextIndex = t->index + 1; + nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex]; + RINOK_THREAD(Event_Set(&nextThread->canRead)) + // We have started executing for new iteration (with next thread) + // And that next thread now is responsible for possible exit from decoding (threading_code) + } + } + + // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite) + // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case + // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block): + // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration + // - otherwise we stop decoding and exit from ThreadFunc2() + + // Don't change (finish) variable in the further code + + + // ---------- CODE ---------- + + inPrev = 0; + outPrev = 0; + inCodePos = 0; + outCodePos = 0; + + if (res == SZ_OK && needCode && codeRes == SZ_OK) + { + BoolInt isStartBlock = True; + CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; + + for (;;) + { + size_t inSize; + int stop; + + if (isStartBlock) + inSize = inDataSize_Start; + else + { + UInt64 rem = inDataSize - inCodePos; + inSize = p->inBufSize; + if (inSize > rem) + inSize = (size_t)rem; + } + + inCodePos += inSize; + stop = True; + + codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index, + (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize, + (inCodePos == inDataSize), // srcFinished + &inCodePos, &outCodePos, &stop); + + if (codeRes != SZ_OK) + { + PRF(printf("\nCode Interrupt error = %x\n", codeRes)); + // we interrupt only later blocks + MtDec_Interrupt(p, blockIndex); + break; + } + + if (stop || inCodePos == inDataSize) + break; + + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep) + { + // Sleep(1); + res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted); + if (res != SZ_OK || wasInterrupted) + break; + inPrev = inCodePos; + outPrev = outCodePos; + } + } + + link = link->next; + isStartBlock = False; + } + } + + + // ---------- WRITE ---------- + + RINOK_THREAD(Event_Wait(&t->canWrite)); + + { + BoolInt isErrorMode = False; + BoolInt canRecode = True; + BoolInt needWriteToStream = needWrite; + + if (p->exitThread) return 0; // it's never executed in normal cases + + if (p->wasInterrupted) + wasInterrupted = True; + else + { + if (codeRes != SZ_OK) // || !needCode // check it !!! + { + p->wasInterrupted = True; + p->codeRes = codeRes; + if (codeRes == SZ_ERROR_MEM) + isAllocError = True; + } + + if (threadingErrorSRes) + { + p->wasInterrupted = True; + p->threadingErrorSRes = threadingErrorSRes; + needWriteToStream = False; + } + if (isAllocError) + { + p->wasInterrupted = True; + p->isAllocError = True; + needWriteToStream = False; + } + if (overflow) + { + p->wasInterrupted = True; + p->overflow = True; + needWriteToStream = False; + } + } + + if (needCode) + { + if (wasInterrupted) + { + inCodePos = 0; + outCodePos = 0; + } + { + const UInt64 inDelta = inCodePos - inPrev; + const UInt64 outDelta = outCodePos - outPrev; + // if (inDelta != 0 || outDelta != 0) + res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta); + } + } + + needContinue = (!finish); + + // if (res == SZ_OK && needWrite && !wasInterrupted) + if (needWrite) + { + // p->inProcessed += inCodePos; + + PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size)); + + res = p->mtCallback->Write(p->mtCallbackObject, t->index, + res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite + afterEndData, afterEndData_Size, afterEndData_IsCross, + &needContinue, + &canRecode); + + // res = SZ_ERROR_FAIL; // for test + + PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue)); + PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed)); + + if (res != SZ_OK) + { + PRF(printf("\nWrite error = %d\n", res)); + isErrorMode = True; + p->wasInterrupted = True; + } + if (res != SZ_OK + || (!needContinue && !finish)) + { + PRF(printf("\nWrite Interrupt error = %x\n", res)); + MtDec_Interrupt(p, blockIndex); + } + } + + if (canRecode) + if (!needCode + || res != SZ_OK + || p->wasInterrupted + || codeRes != SZ_OK + || wasInterrupted + || p->numFilledThreads != 0 + || isErrorMode) + { + if (p->numFilledThreads == 0) + p->filledThreadStart = t->index; + if (inDataSize != 0 || !finish) + { + t->inDataSize_Start = inDataSize_Start; + t->inDataSize = inDataSize; + p->numFilledThreads++; + } + PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads)); + PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart)); + } + + if (!finish) + { + RINOK_THREAD(Event_Set(&nextThread->canWrite)); + } + else + { + if (needContinue) + { + // we restore decoding with new iteration + RINOK_THREAD(Event_Set(&p->threads[0].canWrite)); + } + else + { + // we exit from decoding + if (t->index == 0) + return SZ_OK; + p->exitThread = True; + } + RINOK_THREAD(Event_Set(&p->threads[0].canRead)); + } + } + } +} + +#ifdef _WIN32 +#define USE_ALLOCA +#endif + +#ifdef USE_ALLOCA +#ifdef _WIN32 +#include +#else +#include +#endif +#endif + + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc1(void *pp) +{ + WRes res; + + CMtDecThread *t = (CMtDecThread *)pp; + CMtDec *p; + + // fprintf(stdout, "\n%d = %p\n", t->index, &t); + + res = ThreadFunc2(t); + p = t->mtDec; + if (res == 0) + return (THREAD_FUNC_RET_TYPE)(UINT_PTR)p->exitThreadWRes; + { + // it's unexpected situation for some threading function error + if (p->exitThreadWRes == 0) + p->exitThreadWRes = res; + PRF(printf("\nthread exit error = %d\n", res)); + p->exitThread = True; + Event_Set(&p->threads[0].canRead); + Event_Set(&p->threads[0].canWrite); + MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); + } + return (THREAD_FUNC_RET_TYPE)(UINT_PTR)res; +} + +static MY_NO_INLINE THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + #ifdef USE_ALLOCA + CMtDecThread *t = (CMtDecThread *)pp; + // fprintf(stderr, "\n%d = %p - before", t->index, &t); + t->allocaPtr = alloca(t->index * 128); + #endif + return ThreadFunc1(pp); +} + + +int MtDec_PrepareRead(CMtDec *p) +{ + if (p->crossBlock && p->crossStart == p->crossEnd) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + if (i > p->numStartedThreads + || p->numFilledThreads <= + (i >= p->filledThreadStart ? + i - p->filledThreadStart : + i + p->numStartedThreads - p->filledThreadStart)) + MtDecThread_FreeInBufs(&p->threads[i]); + } + + return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd); +} + + +const Byte *MtDec_Read(CMtDec *p, size_t *inLim) +{ + while (p->numFilledThreads != 0) + { + CMtDecThread *t = &p->threads[p->filledThreadStart]; + + if (*inLim != 0) + { + { + void *link = t->inBuf; + void *next = ((CMtDecBufLink *)link)->next; + ISzAlloc_Free(p->alloc, link); + t->inBuf = next; + } + + if (t->inDataSize == 0) + { + MtDecThread_FreeInBufs(t); + if (--p->numFilledThreads == 0) + break; + if (++p->filledThreadStart == p->numStartedThreads) + p->filledThreadStart = 0; + t = &p->threads[p->filledThreadStart]; + } + } + + { + size_t lim = t->inDataSize_Start; + if (lim != 0) + t->inDataSize_Start = 0; + else + { + UInt64 rem = t->inDataSize; + lim = p->inBufSize; + if (lim > rem) + lim = (size_t)rem; + } + t->inDataSize -= lim; + *inLim = lim; + return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf); + } + } + + { + size_t crossSize = p->crossEnd - p->crossStart; + if (crossSize != 0) + { + const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; + *inLim = crossSize; + p->crossStart = 0; + p->crossEnd = 0; + return data; + } + *inLim = 0; + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + return NULL; + } +} + + +void MtDec_Construct(CMtDec *p) +{ + unsigned i; + + p->inBufSize = (size_t)1 << 18; + + p->numThreadsMax = 0; + + p->inStream = NULL; + + // p->inData = NULL; + // p->inDataSize = 0; + + p->crossBlock = NULL; + p->crossStart = 0; + p->crossEnd = 0; + + p->numFilledThreads = 0; + + p->progress = NULL; + p->alloc = NULL; + + p->mtCallback = NULL; + p->mtCallbackObject = NULL; + + p->allocatedBufsSize = 0; + + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + t->mtDec = p; + t->index = i; + t->inBuf = NULL; + Event_Construct(&t->canRead); + Event_Construct(&t->canWrite); + Thread_Construct(&t->thread); + } + + // Event_Construct(&p->finishedEvent); + + CriticalSection_Init(&p->mtProgress.cs); +} + + +static void MtDec_Free(CMtDec *p) +{ + unsigned i; + + p->exitThread = True; + + for (i = 0; i < MTDEC__THREADS_MAX; i++) + MtDecThread_Destruct(&p->threads[i]); + + // Event_Close(&p->finishedEvent); + + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } +} + + +void MtDec_Destruct(CMtDec *p) +{ + MtDec_Free(p); + + CriticalSection_Delete(&p->mtProgress.cs); +} + + +SRes MtDec_Code(CMtDec *p) +{ + unsigned i; + + p->inProcessed = 0; + + p->blockIndex = 1; // it must be larger than not_defined index (0) + p->isAllocError = False; + p->overflow = False; + p->threadingErrorSRes = SZ_OK; + + p->needContinue = True; + + p->readWasFinished = False; + p->needInterrupt = False; + p->interruptIndex = (UInt64)(Int64)-1; + + p->readProcessed = 0; + p->readRes = SZ_OK; + p->codeRes = SZ_OK; + p->wasInterrupted = False; + + p->crossStart = 0; + p->crossEnd = 0; + + p->filledThreadStart = 0; + p->numFilledThreads = 0; + + { + unsigned numThreads = p->numThreadsMax; + if (numThreads > MTDEC__THREADS_MAX) + numThreads = MTDEC__THREADS_MAX; + p->numStartedThreads_Limit = numThreads; + p->numStartedThreads = 0; + } + + if (p->inBufSize != p->allocatedBufsSize) + { + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CMtDecThread *t = &p->threads[i]; + if (t->inBuf) + MtDecThread_FreeInBufs(t); + } + if (p->crossBlock) + { + ISzAlloc_Free(p->alloc, p->crossBlock); + p->crossBlock = NULL; + } + + p->allocatedBufsSize = p->inBufSize; + } + + MtProgress_Init(&p->mtProgress, p->progress); + + // RINOK_THREAD(ArEvent_OptCreate_And_Reset(&p->finishedEvent)); + p->exitThread = False; + p->exitThreadWRes = 0; + + { + WRes wres; + SRes sres; + CMtDecThread *nextThread = &p->threads[p->numStartedThreads++]; + // wres = MtDecThread_CreateAndStart(nextThread); + wres = MtDecThread_CreateEvents(nextThread); + if (wres == 0) { wres = Event_Set(&nextThread->canWrite); + if (wres == 0) { wres = Event_Set(&nextThread->canRead); + if (wres == 0) { THREAD_FUNC_RET_TYPE res = ThreadFunc(nextThread); + wres = (WRes)(UINT_PTR)res; + if (wres != 0) + { + p->needContinue = False; + MtDec_CloseThreads(p); + }}}} + + // wres = 17; // for test + // wres = Event_Wait(&p->finishedEvent); + + sres = MY_SRes_HRESULT_FROM_WRes(wres); + + if (sres != 0) + p->threadingErrorSRes = sres; + + if ( + // wres == 0 + // wres != 0 + // || p->mtc.codeRes == SZ_ERROR_MEM + p->isAllocError + || p->threadingErrorSRes != SZ_OK + || p->overflow) + { + // p->needContinue = True; + } + else + p->needContinue = False; + + if (p->needContinue) + return SZ_OK; + + // if (sres != SZ_OK) + return sres; + // return SZ_ERROR_FAIL; + } +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/MtDec.h b/3rdparty/lzma-21.03beta/C/MtDec.h new file mode 100644 index 0000000..c2da46a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/MtDec.h @@ -0,0 +1,202 @@ +/* MtDec.h -- Multi-thread Decoder +2020-03-05 : Igor Pavlov : Public domain */ + +#ifndef __MT_DEC_H +#define __MT_DEC_H + +#include "7zTypes.h" + +#ifndef _7ZIP_ST +#include "Threads.h" +#endif + +EXTERN_C_BEGIN + +#ifndef _7ZIP_ST + +#ifndef _7ZIP_ST + #define MTDEC__THREADS_MAX 32 +#else + #define MTDEC__THREADS_MAX 1 +#endif + + +typedef struct +{ + ICompressProgress *progress; + SRes res; + UInt64 totalInSize; + UInt64 totalOutSize; + CCriticalSection cs; +} CMtProgress; + +void MtProgress_Init(CMtProgress *p, ICompressProgress *progress); +SRes MtProgress_Progress_ST(CMtProgress *p); +SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize); +SRes MtProgress_GetError(CMtProgress *p); +void MtProgress_SetError(CMtProgress *p, SRes res); + +struct _CMtDec; + +typedef struct +{ + struct _CMtDec *mtDec; + unsigned index; + void *inBuf; + + size_t inDataSize_Start; // size of input data in start block + UInt64 inDataSize; // total size of input data in all blocks + + CThread thread; + CAutoResetEvent canRead; + CAutoResetEvent canWrite; + void *allocaPtr; +} CMtDecThread; + +void MtDecThread_FreeInBufs(CMtDecThread *t); + + +typedef enum +{ + MTDEC_PARSE_CONTINUE, // continue this block with more input data + MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread + MTDEC_PARSE_NEW, // new block + MTDEC_PARSE_END // end of block threading. But we still can return to threading after Write(&needContinue) +} EMtDecParseState; + +typedef struct +{ + // in + int startCall; + const Byte *src; + size_t srcSize; + // in : (srcSize == 0) is allowed + // out : it's allowed to return less that actually was used ? + int srcFinished; + + // out + EMtDecParseState state; + BoolInt canCreateNewThread; + UInt64 outPos; // check it (size_t) +} CMtDecCallbackInfo; + + +typedef struct +{ + void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci); + + // PreCode() and Code(): + // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks + SRes (*PreCode)(void *p, unsigned coderIndex); + SRes (*Code)(void *p, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop); + // stop - means stop another Code calls + + + /* Write() must be called, if Parse() was called + set (needWrite) if + { + && (was not interrupted by progress) + && (was not interrupted in previous block) + } + + out: + if (*needContinue), decoder still need to continue decoding with new iteration, + even after MTDEC_PARSE_END + if (*canRecode), we didn't flush current block data, so we still can decode current block later. + */ + SRes (*Write)(void *p, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + // int srcFinished, + BoolInt *needContinue, + BoolInt *canRecode); + +} IMtDecCallback2; + + + +typedef struct _CMtDec +{ + /* input variables */ + + size_t inBufSize; /* size of input block */ + unsigned numThreadsMax; + // size_t inBlockMax; + unsigned numThreadsMax_2; + + ISeqInStream *inStream; + // const Byte *inData; + // size_t inDataSize; + + ICompressProgress *progress; + ISzAllocPtr alloc; + + IMtDecCallback2 *mtCallback; + void *mtCallbackObject; + + + /* internal variables */ + + size_t allocatedBufsSize; + + BoolInt exitThread; + WRes exitThreadWRes; + + UInt64 blockIndex; + BoolInt isAllocError; + BoolInt overflow; + SRes threadingErrorSRes; + + BoolInt needContinue; + + // CAutoResetEvent finishedEvent; + + SRes readRes; + SRes codeRes; + + BoolInt wasInterrupted; + + unsigned numStartedThreads_Limit; + unsigned numStartedThreads; + + Byte *crossBlock; + size_t crossStart; + size_t crossEnd; + UInt64 readProcessed; + BoolInt readWasFinished; + UInt64 inProcessed; + + unsigned filledThreadStart; + unsigned numFilledThreads; + + #ifndef _7ZIP_ST + BoolInt needInterrupt; + UInt64 interruptIndex; + CMtProgress mtProgress; + CMtDecThread threads[MTDEC__THREADS_MAX]; + #endif +} CMtDec; + + +void MtDec_Construct(CMtDec *p); +void MtDec_Destruct(CMtDec *p); + +/* +MtDec_Code() returns: + SZ_OK - in most cases + MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function +*/ + +SRes MtDec_Code(CMtDec *p); +Byte *MtDec_GetCrossBuff(CMtDec *p); + +int MtDec_PrepareRead(CMtDec *p); +const Byte *MtDec_Read(CMtDec *p, size_t *inLim); + +#endif + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Ppmd.h b/3rdparty/lzma-21.03beta/C/Ppmd.h new file mode 100644 index 0000000..b198792 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Ppmd.h @@ -0,0 +1,167 @@ +/* Ppmd.h -- PPMD codec common code +2021-04-13 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#ifndef __PPMD_H +#define __PPMD_H + +#include "CpuArch.h" + +EXTERN_C_BEGIN + +#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) +/* + PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block. + if (PPMD_32BIT is defined), the PPMD code stores internal pointers to 32-bit reference fields. + if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields. + if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed, + if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional, + and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit. + PPMD code works slightly faster in (PPMD_32BIT) mode. +*/ + #define PPMD_32BIT +#endif + +#define PPMD_INT_BITS 7 +#define PPMD_PERIOD_BITS 7 +#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) + +#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) +#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) +#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) +#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) + +#define PPMD_N1 4 +#define PPMD_N2 4 +#define PPMD_N3 4 +#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) +#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) + +MY_CPU_pragma_pack_push_1 +/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ + +/* SEE-contexts for PPM-contexts with masked symbols */ +typedef struct +{ + UInt16 Summ; /* Freq */ + Byte Shift; /* Speed of Freq change; low Shift is for fast change */ + Byte Count; /* Count to next change of Shift */ +} CPpmd_See; + +#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ + { (p)->Summ = (UInt16)((p)->Summ << 1); (p)->Count = (Byte)(3 << (p)->Shift++); } + + +typedef struct +{ + Byte Symbol; + Byte Freq; + UInt16 Successor_0; + UInt16 Successor_1; +} CPpmd_State; + +typedef struct CPpmd_State2_ +{ + Byte Symbol; + Byte Freq; +} CPpmd_State2; + +typedef struct CPpmd_State4_ +{ + UInt16 Successor_0; + UInt16 Successor_1; +} CPpmd_State4; + +MY_CPU_pragma_pop + +/* + PPMD code can write full CPpmd_State structure data to CPpmd*_Context + at (byte offset = 2) instead of some fields of original CPpmd*_Context structure. + + If we use pointers to different types, but that point to shared + memory space, we can have aliasing problem (strict aliasing). + + XLC compiler in -O2 mode can change the order of memory write instructions + in relation to read instructions, if we have use pointers to different types. + + To solve that aliasing problem we use combined CPpmd*_Context structure + with unions that contain the fields from both structures: + the original CPpmd*_Context and CPpmd_State. + So we can access the fields from both structures via one pointer, + and the compiler doesn't change the order of write instructions + in relation to read instructions. + + If we don't use memory write instructions to shared memory in + some local code, and we use only reading instructions (read only), + then probably it's safe to use pointers to different types for reading. +*/ + + + +#ifdef PPMD_32BIT + + #define Ppmd_Ref_Type(type) type * + #define Ppmd_GetRef(p, ptr) (ptr) + #define Ppmd_GetPtr(p, ptr) (ptr) + #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr) + +#else + + #define Ppmd_Ref_Type(type) UInt32 + #define Ppmd_GetRef(p, ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) + #define Ppmd_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs)) + +#endif // PPMD_32BIT + + +typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref; +typedef Ppmd_Ref_Type(void) CPpmd_Void_Ref; +typedef Ppmd_Ref_Type(Byte) CPpmd_Byte_Ref; + + +/* +#ifdef MY_CPU_LE_UNALIGN +// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache. +#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0) +#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v) + +#else +*/ + +/* + We can write 16-bit halves to 32-bit (Successor) field in any selected order. + But the native order is more consistent way. + So we use the native order, if LE/BE order can be detected here at compile time. +*/ + +#ifdef MY_CPU_BE + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); } + +#else + + #define Ppmd_GET_SUCCESSOR(p) \ + ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) ) + + #define Ppmd_SET_SUCCESSOR(p, v) { \ + (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \ + (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); } + +#endif + +// #endif + + +#define PPMD_SetAllBitsIn256Bytes(p) \ + { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \ + p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }} + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Ppmd7.c b/3rdparty/lzma-21.03beta/C/Ppmd7.c new file mode 100644 index 0000000..cf401cb --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Ppmd7.c @@ -0,0 +1,1104 @@ +/* Ppmd7.c -- PPMdH codec +2021-04-13 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include + +#include "Ppmd7.h" + +/* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */ +// #define PPMD7_ORDER_0_SUPPPORT + +MY_ALIGN(16) +static const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +MY_ALIGN(16) +static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; + +#define MAX_FREQ 124 +#define UNIT_SIZE 12 + +#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) +#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1]) +#define I2U(indx) ((unsigned)p->Indx2Units[indx]) +#define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx]) + +#define REF(ptr) Ppmd_GetRef(p, ptr) + +#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define STATS(ctx) Ppmd7_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +typedef CPpmd7_Context * CTX_PTR; + +struct CPpmd7_Node_; + +typedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref; + +typedef struct CPpmd7_Node_ +{ + UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ + UInt16 NU; + CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ + CPpmd7_Node_Ref Prev; +} CPpmd7_Node; + +#define NODE(r) Ppmd_GetPtr_Type(p, r, CPpmd7_Node) + +void Ppmd7_Construct(CPpmd7 *p) +{ + unsigned i, k, m; + + p->Base = NULL; + + for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) + { + unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); + do { p->Units2Indx[k++] = (Byte)i; } while (--step); + p->Indx2Units[i] = (Byte)k; + } + + p->NS2BSIndx[0] = (0 << 1); + p->NS2BSIndx[1] = (1 << 1); + memset(p->NS2BSIndx + 2, (2 << 1), 9); + memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); + + for (i = 0; i < 3; i++) + p->NS2Indx[i] = (Byte)i; + + for (m = i, k = 1; i < 256; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 2; + } + + memcpy(p->ExpEscape, PPMD7_kExpEscape, 16); +} + + +void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->Base); + p->Size = 0; + p->Base = NULL; +} + + +BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc) +{ + if (!p->Base || p->Size != size) + { + Ppmd7_Free(p, alloc); + p->AlignOffset = (4 - size) & 3; + if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL) + return False; + p->Size = size; + } + return True; +} + + + +// ---------- Internal Memory Allocator ---------- + +/* We can use CPpmd7_Node in list of free units (as in Ppmd8) + But we still need one additional list walk pass in GlueFreeBlocks(). + So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in InsertNode() / RemoveNode() +*/ + +#define EMPTY_NODE 0 + + +static void InsertNode(CPpmd7 *p, void *node, unsigned indx) +{ + *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx]; + + p->FreeList[indx] = REF(node); + +} + + +static void *RemoveNode(CPpmd7 *p, unsigned indx) +{ + CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); + p->FreeList[indx] = *node; + // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]); + // p->FreeList[indx] = node->Next; + return node; +} + + +static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +{ + unsigned i, nu = I2U(oldIndx) - I2U(newIndx); + ptr = (Byte *)ptr + U2B(I2U(newIndx)); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + } + InsertNode(p, ptr, i); +} + + +/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */ + +typedef union _CPpmd7_Node_Union +{ + CPpmd7_Node Node; + CPpmd7_Node_Ref NextRef; +} CPpmd7_Node_Union; + +/* Original PPmdH (Ppmd7) code uses doubly linked list in GlueFreeBlocks() + we use single linked list similar to Ppmd8 code */ + + +static void GlueFreeBlocks(CPpmd7 *p) +{ + /* + we use first UInt16 field of 12-bytes UNITs as record type stamp + CPpmd_State { Byte Symbol; Byte Freq; : Freq != 0 + CPpmd7_Context { UInt16 NumStats; : NumStats != 0 + CPpmd7_Node { UInt16 Stamp : Stamp == 0 for free record + : Stamp == 1 for head record and guard + Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record. + */ + CPpmd7_Node_Ref head, n = 0; + + p->GlueCount = 255; + + + /* we set guard NODE at LoUnit */ + if (p->LoUnit != p->HiUnit) + ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1; + + { + /* Create list of free blocks. + We still need one additional list walk pass before Glue. */ + unsigned i; + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + const UInt16 nu = I2U_UInt16(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + /* Don't change the order of the following commands: */ + CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next); + const CPpmd7_Node_Ref tmp = next; + next = un->NextRef; + un->Node.Stamp = EMPTY_NODE; + un->Node.NU = nu; + un->Node.Next = n; + n = tmp; + } + } + } + + head = n; + /* Glue and Fill must walk the list in same direction */ + { + /* Glue free blocks */ + CPpmd7_Node_Ref *prev = &head; + while (n) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = node->NU; + n = node->Next; + if (nu == 0) + { + *prev = n; + continue; + } + prev = &node->Next; + for (;;) + { + CPpmd7_Node *node2 = node + nu; + nu += node2->NU; + if (node2->Stamp != EMPTY_NODE || nu >= 0x10000) + break; + node->NU = (UInt16)nu; + node2->NU = 0; + } + } + } + + /* Fill lists of free blocks */ + for (n = head; n != 0;) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = node->NU; + unsigned i; + n = node->Next; + if (nu == 0) + continue; + for (; nu > 128; nu -= 128, node += 128) + InsertNode(p, node, PPMD_NUM_INDEXES - 1); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, node + k, (unsigned)nu - k - 1); + } + InsertNode(p, node, i); + } +} + + +MY_NO_INLINE +static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) +{ + unsigned i; + + if (p->GlueCount == 0) + { + GlueFreeBlocks(p); + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + } + + i = indx; + + do + { + if (++i == PPMD_NUM_INDEXES) + { + UInt32 numBytes = U2B(I2U(indx)); + Byte *us = p->UnitsStart; + p->GlueCount--; + return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL; + } + } + while (p->FreeList[i] == 0); + + { + void *block = RemoveNode(p, i); + SplitBlock(p, block, i, indx); + return block; + } +} + + +static void *AllocUnits(CPpmd7 *p, unsigned indx) +{ + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + { + UInt32 numBytes = U2B(I2U(indx)); + Byte *lo = p->LoUnit; + if ((UInt32)(p->HiUnit - lo) >= numBytes) + { + p->LoUnit = lo + numBytes; + return lo; + } + } + return AllocUnitsRare(p, indx); +} + + +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } + + +/* +static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) +{ + unsigned i0 = U2I(oldNU); + unsigned i1 = U2I(newNU); + if (i0 == i1) + return oldPtr; + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + MyMem12Cpy(ptr, oldPtr, newNU); + InsertNode(p, oldPtr, i0); + return ptr; + } + SplitBlock(p, oldPtr, i0, i1); + return oldPtr; +} +*/ + + +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) +static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) +{ + Ppmd_SET_SUCCESSOR(p, v); +} + + + +MY_NO_INLINE +static +void RestartModel(CPpmd7 *p) +{ + unsigned i, k; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + + p->Text = p->Base + p->AlignOffset; + p->HiUnit = p->Text + p->Size; + p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; + p->GlueCount = 0; + + p->OrderFall = p->MaxOrder; + p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; + p->PrevSuccess = 0; + + { + CPpmd7_Context *mc = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + + p->LoUnit += U2B(256 / 2); + p->MaxContext = p->MinContext = mc; + p->FoundState = s; + + mc->NumStats = 256; + mc->Union2.SummFreq = 256 + 1; + mc->Union4.Stats = REF(s); + mc->Suffix = 0; + + for (i = 0; i < 256; i++, s++) + { + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + #ifdef PPMD7_ORDER_0_SUPPPORT + if (p->MaxOrder == 0) + { + CPpmd_Void_Ref r = REF(mc); + s = p->FoundState; + for (i = 0; i < 256; i++, s++) + SetSuccessor(s, r); + return; + } + #endif + } + + for (i = 0; i < 128; i++) + + + + for (k = 0; k < 8; k++) + { + unsigned m; + UInt16 *dest = p->BinSumm[i] + k; + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); + for (m = 0; m < 64; m += 8) + dest[m] = val; + } + + + for (i = 0; i < 25; i++) + { + + CPpmd_See *s = p->See[i]; + + + + unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4)); + for (k = 0; k < 16; k++, s++) + { + s->Summ = (UInt16)summ; + s->Shift = (PPMD_PERIOD_BITS - 4); + s->Count = 4; + } + } + + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Count = 64; /* unused */ +} + + +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) +{ + p->MaxOrder = maxOrder; + + RestartModel(p); +} + + + +/* + CreateSuccessors() + It's called when (FoundState->Successor) is RAW-Successor, + that is the link to position in Raw text. + So we create Context records and write the links to + FoundState->Successor and to identical RAW-Successors in suffix + contexts of MinContex. + + The function returns: + if (OrderFall == 0) then MinContext is already at MAX order, + { return pointer to new or existing context of same MAX order } + else + { return pointer to new real context that will be (Order+1) in comparison with MinContext + + also it can return pointer to real context of same order, +*/ + +MY_NO_INLINE +static CTX_PTR CreateSuccessors(CPpmd7 *p) +{ + CTX_PTR c = p->MinContext; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + Byte newSym, newFreq; + unsigned numPs = 0; + CPpmd_State *ps[PPMD7_MAX_ORDER]; + + if (p->OrderFall != 0) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + + + if (c->NumStats != 1) + { + Byte sym = p->FoundState->Symbol; + for (s = STATS(c); s->Symbol != sym; s++); + + } + else + { + s = ONE_STATE(c); + + } + successor = SUCCESSOR(s); + if (successor != upBranch) + { + // (c) is real record Context here, + c = CTX(successor); + if (numPs == 0) + { + // (c) is real record MAX Order Context here, + // So we don't need to create any new contexts. + return c; + } + break; + } + ps[numPs++] = s; + } + + // All created contexts will have single-symbol with new RAW-Successor + // All new RAW-Successors will point to next position in RAW text + // after FoundState->Successor + + newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + upBranch++; + + + if (c->NumStats == 1) + newFreq = ONE_STATE(c)->Freq; + else + { + UInt32 cf, s0; + CPpmd_State *s; + for (s = STATS(c); s->Symbol != newSym; s++); + cf = (UInt32)s->Freq - 1; + s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf; + /* + cf - is frequency of symbol that will be Successor in new context records. + s0 - is commulative frequency sum of another symbols from parent context. + max(newFreq)= (s->Freq + 1), when (s0 == 1) + we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[] + so (s->Freq < 128) - is requirement for multi-symbol contexts + */ + newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1)); + } + + // Create new single-symbol contexts from low order to high order in loop + + do + { + CTX_PTR c1; + /* = AllocContext(p); */ + if (p->HiUnit != p->LoUnit) + c1 = (CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); + else if (p->FreeList[0] != 0) + c1 = (CTX_PTR)RemoveNode(p, 0); + else + { + c1 = (CTX_PTR)AllocUnitsRare(p, 0); + if (!c1) + return NULL; + } + + c1->NumStats = 1; + ONE_STATE(c1)->Symbol = newSym; + ONE_STATE(c1)->Freq = newFreq; + SetSuccessor(ONE_STATE(c1), upBranch); + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + while (numPs != 0); + + return c; +} + + + +#define SwapStates(s) \ + { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; } + + +void Ppmd7_UpdateModel(CPpmd7 *p); +MY_NO_INLINE +void Ppmd7_UpdateModel(CPpmd7 *p) +{ + CPpmd_Void_Ref maxSuccessor, minSuccessor; + CTX_PTR c, mc; + unsigned s0, ns; + + + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + /* Update Freqs in Suffix Context */ + + c = SUFFIX(p->MinContext); + + if (c->NumStats == 1) + { + CPpmd_State *s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + CPpmd_State *s = STATS(c); + Byte sym = p->FoundState->Symbol; + + if (s->Symbol != sym) + { + do + { + // s++; if (s->Symbol == sym) break; + s++; + } + while (s->Symbol != sym); + + if (s[0].Freq >= s[-1].Freq) + { + SwapStates(s); + s--; + } + } + + if (s->Freq < MAX_FREQ - 9) + { + s->Freq = (Byte)(s->Freq + 2); + c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2); + } + } + } + + + if (p->OrderFall == 0) + { + /* MAX ORDER context */ + /* (FoundState->Successor) is RAW-Successor. */ + p->MaxContext = p->MinContext = CreateSuccessors(p); + if (!p->MinContext) + { + RestartModel(p); + return; + } + SetSuccessor(p->FoundState, REF(p->MinContext)); + return; + } + + + /* NON-MAX ORDER context */ + + { + Byte *text = p->Text; + *text++ = p->FoundState->Symbol; + p->Text = text; + if (text >= p->UnitsStart) + { + RestartModel(p); + return; + } + maxSuccessor = REF(text); + } + + minSuccessor = SUCCESSOR(p->FoundState); + + if (minSuccessor) + { + // there is Successor for FoundState in MinContext. + // So the next context will be one order higher than MinContext. + + if (minSuccessor <= maxSuccessor) + { + // minSuccessor is RAW-Successor. So we will create real contexts records: + CTX_PTR cs = CreateSuccessors(p); + if (!cs) + { + RestartModel(p); + return; + } + minSuccessor = REF(cs); + } + + // minSuccessor now is real Context pointer that points to existing (Order+1) context + + if (--p->OrderFall == 0) + { + /* + if we move to MaxOrder context, then minSuccessor will be common Succesor for both: + MinContext that is (MaxOrder - 1) + MaxContext that is (MaxOrder) + so we don't need new RAW-Successor, and we can use real minSuccessor + as succssors for both MinContext and MaxContext. + */ + maxSuccessor = minSuccessor; + + /* + if (MaxContext != MinContext) + { + there was order fall from MaxOrder and we don't need current symbol + to transfer some RAW-Succesors to real contexts. + So we roll back pointer in raw data for one position. + } + */ + p->Text -= (p->MaxContext != p->MinContext); + } + } + else + { + /* + FoundState has NULL-Successor here. + And only root 0-order context can contain NULL-Successors. + We change Successor in FoundState to RAW-Successor, + And next context will be same 0-order root Context. + */ + SetSuccessor(p->FoundState, maxSuccessor); + minSuccessor = REF(p->MinContext); + } + + mc = p->MinContext; + c = p->MaxContext; + + p->MaxContext = p->MinContext = CTX(minSuccessor); + + if (c == mc) + return; + + // s0 : is pure Escape Freq + s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1); + + do + { + unsigned ns1; + UInt32 sum; + + if ((ns1 = c->NumStats) != 1) + { + if ((ns1 & 1) == 0) + { + /* Expand for one UNIT */ + unsigned oldNU = ns1 >> 1; + unsigned i = U2I(oldNU); + if (i != U2I((size_t)oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RestartModel(p); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Union4.Stats = STATS_REF(ptr); + } + } + sum = c->Union2.SummFreq; + /* max increase of Escape_Freq is 3 here. + total increase of Union2.SummFreq for all symbols is less than 256 here */ + sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)); + /* original PPMdH uses 16-bit variable for (sum) here. + But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ + // sum = (UInt16)sum; + } + else + { + // instead of One-symbol context we create 2-symbol context + CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + if (!s) + { + RestartModel(p); + return; + } + { + unsigned freq = c->Union2.State2.Freq; + // s = *ONE_STATE(c); + s->Symbol = c->Union2.State2.Symbol; + s->Successor_0 = c->Union4.State4.Successor_0; + s->Successor_1 = c->Union4.State4.Successor_1; + // SetSuccessor(s, c->Union4.Stats); // call it only for debug purposes to check the order of + // (Successor_0 and Successor_1) in LE/BE. + c->Union4.Stats = REF(s); + if (freq < MAX_FREQ / 4 - 1) + freq <<= 1; + else + freq = MAX_FREQ - 4; + // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context + s->Freq = (Byte)freq; + // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here + sum = freq + p->InitEsc + (ns > 3); + } + } + + { + CPpmd_State *s = STATS(c) + ns1; + UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq; + UInt32 sf = (UInt32)s0 + sum; + s->Symbol = p->FoundState->Symbol; + c->NumStats = (UInt16)(ns1 + 1); + SetSuccessor(s, maxSuccessor); + + if (cf < 6 * sf) + { + cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf); + sum += 3; + /* It can add (0, 1, 2) to Escape_Freq */ + } + else + { + cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + sum += cf; + } + + c->Union2.SummFreq = (UInt16)sum; + s->Freq = (Byte)cf; + } + c = SUFFIX(c); + } + while (c != mc); +} + + + +MY_NO_INLINE +static void Rescale(CPpmd7 *p) +{ + unsigned i, adder, sumFreq, escFreq; + CPpmd_State *stats = STATS(p->MinContext); + CPpmd_State *s = p->FoundState; + + /* Sort the list by Freq */ + if (s != stats) + { + CPpmd_State tmp = *s; + do + s[0] = s[-1]; + while (--s != stats); + *s = tmp; + } + + sumFreq = s->Freq; + escFreq = p->MinContext->Union2.SummFreq - sumFreq; + + /* + if (p->OrderFall == 0), adder = 0 : it's allowed to remove symbol from MAX Order context + if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context + */ + + adder = (p->OrderFall != 0); + + #ifdef PPMD7_ORDER_0_SUPPPORT + adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context + #endif + + sumFreq = (sumFreq + 4 + adder) >> 1; + i = (unsigned)p->MinContext->NumStats - 1; + s->Freq = (Byte)sumFreq; + + do + { + unsigned freq = (++s)->Freq; + escFreq -= freq; + freq = (freq + adder) >> 1; + sumFreq += freq; + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) + { + CPpmd_State tmp = *s; + CPpmd_State *s1 = s; + do + { + s1[0] = s1[-1]; + } + while (--s1 != stats && freq > s1[-1].Freq); + *s1 = tmp; + } + } + while (--i); + + if (s->Freq == 0) + { + /* Remove all items with Freq == 0 */ + CPpmd7_Context *mc; + unsigned numStats, numStatsNew, n0, n1; + + i = 0; do { i++; } while ((--s)->Freq == 0); + + /* We increase (escFreq) for the number of removed symbols. + So we will have (0.5) increase for Escape_Freq in avarage per + removed symbol after Escape_Freq halving */ + escFreq += i; + mc = p->MinContext; + numStats = mc->NumStats; + numStatsNew = numStats - i; + mc->NumStats = (UInt16)(numStatsNew); + n0 = (numStats + 1) >> 1; + + if (numStatsNew == 1) + { + /* Create Single-Symbol context */ + unsigned freq = stats->Freq; + + do + { + escFreq >>= 1; + freq = (freq + 1) >> 1; + } + while (escFreq > 1); + + s = ONE_STATE(mc); + *s = *stats; + s->Freq = (Byte)freq; // (freq <= 260 / 4) + p->FoundState = s; + InsertNode(p, stats, U2I(n0)); + return; + } + + n1 = (numStatsNew + 1) >> 1; + if (n0 != n1) + { + // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + unsigned i0 = U2I(n0); + unsigned i1 = U2I(n1); + if (i0 != i1) + { + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + p->MinContext->Union4.Stats = STATS_REF(ptr); + MyMem12Cpy(ptr, (const void *)stats, n1); + InsertNode(p, stats, i0); + } + else + SplitBlock(p, stats, i0, i1); + } + } + } + { + CPpmd7_Context *mc = p->MinContext; + mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + // Escape_Freq halving here + p->FoundState = STATS(mc); + } +} + + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) +{ + CPpmd_See *see; + const CPpmd7_Context *mc = p->MinContext; + unsigned numStats = mc->NumStats; + if (numStats != 256) + { + unsigned nonMasked = numStats - numMasked; + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats) + + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats) + + 4 * (unsigned)(numMasked > nonMasked) + + p->HiBitsFlag; + { + // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ + unsigned summ = (UInt16)see->Summ; // & 0xFFFF + unsigned r = (summ >> see->Shift); + see->Summ = (UInt16)(summ - r); + *escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + *escFreq = 1; + } + return see; +} + + +static void NextContext(CPpmd7 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; + else + Ppmd7_UpdateModel(p); +} + + +void Ppmd7_Update1(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + unsigned freq = s->Freq; + freq += 4; + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > s[-1].Freq) + { + SwapStates(s); + p->FoundState = --s; + if (freq > MAX_FREQ) + Rescale(p); + } + NextContext(p); +} + + +void Ppmd7_Update1_0(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + CPpmd7_Context *mc = p->MinContext; + unsigned freq = s->Freq; + unsigned summFreq = mc->Union2.SummFreq; + p->PrevSuccess = (2 * freq > summFreq); + p->RunLength += (int)p->PrevSuccess; + mc->Union2.SummFreq = (UInt16)(summFreq + 4); + freq += 4; + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) + Rescale(p); + NextContext(p); +} + + +/* +void Ppmd7_UpdateBin(CPpmd7 *p) +{ + unsigned freq = p->FoundState->Freq; + p->FoundState->Freq = (Byte)(freq + (freq < 128)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} +*/ + +void Ppmd7_Update2(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + unsigned freq = s->Freq; + freq += 4; + p->RunLength = p->InitRL; + p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4); + s->Freq = (Byte)freq; + if (freq > MAX_FREQ) + Rescale(p); + Ppmd7_UpdateModel(p); +} + + + +/* +PPMd Memory Map: +{ + [ 0 ] contains subset of original raw text, that is required to create context + records, Some symbols are not written, when max order context was reached + [ Text ] free area + [ UnitsStart ] CPpmd_State vectors and CPpmd7_Context records + [ LoUnit ] free area for CPpmd_State and CPpmd7_Context items +[ HiUnit ] CPpmd7_Context records + [ Size ] end of array +} + +These addresses don't cross at any time. +And the following condtions is true for addresses: + (0 <= Text < UnitsStart <= LoUnit <= HiUnit <= Size) + +Raw text is BYTE--aligned. +the data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs. + +Last UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record. +The code can free UNITs memory blocks that were allocated to store CPpmd_State vectors. +The code doesn't free UNITs allocated for CPpmd7_Context records. + +The code calls RestartModel(), when there is no free memory for allocation. +And RestartModel() changes the state to orignal start state, with full free block. + + +The code allocates UNITs with the following order: + +Allocation of 1 UNIT for Context record + - from free space (HiUnit) down to (LoUnit) + - from FreeList[0] + - AllocUnitsRare() + +AllocUnits() for CPpmd_State vectors: + - from FreeList[i] + - from free space (LoUnit) up to (HiUnit) + - AllocUnitsRare() + +AllocUnitsRare() + - if (GlueCount == 0) + { Glue lists, GlueCount = 255, allocate from FreeList[i]] } + - loop for all higher sized FreeList[...] lists + - from (UnitsStart - Text), GlueCount-- + - ERROR + + +Each Record with Context contains the CPpmd_State vector, where each +CPpmd_State contains the link to Successor. +There are 3 types of Successor: + 1) NULL-Successor - NULL pointer. NULL-Successor links can be stored + only in 0-order Root Context Record. + We use 0 value as NULL-Successor + 2) RAW-Successor - the link to position in raw text, + that "RAW-Successor" is being created after first + occurrence of new symbol for some existing context record. + (RAW-Successor > 0). + 3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1), + that record is being created when we go via RAW-Successor again. + +For any successors at any time: the following condtions are true for Successor links: +(NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor) + + +---------- Symbol Frequency, SummFreq and Range in Range_Coder ---------- + +CPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq + +The PPMd code tries to fulfill the condition: + (SummFreq <= (256 * 128 = RC::kBot)) + +We have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124) +So (4 = 128 - 124) is average reserve for Escape_Freq for each symbol. +If (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7. +SummFreq and Escape_Freq can be changed in Rescale() and *Update*() functions. +Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Rescale() for +max-order context. + +When the PPMd code still break (Total <= RC::Range) condition in range coder, +we have two ways to resolve that problem: + 1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases. + 2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value. +*/ diff --git a/3rdparty/lzma-21.03beta/C/Ppmd7.h b/3rdparty/lzma-21.03beta/C/Ppmd7.h new file mode 100644 index 0000000..d31809a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Ppmd7.h @@ -0,0 +1,181 @@ +/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + + +#ifndef __PPMD7_H +#define __PPMD7_H + +#include "Ppmd.h" + +EXTERN_C_BEGIN + +#define PPMD7_MIN_ORDER 2 +#define PPMD7_MAX_ORDER 64 + +#define PPMD7_MIN_MEM_SIZE (1 << 11) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) + +struct CPpmd7_Context_; + +typedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref; + +// MY_CPU_pragma_pack_push_1 + +typedef struct CPpmd7_Context_ +{ + UInt16 NumStats; + + + union + { + UInt16 SummFreq; + CPpmd_State2 State2; + } Union2; + + union + { + CPpmd_State_Ref Stats; + CPpmd_State4 State4; + } Union4; + + CPpmd7_Context_Ref Suffix; +} CPpmd7_Context; + +// MY_CPU_pragma_pop + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2) + + + + +typedef struct +{ + UInt32 Range; + UInt32 Code; + UInt32 Low; + IByteIn *Stream; +} CPpmd7_RangeDec; + + +typedef struct +{ + UInt32 Range; + Byte Cache; + // Byte _dummy_[3]; + UInt64 Low; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + + +typedef struct +{ + CPpmd7_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + UInt32 AlignOffset; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + + + + + union + { + CPpmd7_RangeDec dec; + CPpmd7z_RangeEnc enc; + } rc; + + Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + + Byte NS2BSIndx[256], NS2Indx[256]; + Byte ExpEscape[16]; + CPpmd_See DummySee, See[25][16]; + UInt16 BinSumm[128][64]; + // int LastSymbol; +} CPpmd7; + + +void Ppmd7_Construct(CPpmd7 *p); +BoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc); +void Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc); +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); +#define Ppmd7_WasAllocated(p) ((p)->Base != NULL) + + +/* ---------- Internal Functions ---------- */ + +#define Ppmd7_GetPtr(p, ptr) Ppmd_GetPtr(p, ptr) +#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context) +#define Ppmd7_GetStats(p, ctx) Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State) + +void Ppmd7_Update1(CPpmd7 *p); +void Ppmd7_Update1_0(CPpmd7 *p); +void Ppmd7_Update2(CPpmd7 *p); + +#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3)) +#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4)) +// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3)) +// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4)) + +#define Ppmd7_GetBinSumm(p) \ + &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \ + [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \ + + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \ + + PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \ + + (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ] + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); + + +/* +We support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure: + 1) Ppmd7a_*: original PPMdH + 2) Ppmd7z_*: modified PPMdH with 7z Range Coder +Ppmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH) +*/ + +/* ---------- Decode ---------- */ + +#define PPMD7_SYM_END (-1) +#define PPMD7_SYM_ERROR (-2) + +/* +You must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init() + +Ppmd7*_DecodeSymbol() +out: + >= 0 : decoded byte + -1 : PPMD7_SYM_END : End of payload marker + -2 : PPMD7_SYM_ERROR : Data error +*/ + +/* Ppmd7a_* : original PPMdH */ +BoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p); +#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd7a_DecodeSymbol(CPpmd7 *p); + +/* Ppmd7z_* : modified PPMdH with 7z Range Coder */ +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p); +#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) +int Ppmd7z_DecodeSymbol(CPpmd7 *p); +// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim); + + +/* ---------- Encode ---------- */ + +void Ppmd7z_Init_RangeEnc(CPpmd7 *p); +void Ppmd7z_Flush_RangeEnc(CPpmd7 *p); +// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol); +void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Ppmd7Dec.c b/3rdparty/lzma-21.03beta/C/Ppmd7Dec.c new file mode 100644 index 0000000..55d74ff --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Ppmd7Dec.c @@ -0,0 +1,297 @@ +/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + + +#define READ_BYTE(p) IByteIn_Read((p)->Stream) + +BoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p) +{ + unsigned i; + p->Code = 0; + p->Range = 0xFFFFFFFF; + if (READ_BYTE(p) != 0) + return False; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | READ_BYTE(p); + return (p->Code < 0xFFFFFFFF); +} + +#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \ + { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8; + +#define RC_NORM_1(p) RC_NORM_BASE(p) } +#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} + +// we must use only one type of Normalization from two: LOCAL or REMOTE +#define RC_NORM_LOCAL(p) // RC_NORM(p) +#define RC_NORM_REMOTE(p) RC_NORM(p) + +#define R (&p->rc.dec) + +MY_FORCE_INLINE +// MY_NO_INLINE +static void RangeDec_Decode(CPpmd7 *p, UInt32 start, UInt32 size) +{ + + + R->Code -= start * R->Range; + R->Range *= size; + RC_NORM_LOCAL(R) +} + +#define RC_Decode(start, size) RangeDec_Decode(p, start, size); +#define RC_DecodeFinal(start, size) RC_Decode(start, size) RC_NORM_REMOTE(R) +#define RC_GetThreshold(total) (R->Code / (R->Range /= (total))) + + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +typedef CPpmd7_Context * CTX_PTR; +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) +void Ppmd7_UpdateModel(CPpmd7 *p); + +#define MASK(sym) ((unsigned char *)charMask)[sym] +// MY_FORCE_INLINE +// static +int Ppmd7z_DecodeSymbol(CPpmd7 *p) +{ + size_t charMask[256 / sizeof(size_t)]; + + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + UInt32 summFreq = p->MinContext->Union2.SummFreq; + + + + + count = RC_GetThreshold(summFreq); + hiCnt = count; + + if ((Int32)(count -= s->Freq) < 0) + { + Byte sym; + RC_DecodeFinal(0, s->Freq); + p->FoundState = s; + sym = s->Symbol; + Ppmd7_Update1_0(p); + return sym; + } + + p->PrevSuccess = 0; + i = (unsigned)p->MinContext->NumStats - 1; + + do + { + if ((Int32)(count -= (++s)->Freq) < 0) + { + Byte sym; + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); + p->FoundState = s; + sym = s->Symbol; + Ppmd7_Update1(p); + return sym; + } + } + while (--i); + + if (hiCnt >= summFreq) + return PPMD7_SYM_ERROR; + + hiCnt -= count; + RC_Decode(hiCnt, summFreq - hiCnt); + + p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); + PPMD_SetAllBitsIn256Bytes(charMask); + // i = p->MinContext->NumStats - 1; + // do { MASK((--s)->Symbol) = 0; } while (--i); + { + CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + MASK(s->Symbol) = 0; + do + { + unsigned sym0 = s2[0].Symbol; + unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } + } + else + { + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + UInt16 *prob = Ppmd7_GetBinSumm(p); + UInt32 pr = *prob; + UInt32 size0 = (R->Range >> 14) * pr; + pr = PPMD_UPDATE_PROB_1(pr); + + if (R->Code < size0) + { + Byte sym; + *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); + + // RangeDec_DecodeBit0(size0); + R->Range = size0; + RC_NORM_1(R) + /* we can use single byte normalization here because of + (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */ + + // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + // Ppmd7_UpdateBin(p); + { + unsigned freq = s->Freq; + CTX_PTR c = CTX(SUCCESSOR(s)); + sym = s->Symbol; + p->FoundState = s; + p->PrevSuccess = 1; + p->RunLength++; + s->Freq = (Byte)(freq + (freq < 128)); + // NextContext(p); + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; + else + Ppmd7_UpdateModel(p); + } + return sym; + } + + *prob = (UInt16)pr; + p->InitEsc = p->ExpEscape[pr >> 10]; + + // RangeDec_DecodeBit1(size0); + + R->Code -= size0; + R->Range -= size0; + RC_NORM_LOCAL(R) + + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; + p->PrevSuccess = 0; + } + + for (;;) + { + CPpmd_State *s, *s2; + UInt32 freqSum, count, hiCnt; + + CPpmd_See *see; + CPpmd7_Context *mc; + unsigned numMasked; + RC_NORM_REMOTE(R) + mc = p->MinContext; + numMasked = mc->NumStats; + + do + { + p->OrderFall++; + if (!mc->Suffix) + return PPMD7_SYM_END; + mc = Ppmd7_GetContext(p, mc->Suffix); + } + while (mc->NumStats == numMasked); + + s = Ppmd7_GetStats(p, mc); + + { + unsigned num = mc->NumStats; + unsigned num2 = num / 2; + + num &= 1; + hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); + s += num; + p->MinContext = mc; + + do + { + unsigned sym0 = s[0].Symbol; + unsigned sym1 = s[1].Symbol; + s += 2; + hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); + hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); + } + while (--num2); + } + + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + + + + + count = RC_GetThreshold(freqSum); + + if (count < hiCnt) + { + Byte sym; + + s = Ppmd7_GetStats(p, p->MinContext); + hiCnt = count; + // count -= s->Freq & (unsigned)(MASK(s->Symbol)); + // if ((Int32)count >= 0) + { + for (;;) + { + count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; + // count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; + }; + } + s--; + RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq); + + // new (see->Summ) value can overflow over 16-bits in some rare cases + Ppmd_See_Update(see); + p->FoundState = s; + sym = s->Symbol; + Ppmd7_Update2(p); + return sym; + } + + if (count >= freqSum) + return PPMD7_SYM_ERROR; + + RC_Decode(hiCnt, freqSum - hiCnt); + + // We increase (see->Summ) for sum of Freqs of all non_Masked symbols. + // new (see->Summ) value can overflow over 16-bits in some rare cases + see->Summ = (UInt16)(see->Summ + freqSum); + + s = Ppmd7_GetStats(p, p->MinContext); + s2 = s + p->MinContext->NumStats; + do + { + MASK(s->Symbol) = 0; + s++; + } + while (s != s2); + } +} + +/* +Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim) +{ + int sym = 0; + if (buf != lim) + do + { + sym = Ppmd7z_DecodeSymbol(p); + if (sym < 0) + break; + *buf = (Byte)sym; + } + while (++buf < lim); + p->LastSymbol = sym; + return buf; +} +*/ diff --git a/3rdparty/lzma-21.03beta/C/Ppmd7Enc.c b/3rdparty/lzma-21.03beta/C/Ppmd7Enc.c new file mode 100644 index 0000000..62139c5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Ppmd7Enc.c @@ -0,0 +1,323 @@ +/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder +2021-04-13 : Igor Pavlov : Public domain +This code is based on: + PPMd var.H (2001): Dmitry Shkarin : Public domain */ + + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +#define R (&p->rc.enc) + +void Ppmd7z_Init_RangeEnc(CPpmd7 *p) +{ + R->Low = 0; + R->Range = 0xFFFFFFFF; + R->Cache = 0; + R->CacheSize = 1; +} + +MY_NO_INLINE +static void RangeEnc_ShiftLow(CPpmd7 *p) +{ + if ((UInt32)R->Low < (UInt32)0xFF000000 || (unsigned)(R->Low >> 32) != 0) + { + Byte temp = R->Cache; + do + { + IByteOut_Write(R->Stream, (Byte)(temp + (Byte)(R->Low >> 32))); + temp = 0xFF; + } + while (--R->CacheSize != 0); + R->Cache = (Byte)((UInt32)R->Low >> 24); + } + R->CacheSize++; + R->Low = (UInt32)((UInt32)R->Low << 8); +} + +#define RC_NORM_BASE(p) if (R->Range < kTopValue) { R->Range <<= 8; RangeEnc_ShiftLow(p); +#define RC_NORM_1(p) RC_NORM_BASE(p) } +#define RC_NORM(p) RC_NORM_BASE(p) RC_NORM_BASE(p) }} + +// we must use only one type of Normalization from two: LOCAL or REMOTE +#define RC_NORM_LOCAL(p) // RC_NORM(p) +#define RC_NORM_REMOTE(p) RC_NORM(p) + +/* +#define RangeEnc_Encode(p, start, _size_) \ + { UInt32 size = _size_; \ + R->Low += start * R->Range; \ + R->Range *= size; \ + RC_NORM_LOCAL(p); } +*/ + +MY_FORCE_INLINE +// MY_NO_INLINE +static void RangeEnc_Encode(CPpmd7 *p, UInt32 start, UInt32 size) +{ + R->Low += start * R->Range; + R->Range *= size; + RC_NORM_LOCAL(p); +} + +void Ppmd7z_Flush_RangeEnc(CPpmd7 *p) +{ + unsigned i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + + + +#define RC_Encode(start, size) RangeEnc_Encode(p, start, size); +#define RC_EncodeFinal(start, size) RC_Encode(start, size); RC_NORM_REMOTE(p); + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define SUFFIX(ctx) CTX((ctx)->Suffix) +typedef CPpmd7_Context * CTX_PTR; +#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) + +void Ppmd7_UpdateModel(CPpmd7 *p); + +#define MASK(sym) ((unsigned char *)charMask)[sym] + +MY_FORCE_INLINE +static +void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + + + + + R->Range /= p->MinContext->Union2.SummFreq; + + if (s->Symbol == symbol) + { + // R->Range /= p->MinContext->Union2.SummFreq; + RC_EncodeFinal(0, s->Freq); + p->FoundState = s; + Ppmd7_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = (unsigned)p->MinContext->NumStats - 1; + do + { + if ((++s)->Symbol == symbol) + { + // R->Range /= p->MinContext->Union2.SummFreq; + RC_EncodeFinal(sum, s->Freq); + p->FoundState = s; + Ppmd7_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + // R->Range /= p->MinContext->Union2.SummFreq; + RC_Encode(sum, p->MinContext->Union2.SummFreq - sum); + + p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol); + PPMD_SetAllBitsIn256Bytes(charMask); + // MASK(s->Symbol) = 0; + // i = p->MinContext->NumStats - 1; + // do { MASK((--s)->Symbol) = 0; } while (--i); + { + CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + MASK(s->Symbol) = 0; + do + { + unsigned sym0 = s2[0].Symbol; + unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + UInt32 pr = *prob; + UInt32 bound = (R->Range >> 14) * pr; + pr = PPMD_UPDATE_PROB_1(pr); + if (s->Symbol == symbol) + { + *prob = (UInt16)(pr + (1 << PPMD_INT_BITS)); + // RangeEnc_EncodeBit_0(p, bound); + R->Range = bound; + RC_NORM_1(p); + + // p->FoundState = s; + // Ppmd7_UpdateBin(p); + { + unsigned freq = s->Freq; + CTX_PTR c = CTX(SUCCESSOR(s)); + p->FoundState = s; + p->PrevSuccess = 1; + p->RunLength++; + s->Freq = (Byte)(freq + (freq < 128)); + // NextContext(p); + if (p->OrderFall == 0 && (const Byte *)c > p->Text) + p->MaxContext = p->MinContext = c; + else + Ppmd7_UpdateModel(p); + } + return; + } + + *prob = (UInt16)pr; + p->InitEsc = p->ExpEscape[pr >> 10]; + // RangeEnc_EncodeBit_1(p, bound); + R->Low += bound; + R->Range -= bound; + RC_NORM_LOCAL(p) + + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + p->PrevSuccess = 0; + } + + for (;;) + { + CPpmd_See *see; + CPpmd_State *s; + UInt32 sum, escFreq; + CPpmd7_Context *mc; + unsigned i, numMasked; + + RC_NORM_REMOTE(p) + + mc = p->MinContext; + numMasked = mc->NumStats; + + do + { + p->OrderFall++; + if (!mc->Suffix) + return; /* EndMarker (symbol = -1) */ + mc = Ppmd7_GetContext(p, mc->Suffix); + i = mc->NumStats; + } + while (i == numMasked); + + p->MinContext = mc; + + // see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); + { + if (i != 256) + { + unsigned nonMasked = i - numMasked; + see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]] + + p->HiBitsFlag + + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - i) + + 2 * (unsigned)(mc->Union2.SummFreq < 11 * i) + + 4 * (unsigned)(numMasked > nonMasked); + { + // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ + unsigned summ = (UInt16)see->Summ; // & 0xFFFF + unsigned r = (summ >> see->Shift); + see->Summ = (UInt16)(summ - r); + escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + escFreq = 1; + } + } + + s = Ppmd7_GetStats(p, mc); + sum = 0; + // i = mc->NumStats; + + do + { + unsigned cur = s->Symbol; + if ((int)cur == symbol) + { + UInt32 low = sum; + UInt32 freq = s->Freq; + unsigned num2; + + Ppmd_See_Update(see); + p->FoundState = s; + sum += escFreq; + + num2 = i / 2; + i &= 1; + sum += freq & (0 - (UInt32)i); + if (num2 != 0) + { + s += i; + for (;;) + { + unsigned sym0 = s[0].Symbol; + unsigned sym1 = s[1].Symbol; + s += 2; + sum += (s[-2].Freq & (unsigned)(MASK(sym0))); + sum += (s[-1].Freq & (unsigned)(MASK(sym1))); + if (--num2 == 0) + break; + } + } + + + R->Range /= sum; + RC_EncodeFinal(low, freq); + Ppmd7_Update2(p); + return; + } + sum += (s->Freq & (unsigned)(MASK(cur))); + s++; + } + while (--i); + + { + UInt32 total = sum + escFreq; + see->Summ = (UInt16)(see->Summ + total); + + R->Range /= total; + RC_Encode(sum, escFreq); + } + + { + CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext); + s--; + MASK(s->Symbol) = 0; + do + { + unsigned sym0 = s2[0].Symbol; + unsigned sym1 = s2[1].Symbol; + s2 += 2; + MASK(sym0) = 0; + MASK(sym1) = 0; + } + while (s2 < s); + } + } +} + + +void Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim) +{ + for (; buf < lim; buf++) + { + Ppmd7z_EncodeSymbol(p, *buf); + } +} diff --git a/3rdparty/lzma-21.03beta/C/Precomp.h b/3rdparty/lzma-21.03beta/C/Precomp.h new file mode 100644 index 0000000..e8ff8b4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/3rdparty/lzma-21.03beta/C/RotateDefs.h b/3rdparty/lzma-21.03beta/C/RotateDefs.h new file mode 100644 index 0000000..8f01d1a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/RotateDefs.h @@ -0,0 +1,30 @@ +/* RotateDefs.h -- Rotate functions +2015-03-25 : Igor Pavlov : Public domain */ + +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include + +/* don't use _rotl with MINGW. It can insert slow call to function. */ + +/* #if (_MSC_VER >= 1200) */ +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +/* #endif */ + +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#else + +/* new compilers can translate these macros to fast commands. */ + +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Sha256.c b/3rdparty/lzma-21.03beta/C/Sha256.c new file mode 100644 index 0000000..8b3983e --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Sha256.c @@ -0,0 +1,486 @@ +/* Sha256.c -- SHA-256 Hash +2021-04-01 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "Precomp.h" + +#include + +#include "CpuArch.h" +#include "RotateDefs.h" +#include "Sha256.h" + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +// #define USE_MY_MM +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + #ifdef _MSC_VER + #if _MSC_VER >= 1200 + #define _SHA_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1800) // fix that check + #define _SHA_SUPPORTED + #endif + #endif +#elif defined(MY_CPU_ARM_OR_ARM64) + #ifdef _MSC_VER + #if _MSC_VER >= 1910 + #define _SHA_SUPPORTED + #endif + #elif defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define _SHA_SUPPORTED + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define _SHA_SUPPORTED + #endif + #endif +#endif + +void MY_FAST_CALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +#ifdef _SHA_SUPPORTED + void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); + + static SHA256_FUNC_UPDATE_BLOCKS g_FUNC_UPDATE_BLOCKS = Sha256_UpdateBlocks; + static SHA256_FUNC_UPDATE_BLOCKS g_FUNC_UPDATE_BLOCKS_HW; + + #define UPDATE_BLOCKS(p) p->func_UpdateBlocks +#else + #define UPDATE_BLOCKS(p) Sha256_UpdateBlocks +#endif + + +BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo) +{ + SHA256_FUNC_UPDATE_BLOCKS func = Sha256_UpdateBlocks; + + #ifdef _SHA_SUPPORTED + if (algo != SHA256_ALGO_SW) + { + if (algo == SHA256_ALGO_DEFAULT) + func = g_FUNC_UPDATE_BLOCKS; + else + { + if (algo != SHA256_ALGO_HW) + return False; + func = g_FUNC_UPDATE_BLOCKS_HW; + if (!func) + return False; + } + } + #else + if (algo > 1) + return False; + #endif + + p->func_UpdateBlocks = func; + return True; +} + + +/* define it for speed optimization */ + +#ifdef _SFX + #define STEP_PRE 1 + #define STEP_MAIN 1 +#else + #define STEP_PRE 2 + #define STEP_MAIN 4 + // #define _SHA256_UNROLL +#endif + +#if STEP_MAIN != 16 + #define _SHA256_BIG_W +#endif + + + + +void Sha256_InitState(CSha256 *p) +{ + p->count = 0; + p->state[0] = 0x6a09e667; + p->state[1] = 0xbb67ae85; + p->state[2] = 0x3c6ef372; + p->state[3] = 0xa54ff53a; + p->state[4] = 0x510e527f; + p->state[5] = 0x9b05688c; + p->state[6] = 0x1f83d9ab; + p->state[7] = 0x5be0cd19; +} + +void Sha256_Init(CSha256 *p) +{ + p->func_UpdateBlocks = + #ifdef _SHA_SUPPORTED + g_FUNC_UPDATE_BLOCKS; + #else + NULL; + #endif + Sha256_InitState(p); +} + +#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) +#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) +#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) +#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + + +#define W_PRE(i) (W[(i) + (size_t)(j)] = GetBe32(data + ((size_t)(j) + i) * 4)) + +#define blk2_main(j, i) s1(w(j, (i)-2)) + w(j, (i)-7) + s0(w(j, (i)-15)) + +#ifdef _SHA256_BIG_W + // we use +i instead of +(i) to change the order to solve CLANG compiler warning for signed/unsigned. + #define w(j, i) W[(size_t)(j) + i] + #define blk2(j, i) (w(j, i) = w(j, (i)-16) + blk2_main(j, i)) +#else + #if STEP_MAIN == 16 + #define w(j, i) W[(i) & 15] + #else + #define w(j, i) W[((size_t)(j) + (i)) & 15] + #endif + #define blk2(j, i) (w(j, i) += blk2_main(j, i)) +#endif + +#define W_MAIN(i) blk2(j, i) + + +#define T1(wx, i) \ + tmp = h + S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + h = g; \ + g = f; \ + f = e; \ + e = d + tmp; \ + tmp += S0(a) + Maj(a, b, c); \ + d = c; \ + c = b; \ + b = a; \ + a = tmp; \ + +#define R1_PRE(i) T1( W_PRE, i) +#define R1_MAIN(i) T1( W_MAIN, i) + +#if (!defined(_SHA256_UNROLL) || STEP_MAIN < 8) && (STEP_MAIN >= 4) +#define R2_MAIN(i) \ + R1_MAIN(i) \ + R1_MAIN(i + 1) \ + +#endif + + + +#if defined(_SHA256_UNROLL) && STEP_MAIN >= 8 + +#define T4( a,b,c,d,e,f,g,h, wx, i) \ + h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + tmp = h; \ + h += d; \ + d = tmp + S0(a) + Maj(a, b, c); \ + +#define R4( wx, i) \ + T4 ( a,b,c,d,e,f,g,h, wx, (i )); \ + T4 ( d,a,b,c,h,e,f,g, wx, (i+1)); \ + T4 ( c,d,a,b,g,h,e,f, wx, (i+2)); \ + T4 ( b,c,d,a,f,g,h,e, wx, (i+3)); \ + +#define R4_PRE(i) R4( W_PRE, i) +#define R4_MAIN(i) R4( W_MAIN, i) + + +#define T8( a,b,c,d,e,f,g,h, wx, i) \ + h += S1(e) + Ch(e,f,g) + K[(i)+(size_t)(j)] + wx(i); \ + d += h; \ + h += S0(a) + Maj(a, b, c); \ + +#define R8( wx, i) \ + T8 ( a,b,c,d,e,f,g,h, wx, i ); \ + T8 ( h,a,b,c,d,e,f,g, wx, i+1); \ + T8 ( g,h,a,b,c,d,e,f, wx, i+2); \ + T8 ( f,g,h,a,b,c,d,e, wx, i+3); \ + T8 ( e,f,g,h,a,b,c,d, wx, i+4); \ + T8 ( d,e,f,g,h,a,b,c, wx, i+5); \ + T8 ( c,d,e,f,g,h,a,b, wx, i+6); \ + T8 ( b,c,d,e,f,g,h,a, wx, i+7); \ + +#define R8_PRE(i) R8( W_PRE, i) +#define R8_MAIN(i) R8( W_MAIN, i) + +#endif + +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); + +// static +extern MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define K SHA256_K_ARRAY + + +MY_NO_INLINE +void MY_FAST_CALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + UInt32 W + #ifdef _SHA256_BIG_W + [64]; + #else + [16]; + #endif + + unsigned j; + + UInt32 a,b,c,d,e,f,g,h; + + #if !defined(_SHA256_UNROLL) || (STEP_MAIN <= 4) || (STEP_PRE <= 4) + UInt32 tmp; + #endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + while (numBlocks) + { + + for (j = 0; j < 16; j += STEP_PRE) + { + #if STEP_PRE > 4 + + #if STEP_PRE < 8 + R4_PRE(0); + #else + R8_PRE(0); + #if STEP_PRE == 16 + R8_PRE(8); + #endif + #endif + + #else + + R1_PRE(0); + #if STEP_PRE >= 2 + R1_PRE(1); + #if STEP_PRE >= 4 + R1_PRE(2); + R1_PRE(3); + #endif + #endif + + #endif + } + + for (j = 16; j < 64; j += STEP_MAIN) + { + #if defined(_SHA256_UNROLL) && STEP_MAIN >= 8 + + #if STEP_MAIN < 8 + R4_MAIN(0); + #else + R8_MAIN(0); + #if STEP_MAIN == 16 + R8_MAIN(8); + #endif + #endif + + #else + + R1_MAIN(0); + #if STEP_MAIN >= 2 + R1_MAIN(1); + #if STEP_MAIN >= 4 + R2_MAIN(2); + #if STEP_MAIN >= 8 + R2_MAIN(4); + R2_MAIN(6); + #if STEP_MAIN >= 16 + R2_MAIN(8); + R2_MAIN(10); + R2_MAIN(12); + R2_MAIN(14); + #endif + #endif + #endif + #endif + #endif + } + + a += state[0]; state[0] = a; + b += state[1]; state[1] = b; + c += state[2]; state[2] = c; + d += state[3]; state[3] = d; + e += state[4]; state[4] = e; + f += state[5]; state[5] = f; + g += state[6]; state[6] = g; + h += state[7]; state[7] = h; + + data += 64; + numBlocks--; + } + + /* Wipe variables */ + /* memset(W, 0, sizeof(W)); */ +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 +#undef K + +#define Sha256_UpdateBlock(p) UPDATE_BLOCKS(p)(p->state, p->buffer, 1) + +void Sha256_Update(CSha256 *p, const Byte *data, size_t size) +{ + if (size == 0) + return; + + { + unsigned pos = (unsigned)p->count & 0x3F; + unsigned num; + + p->count += size; + + num = 64 - pos; + if (num > size) + { + memcpy(p->buffer + pos, data, size); + return; + } + + if (pos != 0) + { + size -= num; + memcpy(p->buffer + pos, data, num); + data += num; + Sha256_UpdateBlock(p); + } + } + { + size_t numBlocks = size >> 6; + UPDATE_BLOCKS(p)(p->state, data, numBlocks); + size &= 0x3F; + if (size == 0) + return; + data += (numBlocks << 6); + memcpy(p->buffer, data, size); + } +} + + +void Sha256_Final(CSha256 *p, Byte *digest) +{ + unsigned pos = (unsigned)p->count & 0x3F; + unsigned i; + + p->buffer[pos++] = 0x80; + + if (pos > (64 - 8)) + { + while (pos != 64) { p->buffer[pos++] = 0; } + // memset(&p->buf.buffer[pos], 0, 64 - pos); + Sha256_UpdateBlock(p); + pos = 0; + } + + /* + if (pos & 3) + { + p->buffer[pos] = 0; + p->buffer[pos + 1] = 0; + p->buffer[pos + 2] = 0; + pos += 3; + pos &= ~3; + } + { + for (; pos < 64 - 8; pos += 4) + *(UInt32 *)(&p->buffer[pos]) = 0; + } + */ + + memset(&p->buffer[pos], 0, (64 - 8) - pos); + + { + UInt64 numBits = (p->count << 3); + SetBe32(p->buffer + 64 - 8, (UInt32)(numBits >> 32)); + SetBe32(p->buffer + 64 - 4, (UInt32)(numBits)); + } + + Sha256_UpdateBlock(p); + + for (i = 0; i < 8; i += 2) + { + UInt32 v0 = p->state[i]; + UInt32 v1 = p->state[(size_t)i + 1]; + SetBe32(digest , v0); + SetBe32(digest + 4, v1); + digest += 8; + } + + Sha256_InitState(p); +} + + +void Sha256Prepare() +{ + #ifdef _SHA_SUPPORTED + SHA256_FUNC_UPDATE_BLOCKS f, f_hw; + f = Sha256_UpdateBlocks; + f_hw = NULL; + #ifdef MY_CPU_X86_OR_AMD64 + #ifndef USE_MY_MM + if (CPU_IsSupported_SHA() + && CPU_IsSupported_SSSE3() + // && CPU_IsSupported_SSE41() + ) + #endif + #else + if (CPU_IsSupported_SHA2()) + #endif + { + // printf("\n========== HW SHA256 ======== \n"); + f = f_hw = Sha256_UpdateBlocks_HW; + } + g_FUNC_UPDATE_BLOCKS = f; + g_FUNC_UPDATE_BLOCKS_HW = f_hw; + #endif +} diff --git a/3rdparty/lzma-21.03beta/C/Sha256.h b/3rdparty/lzma-21.03beta/C/Sha256.h new file mode 100644 index 0000000..aa38501 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Sha256.h @@ -0,0 +1,76 @@ +/* Sha256.h -- SHA-256 Hash +2021-01-01 : Igor Pavlov : Public domain */ + +#ifndef __7Z_SHA256_H +#define __7Z_SHA256_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define SHA256_NUM_BLOCK_WORDS 16 +#define SHA256_NUM_DIGEST_WORDS 8 + +#define SHA256_BLOCK_SIZE (SHA256_NUM_BLOCK_WORDS * 4) +#define SHA256_DIGEST_SIZE (SHA256_NUM_DIGEST_WORDS * 4) + +typedef void (MY_FAST_CALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks); + +/* + if (the system supports different SHA256 code implementations) + { + (CSha256::func_UpdateBlocks) will be used + (CSha256::func_UpdateBlocks) can be set by + Sha256_Init() - to default (fastest) + Sha256_SetFunction() - to any algo + } + else + { + (CSha256::func_UpdateBlocks) is ignored. + } +*/ + +typedef struct +{ + SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks; + UInt64 count; + UInt64 __pad_2[2]; + UInt32 state[SHA256_NUM_DIGEST_WORDS]; + + Byte buffer[SHA256_BLOCK_SIZE]; +} CSha256; + + +#define SHA256_ALGO_DEFAULT 0 +#define SHA256_ALGO_SW 1 +#define SHA256_ALGO_HW 2 + +/* +Sha256_SetFunction() +return: + 0 - (algo) value is not supported, and func_UpdateBlocks was not changed + 1 - func_UpdateBlocks was set according (algo) value. +*/ + +BoolInt Sha256_SetFunction(CSha256 *p, unsigned algo); + +void Sha256_InitState(CSha256 *p); +void Sha256_Init(CSha256 *p); +void Sha256_Update(CSha256 *p, const Byte *data, size_t size); +void Sha256_Final(CSha256 *p, Byte *digest); + + + + +// void MY_FAST_CALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +/* +call Sha256Prepare() once at program start. +It prepares all supported implementations, and detects the fastest implementation. +*/ + +void Sha256Prepare(void); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Sha256Opt.c b/3rdparty/lzma-21.03beta/C/Sha256Opt.c new file mode 100644 index 0000000..decc138 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Sha256Opt.c @@ -0,0 +1,373 @@ +/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#if defined(_MSC_VER) +#if (_MSC_VER < 1900) && (_MSC_VER >= 1200) +// #define USE_MY_MM +#endif +#endif + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_SHA + #ifndef __SHA__ + #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) + #if defined(_MSC_VER) + // SSSE3: for clang-cl: + #include + #define __SHA__ + #endif + #endif + + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 8) // fix that check + #define USE_HW_SHA + #ifndef __SHA__ + #define ATTRIB_SHA __attribute__((__target__("sha,ssse3"))) + // #pragma GCC target("sha,ssse3") + #endif + #endif + #elif defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1800) // fix that check + #define USE_HW_SHA + #endif + #elif defined(_MSC_VER) + #ifdef USE_MY_MM + #define USE_VER_MIN 1300 + #else + #define USE_VER_MIN 1910 + #endif + #if _MSC_VER >= USE_VER_MIN + #define USE_HW_SHA + #endif + #endif +// #endif // MY_CPU_X86_OR_AMD64 + +#ifdef USE_HW_SHA + +// #pragma message("Sha256 HW") +// #include + +#if !defined(_MSC_VER) || (_MSC_VER >= 1900) +#include +#else +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +// #include +#endif + +#ifdef USE_MY_MM +#include "My_mm.h" +#endif + +#endif + +/* +SHA256 uses: +SSE2: + _mm_loadu_si128 + _mm_storeu_si128 + _mm_set_epi32 + _mm_add_epi32 + _mm_shuffle_epi32 / pshufd + + + +SSSE3: + _mm_shuffle_epi8 / pshufb + _mm_alignr_epi8 +SHA: + _mm_sha256* +*/ + +// K array must be aligned for 16-bytes at least. +// The compiler can look align attribute and selects +// movdqu - for code without align attribute +// movdqa - for code with align attribute +extern +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +#define K SHA256_K_ARRAY + + +#define ADD_EPI32(dest, src) dest = _mm_add_epi32(dest, src); +#define SHA256_MSG1(dest, src) dest = _mm_sha256msg1_epu32(dest, src); +#define SHA25G_MSG2(dest, src) dest = _mm_sha256msg2_epu32(dest, src); + + +#define LOAD_SHUFFLE(m, k) \ + m = _mm_loadu_si128((const __m128i *)(const void *)(data + (k) * 16)); \ + m = _mm_shuffle_epi8(m, mask); \ + +#define SM1(g0, g1, g2, g3) \ + SHA256_MSG1(g3, g0); \ + +#define SM2(g0, g1, g2, g3) \ + tmp = _mm_alignr_epi8(g1, g0, 4); \ + ADD_EPI32(g2, tmp); \ + SHA25G_MSG2(g2, g1); \ + +// #define LS0(k, g0, g1, g2, g3) LOAD_SHUFFLE(g0, k) +// #define LS1(k, g0, g1, g2, g3) LOAD_SHUFFLE(g1, k+1) + + +#define NNN(g0, g1, g2, g3) + + +#define RND2(t0, t1) \ + t0 = _mm_sha256rnds2_epu32(t0, t1, msg); + +#define RND2_0(m, k) \ + msg = _mm_add_epi32(m, *(const __m128i *) (const void *) &K[(k) * 4]); \ + RND2(state0, state1); \ + msg = _mm_shuffle_epi32(msg, 0x0E); \ + + +#define RND2_1 \ + RND2(state1, state0); \ + + +// We use scheme with 3 rounds ahead for SHA256_MSG1 / 2 rounds ahead for SHA256_MSG2 + +#define R4(k, g0, g1, g2, g3, OP0, OP1) \ + RND2_0(g0, k); \ + OP0(g0, g1, g2, g3); \ + RND2_1; \ + OP1(g0, g1, g2, g3); \ + +#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ + R4 ( (k)*4+0, m0, m1, m2, m3, OP0, OP1 ) \ + R4 ( (k)*4+1, m1, m2, m3, m0, OP2, OP3 ) \ + R4 ( (k)*4+2, m2, m3, m0, m1, OP4, OP5 ) \ + R4 ( (k)*4+3, m3, m0, m1, m2, OP6, OP7 ) \ + +#define PREPARE_STATE \ + tmp = _mm_shuffle_epi32(state0, 0x1B); /* abcd */ \ + state0 = _mm_shuffle_epi32(state1, 0x1B); /* efgh */ \ + state1 = state0; \ + state0 = _mm_unpacklo_epi64(state0, tmp); /* cdgh */ \ + state1 = _mm_unpackhi_epi64(state1, tmp); /* abef */ \ + + +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +#ifdef ATTRIB_SHA +ATTRIB_SHA +#endif +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + const __m128i mask = _mm_set_epi32(0x0c0d0e0f, 0x08090a0b, 0x04050607, 0x00010203); + __m128i tmp; + __m128i state0, state1; + + if (numBlocks == 0) + return; + + state0 = _mm_loadu_si128((const __m128i *) (const void *) &state[0]); + state1 = _mm_loadu_si128((const __m128i *) (const void *) &state[4]); + + PREPARE_STATE + + do + { + __m128i state0_save, state1_save; + __m128i m0, m1, m2, m3; + __m128i msg; + // #define msg tmp + + state0_save = state0; + state1_save = state1; + + LOAD_SHUFFLE (m0, 0) + LOAD_SHUFFLE (m1, 1) + LOAD_SHUFFLE (m2, 2) + LOAD_SHUFFLE (m3, 3) + + + + R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ); + R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ); + + ADD_EPI32(state0, state0_save); + ADD_EPI32(state1, state1_save); + + data += 64; + } + while (--numBlocks); + + PREPARE_STATE + + _mm_storeu_si128((__m128i *) (void *) &state[0], state0); + _mm_storeu_si128((__m128i *) (void *) &state[4], state1); +} + +#endif // USE_HW_SHA + +#elif defined(MY_CPU_ARM_OR_ARM64) + + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_SHA + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_SHA + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_SHA + #endif + #endif + +#ifdef USE_HW_SHA + +// #pragma message("=== Sha256 HW === ") + +#if defined(__clang__) || defined(__GNUC__) + #ifdef MY_CPU_ARM64 + #define ATTRIB_SHA __attribute__((__target__("+crypto"))) + #else + #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) + #endif +#else + // _MSC_VER + // for arm32 + #define _ARM_USE_NEW_NEON_INTRINSICS +#endif + +#if defined(_MSC_VER) && defined(MY_CPU_ARM64) +#include +#else +#include +#endif + +typedef uint32x4_t v128; +// typedef __n128 v128; // MSVC + +#ifdef MY_CPU_BE + #define MY_rev32_for_LE(x) +#else + #define MY_rev32_for_LE(x) x = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(x))) +#endif + +#define LOAD_128(_p) (*(const v128 *)(const void *)(_p)) +#define STORE_128(_p, _v) *(v128 *)(void *)(_p) = (_v) + +#define LOAD_SHUFFLE(m, k) \ + m = LOAD_128((data + (k) * 16)); \ + MY_rev32_for_LE(m); \ + +// K array must be aligned for 16-bytes at least. +extern +MY_ALIGN(64) +const UInt32 SHA256_K_ARRAY[64]; + +#define K SHA256_K_ARRAY + + +#define SHA256_SU0(dest, src) dest = vsha256su0q_u32(dest, src); +#define SHA25G_SU1(dest, src2, src3) dest = vsha256su1q_u32(dest, src2, src3); + +#define SM1(g0, g1, g2, g3) SHA256_SU0(g3, g0) +#define SM2(g0, g1, g2, g3) SHA25G_SU1(g2, g0, g1) +#define NNN(g0, g1, g2, g3) + + +#define R4(k, g0, g1, g2, g3, OP0, OP1) \ + msg = vaddq_u32(g0, *(const v128 *) (const void *) &K[(k) * 4]); \ + tmp = state0; \ + state0 = vsha256hq_u32( state0, state1, msg ); \ + state1 = vsha256h2q_u32( state1, tmp, msg ); \ + OP0(g0, g1, g2, g3); \ + OP1(g0, g1, g2, g3); \ + + +#define R16(k, OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7) \ + R4 ( (k)*4+0, m0, m1, m2, m3, OP0, OP1 ) \ + R4 ( (k)*4+1, m1, m2, m3, m0, OP2, OP3 ) \ + R4 ( (k)*4+2, m2, m3, m0, m1, OP4, OP5 ) \ + R4 ( (k)*4+3, m3, m0, m1, m2, OP6, OP7 ) \ + + +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +#ifdef ATTRIB_SHA +ATTRIB_SHA +#endif +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + v128 state0, state1; + + if (numBlocks == 0) + return; + + state0 = LOAD_128(&state[0]); + state1 = LOAD_128(&state[4]); + + do + { + v128 state0_save, state1_save; + v128 m0, m1, m2, m3; + v128 msg, tmp; + + state0_save = state0; + state1_save = state1; + + LOAD_SHUFFLE (m0, 0) + LOAD_SHUFFLE (m1, 1) + LOAD_SHUFFLE (m2, 2) + LOAD_SHUFFLE (m3, 3) + + R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ); + R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); + R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ); + + state0 = vaddq_u32(state0, state0_save); + state1 = vaddq_u32(state1, state1_save); + + data += 64; + } + while (--numBlocks); + + STORE_128(&state[0], state0); + STORE_128(&state[4], state1); +} + +#endif // USE_HW_SHA + +#endif // MY_CPU_ARM_OR_ARM64 + + +#ifndef USE_HW_SHA + +// #error Stop_Compiling_UNSUPPORTED_SHA +// #include + +// #include "Sha256.h" +void MY_FAST_CALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); + +#pragma message("Sha256 HW-SW stub was used") + +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); +void MY_FAST_CALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) +{ + Sha256_UpdateBlocks(state, data, numBlocks); + /* + UNUSED_VAR(state); + UNUSED_VAR(data); + UNUSED_VAR(numBlocks); + exit(1); + return; + */ +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Sort.c b/3rdparty/lzma-21.03beta/C/Sort.c new file mode 100644 index 0000000..e1097e3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Sort.c @@ -0,0 +1,141 @@ +/* Sort.c -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Sort.h" + +#define HeapSortDown(p, k, size, temp) \ + { for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && p[s + 1] > p[s]) s++; \ + if (temp >= p[s]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSort(UInt32 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt32 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt32 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +void HeapSort64(UInt64 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt64 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt64 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt64 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt64 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +/* +#define HeapSortRefDown(p, vals, n, size, temp) \ + { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ + if (val >= vals[p[s]]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + HeapSortRefDown(p, vals, i, size, temp); + } + while (--i != 0); + } + do + { + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortRefDown(p, vals, 1, size, temp); + } + while (size > 1); +} +*/ diff --git a/3rdparty/lzma-21.03beta/C/Sort.h b/3rdparty/lzma-21.03beta/C/Sort.h new file mode 100644 index 0000000..2e2963a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Sort.h @@ -0,0 +1,18 @@ +/* Sort.h -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#ifndef __7Z_SORT_H +#define __7Z_SORT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void HeapSort(UInt32 *p, size_t size); +void HeapSort64(UInt64 *p, size_t size); + +/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Threads.c b/3rdparty/lzma-21.03beta/C/Threads.c new file mode 100644 index 0000000..7b4f5b5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Threads.c @@ -0,0 +1,540 @@ +/* Threads.c -- multithreading library +2021-07-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 + +#ifndef UNDER_CE +#include +#endif + +#include "Threads.h" + +static WRes GetError() +{ + DWORD res = GetLastError(); + return res ? (WRes)res : 1; +} + +static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); } +static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } + +WRes HandlePtr_Close(HANDLE *p) +{ + if (*p != NULL) + { + if (!CloseHandle(*p)) + return GetError(); + *p = NULL; + } + return 0; +} + +WRes Handle_WaitObject(HANDLE h) +{ + DWORD dw = WaitForSingleObject(h, INFINITE); + /* + (dw) result: + WAIT_OBJECT_0 // 0 + WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space + WAIT_TIMEOUT // 0x00000102 : is compatible with Win32 Error space + WAIT_FAILED // 0xFFFFFFFF + */ + if (dw == WAIT_FAILED) + { + dw = GetLastError(); + if (dw == 0) + return WAIT_FAILED; + } + return (WRes)dw; +} + +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +WRes Thread_Wait_Close(CThread *p) +{ + WRes res = Thread_Wait(p); + WRes res2 = Thread_Close(p); + return (res != 0 ? res : res2); +} + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(*p); +} + + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + #ifdef UNDER_CE + + UNUSED_VAR(affinity) + return Thread_Create(p, func, param); + + #else + + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + HANDLE h; + WRes wres; + unsigned threadId; + h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); + *p = h; + wres = HandleToWRes(h); + if (h) + { + { + // DWORD_PTR prevMask = + SetThreadAffinityMask(h, (DWORD_PTR)affinity); + /* + if (prevMask == 0) + { + // affinity change is non-critical error, so we can ignore it + // wres = GetError(); + } + */ + } + { + DWORD prevSuspendCount = ResumeThread(h); + /* ResumeThread() returns: + 0 : was_not_suspended + 1 : was_resumed + -1 : error + */ + if (prevSuspendCount == (DWORD)-1) + wres = GetError(); + } + } + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return wres; + + #endif +} + + +static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) +{ + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); +} + +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore() + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); +} + +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + // if (Semaphore_IsCreated(p)) + { + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + } + return Semaphore_Create(p, initCount, maxCount); +} + +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } + +WRes CriticalSection_Init(CCriticalSection *p) +{ + /* InitializeCriticalSection() can raise exception: + Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception + Windows Vista+ : no exceptions */ + #ifdef _MSC_VER + __try + #endif + { + InitializeCriticalSection(p); + /* InitializeCriticalSectionAndSpinCount(p, 0); */ + } + #ifdef _MSC_VER + __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } + #endif + return 0; +} + + + + +#else // _WIN32 + +// ---------- POSIX ---------- + +#ifndef __APPLE__ +#ifndef _7ZIP_AFFINITY_DISABLE +// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET +#define _GNU_SOURCE +#endif +#endif + +#include "Threads.h" + +#include +#include +#include +#ifdef _7ZIP_AFFINITY_SUPPORTED +// #include +#endif + + +// #include +// #define PRF(p) p +#define PRF(p) + +#define Print(s) PRF(printf("\n%s\n", s)) + +// #include + +WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet) +{ + // new thread in Posix probably inherits affinity from parrent thread + Print("Thread_Create_With_CpuSet"); + + pthread_attr_t attr; + int ret; + // int ret2; + + p->_created = 0; + + RINOK(pthread_attr_init(&attr)); + + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + if (!ret) + { + if (cpuSet) + { + #ifdef _7ZIP_AFFINITY_SUPPORTED + + /* + printf("\n affinity :"); + unsigned i; + for (i = 0; i < sizeof(*cpuSet) && i < 8; i++) + { + Byte b = *((const Byte *)cpuSet + i); + char temp[32]; + #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + temp[0] = GET_HEX_CHAR((b & 0xF)); + temp[1] = GET_HEX_CHAR((b >> 4)); + // temp[0] = GET_HEX_CHAR((b >> 4)); // big-endian + // temp[1] = GET_HEX_CHAR((b & 0xF)); // big-endian + temp[2] = 0; + printf("%s", temp); + } + printf("\n"); + */ + + // ret2 = + pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + #endif + } + + ret = pthread_create(&p->_tid, &attr, func, param); + + if (!ret) + { + p->_created = 1; + /* + if (cpuSet) + { + // ret2 = + pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet); + // if (ret2) ret = ret2; + } + */ + } + } + // ret2 = + pthread_attr_destroy(&attr); + // if (ret2 != 0) ret = ret2; + return ret; +} + + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + return Thread_Create_With_CpuSet(p, func, param, NULL); +} + + +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity) +{ + Print("Thread_Create_WithAffinity"); + CCpuSet cs; + unsigned i; + CpuSet_Zero(&cs); + for (i = 0; i < sizeof(affinity) * 8; i++) + { + if (affinity == 0) + break; + if (affinity & 1) + { + CpuSet_Set(&cs, i); + } + affinity >>= 1; + } + return Thread_Create_With_CpuSet(p, func, param, &cs); +} + + +WRes Thread_Close(CThread *p) +{ + // Print("Thread_Close"); + int ret; + if (!p->_created) + return 0; + + ret = pthread_detach(p->_tid); + p->_tid = 0; + p->_created = 0; + return ret; +} + + +WRes Thread_Wait_Close(CThread *p) +{ + // Print("Thread_Wait_Close"); + void *thread_return; + int ret; + if (!p->_created) + return EINVAL; + + ret = pthread_join(p->_tid, &thread_return); + // probably we can't use that (_tid) after pthread_join(), so we close thread here + p->_created = 0; + p->_tid = 0; + return ret; +} + + + +static WRes Event_Create(CEvent *p, int manualReset, int signaled) +{ + RINOK(pthread_mutex_init(&p->_mutex, NULL)); + RINOK(pthread_cond_init(&p->_cond, NULL)); + p->_manual_reset = manualReset; + p->_state = (signaled ? True : False); + p->_created = 1; + return 0; +} + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) + { return Event_Create(p, True, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) + { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) + { return Event_Create(p, False, signaled); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) + { return AutoResetEvent_Create(p, 0); } + + +WRes Event_Set(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + p->_state = True; + int res1 = pthread_cond_broadcast(&p->_cond); + int res2 = pthread_mutex_unlock(&p->_mutex); + return (res2 ? res2 : res1); +} + +WRes Event_Reset(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + p->_state = False; + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Event_Wait(CEvent *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + while (p->_state == False) + { + // ETIMEDOUT + // ret = + pthread_cond_wait(&p->_cond, &p->_mutex); + // if (ret != 0) break; + } + if (p->_manual_reset == False) + { + p->_state = False; + } + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Event_Close(CEvent *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + if (initCount > maxCount || maxCount < 1) + return EINVAL; + RINOK(pthread_mutex_init(&p->_mutex, NULL)); + RINOK(pthread_cond_init(&p->_cond, NULL)); + p->_count = initCount; + p->_maxCount = maxCount; + p->_created = 1; + return 0; +} + + +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + if (Semaphore_IsCreated(p)) + { + /* + WRes wres = Semaphore_Close(p); + if (wres != 0) + return wres; + */ + if (initCount > maxCount || maxCount < 1) + return EINVAL; + // return EINVAL; // for debug + p->_count = initCount; + p->_maxCount = maxCount; + return 0; + } + return Semaphore_Create(p, initCount, maxCount); +} + + +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) +{ + UInt32 newCount; + int ret; + + if (releaseCount < 1) + return EINVAL; + + RINOK(pthread_mutex_lock(&p->_mutex)); + + newCount = p->_count + releaseCount; + if (newCount > p->_maxCount) + ret = ERROR_TOO_MANY_POSTS; // EINVAL; + else + { + p->_count = newCount; + ret = pthread_cond_broadcast(&p->_cond); + } + RINOK(pthread_mutex_unlock(&p->_mutex)); + return ret; +} + +WRes Semaphore_Wait(CSemaphore *p) +{ + RINOK(pthread_mutex_lock(&p->_mutex)); + while (p->_count < 1) + { + pthread_cond_wait(&p->_cond, &p->_mutex); + } + p->_count--; + return pthread_mutex_unlock(&p->_mutex); +} + +WRes Semaphore_Close(CSemaphore *p) +{ + if (!p->_created) + return 0; + p->_created = 0; + { + int res1 = pthread_mutex_destroy(&p->_mutex); + int res2 = pthread_cond_destroy(&p->_cond); + return (res1 ? res1 : res2); + } +} + + + +WRes CriticalSection_Init(CCriticalSection *p) +{ + // Print("CriticalSection_Init"); + if (!p) + return EINTR; + return pthread_mutex_init(&p->_mutex, NULL); +} + +void CriticalSection_Enter(CCriticalSection *p) +{ + // Print("CriticalSection_Enter"); + if (p) + { + // int ret = + pthread_mutex_lock(&p->_mutex); + } +} + +void CriticalSection_Leave(CCriticalSection *p) +{ + // Print("CriticalSection_Leave"); + if (p) + { + // int ret = + pthread_mutex_unlock(&p->_mutex); + } +} + +void CriticalSection_Delete(CCriticalSection *p) +{ + // Print("CriticalSection_Delete"); + if (p) + { + // int ret = + pthread_mutex_destroy(&p->_mutex); + } +} + +LONG InterlockedIncrement(LONG volatile *addend) +{ + // Print("InterlockedIncrement"); + #ifdef USE_HACK_UNSAFE_ATOMIC + LONG val = *addend + 1; + *addend = val; + return val; + #else + return __sync_add_and_fetch(addend, 1); + #endif +} + +#endif // _WIN32 diff --git a/3rdparty/lzma-21.03beta/C/Threads.h b/3rdparty/lzma-21.03beta/C/Threads.h new file mode 100644 index 0000000..9e70eca --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Threads.h @@ -0,0 +1,203 @@ +/* Threads.h -- multithreading library +2021-07-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#ifdef _WIN32 +#include +#else + +#if defined(__linux__) +#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) +#ifndef _7ZIP_AFFINITY_DISABLE +#define _7ZIP_AFFINITY_SUPPORTED +// #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED") +// #define _GNU_SOURCE +#endif +#endif +#endif + +#include + +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#ifdef _WIN32 + +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +typedef HANDLE CThread; + +#define Thread_Construct(p) { *(p) = NULL; } +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +// #define Thread_Wait(p) Handle_WaitObject(*(p)) + +typedef + #ifdef UNDER_CE + DWORD + #else + unsigned + #endif + THREAD_FUNC_RET_TYPE; + +typedef DWORD_PTR CAffinityMask; +typedef DWORD_PTR CCpuSet; + +#define CpuSet_Zero(p) { *(p) = 0; } +#define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); } + +#else // _WIN32 + +typedef struct _CThread +{ + pthread_t _tid; + int _created; +} CThread; + +#define Thread_Construct(p) { (p)->_tid = 0; (p)->_created = 0; } +#define Thread_WasCreated(p) ((p)->_created != 0) +WRes Thread_Close(CThread *p); +// #define Thread_Wait Thread_Wait_Close + +typedef void * THREAD_FUNC_RET_TYPE; + +typedef UInt64 CAffinityMask; + +#ifdef _7ZIP_AFFINITY_SUPPORTED + +typedef cpu_set_t CCpuSet; +#define CpuSet_Zero(p) CPU_ZERO(p) +#define CpuSet_Set(p, cpu) CPU_SET(cpu, p) +#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) + +#else + +typedef UInt64 CCpuSet; +#define CpuSet_Zero(p) { *(p) = 0; } +#define CpuSet_Set(p, cpu) { *(p) |= ((UInt64)1 << (cpu)); } +#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) + +#endif + + +#endif // _WIN32 + + +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); +WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity); +WRes Thread_Wait_Close(CThread *p); + +#ifdef _WIN32 +#define Thread_Create_With_CpuSet(p, func, param, cs) \ + Thread_Create_With_Affinity(p, func, param, *cs) +#else +WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); +#endif + + +#ifdef _WIN32 + +typedef HANDLE CEvent; +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); + +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) *(p) = NULL +#define Semaphore_IsCreated(p) (*(p) != NULL) +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +WRes Semaphore_Release1(CSemaphore *p); + +typedef CRITICAL_SECTION CCriticalSection; +WRes CriticalSection_Init(CCriticalSection *p); +#define CriticalSection_Delete(p) DeleteCriticalSection(p) +#define CriticalSection_Enter(p) EnterCriticalSection(p) +#define CriticalSection_Leave(p) LeaveCriticalSection(p) + + +#else // _WIN32 + +typedef struct _CEvent +{ + int _created; + int _manual_reset; + int _state; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CEvent; + +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; + +#define Event_Construct(p) (p)->_created = 0 +#define Event_IsCreated(p) ((p)->_created) + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes Event_Wait(CEvent *p); +WRes Event_Close(CEvent *p); + + +typedef struct _CSemaphore +{ + int _created; + UInt32 _count; + UInt32 _maxCount; + pthread_mutex_t _mutex; + pthread_cond_t _cond; +} CSemaphore; + +#define Semaphore_Construct(p) (p)->_created = 0 +#define Semaphore_IsCreated(p) ((p)->_created) + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) +WRes Semaphore_Wait(CSemaphore *p); +WRes Semaphore_Close(CSemaphore *p); + + +typedef struct _CCriticalSection +{ + pthread_mutex_t _mutex; +} CCriticalSection; + +WRes CriticalSection_Init(CCriticalSection *p); +void CriticalSection_Delete(CCriticalSection *cs); +void CriticalSection_Enter(CCriticalSection *cs); +void CriticalSection_Leave(CCriticalSection *cs); + +LONG InterlockedIncrement(LONG volatile *addend); + +#endif // _WIN32 + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsp b/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsp new file mode 100644 index 0000000..be0f0a7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsp @@ -0,0 +1,241 @@ +# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=7z - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "7z.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "7z - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAcs /Yu"Precomp.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /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" /Yu"Precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z - Win32 Release" +# Name "7z - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# ADD CPP /D "_7ZIP_PPMD_SUPPPORT" +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\BraIA64.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.c +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.c +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7Dec.c +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compiler.h +# End Source File +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zMain.c +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsw b/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsw new file mode 100644 index 0000000..848d13c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/7z.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "7z"=.\7z.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/7zMain.c b/3rdparty/lzma-21.03beta/C/Util/7z/7zMain.c new file mode 100644 index 0000000..9d55509 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/7zMain.c @@ -0,0 +1,887 @@ +/* 7zMain.c - Test application for 7z Decoder +2021-04-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "../../CpuArch.h" + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zBuf.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" + +#ifndef USE_WINDOWS_FILE +/* for mkdir */ +#ifdef _WIN32 +#include +#else +#include +#include +#ifdef __GNUC__ +#include +#endif +#include +// #include +#include +#include +#endif +#endif + + +#define kInputBufSize ((size_t)1 << 18) + +static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + +static void Print(const char *s) +{ + fputs(s, stdout); +} + + +static int Buf_EnsureSize(CBuf *dest, size_t size) +{ + if (dest->size >= size) + return 1; + Buf_Free(dest, &g_Alloc); + return Buf_Create(dest, size, &g_Alloc); +} + +#ifndef _WIN32 +#define _USE_UTF8 +#endif + +/* #define _USE_UTF8 */ + +#ifdef _USE_UTF8 + +#define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) + +#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + +#define _UTF8_HEAD(n, val) ((Byte)(_UTF8_START(n) + (val >> (6 * (n))))) +#define _UTF8_CHAR(n, val) ((Byte)(0x80 + (((val) >> (6 * (n))) & 0x3F))) + +static size_t Utf16_To_Utf8_Calc(const UInt16 *src, const UInt16 *srcLim) +{ + size_t size = 0; + for (;;) + { + UInt32 val; + if (src == srcLim) + return size; + + size++; + val = *src++; + + if (val < 0x80) + continue; + + if (val < _UTF8_RANGE(1)) + { + size++; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + size += 3; + continue; + } + } + + size += 2; + } +} + +static Byte *Utf16_To_Utf8(Byte *dest, const UInt16 *src, const UInt16 *srcLim) +{ + for (;;) + { + UInt32 val; + if (src == srcLim) + return dest; + + val = *src++; + + if (val < 0x80) + { + *dest++ = (Byte)val; + continue; + } + + if (val < _UTF8_RANGE(1)) + { + dest[0] = _UTF8_HEAD(1, val); + dest[1] = _UTF8_CHAR(0, val); + dest += 2; + continue; + } + + if (val >= 0xD800 && val < 0xDC00 && src != srcLim) + { + UInt32 c2 = *src; + if (c2 >= 0xDC00 && c2 < 0xE000) + { + src++; + val = (((val - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + dest[0] = _UTF8_HEAD(3, val); + dest[1] = _UTF8_CHAR(2, val); + dest[2] = _UTF8_CHAR(1, val); + dest[3] = _UTF8_CHAR(0, val); + dest += 4; + continue; + } + } + + dest[0] = _UTF8_HEAD(2, val); + dest[1] = _UTF8_CHAR(1, val); + dest[2] = _UTF8_CHAR(0, val); + dest += 3; + } +} + +static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) +{ + size_t destLen = Utf16_To_Utf8_Calc(src, src + srcLen); + destLen += 1; + if (!Buf_EnsureSize(dest, destLen)) + return SZ_ERROR_MEM; + *Utf16_To_Utf8(dest->data, src, src + srcLen) = 0; + return SZ_OK; +} + +#endif + +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s + #ifndef _USE_UTF8 + , UINT codePage + #endif + ) +{ + unsigned len = 0; + for (len = 0; s[len] != 0; len++) {} + + #ifndef _USE_UTF8 + { + const unsigned size = len * 3 + 100; + if (!Buf_EnsureSize(buf, size)) + return SZ_ERROR_MEM; + { + buf->data[0] = 0; + if (len != 0) + { + const char defaultChar = '_'; + BOOL defUsed; + const unsigned numChars = (unsigned)WideCharToMultiByte( + codePage, 0, (LPCWSTR)s, (int)len, (char *)buf->data, (int)size, &defaultChar, &defUsed); + if (numChars == 0 || numChars >= size) + return SZ_ERROR_FAIL; + buf->data[numChars] = 0; + } + return SZ_OK; + } + } + #else + return Utf16_To_Utf8Buf(buf, s, len); + #endif +} + +#ifdef _WIN32 + #ifndef USE_WINDOWS_FILE + static UINT g_FileCodePage = CP_ACP; + #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage + #endif +#else + #define MY_FILE_CODE_PAGE_PARAM +#endif + +static WRes MyCreateDir(const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + + return CreateDirectoryW((LPCWSTR)name, NULL) ? 0 : GetLastError(); + + #else + + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + + res = + #ifdef _WIN32 + _mkdir((const char *)buf.data) + #else + mkdir((const char *)buf.data, 0777) + #endif + == 0 ? 0 : errno; + Buf_Free(&buf, &g_Alloc); + return res; + + #endif +} + +static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + return OutFile_OpenW(p, (LPCWSTR)name); + #else + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + res = OutFile_Open(p, (const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; + #endif +} + + +static SRes PrintString(const UInt16 *s) +{ + CBuf buf; + SRes res; + Buf_Init(&buf); + res = Utf16_To_Char(&buf, s + #ifndef _USE_UTF8 + , CP_OEMCP + #endif + ); + if (res == SZ_OK) + Print((const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; +} + +static void UInt64ToStr(UInt64 value, char *s, int numDigits) +{ + char temp[32]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + (unsigned)(value % 10)); + value /= 10; + } + while (value != 0); + + for (numDigits -= pos; numDigits > 0; numDigits--) + *s++ = ' '; + + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; +} + +static char *UIntToStr(char *s, unsigned value, int numDigits) +{ + char temp[16]; + int pos = 0; + do + temp[pos++] = (char)('0' + (value % 10)); + while (value /= 10); + + for (numDigits -= pos; numDigits > 0; numDigits--) + *s++ = '0'; + + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; + return s; +} + +static void UIntToStr_2(char *s, unsigned value) +{ + s[0] = (char)('0' + (value / 10)); + s[1] = (char)('0' + (value % 10)); +} + + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + + + +#ifndef _WIN32 + +// MS uses long for BOOL, but long is 32-bit in MS. So we use int. +// typedef long BOOL; +typedef int BOOL; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME; + +static LONG TIME_GetBias() +{ + time_t utc = time(NULL); + struct tm *ptm = localtime(&utc); + int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ + ptm = gmtime(&utc); + ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ + LONG bias = (int)(mktime(ptm)-utc); + return bias; +} + +#define TICKS_PER_SEC 10000000 + +#define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32)) + +#define SET_FILETIME(ft, v64) \ + (ft)->dwLowDateTime = (DWORD)v64; \ + (ft)->dwHighDateTime = (DWORD)(v64 >> 32); + +#define WINAPI +#define TRUE 1 + +static BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime) +{ + UInt64 v = GET_TIME_64(fileTime); + v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC); + SET_FILETIME(localFileTime, v); + return TRUE; +} + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); + +static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft) +{ + UInt64 winTime = GET_TIME_64(ft); + return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; +} + +#if defined(_AIX) + #define MY_ST_TIMESPEC st_timespec +#else + #define MY_ST_TIMESPEC timespec +#endif + +static void FILETIME_To_timespec(const FILETIME *ft, struct MY_ST_TIMESPEC *ts) +{ + if (ft) + { + const Int64 sec = Time_FileTimeToUnixTime64(ft); + // time_t is long + const time_t sec2 = (time_t)sec; + if (sec2 == sec) + { + ts->tv_sec = sec2; + UInt64 winTime = GET_TIME_64(ft); + ts->tv_nsec = (long)((winTime % 10000000) * 100);; + return; + } + } + // else + { + ts->tv_sec = 0; + // ts.tv_nsec = UTIME_NOW; // set to the current time + ts->tv_nsec = UTIME_OMIT; // keep old timesptamp + } +} + +static WRes Set_File_FILETIME(const UInt16 *name, const FILETIME *mTime) +{ + struct timespec times[2]; + + const int flags = 0; // follow link + // = AT_SYMLINK_NOFOLLOW; // don't follow link + + CBuf buf; + int res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + FILETIME_To_timespec(NULL, ×[0]); + FILETIME_To_timespec(mTime, ×[1]); + res = utimensat(AT_FDCWD, (const char *)buf.data, times, flags); + Buf_Free(&buf, &g_Alloc); + if (res == 0) + return 0; + return errno; +} + +#endif + +static void NtfsFileTime_to_FILETIME(const CNtfsFileTime *t, FILETIME *ft) +{ + ft->dwLowDateTime = (DWORD)(t->Low); + ft->dwHighDateTime = (DWORD)(t->High); +} + +static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s) +{ + unsigned year, mon, hour, min, sec; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + UInt32 v; + // UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); + UInt64 v64; + { + FILETIME fileTime, locTime; + NtfsFileTime_to_FILETIME(nTime, &fileTime); + if (!FileTimeToLocalFileTime(&fileTime, &locTime)) + { + locTime.dwHighDateTime = + locTime.dwLowDateTime = 0; + } + v64 = locTime.dwLowDateTime | ((UInt64)locTime.dwHighDateTime << 32); + } + v64 /= 10000000; + sec = (unsigned)(v64 % 60); v64 /= 60; + min = (unsigned)(v64 % 60); v64 /= 60; + hour = (unsigned)(v64 % 24); v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(1601 + v / PERIOD_400 * 400); + v %= PERIOD_400; + + t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; + t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; + t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 0;; mon++) + { + unsigned d = ms[mon]; + if (v < d) + break; + v -= d; + } + s = UIntToStr(s, year, 4); *s++ = '-'; + UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; + UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3; + UIntToStr_2(s, hour); s[2] = ':'; s += 3; + UIntToStr_2(s, min); s[2] = ':'; s += 3; + UIntToStr_2(s, sec); s[2] = 0; +} + +static void PrintLF() +{ + Print("\n"); +} + +static void PrintError(char *s) +{ + Print("\nERROR: "); + Print(s); + PrintLF(); +} + +static void PrintError_WRes(const char *message, WRes wres) +{ + Print("\nERROR: "); + Print(message); + PrintLF(); + { + char s[32]; + UIntToStr(s, (unsigned)wres, 1); + Print("System error code: "); + Print(s); + } + // sprintf(buffer + strlen(buffer), "\nSystem error code: %d", (unsigned)wres); + #ifdef _WIN32 + { + char *s = NULL; + if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, wres, 0, (LPSTR) &s, 0, NULL) != 0 && s) + { + Print(" : "); + Print(s); + LocalFree(s); + } + } + #else + { + const char *s = strerror(wres); + if (s) + { + Print(" : "); + Print(s); + } + } + #endif + PrintLF(); +} + +static void GetAttribString(UInt32 wa, BoolInt isDir, char *s) +{ + #ifdef USE_WINDOWS_FILE + s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); + s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); + s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); + s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); + s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); + s[5] = 0; + #else + s[0] = (char)(((wa & (1 << 4)) != 0 || isDir) ? 'D' : '.'); + s[1] = 0; + #endif +} + + +// #define NUM_PARENTS_MAX 128 + +int MY_CDECL main(int numargs, char *args[]) +{ + ISzAlloc allocImp; + ISzAlloc allocTempImp; + + CFileInStream archiveStream; + CLookToRead2 lookStream; + CSzArEx db; + SRes res; + UInt16 *temp = NULL; + size_t tempSize = 0; + // UInt32 parents[NUM_PARENTS_MAX]; + + Print("\n7z Decoder " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"); + + if (numargs == 1) + { + Print( + "Usage: 7zDec \n\n" + "\n" + " e: Extract files from archive (without using directory names)\n" + " l: List contents of archive\n" + " t: Test integrity of archive\n" + " x: eXtract files with full paths\n"); + return 0; + } + + if (numargs < 3) + { + PrintError("incorrect command"); + return 1; + } + + #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) + g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif + + + allocImp = g_Alloc; + allocTempImp = g_Alloc; + + { + WRes wres = + #ifdef UNDER_CE + InFile_OpenW(&archiveStream.file, L"\test.7z"); // change it + #else + InFile_Open(&archiveStream.file, args[2]); + #endif + if (wres != 0) + { + PrintError_WRes("cannot open input file", wres); + return 1; + } + } + + FileInStream_CreateVTable(&archiveStream); + archiveStream.wres = 0; + LookToRead2_CreateVTable(&lookStream, False); + lookStream.buf = NULL; + + res = SZ_OK; + + { + lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize); + if (!lookStream.buf) + res = SZ_ERROR_MEM; + else + { + lookStream.bufSize = kInputBufSize; + lookStream.realStream = &archiveStream.vt; + LookToRead2_Init(&lookStream); + } + } + + CrcGenerateTable(); + + SzArEx_Init(&db); + + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); + } + + if (res == SZ_OK) + { + char *command = args[1]; + int listCommand = 0, testCommand = 0, fullPaths = 0; + + if (strcmp(command, "l") == 0) listCommand = 1; + else if (strcmp(command, "t") == 0) testCommand = 1; + else if (strcmp(command, "e") == 0) { } + else if (strcmp(command, "x") == 0) { fullPaths = 1; } + else + { + PrintError("incorrect command"); + res = SZ_ERROR_FAIL; + } + + if (res == SZ_OK) + { + UInt32 i; + + /* + if you need cache, use these 3 variables. + if you use external function, you can make these variable as static. + */ + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + // const CSzFileItem *f = db.Files + i; + size_t len; + const BoolInt isDir = SzArEx_IsDir(&db, i); + if (listCommand == 0 && isDir && !fullPaths) + continue; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + // len = SzArEx_GetFullNameLen(&db, i); + + if (len > tempSize) + { + SzFree(NULL, temp); + tempSize = len; + temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); + if (!temp) + { + res = SZ_ERROR_MEM; + break; + } + } + + SzArEx_GetFileNameUtf16(&db, i, temp); + /* + if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) + { + res = SZ_ERROR_FAIL; + break; + } + */ + + if (listCommand) + { + char attr[8], s[32], t[32]; + UInt64 fileSize; + + GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); + + fileSize = SzArEx_GetFileSize(&db, i); + UInt64ToStr(fileSize, s, 10); + + if (SzBitWithVals_Check(&db.MTime, i)) + ConvertFileTimeToString(&db.MTime.Vals[i], t); + else + { + size_t j; + for (j = 0; j < 19; j++) + t[j] = ' '; + t[j] = '\0'; + } + + Print(t); + Print(" "); + Print(attr); + Print(" "); + Print(s); + Print(" "); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (isDir) + Print("/"); + PrintLF(); + continue; + } + + Print(testCommand ? + "T ": + "- "); + res = PrintString(temp); + if (res != SZ_OK) + break; + + if (isDir) + Print("/"); + else + { + res = SzArEx_Extract(&db, &lookStream.vt, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + + if (!testCommand) + { + CSzFile outFile; + size_t processedSize; + size_t j; + UInt16 *name = (UInt16 *)temp; + const UInt16 *destPath = (const UInt16 *)name; + + for (j = 0; name[j] != 0; j++) + if (name[j] == '/') + { + if (fullPaths) + { + name[j] = 0; + MyCreateDir(name); + name[j] = CHAR_PATH_SEPARATOR; + } + else + destPath = name + j + 1; + } + + if (isDir) + { + MyCreateDir(destPath); + PrintLF(); + continue; + } + else + { + WRes wres = OutFile_OpenUtf16(&outFile, destPath); + if (wres != 0) + { + PrintError_WRes("cannot open output file", wres); + res = SZ_ERROR_FAIL; + break; + } + } + + processedSize = outSizeProcessed; + + { + WRes wres = File_Write(&outFile, outBuffer + offset, &processedSize); + if (wres != 0 || processedSize != outSizeProcessed) + { + PrintError_WRes("cannot write output file", wres); + res = SZ_ERROR_FAIL; + break; + } + } + + { + FILETIME mtime; + FILETIME *mtimePtr = NULL; + + #ifdef USE_WINDOWS_FILE + FILETIME ctime; + FILETIME *ctimePtr = NULL; + #endif + + if (SzBitWithVals_Check(&db.MTime, i)) + { + const CNtfsFileTime *t = &db.MTime.Vals[i]; + mtime.dwLowDateTime = (DWORD)(t->Low); + mtime.dwHighDateTime = (DWORD)(t->High); + mtimePtr = &mtime; + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.CTime, i)) + { + const CNtfsFileTime *t = &db.CTime.Vals[i]; + ctime.dwLowDateTime = (DWORD)(t->Low); + ctime.dwHighDateTime = (DWORD)(t->High); + ctimePtr = &ctime; + } + + if (mtimePtr || ctimePtr) + SetFileTime(outFile.handle, ctimePtr, NULL, mtimePtr); + #endif + + { + WRes wres = File_Close(&outFile); + if (wres != 0) + { + PrintError_WRes("cannot close output file", wres); + res = SZ_ERROR_FAIL; + break; + } + } + + #ifndef USE_WINDOWS_FILE + #ifdef _WIN32 + mtimePtr = mtimePtr; + #else + if (mtimePtr) + Set_File_FILETIME(destPath, mtimePtr); + #endif + #endif + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + { + UInt32 attrib = db.Attribs.Vals[i]; + /* p7zip stores posix attributes in high 16 bits and adds 0x8000 as marker. + We remove posix bits, if we detect posix mode field */ + if ((attrib & 0xF0000000) != 0) + attrib &= 0x7FFF; + SetFileAttributesW((LPCWSTR)destPath, attrib); + } + #endif + } + PrintLF(); + } + ISzAlloc_Free(&allocImp, outBuffer); + } + } + + SzFree(NULL, temp); + SzArEx_Free(&db, &allocImp); + ISzAlloc_Free(&allocImp, lookStream.buf); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + Print("\nEverything is Ok\n"); + return 0; + } + + if (res == SZ_ERROR_UNSUPPORTED) + PrintError("decoder doesn't support this archive"); + else if (res == SZ_ERROR_MEM) + PrintError("cannot allocate memory"); + else if (res == SZ_ERROR_CRC) + PrintError("CRC error"); + else if (res == SZ_ERROR_READ /* || archiveStream.Res != 0 */) + PrintError_WRes("Read Error", archiveStream.wres); + else + { + char s[32]; + UInt64ToStr((unsigned)res, s, 0); + PrintError(s); + } + + return 1; +} diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.c b/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.c new file mode 100644 index 0000000..01605e3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.h b/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.h new file mode 100644 index 0000000..588a66f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/makefile b/3rdparty/lzma-21.03beta/C/Util/7z/makefile new file mode 100644 index 0000000..9a49fd5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/makefile @@ -0,0 +1,40 @@ +CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT + +PROG = 7zDec.exe + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zArcIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + +7Z_OBJS = \ + $O\7zMain.obj \ + +OBJS = \ + $O\Precomp.obj \ + $(7Z_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(CCOMPL_USE) +$(C_OBJS): ../../$(*B).c + $(CCOMPL_USE) +$O\Precomp.obj: Precomp.c + $(CCOMPL_PCH) diff --git a/3rdparty/lzma-21.03beta/C/Util/7z/makefile.gcc b/3rdparty/lzma-21.03beta/C/Util/7z/makefile.gcc new file mode 100644 index 0000000..4263d67 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/7z/makefile.gcc @@ -0,0 +1,34 @@ +PROG = 7zdec + +LOCAL_FLAGS = -D_7ZIP_PPMD_SUPPPORT + +include ../../../CPP/7zip/LzmaDec_gcc.mak + + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $O/Bcj2.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/CpuArch.o \ + $O/Delta.o \ + $O/Lzma2Dec.o \ + $O/LzmaDec.o \ + $O/Ppmd7.o \ + $O/Ppmd7Dec.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/7zAlloc.o \ + $O/7zArcIn.o \ + $O/7zBuf.o \ + $O/7zBuf2.o \ + $O/7zDec.o \ + $O/7zMain.o \ + $O/7zFile.o \ + $O/7zStream.o \ + + +include ../../7zip_gcc_c.mak diff --git a/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.c b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.c new file mode 100644 index 0000000..e613b9c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.c @@ -0,0 +1,283 @@ +/* LzmaUtil.c -- Test application for LZMA compression +2021-02-15 : Igor Pavlov : Public domain */ + +#include "../../Precomp.h" + +#include +#include +#include + +#include "../../CpuArch.h" + +#include "../../Alloc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" +#include "../../LzmaDec.h" +#include "../../LzmaEnc.h" + +static const char * const kCantReadMessage = "Cannot read input file"; +static const char * const kCantWriteMessage = "Cannot write output file"; +static const char * const kCantAllocateMessage = "Cannot allocate memory"; +static const char * const kDataErrorMessage = "Data error"; + +static void PrintHelp(char *buffer) +{ + strcat(buffer, + "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n" + "Usage: lzma inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n"); +} + +static int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +static int PrintError_WRes(char *buffer, const char *message, WRes wres) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + sprintf(buffer + strlen(buffer), "\nSystem error code: %d", (unsigned)wres); + #ifndef _WIN32 + { + const char *s = strerror(wres); + if (s) + sprintf(buffer + strlen(buffer), " : %s", s); + } + #endif + strcat(buffer, "\n"); + return 1; +} + +static int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\n7-Zip error code: %d\n", (unsigned)val); + return 1; +} + +static int PrintUserError(char *buffer) +{ + return PrintError(buffer, "Incorrect command"); +} + + +#define IN_BUF_SIZE (1 << 16) +#define OUT_BUF_SIZE (1 << 16) + + +static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, + UInt64 unpackSize) +{ + int thereIsSize = (unpackSize != (UInt64)(Int64)-1); + Byte inBuf[IN_BUF_SIZE]; + Byte outBuf[OUT_BUF_SIZE]; + size_t inPos = 0, inSize = 0, outPos = 0; + LzmaDec_Init(state); + for (;;) + { + if (inPos == inSize) + { + inSize = IN_BUF_SIZE; + RINOK(inStream->Read(inStream, inBuf, &inSize)); + inPos = 0; + } + { + SRes res; + SizeT inProcessed = inSize - inPos; + SizeT outProcessed = OUT_BUF_SIZE - outPos; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + ELzmaStatus status; + if (thereIsSize && outProcessed > unpackSize) + { + outProcessed = (SizeT)unpackSize; + finishMode = LZMA_FINISH_END; + } + + res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, + inBuf + inPos, &inProcessed, finishMode, &status); + inPos += inProcessed; + outPos += outProcessed; + unpackSize -= outProcessed; + + if (outStream) + if (outStream->Write(outStream, outBuf, outPos) != outPos) + return SZ_ERROR_WRITE; + + outPos = 0; + + if (res != SZ_OK || (thereIsSize && unpackSize == 0)) + return res; + + if (inProcessed == 0 && outProcessed == 0) + { + if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + return SZ_ERROR_DATA; + return res; + } + } + } +} + + +static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) +{ + UInt64 unpackSize; + int i; + SRes res = 0; + + CLzmaDec state; + + /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ + unsigned char header[LZMA_PROPS_SIZE + 8]; + + /* Read and parse header */ + + RINOK(SeqInStream_Read(inStream, header, sizeof(header))); + + unpackSize = 0; + for (i = 0; i < 8; i++) + unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); + + LzmaDec_Construct(&state); + RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); + res = Decode2(&state, outStream, inStream, unpackSize); + LzmaDec_Free(&state, &g_Alloc); + return res; +} + +static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) +{ + CLzmaEncHandle enc; + SRes res; + CLzmaEncProps props; + + UNUSED_VAR(rs); + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + LzmaEncProps_Init(&props); + res = LzmaEnc_SetProps(enc, &props); + + if (res == SZ_OK) + { + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + if (outStream->Write(outStream, header, headerSize) != headerSize) + res = SZ_ERROR_WRITE; + else + { + if (res == SZ_OK) + res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); + } + } + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + return res; +} + + +static int main2(int numArgs, const char *args[], char *rs) +{ + CFileSeqInStream inStream; + CFileOutStream outStream; + char c; + int res; + int encodeMode; + BoolInt useOutFile = False; + + FileSeqInStream_CreateVTable(&inStream); + File_Construct(&inStream.file); + inStream.wres = 0; + + FileOutStream_CreateVTable(&outStream); + File_Construct(&outStream.file); + outStream.wres = 0; + + if (numArgs == 1) + { + PrintHelp(rs); + return 0; + } + + if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) + return PrintUserError(rs); + + c = args[1][0]; + encodeMode = (c == 'e' || c == 'E'); + if (!encodeMode && c != 'd' && c != 'D') + return PrintUserError(rs); + + { + size_t t4 = sizeof(UInt32); + size_t t8 = sizeof(UInt64); + if (t4 != 4 || t8 != 8) + return PrintError(rs, "Incorrect UInt32 or UInt64"); + } + + { + WRes wres = InFile_Open(&inStream.file, args[2]); + if (wres != 0) + return PrintError_WRes(rs, "Cannot open input file", wres); + } + + if (numArgs > 3) + { + WRes wres; + useOutFile = True; + wres = OutFile_Open(&outStream.file, args[3]); + if (wres != 0) + return PrintError_WRes(rs, "Cannot open output file", wres); + } + else if (encodeMode) + PrintUserError(rs); + + if (encodeMode) + { + UInt64 fileSize; + WRes wres = File_GetLength(&inStream.file, &fileSize); + if (wres != 0) + return PrintError_WRes(rs, "Cannot get file length", wres); + res = Encode(&outStream.vt, &inStream.vt, fileSize, rs); + } + else + { + res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL); + } + + if (useOutFile) + File_Close(&outStream.file); + File_Close(&inStream.file); + + if (res != SZ_OK) + { + if (res == SZ_ERROR_MEM) + return PrintError(rs, kCantAllocateMessage); + else if (res == SZ_ERROR_DATA) + return PrintError(rs, kDataErrorMessage); + else if (res == SZ_ERROR_WRITE) + return PrintError_WRes(rs, kCantWriteMessage, outStream.wres); + else if (res == SZ_ERROR_READ) + return PrintError_WRes(rs, kCantReadMessage, inStream.wres); + return PrintErrorNumber(rs, res); + } + return 0; +} + + +int MY_CDECL main(int numArgs, const char *args[]) +{ + char rs[800] = { 0 }; + int res = main2(numArgs, args, rs); + fputs(rs, stdout); + return res; +} diff --git a/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsp b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsp new file mode 100644 index 0000000..f060a26 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsp @@ -0,0 +1,168 @@ +# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=LzmaUtil - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LzmaUtil.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaUtil - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe" + +!ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaUtil - Win32 Release" +# Name "LzmaUtil - Win32 Debug" +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zVersion.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaUtil.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsw b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsw new file mode 100644 index 0000000..c52eaf6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/Lzma/LzmaUtil.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile b/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile new file mode 100644 index 0000000..4795322 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile @@ -0,0 +1,28 @@ +# MY_STATIC_LINK=1 +PROG = LZMAc.exe + +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaUtil.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\7zFile.obj \ + $O\7zStream.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile.gcc b/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile.gcc new file mode 100644 index 0000000..f9d59e3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/Lzma/makefile.gcc @@ -0,0 +1,19 @@ +PROG = 7lzma + +include ../../../CPP/7zip/LzmaDec_gcc.mak + + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $O/7zFile.o \ + $O/7zStream.o \ + $O/Alloc.o \ + $O/LzFind.o \ + $O/LzFindMt.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/LzmaUtil.o \ + $O/Threads.o \ + + +include ../../7zip_gcc_c.mak diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.def b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.def new file mode 100644 index 0000000..8bc6add --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.def @@ -0,0 +1,4 @@ +EXPORTS + LzmaCompress + LzmaUncompress + diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsp b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsp new file mode 100644 index 0000000..6ce91dc --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsp @@ -0,0 +1,182 @@ +# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=LzmaLib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LzmaLib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaLib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaLib - Win32 Release" +# Name "LzmaLib - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\LzmaLib.def +# End Source File +# Begin Source File + +SOURCE=.\LzmaLibExports.c +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsw b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsw new file mode 100644 index 0000000..6faf333 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLibExports.c b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLibExports.c new file mode 100644 index 0000000..4a28a9a --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/LzmaLibExports.c @@ -0,0 +1,14 @@ +/* LzmaLibExports.c -- LZMA library DLL Entry point +2015-11-08 : Igor Pavlov : Public domain */ + +#include "../../Precomp.h" + +#include + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + UNUSED_VAR(hInstance); + UNUSED_VAR(dwReason); + UNUSED_VAR(lpReserved); + return TRUE; +} diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/makefile b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/makefile new file mode 100644 index 0000000..eb6ade3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/makefile @@ -0,0 +1,35 @@ +MY_STATIC_LINK=1 +SLIB = sLZMA.lib +PROG = LZMA.dll +SLIBPATH = $O\$(SLIB) + +DEF_FILE = LzmaLib.def +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaLibExports.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzFindOpt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\LzmaLib.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(SLIBPATH): $O $(OBJS) + lib -out:$(SLIBPATH) $(OBJS) $(LIBS) + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/3rdparty/lzma-21.03beta/C/Util/LzmaLib/resource.rc b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/resource.rc new file mode 100644 index 0000000..674832e --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/LzmaLib/resource.rc @@ -0,0 +1,3 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_DLL("LZMA library", "LZMA") diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.c b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.c new file mode 100644 index 0000000..01605e3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.h b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.h new file mode 100644 index 0000000..588a66f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.c b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.c new file mode 100644 index 0000000..ef19aea --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.c @@ -0,0 +1,640 @@ +/* SfxSetup.c - 7z SFX Setup +2019-02-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif + +#ifdef _CONSOLE +#include +#endif + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../CpuArch.h" +#include "../../DllSecur.h" + +#define k_EXE_ExtIndex 2 + +#define kInputBufSize ((size_t)1 << 18) + +static const char * const kExts[] = +{ + "bat" + , "cmd" + , "exe" + , "inf" + , "msi" + #ifdef UNDER_CE + , "cab" + #endif + , "html" + , "htm" +}; + +static const char * const kNames[] = +{ + "setup" + , "install" + , "run" + , "start" +}; + +static unsigned FindExt(const wchar_t *s, unsigned *extLen) +{ + unsigned len = (unsigned)wcslen(s); + unsigned i; + for (i = len; i > 0; i--) + { + if (s[i - 1] == '.') + { + *extLen = len - i; + return i - 1; + } + } + *extLen = 0; + return len; +} + +#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c))) + +static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len) +{ + unsigned i; + for (i = 0; i < num; i++) + { + const char *item = items[i]; + unsigned itemLen = (unsigned)strlen(item); + unsigned j; + if (len != itemLen) + continue; + for (j = 0; j < len; j++) + { + unsigned c = (Byte)item[j]; + if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) + break; + } + if (j == len) + return i; + } + return i; +} + +#ifdef _CONSOLE +static BOOL WINAPI HandlerRoutine(DWORD ctrlType) +{ + UNUSED_VAR(ctrlType); + return TRUE; +} +#endif + +static void PrintErrorMessage(const char *message) +{ + #ifdef _CONSOLE + printf("\n7-Zip Error: %s\n", message); + #else + #ifdef UNDER_CE + WCHAR messageW[256 + 4]; + unsigned i; + for (i = 0; i < 256 && message[i] != 0; i++) + messageW[i] = message[i]; + messageW[i] = 0; + MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR); + #else + MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR); + #endif + #endif +} + +static WRes MyCreateDir(const WCHAR *name) +{ + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); +} + +#ifdef UNDER_CE +#define kBufferSize (1 << 13) +#else +#define kBufferSize (1 << 15) +#endif + +#define kSignatureSearchLimit (1 << 22) + +static BoolInt FindSignature(CSzFile *stream, UInt64 *resPos) +{ + Byte buf[kBufferSize]; + size_t numPrevBytes = 0; + *resPos = 0; + for (;;) + { + size_t processed, pos; + if (*resPos > kSignatureSearchLimit) + return False; + processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + processed += numPrevBytes; + if (processed < k7zStartHeaderSize || + (processed == k7zStartHeaderSize && numPrevBytes != 0)) + return False; + processed -= k7zStartHeaderSize; + for (pos = 0; pos <= processed; pos++) + { + for (; pos <= processed && buf[pos] != '7'; pos++); + if (pos > processed) + break; + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) + { + *resPos += pos; + return True; + } + } + *resPos += processed; + numPrevBytes = k7zStartHeaderSize; + memmove(buf, buf + processed, k7zStartHeaderSize); + } +} + +static BoolInt DoesFileOrDirExist(const WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + handle = FindFirstFileW(path, &fd); + if (handle == INVALID_HANDLE_VALUE) + return False; + FindClose(handle); + return True; +} + +static WRes RemoveDirWithSubItems(WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + WRes res = 0; + size_t len = wcslen(path); + wcscpy(path + len, L"*"); + handle = FindFirstFileW(path, &fd); + path[len] = L'\0'; + if (handle == INVALID_HANDLE_VALUE) + return GetLastError(); + + for (;;) + { + if (wcscmp(fd.cFileName, L".") != 0 && + wcscmp(fd.cFileName, L"..") != 0) + { + wcscpy(path + len, fd.cFileName); + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + res = RemoveDirWithSubItems(path); + } + else + { + SetFileAttributesW(path, 0); + if (DeleteFileW(path) == 0) + res = GetLastError(); + } + + if (res != 0) + break; + } + + if (!FindNextFileW(handle, &fd)) + { + res = GetLastError(); + if (res == ERROR_NO_MORE_FILES) + res = 0; + break; + } + } + + path[len] = L'\0'; + FindClose(handle); + if (res == 0) + { + if (!RemoveDirectoryW(path)) + res = GetLastError(); + } + return res; +} + +#ifdef _CONSOLE +int MY_CDECL main() +#else +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + lpCmdLine, int nCmdShow) +#endif +{ + CFileInStream archiveStream; + CLookToRead2 lookStream; + CSzArEx db; + SRes res = SZ_OK; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + WCHAR sfxPath[MAX_PATH + 2]; + WCHAR path[MAX_PATH * 3 + 2]; + #ifndef UNDER_CE + WCHAR workCurDir[MAX_PATH + 32]; + #endif + size_t pathLen; + DWORD winRes; + const wchar_t *cmdLineParams; + const char *errorMessage = NULL; + BoolInt useShellExecute = True; + DWORD exitCode = 0; + + LoadSecurityDlls(); + + #ifdef _CONSOLE + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + #else + UNUSED_VAR(hInstance); + UNUSED_VAR(hPrevInstance); + UNUSED_VAR(lpCmdLine); + UNUSED_VAR(nCmdShow); + #endif + + CrcGenerateTable(); + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + FileInStream_CreateVTable(&archiveStream); + LookToRead2_CreateVTable(&lookStream, False); + lookStream.buf = NULL; + + winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + { + cmdLineParams = GetCommandLineW(); + #ifndef UNDER_CE + { + BoolInt quoteMode = False; + for (;; cmdLineParams++) + { + wchar_t c = *cmdLineParams; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == 0 || (c == L' ' && !quoteMode)) + break; + } + } + #endif + } + + { + unsigned i; + DWORD d; + winRes = GetTempPathW(MAX_PATH, path); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + pathLen = wcslen(path); + d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + + for (i = 0;; i++, d += GetTickCount()) + { + if (i >= 100) + { + res = SZ_ERROR_FAIL; + break; + } + wcscpy(path + pathLen, L"7z"); + + { + wchar_t *s = path + wcslen(path); + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + } + + if (DoesFileOrDirExist(path)) + continue; + if (CreateDirectoryW(path, NULL)) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + pathLen = wcslen(path); + break; + } + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + res = SZ_ERROR_FAIL; + break; + } + } + + #ifndef UNDER_CE + wcscpy(workCurDir, path); + #endif + if (res != SZ_OK) + errorMessage = "Can't create temp folder"; + } + + if (res != SZ_OK) + { + if (!errorMessage) + errorMessage = "Error"; + PrintErrorMessage(errorMessage); + return 1; + } + + if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) + { + errorMessage = "can not open input file"; + res = SZ_ERROR_FAIL; + } + else + { + UInt64 pos = 0; + if (!FindSignature(&archiveStream.file, &pos)) + res = SZ_ERROR_FAIL; + else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) + res = SZ_ERROR_FAIL; + if (res != 0) + errorMessage = "Can't find 7z archive"; + } + + if (res == SZ_OK) + { + lookStream.buf = (Byte *)ISzAlloc_Alloc(&allocImp, kInputBufSize); + if (!lookStream.buf) + res = SZ_ERROR_MEM; + else + { + lookStream.bufSize = kInputBufSize; + lookStream.realStream = &archiveStream.vt; + LookToRead2_Init(&lookStream); + } + } + + SzArEx_Init(&db); + + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp); + } + + if (res == SZ_OK) + { + UInt32 executeFileIndex = (UInt32)(Int32)-1; + UInt32 minPrice = 1 << 30; + UInt32 i; + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + WCHAR *temp; + + if (SzArEx_GetFileNameUtf16(&db, i, NULL) >= MAX_PATH) + { + res = SZ_ERROR_FAIL; + break; + } + + temp = path + pathLen; + + SzArEx_GetFileNameUtf16(&db, i, (UInt16 *)temp); + { + res = SzArEx_Extract(&db, &lookStream.vt, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + { + CSzFile outFile; + size_t processedSize; + size_t j; + size_t nameStartPos = 0; + for (j = 0; temp[j] != 0; j++) + { + if (temp[j] == '/') + { + temp[j] = 0; + MyCreateDir(path); + temp[j] = CHAR_PATH_SEPARATOR; + nameStartPos = j + 1; + } + } + + if (SzArEx_IsDir(&db, i)) + { + MyCreateDir(path); + continue; + } + else + { + unsigned extLen; + const WCHAR *name = temp + nameStartPos; + unsigned len = (unsigned)wcslen(name); + unsigned nameLen = FindExt(temp + nameStartPos, &extLen); + unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); + unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); + + unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); + if (minPrice > price) + { + minPrice = price; + executeFileIndex = i; + useShellExecute = (extPrice != k_EXE_ExtIndex); + } + + if (DoesFileOrDirExist(path)) + { + errorMessage = "Duplicate file"; + res = SZ_ERROR_FAIL; + break; + } + if (OutFile_OpenW(&outFile, path)) + { + errorMessage = "Can't open output file"; + res = SZ_ERROR_FAIL; + break; + } + } + + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + errorMessage = "Can't write output file"; + res = SZ_ERROR_FAIL; + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.MTime, i)) + { + const CNtfsFileTime *t = db.MTime.Vals + i; + FILETIME mTime; + mTime.dwLowDateTime = t->Low; + mTime.dwHighDateTime = t->High; + SetFileTime(outFile.handle, NULL, NULL, &mTime); + } + #endif + + { + SRes res2 = File_Close(&outFile); + if (res != SZ_OK) + break; + if (res2 != SZ_OK) + { + res = res2; + break; + } + } + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(path, db.Attribs.Vals[i]); + #endif + } + } + + if (res == SZ_OK) + { + if (executeFileIndex == (UInt32)(Int32)-1) + { + errorMessage = "There is no file to execute"; + res = SZ_ERROR_FAIL; + } + else + { + WCHAR *temp = path + pathLen; + UInt32 j; + SzArEx_GetFileNameUtf16(&db, executeFileIndex, (UInt16 *)temp); + for (j = 0; temp[j] != 0; j++) + if (temp[j] == '/') + temp[j] = CHAR_PATH_SEPARATOR; + } + } + ISzAlloc_Free(&allocImp, outBuffer); + } + + SzArEx_Free(&db, &allocImp); + + ISzAlloc_Free(&allocImp, lookStream.buf); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + HANDLE hProcess = 0; + + #ifndef UNDER_CE + WCHAR oldCurDir[MAX_PATH + 2]; + oldCurDir[0] = 0; + { + DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); + if (needLen == 0 || needLen > MAX_PATH) + oldCurDir[0] = 0; + SetCurrentDirectory(workCurDir); + } + #endif + + if (useShellExecute) + { + SHELLEXECUTEINFO ei; + UINT32 executeRes; + BOOL success; + + memset(&ei, 0, sizeof(ei)); + ei.cbSize = sizeof(ei); + ei.lpFile = path; + ei.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + /* | SEE_MASK_NO_CONSOLE */ + ; + if (wcslen(cmdLineParams) != 0) + ei.lpParameters = cmdLineParams; + ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */ + success = ShellExecuteEx(&ei); + executeRes = (UINT32)(UINT_PTR)ei.hInstApp; + if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ + res = SZ_ERROR_FAIL; + else + hProcess = ei.hProcess; + } + else + { + STARTUPINFOW si; + PROCESS_INFORMATION pi; + WCHAR cmdLine[MAX_PATH * 3]; + + wcscpy(cmdLine, path); + wcscat(cmdLine, cmdLineParams); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) + res = SZ_ERROR_FAIL; + else + { + CloseHandle(pi.hThread); + hProcess = pi.hProcess; + } + } + + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + if (!GetExitCodeProcess(hProcess, &exitCode)) + exitCode = 1; + CloseHandle(hProcess); + } + + #ifndef UNDER_CE + SetCurrentDirectory(oldCurDir); + #endif + } + + path[pathLen] = L'\0'; + RemoveDirWithSubItems(path); + + if (res == SZ_OK) + return (int)exitCode; + + { + if (res == SZ_ERROR_UNSUPPORTED) + errorMessage = "Decoder doesn't support this archive"; + else if (res == SZ_ERROR_MEM) + errorMessage = "Can't allocate required memory"; + else if (res == SZ_ERROR_CRC) + errorMessage = "CRC error"; + else + { + if (!errorMessage) + errorMessage = "ERROR"; + } + + if (errorMessage) + PrintErrorMessage(errorMessage); + } + return 1; +} diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsp b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsp new file mode 100644 index 0000000..60439a6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsp @@ -0,0 +1,231 @@ +# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SfxSetup - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SfxSetup - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SfxSetup - Win32 Release" +# Name "SfxSetup - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\BraIA64.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.c +# End Source File +# Begin Source File + +SOURCE=..\..\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\DllSecur.c +# End Source File +# Begin Source File + +SOURCE=..\..\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SfxSetup.c +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsw b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsw new file mode 100644 index 0000000..ea23111 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/SfxSetup.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile new file mode 100644 index 0000000..544da67 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile @@ -0,0 +1,37 @@ +PROG = 7zS2.sfx +MY_FIXED = 1 + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile_con b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile_con new file mode 100644 index 0000000..d0f8352 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/makefile_con @@ -0,0 +1,38 @@ +PROG = 7zS2con.sfx +MY_FIXED = 1 +CFLAGS = $(CFLAGS) -D_CONSOLE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/resource.rc b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/resource.rc new file mode 100644 index 0000000..0c1637f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/resource.rc @@ -0,0 +1,5 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") + +1 ICON "setup.ico" diff --git a/3rdparty/lzma-21.03beta/C/Util/SfxSetup/setup.ico b/3rdparty/lzma-21.03beta/C/Util/SfxSetup/setup.ico new file mode 100644 index 0000000000000000000000000000000000000000..dbb6ca8b478520c64f5061355813df6a810a67f1 GIT binary patch literal 1078 zcmZQzU}RuoP*4zH0D%`w3=C=v3=9GS5WWT@0|Os31A_(w1A_ts1A_wtNIeTkDMJGj zn8HFdFfcSQFfcSUKq!U=5R>7+fddQ;4IqjC3=IDn7#RNlhfoavK}?4K|3QN2#x)y5 zfB{sZzZwFJVf^h|+_$^9Y&V7~=&vsEu6C)eHijzb2gz@7-);<5&|eLbb*YB)w{PF# z4$=>ocX9Eq2I+?w*uNbD;OZgPgY*8Ke z&R&2dkIo0H0?Q+eD+lr6wsmxLG<;xS|Nnu3`Tqw7#{VA}7(lrG0|SFS8fN&wzyQV% z7#J81fRY+CHGm8R@j>EW7#JA-kcdI)9F+1wX`PV)lFmWqL5)YFsF2P<$p@6sK*<`E zVnN9bOoNgj10;Ddb2M;(Qjr0FL-Th~YT<8SuDAdH|FeAqgYozJ^6$nC3>+Wj)4upO zFmU{ofA$ANgCn(pfy2ec1(X{>bU{G_0|z*`8xF`bFdX1#U^u`I#dyLI6qe{108KGc A{Qv*} literal 0 HcmV?d00001 diff --git a/3rdparty/lzma-21.03beta/C/Xz.c b/3rdparty/lzma-21.03beta/C/Xz.c new file mode 100644 index 0000000..7c53b60 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Xz.c @@ -0,0 +1,90 @@ +/* Xz.c - Xz +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" +#include "XzCrc64.h" + +const Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; +/* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */ + +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) +{ + unsigned i = 0; + do + { + buf[i++] = (Byte)((v & 0x7F) | 0x80); + v >>= 7; + } + while (v != 0); + buf[(size_t)i - 1] &= 0x7F; + return i; +} + +void Xz_Construct(CXzStream *p) +{ + p->numBlocks = 0; + p->blocks = NULL; + p->flags = 0; +} + +void Xz_Free(CXzStream *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->blocks); + p->numBlocks = 0; + p->blocks = NULL; +} + +unsigned XzFlags_GetCheckSize(CXzStreamFlags f) +{ + unsigned t = XzFlags_GetCheckType(f); + return (t == 0) ? 0 : ((unsigned)4 << ((t - 1) / 3)); +} + +void XzCheck_Init(CXzCheck *p, unsigned mode) +{ + p->mode = mode; + switch (mode) + { + case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; + case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; + case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; + } +} + +void XzCheck_Update(CXzCheck *p, const void *data, size_t size) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; + case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; + case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; + } +} + +int XzCheck_Final(CXzCheck *p, Byte *digest) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: + SetUi32(digest, CRC_GET_DIGEST(p->crc)); + break; + case XZ_CHECK_CRC64: + { + int i; + UInt64 v = CRC64_GET_DIGEST(p->crc64); + for (i = 0; i < 8; i++, v >>= 8) + digest[i] = (Byte)(v & 0xFF); + break; + } + case XZ_CHECK_SHA256: + Sha256_Final(&p->sha, digest); + break; + default: + return 0; + } + return 1; +} diff --git a/3rdparty/lzma-21.03beta/C/Xz.h b/3rdparty/lzma-21.03beta/C/Xz.h new file mode 100644 index 0000000..849b944 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/Xz.h @@ -0,0 +1,517 @@ +/* Xz.h - Xz interface +2021-04-01 : Igor Pavlov : Public domain */ + +#ifndef __XZ_H +#define __XZ_H + +#include "Sha256.h" + +EXTERN_C_BEGIN + +#define XZ_ID_Subblock 1 +#define XZ_ID_Delta 3 +#define XZ_ID_X86 4 +#define XZ_ID_PPC 5 +#define XZ_ID_IA64 6 +#define XZ_ID_ARM 7 +#define XZ_ID_ARMT 8 +#define XZ_ID_SPARC 9 +#define XZ_ID_LZMA2 0x21 + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v); + +/* ---------- xz block ---------- */ + +#define XZ_BLOCK_HEADER_SIZE_MAX 1024 + +#define XZ_NUM_FILTERS_MAX 4 +#define XZ_BF_NUM_FILTERS_MASK 3 +#define XZ_BF_PACK_SIZE (1 << 6) +#define XZ_BF_UNPACK_SIZE (1 << 7) + +#define XZ_FILTER_PROPS_SIZE_MAX 20 + +typedef struct +{ + UInt64 id; + UInt32 propsSize; + Byte props[XZ_FILTER_PROPS_SIZE_MAX]; +} CXzFilter; + +typedef struct +{ + UInt64 packSize; + UInt64 unpackSize; + Byte flags; + CXzFilter filters[XZ_NUM_FILTERS_MAX]; +} CXzBlock; + +#define XzBlock_GetNumFilters(p) (((unsigned)(p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) +#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) +#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) +#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0) + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header); +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, BoolInt *isIndex, UInt32 *headerSizeRes); + +/* ---------- xz stream ---------- */ + +#define XZ_SIG_SIZE 6 +#define XZ_FOOTER_SIG_SIZE 2 + +extern const Byte XZ_SIG[XZ_SIG_SIZE]; + +/* +extern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; +*/ + +#define XZ_FOOTER_SIG_0 'Y' +#define XZ_FOOTER_SIG_1 'Z' + +#define XZ_STREAM_FLAGS_SIZE 2 +#define XZ_STREAM_CRC_SIZE 4 + +#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE) +#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4) + +#define XZ_CHECK_MASK 0xF +#define XZ_CHECK_NO 0 +#define XZ_CHECK_CRC32 1 +#define XZ_CHECK_CRC64 4 +#define XZ_CHECK_SHA256 10 + +typedef struct +{ + unsigned mode; + UInt32 crc; + UInt64 crc64; + CSha256 sha; +} CXzCheck; + +void XzCheck_Init(CXzCheck *p, unsigned mode); +void XzCheck_Update(CXzCheck *p, const void *data, size_t size); +int XzCheck_Final(CXzCheck *p, Byte *digest); + +typedef UInt16 CXzStreamFlags; + +#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK) +#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK) +#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32) +unsigned XzFlags_GetCheckSize(CXzStreamFlags f); + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf); +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream); + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; +} CXzBlockSizes; + +typedef struct +{ + CXzStreamFlags flags; + size_t numBlocks; + CXzBlockSizes *blocks; + UInt64 startOffset; +} CXzStream; + +void Xz_Construct(CXzStream *p); +void Xz_Free(CXzStream *p, ISzAllocPtr alloc); + +#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) + +UInt64 Xz_GetUnpackSize(const CXzStream *p); +UInt64 Xz_GetPackSize(const CXzStream *p); + +typedef struct +{ + size_t num; + size_t numAllocated; + CXzStream *streams; +} CXzs; + +void Xzs_Construct(CXzs *p); +void Xzs_Free(CXzs *p, ISzAllocPtr alloc); +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc); + +UInt64 Xzs_GetNumBlocks(const CXzs *p); +UInt64 Xzs_GetUnpackSize(const CXzs *p); + + +// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + +typedef enum +{ + CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ + CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + CODER_STATUS_NOT_FINISHED, /* stream was not finished */ + CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ +} ECoderStatus; + + +// ECoderFinishMode values are identical to ELzmaFinishMode + +typedef enum +{ + CODER_FINISH_ANY, /* finish at any point */ + CODER_FINISH_END /* block must be finished at the end */ +} ECoderFinishMode; + + +typedef struct _IStateCoder +{ + void *p; + void (*Free)(void *p, ISzAllocPtr alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc); + void (*Init)(void *p); + SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status); + SizeT (*Filter)(void *p, Byte *data, SizeT size); +} IStateCoder; + + + +#define MIXCODER_NUM_FILTERS_MAX 4 + +typedef struct +{ + ISzAllocPtr alloc; + Byte *buf; + unsigned numCoders; + + Byte *outBuf; + size_t outBufSize; + size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode) + BoolInt wasFinished; + SRes res; + ECoderStatus status; + // BoolInt SingleBufMode; + + int finished[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; + UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; + SRes results[MIXCODER_NUM_FILTERS_MAX]; + IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; +} CMixCoder; + + +typedef enum +{ + XZ_STATE_STREAM_HEADER, + XZ_STATE_STREAM_INDEX, + XZ_STATE_STREAM_INDEX_CRC, + XZ_STATE_STREAM_FOOTER, + XZ_STATE_STREAM_PADDING, + XZ_STATE_BLOCK_HEADER, + XZ_STATE_BLOCK, + XZ_STATE_BLOCK_FOOTER +} EXzState; + + +typedef struct +{ + EXzState state; + UInt32 pos; + unsigned alignPos; + unsigned indexPreSize; + + CXzStreamFlags streamFlags; + + UInt32 blockHeaderSize; + UInt64 packSize; + UInt64 unpackSize; + + UInt64 numBlocks; // number of finished blocks in current stream + UInt64 indexSize; + UInt64 indexPos; + UInt64 padSize; + + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; + + UInt32 crc; + CMixCoder decoder; + CXzBlock block; + CXzCheck check; + CSha256 sha; + + BoolInt parseMode; + BoolInt headerParsedOk; + BoolInt decodeToStreamSignature; + unsigned decodeOnlyOneBlock; + + Byte *outBuf; + size_t outBufSize; + size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked + + Byte shaDigest[SHA256_DIGEST_SIZE]; + Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; +} CXzUnpacker; + +/* alloc : aligned for cache line allocation is better */ +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc); +void XzUnpacker_Init(CXzUnpacker *p); +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize); +void XzUnpacker_Free(CXzUnpacker *p); + +/* + XzUnpacker + The sequence for decoding functions: + { + XzUnpacker_Construct() + [Decoding_Calls] + XzUnpacker_Free() + } + + [Decoding_Calls] + + There are 3 types of interfaces for [Decoding_Calls] calls: + + Interface-1 : Partial output buffers: + { + XzUnpacker_Init() + for() + { + XzUnpacker_Code(); + } + XzUnpacker_IsStreamWasFinished() + } + + Interface-2 : Direct output buffer: + Use it, if you know exact size of decoded data, and you need + whole xz unpacked data in one output buffer. + xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode. + { + XzUnpacker_Init() + XzUnpacker_SetOutBufMode(); // to set output buffer and size + for() + { + XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code() + } + XzUnpacker_IsStreamWasFinished() + } + + Interface-3 : Direct output buffer : One call full decoding + It unpacks whole input buffer to output buffer in one call. + It uses Interface-2 internally. + { + XzUnpacker_CodeFull() + XzUnpacker_IsStreamWasFinished() + } +*/ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + CODER_FINISH_ANY - use smallest number of input bytes + CODER_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - the decoder can return it in two cases: + 1) it needs more input data to finish current xz stream + 2) xz stream was finished successfully. But the decoder supports multiple + concatented xz streams. So it expects more input data for new xz streams. + Call XzUnpacker_IsStreamWasFinished() to check that latest xz stream was finished successfully. + + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. +*/ + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status); + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status); + +/* +If you decode full xz stream(s), then you can call XzUnpacker_IsStreamWasFinished() +after successful XzUnpacker_CodeFull() or after last call of XzUnpacker_Code(). +*/ + +BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p); + +/* +XzUnpacker_GetExtraSize() returns then number of unconfirmed bytes, + if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state. +These bytes can be some data after xz archive, or +it can be start of new xz stream. + +Call XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of +xz stream in two cases, if XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p); + + +/* + for random block decoding: + XzUnpacker_Init(); + set CXzUnpacker::streamFlags + XzUnpacker_PrepareToRandomBlockDecoding() + loop + { + XzUnpacker_Code() + XzUnpacker_IsBlockFinished() + } +*/ + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p); +BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p); + +#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags)) + + + + + + +/* ---- Single-Thread and Multi-Thread xz Decoding with Input/Output Streams ---- */ + +/* + if (CXzDecMtProps::numThreads > 1), the decoder can try to use + Multi-Threading. The decoder analyses xz block header, and if + there are pack size and unpack size values stored in xz block header, + the decoder reads compressed data of block to internal buffers, + and then it can start parallel decoding, if there are another blocks. + The decoder can switch back to Single-Thread decoding after some conditions. + + The sequence of calls for xz decoding with in/out Streams: + { + XzDecMt_Create() + XzDecMtProps_Init(XzDecMtProps) to set default values of properties + // then you can change some XzDecMtProps parameters with required values + // here you can set the number of threads and (memUseMax) - the maximum + Memory usage for multithreading decoding. + for() + { + XzDecMt_Decode() // one call per one file + } + XzDecMt_Destroy() + } +*/ + + +typedef struct +{ + size_t inBufSize_ST; // size of input buffer for Single-Thread decoding + size_t outStep_ST; // size of output buffer for Single-Thread decoding + BoolInt ignoreErrors; // if set to 1, the decoder can ignore some errors and it skips broken parts of data. + + #ifndef _7ZIP_ST + unsigned numThreads; // the number of threads for Multi-Thread decoding. if (umThreads == 1) it will use Single-thread decoding + size_t inBufSize_MT; // size of small input data buffers for Multi-Thread decoding. Big number of such small buffers can be created + size_t memUseMax; // the limit of total memory usage for Multi-Thread decoding. + // it's recommended to set (memUseMax) manually to value that is smaller of total size of RAM in computer. + #endif +} CXzDecMtProps; + +void XzDecMtProps_Init(CXzDecMtProps *p); + + +typedef void * CXzDecMtHandle; + +/* + alloc : XzDecMt uses CAlignOffsetAlloc internally for addresses allocated by (alloc). + allocMid : for big allocations, aligned allocation is better +*/ + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid); +void XzDecMt_Destroy(CXzDecMtHandle p); + + +typedef struct +{ + Byte UnpackSize_Defined; + Byte NumStreams_Defined; + Byte NumBlocks_Defined; + + Byte DataAfterEnd; // there are some additional data after good xz streams, and that data is not new xz stream. + Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data + + UInt64 InSize; // pack size processed. That value doesn't include the data after + // end of xz stream, if that data was not correct + UInt64 OutSize; + + UInt64 NumStreams; + UInt64 NumBlocks; + + SRes DecodeRes; // the error code of xz streams data decoding + SRes ReadRes; // error code from ISeqInStream:Read() + SRes ProgressRes; // error code from ICompressProgress:Progress() + + SRes CombinedRes; // Combined result error code that shows main rusult + // = S_OK, if there is no error. + // but check also (DataAfterEnd) that can show additional minor errors. + + SRes CombinedRes_Type; // = SZ_ERROR_READ, if error from ISeqInStream + // = SZ_ERROR_PROGRESS, if error from ICompressProgress + // = SZ_ERROR_WRITE, if error from ISeqOutStream + // = SZ_ERROR_* codes for decoding +} CXzStatInfo; + +void XzStatInfo_Clear(CXzStatInfo *p); + +/* + +XzDecMt_Decode() +SRes: it's combined decoding result. It also is equal to stat->CombinedRes. + + SZ_OK - no error + check also output value in (stat->DataAfterEnd) + that can show additional possible error + + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_NO_ARCHIVE - is not xz archive + SZ_ERROR_ARCHIVE - Headers error + SZ_ERROR_DATA - Data Error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC Error + SZ_ERROR_INPUT_EOF - it needs more input data + SZ_ERROR_WRITE - ISeqOutStream error + (SZ_ERROR_READ) - ISeqInStream errors + (SZ_ERROR_PROGRESS) - ICompressProgress errors + // SZ_ERROR_THREAD - error in multi-threading functions + MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function +*/ + +SRes XzDecMt_Decode(CXzDecMtHandle p, + const CXzDecMtProps *props, + const UInt64 *outDataSize, // NULL means undefined + int finishMode, // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished + ISeqOutStream *outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, // out: decoding results and statistics + int *isMT, // out: 0 means that ST (Single-Thread) version was used + // 1 means that MT (Multi-Thread) version was used + ICompressProgress *progress); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/XzCrc64.c b/3rdparty/lzma-21.03beta/C/XzCrc64.c new file mode 100644 index 0000000..b6d02cb --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzCrc64.c @@ -0,0 +1,86 @@ +/* XzCrc64.c -- CRC64 calculation +2017-05-23 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "XzCrc64.h" +#include "CpuArch.h" + +#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) + +#ifdef MY_CPU_LE + #define CRC64_NUM_TABLES 4 +#else + #define CRC64_NUM_TABLES 5 + #define CRC_UINT64_SWAP(v) \ + ((v >> 56) \ + | ((v >> 40) & ((UInt64)0xFF << 8)) \ + | ((v >> 24) & ((UInt64)0xFF << 16)) \ + | ((v >> 8) & ((UInt64)0xFF << 24)) \ + | ((v << 8) & ((UInt64)0xFF << 32)) \ + | ((v << 24) & ((UInt64)0xFF << 40)) \ + | ((v << 40) & ((UInt64)0xFF << 48)) \ + | ((v << 56))) + + UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (MY_FAST_CALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC64_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES]; + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void MY_FAST_CALL Crc64GenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt64 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); + g_Crc64Table[i] = r; + } + for (i = 256; i < 256 * CRC64_NUM_TABLES; i++) + { + UInt64 r = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE + + g_Crc64Update = XzCrc64UpdateT4; + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--) + { + UInt64 x = g_Crc64Table[(size_t)i - 256]; + g_Crc64Table[i] = CRC_UINT64_SWAP(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif +} diff --git a/3rdparty/lzma-21.03beta/C/XzCrc64.h b/3rdparty/lzma-21.03beta/C/XzCrc64.h new file mode 100644 index 0000000..08dbc33 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzCrc64.h @@ -0,0 +1,26 @@ +/* XzCrc64.h -- CRC64 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __XZ_CRC64_H +#define __XZ_CRC64_H + +#include + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt64 g_Crc64Table[]; + +void MY_FAST_CALL Crc64GenerateTable(void); + +#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) +#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) +#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size); +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/XzCrc64Opt.c b/3rdparty/lzma-21.03beta/C/XzCrc64Opt.c new file mode 100644 index 0000000..93a9fff --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzCrc64Opt.c @@ -0,0 +1,71 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2021-02-09 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifndef MY_CPU_BE + +#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)v ^ *(const UInt32 *)(const void *)p; + v = (v >> 32) + ^ (table + 0x300)[((d ) & 0xFF)] + ^ (table + 0x200)[((d >> 8) & 0xFF)] + ^ (table + 0x100)[((d >> 16) & 0xFF)] + ^ (table + 0x000)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT64_SWAP(v) \ + ((v >> 56) \ + | ((v >> 40) & ((UInt64)0xFF << 8)) \ + | ((v >> 24) & ((UInt64)0xFF << 16)) \ + | ((v >> 8) & ((UInt64)0xFF << 24)) \ + | ((v << 8) & ((UInt64)0xFF << 32)) \ + | ((v << 24) & ((UInt64)0xFF << 40)) \ + | ((v << 40) & ((UInt64)0xFF << 48)) \ + | ((v << 56))) + +#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + table += 0x100; + v = CRC_UINT64_SWAP(v); + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)(const void *)p; + v = (v << 32) + ^ (table + 0x000)[((d ) & 0xFF)] + ^ (table + 0x100)[((d >> 8) & 0xFF)] + ^ (table + 0x200)[((d >> 16) & 0xFF)] + ^ (table + 0x300)[((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC64_UPDATE_BYTE_2_BE(v, *p); + return CRC_UINT64_SWAP(v); +} + +#endif diff --git a/3rdparty/lzma-21.03beta/C/XzDec.c b/3rdparty/lzma-21.03beta/C/XzDec.c new file mode 100644 index 0000000..3db9b3f --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzDec.c @@ -0,0 +1,2836 @@ +/* XzDec.c -- Xz Decode +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +// #include + +// #define XZ_DUMP + +/* #define XZ_DUMP */ + +#ifdef XZ_DUMP +#include +#endif + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +#define PRF_STR(s) PRF(printf("\n" s "\n")) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "Lzma2Dec.h" + +// #define USE_SUBBLOCK + +#ifdef USE_SUBBLOCK +#include "Bcj3Dec.c" +#include "SbDec.h" +#endif + +#include "Xz.h" + +#define XZ_CHECK_SIZE_MAX 64 + +#define CODER_BUF_SIZE ((size_t)1 << 17) + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) +{ + unsigned i, limit; + *value = 0; + limit = (maxSize > 9) ? 9 : (unsigned)maxSize; + + for (i = 0; i < limit;) + { + Byte b = p[i]; + *value |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return (b == 0 && i != 1) ? 0 : i; + } + return 0; +} + +/* ---------- BraState ---------- */ + +#define BRA_BUF_SIZE (1 << 14) + +typedef struct +{ + size_t bufPos; + size_t bufConv; + size_t bufTotal; + + int encodeMode; + + UInt32 methodId; + UInt32 delta; + UInt32 ip; + UInt32 x86State; + Byte deltaState[DELTA_STATE_SIZE]; + + Byte buf[BRA_BUF_SIZE]; +} CBraState; + +static void BraState_Free(void *pp, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, pp); +} + +static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + CBraState *p = ((CBraState *)pp); + UNUSED_VAR(alloc); + p->ip = 0; + if (p->methodId == XZ_ID_Delta) + { + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + p->delta = (unsigned)props[0] + 1; + } + else + { + if (propSize == 4) + { + UInt32 v = GetUi32(props); + switch (p->methodId) + { + case XZ_ID_PPC: + case XZ_ID_ARM: + case XZ_ID_SPARC: + if ((v & 3) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_ARMT: + if ((v & 1) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_IA64: + if ((v & 0xF) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + } + p->ip = v; + } + else if (propSize != 0) + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; +} + +static void BraState_Init(void *pp) +{ + CBraState *p = ((CBraState *)pp); + p->bufPos = p->bufConv = p->bufTotal = 0; + x86_Convert_Init(p->x86State); + if (p->methodId == XZ_ID_Delta) + Delta_Init(p->deltaState); +} + + +#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break; + +static SizeT BraState_Filter(void *pp, Byte *data, SizeT size) +{ + CBraState *p = ((CBraState *)pp); + switch (p->methodId) + { + case XZ_ID_Delta: + if (p->encodeMode) + Delta_Encode(p->deltaState, p->delta, data, size); + else + Delta_Decode(p->deltaState, p->delta, data, size); + break; + case XZ_ID_X86: + size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode); + break; + CASE_BRA_CONV(PPC) + CASE_BRA_CONV(IA64) + CASE_BRA_CONV(ARM) + CASE_BRA_CONV(ARMT) + CASE_BRA_CONV(SPARC) + } + p->ip += (UInt32)size; + return size; +} + + +static SRes BraState_Code2(void *pp, + Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CBraState *p = ((CBraState *)pp); + SizeT destRem = *destLen; + SizeT srcRem = *srcLen; + UNUSED_VAR(finishMode); + + *destLen = 0; + *srcLen = 0; + // *wasFinished = False; + *status = CODER_STATUS_NOT_FINISHED; + + while (destRem > 0) + { + if (p->bufPos != p->bufConv) + { + size_t size = p->bufConv - p->bufPos; + if (size > destRem) + size = destRem; + memcpy(dest, p->buf + p->bufPos, size); + p->bufPos += size; + *destLen += size; + dest += size; + destRem -= size; + continue; + } + + p->bufTotal -= p->bufPos; + memmove(p->buf, p->buf + p->bufPos, p->bufTotal); + p->bufPos = 0; + p->bufConv = 0; + { + size_t size = BRA_BUF_SIZE - p->bufTotal; + if (size > srcRem) + size = srcRem; + memcpy(p->buf + p->bufTotal, src, size); + *srcLen += size; + src += size; + srcRem -= size; + p->bufTotal += size; + } + if (p->bufTotal == 0) + break; + + p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal); + + if (p->bufConv == 0) + { + if (!srcWasFinished) + break; + p->bufConv = p->bufTotal; + } + } + + if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + // *wasFinished = 1; + } + + return SZ_OK; +} + + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc); +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc) +{ + CBraState *decoder; + if (id < XZ_ID_Delta || id > XZ_ID_SPARC) + return SZ_ERROR_UNSUPPORTED; + decoder = (CBraState *)p->p; + if (!decoder) + { + decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState)); + if (!decoder) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = BraState_Free; + p->SetProps = BraState_SetProps; + p->Init = BraState_Init; + p->Code2 = BraState_Code2; + p->Filter = BraState_Filter; + } + decoder->methodId = (UInt32)id; + decoder->encodeMode = encodeMode; + return SZ_OK; +} + + + +/* ---------- SbState ---------- */ + +#ifdef USE_SUBBLOCK + +static void SbState_Free(void *pp, ISzAllocPtr alloc) +{ + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); + ISzAlloc_Free(alloc, pp); +} + +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + UNUSED_VAR(pp); + UNUSED_VAR(props); + UNUSED_VAR(alloc); + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static void SbState_Init(void *pp) +{ + SbDec_Init((CSbDec *)pp); +} + +static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished + ECoderStatus *status) +{ + CSbDec *p = (CSbDec *)pp; + SRes res; + UNUSED_VAR(srcWasFinished); + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ + *status = (*destLen == 0 && *srcLen == 0) ? + CODER_STATUS_FINISHED_WITH_MARK : + CODER_STATUS_NOT_FINISHED; + return res; +} + +static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc) +{ + CSbDec *decoder = (CSbDec *)p->p; + if (!decoder) + { + decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec)); + if (!decoder) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = SbState_Free; + p->SetProps = SbState_SetProps; + p->Init = SbState_Init; + p->Code2 = SbState_Code2; + p->Filter = NULL; + } + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); + return SZ_OK; +} + +#endif + + + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + CLzma2Dec decoder; + BoolInt outBufMode; +} CLzma2Dec_Spec; + + +static void Lzma2State_Free(void *pp, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + Lzma2Dec_FreeProbs(&p->decoder, alloc); + else + Lzma2Dec_Free(&p->decoder, alloc); + ISzAlloc_Free(alloc, pp); +} + +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) +{ + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + { + CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; + if (p->outBufMode) + return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc); + else + return Lzma2Dec_Allocate(&p->decoder, props[0], alloc); + } +} + +static void Lzma2State_Init(void *pp) +{ + Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder); +} + + +/* + if (outBufMode), then (dest) is not used. Use NULL. + Data is unpacked to (spec->decoder.decoder.dic) output buffer. +*/ + +static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, + // int *wasFinished, + ECoderStatus *status) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp; + ELzmaStatus status2; + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ + SRes res; + UNUSED_VAR(srcWasFinished); + if (spec->outBufMode) + { + SizeT dicPos = spec->decoder.decoder.dicPos; + SizeT dicLimit = dicPos + *destLen; + res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + *destLen = spec->decoder.decoder.dicPos - dicPos; + } + else + res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2); + // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK); + // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder + *status = (ECoderStatus)status2; + return res; +} + + +static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if (!spec) + { + spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec)); + if (!spec) + return SZ_ERROR_MEM; + p->p = spec; + p->Free = Lzma2State_Free; + p->SetProps = Lzma2State_SetProps; + p->Init = Lzma2State_Init; + p->Code2 = Lzma2State_Code2; + p->Filter = NULL; + Lzma2Dec_Construct(&spec->decoder); + } + spec->outBufMode = False; + if (outBuf) + { + spec->outBufMode = True; + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + +static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize) +{ + CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; + if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf)) + return SZ_ERROR_FAIL; + if (outBuf) + { + spec->decoder.decoder.dic = outBuf; + spec->decoder.decoder.dicBufSize = outBufSize; + } + return SZ_OK; +} + + + +static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc) +{ + unsigned i; + p->alloc = alloc; + p->buf = NULL; + p->numCoders = 0; + + p->outBufSize = 0; + p->outBuf = NULL; + // p->SingleBufMode = False; + + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + p->coders[i].p = NULL; +} + + +static void MixCoder_Free(CMixCoder *p) +{ + unsigned i; + p->numCoders = 0; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + { + IStateCoder *sc = &p->coders[i]; + if (sc->p) + { + sc->Free(sc->p, p->alloc); + sc->p = NULL; + } + } + if (p->buf) + { + ISzAlloc_Free(p->alloc, p->buf); + p->buf = NULL; /* 9.31: the BUG was fixed */ + } +} + +static void MixCoder_Init(CMixCoder *p) +{ + unsigned i; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++) + { + p->size[i] = 0; + p->pos[i] = 0; + p->finished[i] = 0; + } + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + coder->Init(coder->p); + p->results[i] = SZ_OK; + } + p->outWritten = 0; + p->wasFinished = False; + p->res = SZ_OK; + p->status = CODER_STATUS_NOT_SPECIFIED; +} + + +static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + p->ids[coderIndex] = methodId; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); + #ifdef USE_SUBBLOCK + case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); + #endif + } + if (coderIndex == 0) + return SZ_ERROR_UNSUPPORTED; + return BraState_SetFromMethod(sc, methodId, 0, p->alloc); +} + + +static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) +{ + IStateCoder *sc = &p->coders[coderIndex]; + switch (methodId) + { + case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize); + } + return SZ_ERROR_UNSUPPORTED; +} + + + +/* + if (destFinish) - then unpack data block is finished at (*destLen) position, + and we can return data that were not processed by filter + +output (status) can be : + CODER_STATUS_NOT_FINISHED + CODER_STATUS_FINISHED_WITH_MARK + CODER_STATUS_NEEDS_MORE_INPUT - not implemented still +*/ + +static SRes MixCoder_Code(CMixCoder *p, + Byte *dest, SizeT *destLen, int destFinish, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + + *destLen = 0; + *srcLen = 0; + + if (p->wasFinished) + return p->res; + + p->status = CODER_STATUS_NOT_FINISHED; + + // if (p->SingleBufMode) + if (p->outBuf) + { + SRes res; + SizeT destLen2, srcLen2; + int wasFinished; + + PRF_STR("------- MixCoder Single ----------"); + + srcLen2 = srcLenOrig; + destLen2 = destLenOrig; + + { + IStateCoder *coder = &p->coders[0]; + res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, + // &wasFinished, + &p->status); + wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); + } + + p->res = res; + + /* + if (wasFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + else + { + if (res == SZ_OK) + if (destLen2 != destLenOrig) + p->status = CODER_STATUS_NEEDS_MORE_INPUT; + } + */ + + + *srcLen = srcLen2; + src += srcLen2; + p->outWritten += destLen2; + + if (res != SZ_OK || srcWasFinished || wasFinished) + p->wasFinished = True; + + if (p->numCoders == 1) + *destLen = destLen2; + else if (p->wasFinished) + { + unsigned i; + size_t processed = p->outWritten; + + for (i = 1; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + processed = coder->Filter(coder->p, p->outBuf, processed); + if (wasFinished || (destFinish && p->outWritten == destLenOrig)) + processed = p->outWritten; + PRF_STR_INT("filter", i); + } + *destLen = processed; + } + return res; + } + + PRF_STR("standard mix"); + + if (p->numCoders != 1) + { + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + if (!p->buf) + return SZ_ERROR_MEM; + } + + finishMode = CODER_FINISH_ANY; + } + + for (;;) + { + BoolInt processed = False; + BoolInt allFinished = True; + SRes resMain = SZ_OK; + unsigned i; + + p->status = CODER_STATUS_NOT_FINISHED; + /* + if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) + break; + */ + + for (i = 0; i < p->numCoders; i++) + { + SRes res; + IStateCoder *coder = &p->coders[i]; + Byte *dest2; + SizeT destLen2, srcLen2; // destLen2_Orig; + const Byte *src2; + int srcFinished2; + int encodingWasFinished; + ECoderStatus status2; + + if (i == 0) + { + src2 = src; + srcLen2 = srcLenOrig - *srcLen; + srcFinished2 = srcWasFinished; + } + else + { + size_t k = i - 1; + src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; + srcLen2 = p->size[k] - p->pos[k]; + srcFinished2 = p->finished[k]; + } + + if (i == p->numCoders - 1) + { + dest2 = dest; + destLen2 = destLenOrig - *destLen; + } + else + { + if (p->pos[i] != p->size[i]) + continue; + dest2 = p->buf + (CODER_BUF_SIZE * i); + destLen2 = CODER_BUF_SIZE; + } + + // destLen2_Orig = destLen2; + + if (p->results[i] != SZ_OK) + { + if (resMain == SZ_OK) + resMain = p->results[i]; + continue; + } + + res = coder->Code2(coder->p, + dest2, &destLen2, + src2, &srcLen2, srcFinished2, + finishMode, + // &encodingWasFinished, + &status2); + + if (res != SZ_OK) + { + p->results[i] = res; + if (resMain == SZ_OK) + resMain = res; + } + + encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); + + if (!encodingWasFinished) + { + allFinished = False; + if (p->numCoders == 1 && res == SZ_OK) + p->status = status2; + } + + if (i == 0) + { + *srcLen += srcLen2; + src += srcLen2; + } + else + p->pos[(size_t)i - 1] += srcLen2; + + if (i == p->numCoders - 1) + { + *destLen += destLen2; + dest += destLen2; + } + else + { + p->size[i] = destLen2; + p->pos[i] = 0; + p->finished[i] = encodingWasFinished; + } + + if (destLen2 != 0 || srcLen2 != 0) + processed = True; + } + + if (!processed) + { + if (allFinished) + p->status = CODER_STATUS_FINISHED_WITH_MARK; + return resMain; + } + } +} + + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) +{ + *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); + if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != + GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) + return SZ_ERROR_NO_ARCHIVE; + return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) +{ + return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) + && GetUi32(buf) == CrcCalc(buf + 4, 6) + && flags == GetBe16(buf + 8) + && buf[10] == XZ_FOOTER_SIG_0 + && buf[11] == XZ_FOOTER_SIG_1; +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + + +static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p) +{ + unsigned numFilters = XzBlock_GetNumFilters(p) - 1; + unsigned i; + { + const CXzFilter *f = &p->filters[numFilters]; + if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) + return False; + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + if (f->id == XZ_ID_Delta) + { + if (f->propsSize != 1) + return False; + } + else if (f->id < XZ_ID_Delta + || f->id > XZ_ID_SPARC + || (f->propsSize != 0 && f->propsSize != 4)) + return False; + } + return True; +} + + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header) +{ + unsigned pos; + unsigned numFilters, i; + unsigned headerSize = (unsigned)header[0] << 2; + + /* (headerSize != 0) : another code checks */ + + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) + return SZ_ERROR_ARCHIVE; + + pos = 1; + p->flags = header[pos++]; + + p->packSize = (UInt64)(Int64)-1; + if (XzBlock_HasPackSize(p)) + { + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize); + if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) + return SZ_ERROR_ARCHIVE; + } + + p->unpackSize = (UInt64)(Int64)-1; + if (XzBlock_HasUnpackSize(p)) + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize); + + numFilters = XzBlock_GetNumFilters(p); + for (i = 0; i < numFilters; i++) + { + CXzFilter *filter = p->filters + i; + UInt64 size; + READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id); + READ_VARINT_AND_CHECK(header, pos, headerSize, &size); + if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) + return SZ_ERROR_ARCHIVE; + filter->propsSize = (UInt32)size; + memcpy(filter->props, header + pos, (size_t)size); + pos += (unsigned)size; + + #ifdef XZ_DUMP + printf("\nf[%u] = %2X: ", i, (unsigned)filter->id); + { + unsigned i; + for (i = 0; i < size; i++) + printf(" %2X", filter->props[i]); + } + #endif + } + + if (XzBlock_HasUnsupportedFlags(p)) + return SZ_ERROR_UNSUPPORTED; + + while (pos < headerSize) + if (header[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return SZ_OK; +} + + + + +static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) +{ + unsigned i; + BoolInt needReInit = True; + unsigned numFilters = XzBlock_GetNumFilters(block); + + if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) + { + needReInit = False; + for (i = 0; i < numFilters; i++) + if (p->ids[i] != block->filters[numFilters - 1 - i].id) + { + needReInit = True; + break; + } + } + + // p->SingleBufMode = (outBuf != NULL); + p->outBuf = outBuf; + p->outBufSize = outBufSize; + + // p->SingleBufMode = False; + // outBuf = NULL; + + if (needReInit) + { + MixCoder_Free(p); + for (i = 0; i < numFilters; i++) + { + RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)); + } + p->numCoders = numFilters; + } + else + { + RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)); + } + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + IStateCoder *sc = &p->coders[i]; + RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); + } + + MixCoder_Init(p); + return SZ_OK; +} + + + +void XzUnpacker_Init(CXzUnpacker *p) +{ + p->state = XZ_STATE_STREAM_HEADER; + p->pos = 0; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; + p->decodeOnlyOneBlock = 0; + + p->parseMode = False; + p->decodeToStreamSignature = False; + + // p->outBuf = NULL; + // p->outBufSize = 0; + p->outDataWritten = 0; +} + + +void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) +{ + p->outBuf = outBuf; + p->outBufSize = outBufSize; +} + + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + p->outBuf = NULL; + p->outBufSize = 0; + XzUnpacker_Init(p); +} + + +void XzUnpacker_Free(CXzUnpacker *p) +{ + MixCoder_Free(&p->decoder); +} + + +void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p) +{ + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + p->decodeOnlyOneBlock = 1; +} + + +static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize) +{ + Byte temp[32]; + unsigned num = Xz_WriteVarInt(temp, packSize); + num += Xz_WriteVarInt(temp + num, unpackSize); + Sha256_Update(&p->sha, temp, num); + p->indexSize += num; + p->numBlocks++; +} + + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcFinished, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + for (;;) + { + SizeT srcRem; + + if (p->state == XZ_STATE_BLOCK) + { + SizeT destLen2 = destLenOrig - *destLen; + SizeT srcLen2 = srcLenOrig - *srcLen; + SRes res; + + ECoderFinishMode finishMode2 = finishMode; + BoolInt srcFinished2 = srcFinished; + BoolInt destFinish = False; + + if (p->block.packSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.packSize - p->packSize; + if (srcLen2 >= rem) + { + srcFinished2 = True; + srcLen2 = (SizeT)rem; + } + if (rem == 0 && p->block.unpackSize == p->unpackSize) + return SZ_ERROR_DATA; + } + + if (p->block.unpackSize != (UInt64)(Int64)-1) + { + UInt64 rem = p->block.unpackSize - p->unpackSize; + if (destLen2 >= rem) + { + destFinish = True; + finishMode2 = CODER_FINISH_END; + destLen2 = (SizeT)rem; + } + } + + /* + if (srcLen2 == 0 && destLen2 == 0) + { + *status = CODER_STATUS_NOT_FINISHED; + return SZ_OK; + } + */ + + { + res = MixCoder_Code(&p->decoder, + (p->outBuf ? NULL : dest), &destLen2, destFinish, + src, &srcLen2, srcFinished2, + finishMode2); + + *status = p->decoder.status; + XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); + if (!p->outBuf) + dest += destLen2; + p->outDataWritten += destLen2; + } + + (*srcLen) += srcLen2; + src += srcLen2; + p->packSize += srcLen2; + (*destLen) += destLen2; + p->unpackSize += destLen2; + + RINOK(res); + + if (*status != CODER_STATUS_FINISHED_WITH_MARK) + { + if (p->block.packSize == p->packSize + && *status == CODER_STATUS_NEEDS_MORE_INPUT) + { + PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT"); + *status = CODER_STATUS_NOT_SPECIFIED; + return SZ_ERROR_DATA; + } + + return SZ_OK; + } + { + XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); + p->state = XZ_STATE_BLOCK_FOOTER; + p->pos = 0; + p->alignPos = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + + if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) + || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) + { + PRF_STR("ERROR: block.size mismatch"); + return SZ_ERROR_DATA; + } + } + // continue; + } + + srcRem = srcLenOrig - *srcLen; + + // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes + if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + switch (p->state) + { + case XZ_STATE_STREAM_HEADER: + { + if (p->pos < XZ_STREAM_HEADER_SIZE) + { + if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) + return SZ_ERROR_NO_ARCHIVE; + if (p->decodeToStreamSignature) + return SZ_OK; + p->buf[p->pos++] = *src++; + (*srcLen)++; + } + else + { + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->numStartedStreams++; + p->indexSize = 0; + p->numBlocks = 0; + Sha256_Init(&p->sha); + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + } + break; + } + + case XZ_STATE_BLOCK_HEADER: + { + if (p->pos == 0) + { + p->buf[p->pos++] = *src++; + (*srcLen)++; + if (p->buf[0] == 0) + { + if (p->decodeOnlyOneBlock) + return SZ_ERROR_DATA; + p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); + p->indexPos = p->indexPreSize; + p->indexSize += p->indexPreSize; + Sha256_Final(&p->sha, p->shaDigest); + Sha256_Init(&p->sha); + p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); + p->state = XZ_STATE_STREAM_INDEX; + break; + } + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; + break; + } + + if (p->pos != p->blockHeaderSize) + { + UInt32 cur = p->blockHeaderSize - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + RINOK(XzBlock_Parse(&p->block, p->buf)); + if (!XzBlock_AreSupportedFilters(&p->block)) + return SZ_ERROR_UNSUPPORTED; + p->numTotalBlocks++; + p->state = XZ_STATE_BLOCK; + p->packSize = 0; + p->unpackSize = 0; + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); + if (p->parseMode) + { + p->headerParsedOk = True; + return SZ_OK; + } + RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)); + } + break; + } + + case XZ_STATE_BLOCK_FOOTER: + { + if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->alignPos++; + if (*src++ != 0) + return SZ_ERROR_CRC; + } + else + { + UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); + UInt32 cur = checkSize - p->pos; + if (cur != 0) + { + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (checkSize != p->pos) + break; + } + { + Byte digest[XZ_CHECK_SIZE_MAX]; + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) + return SZ_ERROR_CRC; + if (p->decodeOnlyOneBlock) + { + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + } + } + } + break; + } + + case XZ_STATE_STREAM_INDEX: + { + if (p->pos < p->indexPreSize) + { + (*srcLen)++; + if (*src++ != p->buf[p->pos++]) + return SZ_ERROR_CRC; + } + else + { + if (p->indexPos < p->indexSize) + { + UInt64 cur = p->indexSize - p->indexPos; + if (srcRem > cur) + srcRem = (SizeT)cur; + p->crc = CrcUpdate(p->crc, src, srcRem); + Sha256_Update(&p->sha, src, srcRem); + (*srcLen) += srcRem; + src += srcRem; + p->indexPos += srcRem; + } + else if ((p->indexPos & 3) != 0) + { + Byte b = *src++; + p->crc = CRC_UPDATE_BYTE(p->crc, b); + (*srcLen)++; + p->indexPos++; + p->indexSize++; + if (b != 0) + return SZ_ERROR_CRC; + } + else + { + Byte digest[SHA256_DIGEST_SIZE]; + p->state = XZ_STATE_STREAM_INDEX_CRC; + p->indexSize += 4; + p->pos = 0; + Sha256_Final(&p->sha, digest); + if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) + return SZ_ERROR_CRC; + } + } + break; + } + + case XZ_STATE_STREAM_INDEX_CRC: + { + if (p->pos < 4) + { + (*srcLen)++; + p->buf[p->pos++] = *src++; + } + else + { + const Byte *ptr = p->buf; + p->state = XZ_STATE_STREAM_FOOTER; + p->pos = 0; + if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_FOOTER: + { + UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (p->pos == XZ_STREAM_FOOTER_SIZE) + { + p->state = XZ_STATE_STREAM_PADDING; + p->numFinishedStreams++; + p->padSize = 0; + if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_PADDING: + { + if (*src != 0) + { + if (((UInt32)p->padSize & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + p->pos = 0; + p->state = XZ_STATE_STREAM_HEADER; + } + else + { + (*srcLen)++; + src++; + p->padSize++; + } + break; + } + + case XZ_STATE_BLOCK: break; /* to disable GCC warning */ + } + } + /* + if (p->state == XZ_STATE_FINISHED) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + */ +} + + +SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + XzUnpacker_Init(p); + XzUnpacker_SetOutBuf(p, dest, *destLen); + + return XzUnpacker_Code(p, + NULL, destLen, + src, srcLen, True, + finishMode, status); +} + + +BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); +} + +BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) +{ + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); +} + +UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num = p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num = p->padSize + p->pos; + return num; +} + + + + + + + + + + + + + + + + + + + + + +#ifndef _7ZIP_ST +#include "MtDec.h" +#endif + + +void XzDecMtProps_Init(CXzDecMtProps *p) +{ + p->inBufSize_ST = 1 << 18; + p->outStep_ST = 1 << 20; + p->ignoreErrors = False; + + #ifndef _7ZIP_ST + p->numThreads = 1; + p->inBufSize_MT = 1 << 18; + p->memUseMax = sizeof(size_t) << 28; + #endif +} + + + +#ifndef _7ZIP_ST + +/* ---------- CXzDecMtThread ---------- */ + +typedef struct +{ + Byte *outBuf; + size_t outBufSize; + size_t outPreSize; + size_t inPreSize; + size_t inPreHeaderSize; + size_t blockPackSize_for_Index; // including block header and checksum. + size_t blockPackTotal; // including stream header, block header and checksum. + size_t inCodeSize; + size_t outCodeSize; + ECoderStatus status; + SRes codeRes; + BoolInt skipMode; + // BoolInt finishedWithMark; + EMtDecParseState parseState; + BoolInt parsing_Truncated; + BoolInt atBlockHeader; + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + BoolInt dec_created; + CXzUnpacker dec; + + Byte mtPad[1 << 7]; +} CXzDecMtThread; + +#endif + + +/* ---------- CXzDecMt ---------- */ + +typedef struct +{ + CAlignOffsetAlloc alignOffsetAlloc; + ISzAllocPtr allocMid; + + CXzDecMtProps props; + size_t unpackBlockMaxSize; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + + BoolInt finishMode; + BoolInt outSize_Defined; + UInt64 outSize; + + UInt64 outProcessed; + UInt64 inProcessed; + UInt64 readProcessed; + BoolInt readWasFinished; + SRes readRes; + SRes writeRes; + + Byte *outBuf; + size_t outBufSize; + Byte *inBuf; + size_t inBufSize; + + CXzUnpacker dec; + + ECoderStatus status; + SRes codeRes; + + #ifndef _7ZIP_ST + BoolInt mainDecoderWasCalled; + // int statErrorDefined; + int finishedDecoderIndex; + + // global values that are used in Parse stage + CXzStreamFlags streamFlags; + // UInt64 numFinishedStreams + UInt64 numStreams; + UInt64 numTotalBlocks; + UInt64 numBlocks; + + // UInt64 numBadBlocks; + SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage + // it can be = SZ_ERROR_INPUT_EOF + // it can be = SZ_ERROR_DATA, in some another cases + BoolInt isBlockHeaderState_Parse; + BoolInt isBlockHeaderState_Write; + UInt64 outProcessed_Parse; + BoolInt parsing_Truncated; + + BoolInt mtc_WasConstructed; + CMtDec mtc; + CXzDecMtThread coders[MTDEC__THREADS_MAX]; + #endif + +} CXzDecMt; + + + +CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) +{ + CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt)); + if (!p) + return NULL; + + AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); + p->alignOffsetAlloc.baseAlloc = alloc; + p->alignOffsetAlloc.numAlignBits = 7; + p->alignOffsetAlloc.offset = 0; + + p->allocMid = allocMid; + + p->outBuf = NULL; + p->outBufSize = 0; + p->inBuf = NULL; + p->inBufSize = 0; + + XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); + + p->unpackBlockMaxSize = 0; + + XzDecMtProps_Init(&p->props); + + #ifndef _7ZIP_ST + p->mtc_WasConstructed = False; + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + coder->dec_created = False; + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + #endif + + return p; +} + + +#ifndef _7ZIP_ST + +static void XzDecMt_FreeOutBufs(CXzDecMt *p) +{ + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *coder = &p->coders[i]; + if (coder->outBuf) + { + ISzAlloc_Free(p->allocMid, coder->outBuf); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + } + p->unpackBlockMaxSize = 0; +} + +#endif + + + +static void XzDecMt_FreeSt(CXzDecMt *p) +{ + XzUnpacker_Free(&p->dec); + + if (p->outBuf) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBuf = NULL; + } + p->outBufSize = 0; + + if (p->inBuf) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBuf = NULL; + } + p->inBufSize = 0; +} + + +void XzDecMt_Destroy(CXzDecMtHandle pp) +{ + CXzDecMt *p = (CXzDecMt *)pp; + + XzDecMt_FreeSt(p); + + #ifndef _7ZIP_ST + + if (p->mtc_WasConstructed) + { + MtDec_Destruct(&p->mtc); + p->mtc_WasConstructed = False; + } + { + unsigned i; + for (i = 0; i < MTDEC__THREADS_MAX; i++) + { + CXzDecMtThread *t = &p->coders[i]; + if (t->dec_created) + { + // we don't need to free dict here + XzUnpacker_Free(&t->dec); + t->dec_created = False; + } + } + } + XzDecMt_FreeOutBufs(p); + + #endif + + ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); +} + + + +#ifndef _7ZIP_ST + +static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) +{ + CXzDecMt *me = (CXzDecMt *)obj; + CXzDecMtThread *coder = &me->coders[coderIndex]; + size_t srcSize = cc->srcSize; + + cc->srcSize = 0; + cc->outPos = 0; + cc->state = MTDEC_PARSE_CONTINUE; + + cc->canCreateNewThread = True; + + if (cc->startCall) + { + coder->outPreSize = 0; + coder->inPreSize = 0; + coder->inPreHeaderSize = 0; + coder->parseState = MTDEC_PARSE_CONTINUE; + coder->parsing_Truncated = False; + coder->skipMode = False; + coder->codeRes = SZ_OK; + coder->status = CODER_STATUS_NOT_SPECIFIED; + coder->inCodeSize = 0; + coder->outCodeSize = 0; + + coder->numStreams = me->numStreams; + coder->numTotalBlocks = me->numTotalBlocks; + coder->numBlocks = me->numBlocks; + + if (!coder->dec_created) + { + XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); + coder->dec_created = True; + } + + XzUnpacker_Init(&coder->dec); + + if (me->isBlockHeaderState_Parse) + { + coder->dec.streamFlags = me->streamFlags; + coder->atBlockHeader = True; + XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); + } + else + { + coder->atBlockHeader = False; + me->isBlockHeaderState_Parse = True; + } + + coder->dec.numStartedStreams = me->numStreams; + coder->dec.numTotalBlocks = me->numTotalBlocks; + coder->dec.numBlocks = me->numBlocks; + } + + while (!coder->skipMode) + { + ECoderStatus status; + SRes res; + size_t srcSize2 = srcSize; + size_t destSize = (size_t)0 - 1; + + coder->dec.parseMode = True; + coder->dec.headerParsedOk = False; + + PRF_STR_INT("Parse", srcSize2); + + res = XzUnpacker_Code(&coder->dec, + NULL, &destSize, + cc->src, &srcSize2, cc->srcFinished, + CODER_FINISH_END, &status); + + // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); + + coder->codeRes = res; + coder->status = status; + cc->srcSize += srcSize2; + srcSize -= srcSize2; + coder->inPreHeaderSize += srcSize2; + coder->inPreSize = coder->inPreHeaderSize; + + if (res != SZ_OK) + { + cc->state = + coder->parseState = MTDEC_PARSE_END; + /* + if (res == SZ_ERROR_MEM) + return res; + return SZ_OK; + */ + return; // res; + } + + if (coder->dec.headerParsedOk) + { + const CXzBlock *block = &coder->dec.block; + if (XzBlock_HasUnpackSize(block) + // && block->unpackSize <= me->props.outBlockMax + && XzBlock_HasPackSize(block)) + { + { + if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) + { + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + } + { + UInt64 packSize = block->packSize; + UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); + UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); + UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; + // if (blockPackSum <= me->props.inBlockMax) + // unpackBlockMaxSize + { + coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); + coder->blockPackTotal = (size_t)blockPackSum; + coder->outPreSize = (size_t)block->unpackSize; + coder->streamFlags = coder->dec.streamFlags; + me->streamFlags = coder->dec.streamFlags; + coder->skipMode = True; + break; + } + } + } + } + else + // if (coder->inPreSize <= me->props.inBlockMax) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = + coder->parseState = MTDEC_PARSE_END; + return; // SZ_OK; + } + cc->state = MTDEC_PARSE_OVERFLOW; + return; // SZ_OK; + } + + // ---------- skipMode ---------- + { + UInt64 rem = coder->blockPackTotal - coder->inPreSize; + size_t cur = srcSize; + if (cur > rem) + cur = (size_t)rem; + cc->srcSize += cur; + coder->inPreSize += cur; + srcSize -= cur; + + if (coder->inPreSize == coder->blockPackTotal) + { + if (srcSize == 0) + { + if (!cc->srcFinished) + return; // SZ_OK; + cc->state = MTDEC_PARSE_END; + } + else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block + cc->state = MTDEC_PARSE_END; + else + { + cc->state = MTDEC_PARSE_NEW; + + { + size_t blockMax = me->unpackBlockMaxSize; + if (blockMax < coder->outPreSize) + blockMax = coder->outPreSize; + { + UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; + if (me->props.memUseMax < required) + cc->canCreateNewThread = False; + } + } + + if (me->outSize_Defined) + { + // next block can be zero size + const UInt64 rem2 = me->outSize - me->outProcessed_Parse; + if (rem2 < coder->outPreSize) + { + coder->parsing_Truncated = True; + cc->state = MTDEC_PARSE_END; + } + me->outProcessed_Parse += coder->outPreSize; + } + } + } + else if (cc->srcFinished) + cc->state = MTDEC_PARSE_END; + else + return; // SZ_OK; + + coder->parseState = cc->state; + cc->outPos = coder->outPreSize; + + me->numStreams = coder->dec.numStartedStreams; + me->numTotalBlocks = coder->dec.numTotalBlocks; + me->numBlocks = coder->dec.numBlocks + 1; + return; // SZ_OK; + } +} + + +static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + Byte *dest; + + if (!coder->dec.headerParsedOk) + return SZ_OK; + + dest = coder->outBuf; + + if (!dest || coder->outBufSize < coder->outPreSize) + { + if (dest) + { + ISzAlloc_Free(me->allocMid, dest); + coder->outBuf = NULL; + coder->outBufSize = 0; + } + { + size_t outPreSize = coder->outPreSize; + if (outPreSize == 0) + outPreSize = 1; + dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); + } + if (!dest) + return SZ_ERROR_MEM; + coder->outBuf = dest; + coder->outBufSize = coder->outPreSize; + + if (coder->outBufSize > me->unpackBlockMaxSize) + me->unpackBlockMaxSize = coder->outBufSize; + } + + // return SZ_ERROR_MEM; + + XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); + + { + SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); + // res = SZ_ERROR_UNSUPPORTED; // to test + coder->codeRes = res; + if (res != SZ_OK) + { + // if (res == SZ_ERROR_MEM) return res; + if (me->props.ignoreErrors && res != SZ_ERROR_MEM) + return SZ_OK; + return res; + } + } + + return SZ_OK; +} + + +static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, + const Byte *src, size_t srcSize, int srcFinished, + // int finished, int blockFinished, + UInt64 *inCodePos, UInt64 *outCodePos, int *stop) +{ + CXzDecMt *me = (CXzDecMt *)pp; + CXzDecMtThread *coder = &me->coders[coderIndex]; + + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + *stop = True; + + if (srcSize > coder->inPreSize - coder->inCodeSize) + return SZ_ERROR_FAIL; + + if (coder->inCodeSize < coder->inPreHeaderSize) + { + size_t step = coder->inPreHeaderSize - coder->inCodeSize; + if (step > srcSize) + step = srcSize; + src += step; + srcSize -= step; + coder->inCodeSize += step; + *inCodePos = coder->inCodeSize; + if (coder->inCodeSize < coder->inPreHeaderSize) + { + *stop = False; + return SZ_OK; + } + } + + if (!coder->dec.headerParsedOk) + return SZ_OK; + if (!coder->outBuf) + return SZ_OK; + + if (coder->codeRes == SZ_OK) + { + ECoderStatus status; + SRes res; + size_t srcProcessed = srcSize; + size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; + + // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); + + res = XzUnpacker_Code(&coder->dec, + NULL, &outSizeCur, + src, &srcProcessed, srcFinished, + // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, + CODER_FINISH_END, + &status); + + // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); + + coder->codeRes = res; + coder->status = status; + coder->inCodeSize += srcProcessed; + coder->outCodeSize = coder->dec.outDataWritten; + *inCodePos = coder->inCodeSize; + *outCodePos = coder->outCodeSize; + + if (res == SZ_OK) + { + if (srcProcessed == srcSize) + *stop = False; + return SZ_OK; + } + } + + if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) + { + *inCodePos = coder->inPreSize; + *outCodePos = coder->outPreSize; + return SZ_OK; + } + return coder->codeRes; +} + + +#define XZDECMT_STREAM_WRITE_STEP (1 << 24) + +static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, + BoolInt needWriteToStream, + const Byte *src, size_t srcSize, BoolInt isCross, + // int srcFinished, + BoolInt *needContinue, + BoolInt *canRecode) +{ + CXzDecMt *me = (CXzDecMt *)pp; + const CXzDecMtThread *coder = &me->coders[coderIndex]; + + // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); + + *needContinue = False; + *canRecode = True; + + if (!needWriteToStream) + return SZ_OK; + + if (!coder->dec.headerParsedOk || !coder->outBuf) + { + if (me->finishedDecoderIndex < 0) + me->finishedDecoderIndex = (int)coderIndex; + return SZ_OK; + } + + if (me->finishedDecoderIndex >= 0) + return SZ_OK; + + me->mtc.inProcessed += coder->inCodeSize; + + *canRecode = False; + + { + SRes res; + size_t size = coder->outCodeSize; + Byte *data = coder->outBuf; + + // we use in me->dec: sha, numBlocks, indexSize + + if (!me->isBlockHeaderState_Write) + { + XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); + me->dec.decodeOnlyOneBlock = False; + me->dec.numStartedStreams = coder->dec.numStartedStreams; + me->dec.streamFlags = coder->streamFlags; + + me->isBlockHeaderState_Write = True; + } + + me->dec.numTotalBlocks = coder->dec.numTotalBlocks; + XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); + + if (coder->outPreSize != size) + { + if (me->props.ignoreErrors) + { + memset(data + size, 0, coder->outPreSize - size); + size = coder->outPreSize; + } + // me->numBadBlocks++; + if (me->mainErrorCode == SZ_OK) + { + if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) + me->mainErrorCode = SZ_ERROR_INPUT_EOF; + else + me->mainErrorCode = SZ_ERROR_DATA; + } + } + + if (me->writeRes != SZ_OK) + return me->writeRes; + + res = SZ_OK; + { + if (me->outSize_Defined) + { + const UInt64 rem = me->outSize - me->outProcessed; + if (size > rem) + size = (SizeT)rem; + } + + for (;;) + { + size_t cur = size; + size_t written; + if (cur > XZDECMT_STREAM_WRITE_STEP) + cur = XZDECMT_STREAM_WRITE_STEP; + + written = ISeqOutStream_Write(me->outStream, data, cur); + + // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); + + me->outProcessed += written; + if (written != cur) + { + me->writeRes = SZ_ERROR_WRITE; + res = me->writeRes; + break; + } + data += cur; + size -= cur; + // PRF_STR_INT("Written size =", size); + if (size == 0) + break; + res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); + if (res != SZ_OK) + break; + } + } + + if (coder->codeRes != SZ_OK) + if (!me->props.ignoreErrors) + { + me->finishedDecoderIndex = (int)coderIndex; + return res; + } + + RINOK(res); + + if (coder->inPreSize != coder->inCodeSize + || coder->blockPackTotal != coder->inCodeSize) + { + me->finishedDecoderIndex = (int)coderIndex; + return SZ_OK; + } + + if (coder->parseState != MTDEC_PARSE_END) + { + *needContinue = True; + return SZ_OK; + } + } + + // (coder->state == MTDEC_PARSE_END) means that there are no other working threads + // so we can use mtc variables without lock + + PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed); + + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + { + CXzUnpacker *dec = &me->dec; + + PRF_STR_INT("PostSingle", srcSize); + + { + size_t srcProcessed = srcSize; + ECoderStatus status; + size_t outSizeCur = 0; + SRes res; + + // dec->decodeOnlyOneBlock = False; + dec->decodeToStreamSignature = True; + + me->mainDecoderWasCalled = True; + + if (coder->parsing_Truncated) + { + me->parsing_Truncated = True; + return SZ_OK; + } + + /* + We have processed all xz-blocks of stream, + And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where + (src) is a pointer to xz-Index structure. + We finish reading of current xz-Stream, including Zero padding after xz-Stream. + We exit, if we reach extra byte (first byte of new-Stream or another data). + But we don't update input stream pointer for that new extra byte. + If extra byte is not correct first byte of xz-signature, + we have SZ_ERROR_NO_ARCHIVE error here. + */ + + res = XzUnpacker_Code(dec, + NULL, &outSizeCur, + src, &srcProcessed, + me->mtc.readWasFinished, // srcFinished + CODER_FINISH_END, // CODER_FINISH_ANY, + &status); + + // res = SZ_ERROR_ARCHIVE; // for failure test + + me->status = status; + me->codeRes = res; + + if (isCross) + me->mtc.crossStart += srcProcessed; + + me->mtc.inProcessed += srcProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + srcSize -= srcProcessed; + src += srcProcessed; + + if (res != SZ_OK) + { + return SZ_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + + if (!isCross) + { + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + if (srcSize != 0) + memcpy(crossBuf, src, srcSize); + me->mtc.crossStart = 0; + me->mtc.crossEnd = srcSize; + } + + PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd); + + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0) + { + return SZ_ERROR_FAIL; + } + + if (me->mtc.readWasFinished) + { + return SZ_OK; + } + } + + { + size_t inPos; + size_t inLim; + // const Byte *inData; + UInt64 inProgressPrev = me->mtc.inProcessed; + + // XzDecMt_Prepare_InBuf_ST(p); + Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); + if (!crossBuf) + return SZ_ERROR_MEM; + + inPos = 0; + inLim = 0; + + // inData = crossBuf; + + for (;;) + { + SizeT inProcessed; + SizeT outProcessed; + ECoderStatus status; + SRes res; + + if (inPos == inLim) + { + if (!me->mtc.readWasFinished) + { + inPos = 0; + inLim = me->mtc.inBufSize; + me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim); + me->mtc.readProcessed += inLim; + if (inLim == 0 || me->mtc.readRes != SZ_OK) + me->mtc.readWasFinished = True; + } + } + + inProcessed = inLim - inPos; + outProcessed = 0; + + res = XzUnpacker_Code(dec, + NULL, &outProcessed, + crossBuf + inPos, &inProcessed, + (inProcessed == 0), // srcFinished + CODER_FINISH_END, &status); + + me->codeRes = res; + me->status = status; + inPos += inProcessed; + me->mtc.inProcessed += inProcessed; + me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; + + if (res != SZ_OK) + { + return SZ_OK; + // return res; + } + + if (dec->state == XZ_STATE_STREAM_HEADER) + { + *needContinue = True; + me->mtc.crossStart = inPos; + me->mtc.crossEnd = inLim; + me->isBlockHeaderState_Parse = False; + me->isBlockHeaderState_Write = False; + return SZ_OK; + } + + if (status != CODER_STATUS_NEEDS_MORE_INPUT) + return SZ_ERROR_FAIL; + + if (me->mtc.progress) + { + UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; + if (inDelta >= (1 << 22)) + { + RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)); + inProgressPrev = me->mtc.inProcessed; + } + } + if (me->mtc.readWasFinished) + return SZ_OK; + } + } + } +} + + +#endif + + + +void XzStatInfo_Clear(CXzStatInfo *p) +{ + p->InSize = 0; + p->OutSize = 0; + + p->NumStreams = 0; + p->NumBlocks = 0; + + p->UnpackSize_Defined = False; + + p->NumStreams_Defined = False; + p->NumBlocks_Defined = False; + + p->DataAfterEnd = False; + p->DecodingTruncated = False; + + p->DecodeRes = SZ_OK; + p->ReadRes = SZ_OK; + p->ProgressRes = SZ_OK; + + p->CombinedRes = SZ_OK; + p->CombinedRes_Type = SZ_OK; +} + + + +/* + XzDecMt_Decode_ST() can return SZ_OK or the following errors + - SZ_ERROR_MEM for memory allocation error + - error from XzUnpacker_Code() function + - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case + - ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS. + But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors. + ISeqInStream::Read() result is set to p->readRes. + also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. +*/ + +static SRes XzDecMt_Decode_ST(CXzDecMt *p + #ifndef _7ZIP_ST + , BoolInt tMode + #endif + , CXzStatInfo *stat) +{ + size_t outPos; + size_t inPos, inLim; + const Byte *inData; + UInt64 inPrev, outPrev; + + CXzUnpacker *dec; + + #ifndef _7ZIP_ST + if (tMode) + { + XzDecMt_FreeOutBufs(p); + tMode = MtDec_PrepareRead(&p->mtc); + } + #endif + + if (!p->outBuf || p->outBufSize != p->props.outStep_ST) + { + ISzAlloc_Free(p->allocMid, p->outBuf); + p->outBufSize = 0; + p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); + if (!p->outBuf) + return SZ_ERROR_MEM; + p->outBufSize = p->props.outStep_ST; + } + + if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) + { + ISzAlloc_Free(p->allocMid, p->inBuf); + p->inBufSize = 0; + p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); + if (!p->inBuf) + return SZ_ERROR_MEM; + p->inBufSize = p->props.inBufSize_ST; + } + + dec = &p->dec; + dec->decodeToStreamSignature = False; + // dec->decodeOnlyOneBlock = False; + + XzUnpacker_SetOutBuf(dec, NULL, 0); + + inPrev = p->inProcessed; + outPrev = p->outProcessed; + + inPos = 0; + inLim = 0; + inData = NULL; + outPos = 0; + + for (;;) + { + SizeT outSize; + BoolInt finished; + ECoderFinishMode finishMode; + SizeT inProcessed; + ECoderStatus status; + SRes res; + + SizeT outProcessed; + + + + if (inPos == inLim) + { + #ifndef _7ZIP_ST + if (tMode) + { + inData = MtDec_Read(&p->mtc, &inLim); + inPos = 0; + if (inData) + continue; + tMode = False; + inLim = 0; + } + #endif + + if (!p->readWasFinished) + { + inPos = 0; + inLim = p->inBufSize; + inData = p->inBuf; + p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim); + p->readProcessed += inLim; + if (inLim == 0 || p->readRes != SZ_OK) + p->readWasFinished = True; + } + } + + outSize = p->props.outStep_ST - outPos; + + finishMode = CODER_FINISH_ANY; + if (p->outSize_Defined) + { + const UInt64 rem = p->outSize - p->outProcessed; + if (outSize >= rem) + { + outSize = (SizeT)rem; + if (p->finishMode) + finishMode = CODER_FINISH_END; + } + } + + inProcessed = inLim - inPos; + outProcessed = outSize; + + res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, + inData + inPos, &inProcessed, + (inPos == inLim), // srcFinished + finishMode, &status); + + p->codeRes = res; + p->status = status; + + inPos += inProcessed; + outPos += outProcessed; + p->inProcessed += inProcessed; + p->outProcessed += outProcessed; + + finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); + + if (finished || outProcessed >= outSize) + if (outPos != 0) + { + const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); + // p->outProcessed += written; // 21.01: BUG fixed + if (written != outPos) + { + stat->CombinedRes_Type = SZ_ERROR_WRITE; + return SZ_ERROR_WRITE; + } + outPos = 0; + } + + if (p->progress && res == SZ_OK) + { + if (p->inProcessed - inPrev >= (1 << 22) || + p->outProcessed - outPrev >= (1 << 22)) + { + res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); + if (res != SZ_OK) + { + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + stat->ProgressRes = res; + return res; + } + inPrev = p->inProcessed; + outPrev = p->outProcessed; + } + } + + if (finished) + { + // p->codeRes is preliminary error from XzUnpacker_Code. + // and it can be corrected later as final result + // so we return SZ_OK here instead of (res); + return SZ_OK; + // return res; + } + } +} + + + +/* +XzStatInfo_SetStat() transforms + CXzUnpacker return code and status to combined CXzStatInfo results. + it can convert SZ_OK to SZ_ERROR_INPUT_EOF + it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1) +*/ + +static void XzStatInfo_SetStat(const CXzUnpacker *dec, + int finishMode, + // UInt64 readProcessed, + UInt64 inProcessed, + SRes res, // it's result from CXzUnpacker unpacker + ECoderStatus status, + BoolInt decodingTruncated, + CXzStatInfo *stat) +{ + UInt64 extraSize; + + stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); + stat->InSize = inProcessed; + stat->NumStreams = dec->numStartedStreams; + stat->NumBlocks = dec->numTotalBlocks; + + stat->UnpackSize_Defined = True; + stat->NumStreams_Defined = True; + stat->NumBlocks_Defined = True; + + extraSize = XzUnpacker_GetExtraSize(dec); + + if (res == SZ_OK) + { + if (status == CODER_STATUS_NEEDS_MORE_INPUT) + { + // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams + // any extra data is part of correct data + extraSize = 0; + // if xz stream was not finished, then we need more data + if (!XzUnpacker_IsStreamWasFinished(dec)) + res = SZ_ERROR_INPUT_EOF; + } + else + { + // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding + // so he we have (status == CODER_STATUS_NOT_FINISHED) + // if (status != CODER_STATUS_FINISHED_WITH_MARK) + if (!decodingTruncated || finishMode) + res = SZ_ERROR_DATA; + } + } + else if (res == SZ_ERROR_NO_ARCHIVE) + { + /* + SZ_ERROR_NO_ARCHIVE is possible for 2 states: + XZ_STATE_STREAM_HEADER - if bad signature or bad CRC + XZ_STATE_STREAM_PADDING - if non-zero padding data + extraSize and inProcessed don't include "bad" byte + */ + // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error + if (inProcessed != extraSize) // if there were good xz streams before error + { + // if (extraSize != 0 || readProcessed != inProcessed) + { + // he we suppose that all xz streams were finsihed OK, and we have + // some extra data after all streams + stat->DataAfterEnd = True; + res = SZ_OK; + } + } + } + + if (stat->DecodeRes == SZ_OK) + stat->DecodeRes = res; + + stat->InSize -= extraSize; +} + + + +SRes XzDecMt_Decode(CXzDecMtHandle pp, + const CXzDecMtProps *props, + const UInt64 *outDataSize, int finishMode, + ISeqOutStream *outStream, + // Byte *outBuf, size_t *outBufSize, + ISeqInStream *inStream, + // const Byte *inData, size_t inDataSize, + CXzStatInfo *stat, + int *isMT, + ICompressProgress *progress) +{ + CXzDecMt *p = (CXzDecMt *)pp; + #ifndef _7ZIP_ST + BoolInt tMode; + #endif + + XzStatInfo_Clear(stat); + + p->props = *props; + + p->inStream = inStream; + p->outStream = outStream; + p->progress = progress; + // p->stat = stat; + + p->outSize = 0; + p->outSize_Defined = False; + if (outDataSize) + { + p->outSize_Defined = True; + p->outSize = *outDataSize; + } + + p->finishMode = finishMode; + + // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test + + p->writeRes = SZ_OK; + p->outProcessed = 0; + p->inProcessed = 0; + p->readProcessed = 0; + p->readWasFinished = False; + p->readRes = SZ_OK; + + p->codeRes = SZ_OK; + p->status = CODER_STATUS_NOT_SPECIFIED; + + XzUnpacker_Init(&p->dec); + + *isMT = False; + + /* + p->outBuf = NULL; + p->outBufSize = 0; + if (!outStream) + { + p->outBuf = outBuf; + p->outBufSize = *outBufSize; + *outBufSize = 0; + } + */ + + + #ifndef _7ZIP_ST + + p->isBlockHeaderState_Parse = False; + p->isBlockHeaderState_Write = False; + // p->numBadBlocks = 0; + p->mainErrorCode = SZ_OK; + p->mainDecoderWasCalled = False; + + tMode = False; + + if (p->props.numThreads > 1) + { + IMtDecCallback2 vt; + BoolInt needContinue; + SRes res; + // we just free ST buffers here + // but we still keep state variables, that was set in XzUnpacker_Init() + XzDecMt_FreeSt(p); + + p->outProcessed_Parse = 0; + p->parsing_Truncated = False; + + p->numStreams = 0; + p->numTotalBlocks = 0; + p->numBlocks = 0; + p->finishedDecoderIndex = -1; + + if (!p->mtc_WasConstructed) + { + p->mtc_WasConstructed = True; + MtDec_Construct(&p->mtc); + } + + p->mtc.mtCallback = &vt; + p->mtc.mtCallbackObject = p; + + p->mtc.progress = progress; + p->mtc.inStream = inStream; + p->mtc.alloc = &p->alignOffsetAlloc.vt; + // p->mtc.inData = inData; + // p->mtc.inDataSize = inDataSize; + p->mtc.inBufSize = p->props.inBufSize_MT; + // p->mtc.inBlockMax = p->props.inBlockMax; + p->mtc.numThreadsMax = p->props.numThreads; + + *isMT = True; + + vt.Parse = XzDecMt_Callback_Parse; + vt.PreCode = XzDecMt_Callback_PreCode; + vt.Code = XzDecMt_Callback_Code; + vt.Write = XzDecMt_Callback_Write; + + + res = MtDec_Code(&p->mtc); + + + stat->InSize = p->mtc.inProcessed; + + p->inProcessed = p->mtc.inProcessed; + p->readRes = p->mtc.readRes; + p->readWasFinished = p->mtc.readWasFinished; + p->readProcessed = p->mtc.readProcessed; + + tMode = True; + needContinue = False; + + if (res == SZ_OK) + { + if (p->mtc.mtProgress.res != SZ_OK) + { + res = p->mtc.mtProgress.res; + stat->ProgressRes = res; + stat->CombinedRes_Type = SZ_ERROR_PROGRESS; + } + else + needContinue = p->mtc.needContinue; + } + + if (!needContinue) + { + { + SRes codeRes; + BoolInt truncated = False; + ECoderStatus status; + const CXzUnpacker *dec; + + stat->OutSize = p->outProcessed; + + if (p->finishedDecoderIndex >= 0) + { + const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; + codeRes = coder->codeRes; + dec = &coder->dec; + status = coder->status; + } + else if (p->mainDecoderWasCalled) + { + codeRes = p->codeRes; + dec = &p->dec; + status = p->status; + truncated = p->parsing_Truncated; + } + else + return SZ_ERROR_FAIL; + + if (p->mainErrorCode != SZ_OK) + stat->DecodeRes = p->mainErrorCode; + + XzStatInfo_SetStat(dec, p->finishMode, + // p->mtc.readProcessed, + p->mtc.inProcessed, + codeRes, status, + truncated, + stat); + } + + if (res == SZ_OK) + { + stat->ReadRes = p->mtc.readRes; + + if (p->writeRes != SZ_OK) + { + res = p->writeRes; + stat->CombinedRes_Type = SZ_ERROR_WRITE; + } + else if (p->mtc.readRes != SZ_OK + // && p->mtc.inProcessed == p->mtc.readProcessed + && stat->DecodeRes == SZ_ERROR_INPUT_EOF) + { + res = p->mtc.readRes; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + else if (stat->DecodeRes != SZ_OK) + res = stat->DecodeRes; + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } + + PRF_STR("----- decoding ST -----"); + } + + #endif + + + *isMT = False; + + { + SRes res = XzDecMt_Decode_ST(p + #ifndef _7ZIP_ST + , tMode + #endif + , stat + ); + + #ifndef _7ZIP_ST + // we must set error code from MT decoding at first + if (p->mainErrorCode != SZ_OK) + stat->DecodeRes = p->mainErrorCode; + #endif + + XzStatInfo_SetStat(&p->dec, + p->finishMode, + // p->readProcessed, + p->inProcessed, + p->codeRes, p->status, + False, // truncated + stat); + + stat->ReadRes = p->readRes; + + if (res == SZ_OK) + { + if (p->readRes != SZ_OK + // && p->inProcessed == p->readProcessed + && stat->DecodeRes == SZ_ERROR_INPUT_EOF) + { + // we set read error as combined error, only if that error was the reason + // of decoding problem + res = p->readRes; + stat->CombinedRes_Type = SZ_ERROR_READ; + } + else if (stat->DecodeRes != SZ_OK) + res = stat->DecodeRes; + } + + stat->CombinedRes = res; + if (stat->CombinedRes_Type == SZ_OK) + stat->CombinedRes_Type = res; + return res; + } +} diff --git a/3rdparty/lzma-21.03beta/C/XzEnc.c b/3rdparty/lzma-21.03beta/C/XzEnc.c new file mode 100644 index 0000000..be174cc --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzEnc.c @@ -0,0 +1,1330 @@ +/* XzEnc.c -- Xz Encode +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "7zCrc.h" +#include "Bra.h" +#include "CpuArch.h" + +#ifdef USE_SUBBLOCK +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" +#endif + +#include "XzEnc.h" + +// #define _7ZIP_ST + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define MTCODER__THREADS_MAX 1 +#define MTCODER__BLOCKS_MAX 1 +#endif + +#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) + +/* max pack size for LZMA2 block + check-64bytrs: */ +#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64) + +#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) + + +#define XzBlock_ClearFlags(p) (p)->flags = 0; +#define XzBlock_SetNumFilters(p, n) (p)->flags = (Byte)((p)->flags | ((n) - 1)); +#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; +#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; + + +static SRes WriteBytes(ISeqOutStream *s, const void *buf, size_t size) +{ + return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; +} + +static SRes WriteBytesUpdateCrc(ISeqOutStream *s, const void *buf, size_t size, UInt32 *crc) +{ + *crc = CrcUpdate(*crc, buf, size); + return WriteBytes(s, buf, size); +} + + +static SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s) +{ + UInt32 crc; + Byte header[XZ_STREAM_HEADER_SIZE]; + memcpy(header, XZ_SIG, XZ_SIG_SIZE); + header[XZ_SIG_SIZE] = (Byte)(f >> 8); + header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF); + crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE); + SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc); + return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); +} + + +static SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + + unsigned pos = 1; + unsigned numFilters, i; + header[pos++] = p->flags; + + if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); + if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); + numFilters = XzBlock_GetNumFilters(p); + + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + pos += Xz_WriteVarInt(header + pos, f->id); + pos += Xz_WriteVarInt(header + pos, f->propsSize); + memcpy(header + pos, f->props, f->propsSize); + pos += f->propsSize; + } + + while ((pos & 3) != 0) + header[pos++] = 0; + + header[0] = (Byte)(pos >> 2); + SetUi32(header + pos, CrcCalc(header, pos)); + return WriteBytes(s, header, pos + 4); +} + + + + +typedef struct +{ + size_t numBlocks; + size_t size; + size_t allocated; + Byte *blocks; +} CXzEncIndex; + + +static void XzEncIndex_Construct(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; + p->blocks = NULL; +} + +static void XzEncIndex_Init(CXzEncIndex *p) +{ + p->numBlocks = 0; + p->size = 0; +} + +static void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc) +{ + if (p->blocks) + { + ISzAlloc_Free(alloc, p->blocks); + p->blocks = NULL; + } + p->numBlocks = 0; + p->size = 0; + p->allocated = 0; +} + + +static SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc) +{ + Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize); + if (!blocks) + return SZ_ERROR_MEM; + if (p->size != 0) + memcpy(blocks, p->blocks, p->size); + if (p->blocks) + ISzAlloc_Free(alloc, p->blocks); + p->blocks = blocks; + p->allocated = newSize; + return SZ_OK; +} + + +static SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + UInt64 pos; + { + Byte buf[32]; + unsigned pos2 = Xz_WriteVarInt(buf, totalSize); + pos2 += Xz_WriteVarInt(buf + pos2, unpackSize); + pos = numBlocks * pos2; + } + + if (pos <= p->allocated - p->size) + return SZ_OK; + { + UInt64 newSize64 = p->size + pos; + size_t newSize = (size_t)newSize64; + if (newSize != newSize64) + return SZ_ERROR_MEM; + return XzEncIndex_ReAlloc(p, newSize, alloc); + } +} + + +static SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc) +{ + Byte buf[32]; + unsigned pos = Xz_WriteVarInt(buf, totalSize); + pos += Xz_WriteVarInt(buf + pos, unpackSize); + + if (pos > p->allocated - p->size) + { + size_t newSize = p->allocated * 2 + 16 * 2; + if (newSize < p->size + pos) + return SZ_ERROR_MEM; + RINOK(XzEncIndex_ReAlloc(p, newSize, alloc)); + } + memcpy(p->blocks + p->size, buf, pos); + p->size += pos; + p->numBlocks++; + return SZ_OK; +} + + +static SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStream *s) +{ + Byte buf[32]; + UInt64 globalPos; + UInt32 crc = CRC_INIT_VAL; + unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); + + globalPos = pos; + buf[0] = 0; + RINOK(WriteBytesUpdateCrc(s, buf, pos, &crc)); + RINOK(WriteBytesUpdateCrc(s, p->blocks, p->size, &crc)); + globalPos += p->size; + + pos = XZ_GET_PAD_SIZE(globalPos); + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + globalPos += pos; + + crc = CrcUpdate(crc, buf + 4 - pos, pos); + SetUi32(buf + 4, CRC_GET_DIGEST(crc)); + + SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2)); + buf[8 + 8] = (Byte)(flags >> 8); + buf[8 + 9] = (Byte)(flags & 0xFF); + SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6)); + buf[8 + 10] = XZ_FOOTER_SIG_0; + buf[8 + 11] = XZ_FOOTER_SIG_1; + + return WriteBytes(s, buf + 4 - pos, pos + 4 + 12); +} + + + +/* ---------- CSeqCheckInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *realStream; + const Byte *data; + UInt64 limit; + UInt64 processed; + int realStreamFinished; + CXzCheck check; +} CSeqCheckInStream; + +static void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode) +{ + p->limit = (UInt64)(Int64)-1; + p->processed = 0; + p->realStreamFinished = 0; + XzCheck_Init(&p->check, checkMode); +} + +static void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) +{ + XzCheck_Final(&p->check, digest); +} + +static SRes SeqCheckInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSeqCheckInStream *p = CONTAINER_FROM_VTBL(pp, CSeqCheckInStream, vt); + size_t size2 = *size; + SRes res = SZ_OK; + + if (p->limit != (UInt64)(Int64)-1) + { + UInt64 rem = p->limit - p->processed; + if (size2 > rem) + size2 = (size_t)rem; + } + if (size2 != 0) + { + if (p->realStream) + { + res = ISeqInStream_Read(p->realStream, data, &size2); + p->realStreamFinished = (size2 == 0) ? 1 : 0; + } + else + memcpy(data, p->data + (size_t)p->processed, size2); + XzCheck_Update(&p->check, data, size2); + p->processed += size2; + } + *size = size2; + return res; +} + + +/* ---------- CSeqSizeOutStream ---------- */ + +typedef struct +{ + ISeqOutStream vt; + ISeqOutStream *realStream; + Byte *outBuf; + size_t outBufLimit; + UInt64 processed; +} CSeqSizeOutStream; + +static size_t SeqSizeOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CSeqSizeOutStream *p = CONTAINER_FROM_VTBL(pp, CSeqSizeOutStream, vt); + if (p->realStream) + size = ISeqOutStream_Write(p->realStream, data, size); + else + { + if (size > p->outBufLimit - (size_t)p->processed) + return 0; + memcpy(p->outBuf + (size_t)p->processed, data, size); + } + p->processed += size; + return size; +} + + +/* ---------- CSeqInFilter ---------- */ + +#define FILTER_BUF_SIZE (1 << 20) + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; +} CSeqInFilter; + + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc); + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc) +{ + if (!p->buf) + { + p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, alloc)); + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc)); + p->StateCoder.Init(p->StateCoder.p); + return SZ_OK; +} + + +static SRes SeqInFilter_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSeqInFilter *p = CONTAINER_FROM_VTBL(pp, CSeqInFilter, p); + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + *size = 0; + + for (;;) + { + if (!p->srcWasFinished && p->curPos == p->endPos) + { + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos)); + if (p->endPos == 0) + p->srcWasFinished = 1; + } + { + SizeT srcLen = p->endPos - p->curPos; + ECoderStatus status; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code2(p->StateCoder.p, + (Byte *)data, size, + p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, + &status); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != SZ_OK) + return res; + } + } +} + +static void SeqInFilter_Construct(CSeqInFilter *p) +{ + p->buf = NULL; + p->StateCoder.p = NULL; + p->p.Read = SeqInFilter_Read; +} + +static void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc) +{ + if (p->StateCoder.p) + { + p->StateCoder.Free(p->StateCoder.p, alloc); + p->StateCoder.p = NULL; + } + if (p->buf) + { + ISzAlloc_Free(alloc, p->buf); + p->buf = NULL; + } +} + + +/* ---------- CSbEncInStream ---------- */ + +#ifdef USE_SUBBLOCK + +typedef struct +{ + ISeqInStream vt; + ISeqInStream *inStream; + CSbEnc enc; +} CSbEncInStream; + +static SRes SbEncInStream_Read(const ISeqInStream *pp, void *data, size_t *size) +{ + CSbEncInStream *p = CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt); + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + + for (;;) + { + if (p->enc.needRead && !p->enc.readWasFinished) + { + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)); + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; + } + + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)); + if (*size != 0 || !p->enc.needRead) + return SZ_OK; + } +} + +void SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc) +{ + SbEnc_Construct(&p->enc, alloc); + p->vt.Read = SbEncInStream_Read; +} + +SRes SbEncInStream_Init(CSbEncInStream *p) +{ + return SbEnc_Init(&p->enc); +} + +void SbEncInStream_Free(CSbEncInStream *p) +{ + SbEnc_Free(&p->enc); +} + +#endif + + + +/* ---------- CXzProps ---------- */ + + +void XzFilterProps_Init(CXzFilterProps *p) +{ + p->id = 0; + p->delta = 0; + p->ip = 0; + p->ipDefined = False; +} + +void XzProps_Init(CXzProps *p) +{ + p->checkId = XZ_CHECK_CRC32; + p->blockSize = XZ_PROPS__BLOCK_SIZE__AUTO; + p->numBlockThreads_Reduced = -1; + p->numBlockThreads_Max = -1; + p->numTotalThreads = -1; + p->reduceSize = (UInt64)(Int64)-1; + p->forceWriteSizesInHeader = 0; + // p->forceWriteSizesInHeader = 1; + + XzFilterProps_Init(&p->filterProps); + Lzma2EncProps_Init(&p->lzma2Props); +} + + +static void XzEncProps_Normalize_Fixed(CXzProps *p) +{ + UInt64 fileSize; + int t1, t1n, t2, t2r, t3; + { + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + Lzma2EncProps_Normalize(&tp); + t1n = tp.numTotalThreads; + } + + t1 = p->lzma2Props.numTotalThreads; + t2 = p->numBlockThreads_Max; + t3 = p->numTotalThreads; + + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > MTCODER__THREADS_MAX) + t2 = MTCODER__THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzma2Props.numTotalThreads = t1; + + t2r = t2; + + fileSize = p->reduceSize; + + if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1)) + p->lzma2Props.lzmaProps.reduceSize = p->blockSize; + + Lzma2EncProps_Normalize(&p->lzma2Props); + + t1 = p->lzma2Props.numTotalThreads; + + { + if (t2 > 1 && fileSize != (UInt64)(Int64)-1) + { + UInt64 numBlocks = fileSize / p->blockSize; + if (numBlocks * p->blockSize != fileSize) + numBlocks++; + if (numBlocks < (unsigned)t2) + { + t2r = (int)numBlocks; + if (t2r == 0) + t2r = 1; + t3 = t1 * t2r; + } + } + } + + p->numBlockThreads_Max = t2; + p->numBlockThreads_Reduced = t2r; + p->numTotalThreads = t3; +} + + +static void XzProps_Normalize(CXzProps *p) +{ + /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties. + Lzma2Enc_SetProps() will normalize lzma2Props later. */ + + if (p->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID) + { + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + return; + } + else + { + CLzma2EncProps *lzma2 = &p->lzma2Props; + if (p->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + { + // xz-auto + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + { + // if (xz-auto && lzma2-solid) - we use solid for both + p->blockSize = XZ_PROPS__BLOCK_SIZE__SOLID; + p->numBlockThreads_Reduced = 1; + p->numBlockThreads_Max = 1; + if (p->lzma2Props.numTotalThreads <= 0) + p->lzma2Props.numTotalThreads = p->numTotalThreads; + } + else + { + // if (xz-auto && (lzma2-auto || lzma2-fixed_) + // we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block + CLzma2EncProps tp = p->lzma2Props; + if (tp.numTotalThreads <= 0) + tp.numTotalThreads = p->numTotalThreads; + + Lzma2EncProps_Normalize(&tp); + + p->blockSize = tp.blockSize; // fixed or solid + p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced; + p->numBlockThreads_Max = tp.numBlockThreads_Max; + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + lzma2->lzmaProps.reduceSize = tp.blockSize; + lzma2->numBlockThreads_Reduced = 1; + lzma2->numBlockThreads_Max = 1; + return; + } + } + else + { + // xz-fixed + // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize + + p->lzma2Props.lzmaProps.reduceSize = p->reduceSize; + { + UInt64 r = p->reduceSize; + if (r > p->blockSize || r == (UInt64)(Int64)-1) + r = p->blockSize; + lzma2->lzmaProps.reduceSize = r; + } + if (lzma2->blockSize == LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO) + lzma2->blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID) + lzma2->blockSize = p->blockSize; + + XzEncProps_Normalize_Fixed(p); + } + } +} + + +/* ---------- CLzma2WithFilters ---------- */ + +typedef struct +{ + CLzma2EncHandle lzma2; + CSeqInFilter filter; + + #ifdef USE_SUBBLOCK + CSbEncInStream sb; + #endif +} CLzma2WithFilters; + + +static void Lzma2WithFilters_Construct(CLzma2WithFilters *p) +{ + p->lzma2 = NULL; + SeqInFilter_Construct(&p->filter); + + #ifdef USE_SUBBLOCK + SbEncInStream_Construct(&p->sb, alloc); + #endif +} + + +static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc) +{ + if (!p->lzma2) + { + p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc); + if (!p->lzma2) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + + +static void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc) +{ + #ifdef USE_SUBBLOCK + SbEncInStream_Free(&p->sb); + #endif + + SeqInFilter_Free(&p->filter, alloc); + if (p->lzma2) + { + Lzma2Enc_Destroy(p->lzma2); + p->lzma2 = NULL; + } +} + + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; + size_t headerSize; +} CXzEncBlockInfo; + + +static SRes Xz_CompressBlock( + CLzma2WithFilters *lzmaf, + + ISeqOutStream *outStream, + Byte *outBufHeader, + Byte *outBufData, size_t outBufDataLimit, + + ISeqInStream *inStream, + // UInt64 expectedSize, + const Byte *inBuf, // used if (!inStream) + size_t inBufSize, // used if (!inStream), it's block size, props->blockSize is ignored + + const CXzProps *props, + ICompressProgress *progress, + int *inStreamFinished, /* only for inStream version */ + CXzEncBlockInfo *blockSizes, + ISzAllocPtr alloc, + ISzAllocPtr allocBig) +{ + CSeqCheckInStream checkInStream; + CSeqSizeOutStream seqSizeOutStream; + CXzBlock block; + unsigned filterIndex = 0; + CXzFilter *filter = NULL; + const CXzFilterProps *fp = &props->filterProps; + if (fp->id == 0) + fp = NULL; + + *inStreamFinished = False; + + RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig)); + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props)); + + XzBlock_ClearFlags(&block); + XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); + + if (fp) + { + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + Byte *ptr = filter->props; + SetUi32(ptr, fp->ip); + filter->propsSize = 4; + } + } + + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_LZMA2; + f->propsSize = 1; + f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); + } + + seqSizeOutStream.vt.Write = SeqSizeOutStream_Write; + seqSizeOutStream.realStream = outStream; + seqSizeOutStream.outBuf = outBufData; + seqSizeOutStream.outBufLimit = outBufDataLimit; + seqSizeOutStream.processed = 0; + + /* + if (expectedSize != (UInt64)(Int64)-1) + { + block.unpackSize = expectedSize; + if (props->blockSize != (UInt64)(Int64)-1) + if (expectedSize > props->blockSize) + block.unpackSize = props->blockSize; + XzBlock_SetHasUnpackSize(&block); + } + */ + + if (outStream) + { + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)); + } + + checkInStream.vt.Read = SeqCheckInStream_Read; + SeqCheckInStream_Init(&checkInStream, props->checkId); + + checkInStream.realStream = inStream; + checkInStream.data = inBuf; + checkInStream.limit = props->blockSize; + if (!inStream) + checkInStream.limit = inBufSize; + + if (fp) + { + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.vt; + RINOK(SbEncInStream_Init(&lzmaf->sb)); + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.vt; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc)); + } + } + + { + SRes res; + Byte *outBuf = NULL; + size_t outSize = 0; + BoolInt useStream = (fp || inStream); + // useStream = True; + + if (!useStream) + { + XzCheck_Update(&checkInStream.check, inBuf, inBufSize); + checkInStream.processed = inBufSize; + } + + if (!outStream) + { + outBuf = seqSizeOutStream.outBuf; // + (size_t)seqSizeOutStream.processed; + outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed; + } + + res = Lzma2Enc_Encode2(lzmaf->lzma2, + outBuf ? NULL : &seqSizeOutStream.vt, + outBuf, + outBuf ? &outSize : NULL, + + useStream ? + (fp ? + ( + #ifdef USE_SUBBLOCK + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt: + #endif + &lzmaf->filter.p) : + &checkInStream.vt) : NULL, + + useStream ? NULL : inBuf, + useStream ? 0 : inBufSize, + + progress); + + if (outBuf) + seqSizeOutStream.processed += outSize; + + RINOK(res); + blockSizes->unpackSize = checkInStream.processed; + } + { + Byte buf[4 + 64]; + unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); + UInt64 packSize = seqSizeOutStream.processed; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + + SeqCheckInStream_GetDigest(&checkInStream, buf + 4); + RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))); + + blockSizes->totalSize = seqSizeOutStream.processed - padSize; + + if (!outStream) + { + seqSizeOutStream.outBuf = outBufHeader; + seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX; + seqSizeOutStream.processed = 0; + + block.unpackSize = blockSizes->unpackSize; + XzBlock_SetHasUnpackSize(&block); + + block.packSize = packSize; + XzBlock_SetHasPackSize(&block); + + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt)); + + blockSizes->headerSize = (size_t)seqSizeOutStream.processed; + blockSizes->totalSize += seqSizeOutStream.processed; + } + } + + if (inStream) + *inStreamFinished = checkInStream.realStreamFinished; + else + { + *inStreamFinished = False; + if (checkInStream.processed != inBufSize) + return SZ_ERROR_FAIL; + } + + return SZ_OK; +} + + + +typedef struct +{ + ICompressProgress vt; + ICompressProgress *progress; + UInt64 inOffset; + UInt64 outOffset; +} CCompressProgress_XzEncOffset; + + +static SRes CompressProgress_XzEncOffset_Progress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) +{ + const CCompressProgress_XzEncOffset *p = CONTAINER_FROM_VTBL(pp, CCompressProgress_XzEncOffset, vt); + inSize += p->inOffset; + outSize += p->outOffset; + return ICompressProgress_Progress(p->progress, inSize, outSize); +} + + + + +typedef struct +{ + ISzAllocPtr alloc; + ISzAllocPtr allocBig; + + CXzProps xzProps; + UInt64 expectedDataSize; + + CXzEncIndex xzIndex; + + CLzma2WithFilters lzmaf_Items[MTCODER__THREADS_MAX]; + + size_t outBufSize; /* size of allocated outBufs[i] */ + Byte *outBufs[MTCODER__BLOCKS_MAX]; + + #ifndef _7ZIP_ST + unsigned checkType; + ISeqOutStream *outStream; + BoolInt mtCoder_WasConstructed; + CMtCoder mtCoder; + CXzEncBlockInfo EncBlocks[MTCODER__BLOCKS_MAX]; + #endif + +} CXzEnc; + + +static void XzEnc_Construct(CXzEnc *p) +{ + unsigned i; + + XzEncIndex_Construct(&p->xzIndex); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + Lzma2WithFilters_Construct(&p->lzmaf_Items[i]); + + #ifndef _7ZIP_ST + p->mtCoder_WasConstructed = False; + { + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + p->outBufs[i] = NULL; + p->outBufSize = 0; + } + #endif +} + + +static void XzEnc_FreeOutBufs(CXzEnc *p) +{ + unsigned i; + for (i = 0; i < MTCODER__BLOCKS_MAX; i++) + if (p->outBufs[i]) + { + ISzAlloc_Free(p->alloc, p->outBufs[i]); + p->outBufs[i] = NULL; + } + p->outBufSize = 0; +} + + +static void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc) +{ + unsigned i; + + XzEncIndex_Free(&p->xzIndex, alloc); + + for (i = 0; i < MTCODER__THREADS_MAX; i++) + Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc); + + #ifndef _7ZIP_ST + if (p->mtCoder_WasConstructed) + { + MtCoder_Destruct(&p->mtCoder); + p->mtCoder_WasConstructed = False; + } + XzEnc_FreeOutBufs(p); + #endif +} + + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc)); + if (!p) + return NULL; + XzEnc_Construct(p); + XzProps_Init(&p->xzProps); + XzProps_Normalize(&p->xzProps); + p->expectedDataSize = (UInt64)(Int64)-1; + p->alloc = alloc; + p->allocBig = allocBig; + return p; +} + + +void XzEnc_Destroy(CXzEncHandle pp) +{ + CXzEnc *p = (CXzEnc *)pp; + XzEnc_Free(p, p->alloc); + ISzAlloc_Free(p->alloc, p); +} + + +SRes XzEnc_SetProps(CXzEncHandle pp, const CXzProps *props) +{ + CXzEnc *p = (CXzEnc *)pp; + p->xzProps = *props; + XzProps_Normalize(&p->xzProps); + return SZ_OK; +} + + +void XzEnc_SetDataSize(CXzEncHandle pp, UInt64 expectedDataSiize) +{ + CXzEnc *p = (CXzEnc *)pp; + p->expectedDataSize = expectedDataSiize; +} + + + + +#ifndef _7ZIP_ST + +static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex, + const Byte *src, size_t srcSize, int finished) +{ + CXzEnc *me = (CXzEnc *)pp; + SRes res; + CMtProgressThunk progressThunk; + + Byte *dest = me->outBufs[outBufIndex]; + + UNUSED_VAR(finished) + + { + CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + bInfo->totalSize = 0; + bInfo->unpackSize = 0; + bInfo->headerSize = 0; + } + + if (!dest) + { + dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); + if (!dest) + return SZ_ERROR_MEM; + me->outBufs[outBufIndex] = dest; + } + + MtProgressThunk_CreateVTable(&progressThunk); + progressThunk.mtProgress = &me->mtCoder.mtProgress; + MtProgressThunk_Init(&progressThunk); + + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + res = Xz_CompressBlock( + &me->lzmaf_Items[coderIndex], + + NULL, + dest, + dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX, + + NULL, + // srcSize, // expectedSize + src, srcSize, + + &me->xzProps, + &progressThunk.vt, + &inStreamFinished, + &blockSizes, + me->alloc, + me->allocBig); + + if (res == SZ_OK) + me->EncBlocks[outBufIndex] = blockSizes; + + return res; + } +} + + +static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) +{ + CXzEnc *me = (CXzEnc *)pp; + + const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; + const Byte *data = me->outBufs[outBufIndex]; + + RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)); + + { + UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); + RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)); + } + + return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc); +} + +#endif + + + +SRes XzEnc_Encode(CXzEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + CXzEnc *p = (CXzEnc *)pp; + + const CXzProps *props = &p->xzProps; + + XzEncIndex_Init(&p->xzIndex); + { + UInt64 numBlocks = 1; + UInt64 blockSize = props->blockSize; + + if (blockSize != XZ_PROPS__BLOCK_SIZE__SOLID + && props->reduceSize != (UInt64)(Int64)-1) + { + numBlocks = props->reduceSize / blockSize; + if (numBlocks * blockSize != props->reduceSize) + numBlocks++; + } + else + blockSize = (UInt64)1 << 62; + + RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc)); + } + + RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream)); + + + #ifndef _7ZIP_ST + if (props->numBlockThreads_Reduced > 1) + { + IMtCoderCallback2 vt; + + if (!p->mtCoder_WasConstructed) + { + p->mtCoder_WasConstructed = True; + MtCoder_Construct(&p->mtCoder); + } + + vt.Code = XzEnc_MtCallback_Code; + vt.Write = XzEnc_MtCallback_Write; + + p->checkType = props->checkId; + p->xzProps = *props; + + p->outStream = outStream; + + p->mtCoder.allocBig = p->allocBig; + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.inData = NULL; + p->mtCoder.inDataSize = 0; + p->mtCoder.mtCallback = &vt; + p->mtCoder.mtCallbackObject = p; + + if ( props->blockSize == XZ_PROPS__BLOCK_SIZE__SOLID + || props->blockSize == XZ_PROPS__BLOCK_SIZE__AUTO) + return SZ_ERROR_FAIL; + + p->mtCoder.blockSize = (size_t)props->blockSize; + if (p->mtCoder.blockSize != props->blockSize) + return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */ + + { + size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize); + if (destBlockSize < p->mtCoder.blockSize) + return SZ_ERROR_PARAM; + if (p->outBufSize != destBlockSize) + XzEnc_FreeOutBufs(p); + p->outBufSize = destBlockSize; + } + + p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max; + p->mtCoder.expectedDataSize = p->expectedDataSize; + + RINOK(MtCoder_Code(&p->mtCoder)); + } + else + #endif + { + int writeStartSizes; + CCompressProgress_XzEncOffset progress2; + Byte *bufData = NULL; + size_t bufSize = 0; + + progress2.vt.Progress = CompressProgress_XzEncOffset_Progress; + progress2.inOffset = 0; + progress2.outOffset = 0; + progress2.progress = progress; + + writeStartSizes = 0; + + if (props->blockSize != XZ_PROPS__BLOCK_SIZE__SOLID) + { + writeStartSizes = (props->forceWriteSizesInHeader > 0); + + if (writeStartSizes) + { + size_t t2; + size_t t = (size_t)props->blockSize; + if (t != props->blockSize) + return SZ_ERROR_PARAM; + t = XZ_GET_MAX_BLOCK_PACK_SIZE(t); + if (t < props->blockSize) + return SZ_ERROR_PARAM; + t2 = XZ_BLOCK_HEADER_SIZE_MAX + t; + if (!p->outBufs[0] || t2 != p->outBufSize) + { + XzEnc_FreeOutBufs(p); + p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2); + if (!p->outBufs[0]) + return SZ_ERROR_MEM; + p->outBufSize = t2; + } + bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX; + bufSize = t; + } + } + + for (;;) + { + CXzEncBlockInfo blockSizes; + int inStreamFinished; + + /* + UInt64 rem = (UInt64)(Int64)-1; + if (props->reduceSize != (UInt64)(Int64)-1 + && props->reduceSize >= progress2.inOffset) + rem = props->reduceSize - progress2.inOffset; + */ + + blockSizes.headerSize = 0; // for GCC + + RINOK(Xz_CompressBlock( + &p->lzmaf_Items[0], + + writeStartSizes ? NULL : outStream, + writeStartSizes ? p->outBufs[0] : NULL, + bufData, bufSize, + + inStream, + // rem, + NULL, 0, + + props, + progress ? &progress2.vt : NULL, + &inStreamFinished, + &blockSizes, + p->alloc, + p->allocBig)); + + { + UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize); + + if (writeStartSizes) + { + RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize)); + RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize)); + } + + RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc)); + + progress2.inOffset += blockSizes.unpackSize; + progress2.outOffset += totalPackFull; + } + + if (inStreamFinished) + break; + } + } + + return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream); +} + + +#include "Alloc.h" + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + SRes res; + CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc); + if (!xz) + return SZ_ERROR_MEM; + res = XzEnc_SetProps(xz, props); + if (res == SZ_OK) + res = XzEnc_Encode(xz, outStream, inStream, progress); + XzEnc_Destroy(xz); + return res; +} + + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream) +{ + SRes res; + CXzEncIndex xzIndex; + XzEncIndex_Construct(&xzIndex); + res = Xz_WriteHeader((CXzStreamFlags)0, outStream); + if (res == SZ_OK) + res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream); + XzEncIndex_Free(&xzIndex, NULL); // g_Alloc + return res; +} diff --git a/3rdparty/lzma-21.03beta/C/XzEnc.h b/3rdparty/lzma-21.03beta/C/XzEnc.h new file mode 100644 index 0000000..0c29e7e --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzEnc.h @@ -0,0 +1,60 @@ +/* XzEnc.h -- Xz Encode +2017-06-27 : Igor Pavlov : Public domain */ + +#ifndef __XZ_ENC_H +#define __XZ_ENC_H + +#include "Lzma2Enc.h" + +#include "Xz.h" + +EXTERN_C_BEGIN + + +#define XZ_PROPS__BLOCK_SIZE__AUTO LZMA2_ENC_PROPS__BLOCK_SIZE__AUTO +#define XZ_PROPS__BLOCK_SIZE__SOLID LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID + + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + + +typedef struct +{ + CLzma2EncProps lzma2Props; + CXzFilterProps filterProps; + unsigned checkId; + UInt64 blockSize; + int numBlockThreads_Reduced; + int numBlockThreads_Max; + int numTotalThreads; + int forceWriteSizesInHeader; + UInt64 reduceSize; +} CXzProps; + +void XzProps_Init(CXzProps *p); + + +typedef void * CXzEncHandle; + +CXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig); +void XzEnc_Destroy(CXzEncHandle p); +SRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props); +void XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize); +SRes XzEnc_Encode(CXzEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress); + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress); + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream); + +EXTERN_C_END + +#endif diff --git a/3rdparty/lzma-21.03beta/C/XzIn.c b/3rdparty/lzma-21.03beta/C/XzIn.c new file mode 100644 index 0000000..bb6dbb9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/XzIn.c @@ -0,0 +1,324 @@ +/* XzIn.c - Xz input +2021-04-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" + +/* +#define XZ_FOOTER_SIG_CHECK(p) (memcmp((p), XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0) +*/ +#define XZ_FOOTER_SIG_CHECK(p) ((p)[0] == XZ_FOOTER_SIG_0 && (p)[1] == XZ_FOOTER_SIG_1) + + +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream) +{ + Byte sig[XZ_STREAM_HEADER_SIZE]; + RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + return Xz_ParseHeader(p, sig); +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, BoolInt *isIndex, UInt32 *headerSizeRes) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + unsigned headerSize; + *headerSizeRes = 0; + RINOK(SeqInStream_ReadByte(inStream, &header[0])); + headerSize = (unsigned)header[0]; + if (headerSize == 0) + { + *headerSizeRes = 1; + *isIndex = True; + return SZ_OK; + } + + *isIndex = False; + headerSize = (headerSize << 2) + 4; + *headerSizeRes = headerSize; + RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1)); + return XzBlock_Parse(p, header); +} + +#define ADD_SIZE_CHECK(size, val) \ + { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } + +UInt64 Xz_GetUnpackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECK(size, p->blocks[i].unpackSize); + return size; +} + +UInt64 Xz_GetPackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3); + return size; +} + +/* +SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream) +{ + return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); +} +*/ + +static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc) +{ + size_t numBlocks, pos = 1; + UInt32 crc; + + if (size < 5 || buf[0] != 0) + return SZ_ERROR_ARCHIVE; + + size -= 4; + crc = CrcCalc(buf, size); + if (crc != GetUi32(buf + size)) + return SZ_ERROR_ARCHIVE; + + { + UInt64 numBlocks64; + READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64); + numBlocks = (size_t)numBlocks64; + if (numBlocks != numBlocks64 || numBlocks * 2 > size) + return SZ_ERROR_ARCHIVE; + } + + Xz_Free(p, alloc); + if (numBlocks != 0) + { + size_t i; + p->numBlocks = numBlocks; + p->blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); + if (!p->blocks) + return SZ_ERROR_MEM; + for (i = 0; i < numBlocks; i++) + { + CXzBlockSizes *block = &p->blocks[i]; + READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize); + READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize); + if (block->totalSize == 0) + return SZ_ERROR_ARCHIVE; + } + } + while ((pos & 3) != 0) + if (buf[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAllocPtr alloc) +{ + SRes res; + size_t size; + Byte *buf; + if (indexSize > ((UInt32)1 << 31)) + return SZ_ERROR_UNSUPPORTED; + size = (size_t)indexSize; + if (size != indexSize) + return SZ_ERROR_UNSUPPORTED; + buf = (Byte *)ISzAlloc_Alloc(alloc, size); + if (!buf) + return SZ_ERROR_MEM; + res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); + if (res == SZ_OK) + res = Xz_ReadIndex2(p, buf, size, alloc); + ISzAlloc_Free(alloc, buf); + return res; +} + +static SRes LookInStream_SeekRead_ForArc(ILookInStream *stream, UInt64 offset, void *buf, size_t size) +{ + RINOK(LookInStream_SeekTo(stream, offset)); + return LookInStream_Read(stream, buf, size); + /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */ +} + +static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAllocPtr alloc) +{ + UInt64 indexSize; + Byte buf[XZ_STREAM_FOOTER_SIZE]; + UInt64 pos = (UInt64)*startOffset; + + if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); + + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + { + UInt32 total = 0; + pos += XZ_STREAM_FOOTER_SIZE; + + for (;;) + { + size_t i; + #define TEMP_BUF_SIZE (1 << 10) + Byte temp[TEMP_BUF_SIZE]; + + i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; + pos -= i; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)); + total += (UInt32)i; + for (; i != 0; i--) + if (temp[i - 1] != 0) + break; + if (i != 0) + { + if ((i & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + pos += i; + break; + } + if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) + return SZ_ERROR_NO_ARCHIVE; + } + + if (pos < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + pos -= XZ_STREAM_FOOTER_SIZE; + RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); + if (!XZ_FOOTER_SIG_CHECK(buf + 10)) + return SZ_ERROR_NO_ARCHIVE; + } + + p->flags = (CXzStreamFlags)GetBe16(buf + 8); + + if (!XzFlags_IsSupported(p->flags)) + return SZ_ERROR_UNSUPPORTED; + + { + /* to eliminate GCC 6.3 warning: + dereferencing type-punned pointer will break strict-aliasing rules */ + const Byte *buf_ptr = buf; + if (GetUi32(buf_ptr) != CrcCalc(buf + 4, 6)) + return SZ_ERROR_ARCHIVE; + } + + indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; + + if (pos < indexSize) + return SZ_ERROR_ARCHIVE; + + pos -= indexSize; + RINOK(LookInStream_SeekTo(stream, pos)); + RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); + + { + UInt64 totalSize = Xz_GetPackSize(p); + if (totalSize == XZ_SIZE_OVERFLOW + || totalSize >= ((UInt64)1 << 63) + || pos < totalSize + XZ_STREAM_HEADER_SIZE) + return SZ_ERROR_ARCHIVE; + pos -= (totalSize + XZ_STREAM_HEADER_SIZE); + RINOK(LookInStream_SeekTo(stream, pos)); + *startOffset = (Int64)pos; + } + { + CXzStreamFlags headerFlags; + CSecToRead secToRead; + SecToRead_CreateVTable(&secToRead); + secToRead.realStream = stream; + + RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)); + return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; + } +} + + +/* ---------- Xz Streams ---------- */ + +void Xzs_Construct(CXzs *p) +{ + p->num = p->numAllocated = 0; + p->streams = 0; +} + +void Xzs_Free(CXzs *p, ISzAllocPtr alloc) +{ + size_t i; + for (i = 0; i < p->num; i++) + Xz_Free(&p->streams[i], alloc); + ISzAlloc_Free(alloc, p->streams); + p->num = p->numAllocated = 0; + p->streams = 0; +} + +UInt64 Xzs_GetNumBlocks(const CXzs *p) +{ + UInt64 num = 0; + size_t i; + for (i = 0; i < p->num; i++) + num += p->streams[i].numBlocks; + return num; +} + +UInt64 Xzs_GetUnpackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i])); + return size; +} + +/* +UInt64 Xzs_GetPackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i])); + return size; +} +*/ + +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAllocPtr alloc) +{ + Int64 endOffset = 0; + RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END)); + *startOffset = endOffset; + for (;;) + { + CXzStream st; + SRes res; + Xz_Construct(&st); + res = Xz_ReadBackward(&st, stream, startOffset, alloc); + st.startOffset = (UInt64)*startOffset; + RINOK(res); + if (p->num == p->numAllocated) + { + const size_t newNum = p->num + p->num / 4 + 1; + void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream)); + if (!data) + return SZ_ERROR_MEM; + p->numAllocated = newNum; + if (p->num != 0) + memcpy(data, p->streams, p->num * sizeof(CXzStream)); + ISzAlloc_Free(alloc, p->streams); + p->streams = (CXzStream *)data; + } + p->streams[p->num++] = st; + if (*startOffset == 0) + break; + RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset)); + if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK) + return SZ_ERROR_PROGRESS; + } + return SZ_OK; +} diff --git a/3rdparty/lzma-21.03beta/C/var_clang.mak b/3rdparty/lzma-21.03beta/C/var_clang.mak new file mode 100644 index 0000000..a6df26e --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_clang.mak @@ -0,0 +1,11 @@ +PLATFORM= +O=b/c +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/var_clang_arm64.mak b/3rdparty/lzma-21.03beta/C/var_clang_arm64.mak new file mode 100644 index 0000000..4b35409 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_clang_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/var_clang_x64.mak b/3rdparty/lzma-21.03beta/C/var_clang_x64.mak new file mode 100644 index 0000000..34e1b49 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_clang_x64.mak @@ -0,0 +1,11 @@ +PLATFORM=x64 +O=b/c_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/var_clang_x86.mak b/3rdparty/lzma-21.03beta/C/var_clang_x86.mak new file mode 100644 index 0000000..bd2317c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_clang_x86.mak @@ -0,0 +1,11 @@ +PLATFORM=x86 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/var_gcc.mak b/3rdparty/lzma-21.03beta/C/var_gcc.mak new file mode 100644 index 0000000..664491c --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_gcc.mak @@ -0,0 +1,12 @@ +PLATFORM= +O=b/g +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/3rdparty/lzma-21.03beta/C/var_gcc_arm64.mak b/3rdparty/lzma-21.03beta/C/var_gcc_arm64.mak new file mode 100644 index 0000000..4bbb687 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_gcc_arm64.mak @@ -0,0 +1,12 @@ +PLATFORM=arm64 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-mtune=cortex-a53 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/3rdparty/lzma-21.03beta/C/var_gcc_x64.mak b/3rdparty/lzma-21.03beta/C/var_gcc_x64.mak new file mode 100644 index 0000000..1acf604 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_gcc_x64.mak @@ -0,0 +1,10 @@ +PLATFORM=x64 +O=b/g_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ diff --git a/3rdparty/lzma-21.03beta/C/var_gcc_x86.mak b/3rdparty/lzma-21.03beta/C/var_gcc_x86.mak new file mode 100644 index 0000000..f0718ec --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_gcc_x86.mak @@ -0,0 +1,10 @@ +PLATFORM=x86 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ diff --git a/3rdparty/lzma-21.03beta/C/var_mac_arm64.mak b/3rdparty/lzma-21.03beta/C/var_mac_arm64.mak new file mode 100644 index 0000000..adf5fa1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_mac_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/m_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-arch arm64 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/var_mac_x64.mak b/3rdparty/lzma-21.03beta/C/var_mac_x64.mak new file mode 100644 index 0000000..13d7aa7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/var_mac_x64.mak @@ -0,0 +1,11 @@ +PLATFORM=x64 +O=b/m_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-arch x86_64 +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/C/warn_clang.mak b/3rdparty/lzma-21.03beta/C/warn_clang.mak new file mode 100644 index 0000000..ed4f908 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/warn_clang.mak @@ -0,0 +1,37 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + +CFLAGS_WARN_1 = \ + -Wno-deprecated-copy-dtor \ + + + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_1) diff --git a/3rdparty/lzma-21.03beta/C/warn_clang_mac.mak b/3rdparty/lzma-21.03beta/C/warn_clang_mac.mak new file mode 100644 index 0000000..41044a2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/warn_clang_mac.mak @@ -0,0 +1,37 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + +CFLAGS_WARN_MAC = \ + -Wno-poison-system-directories \ + -Wno-c++11-long-long \ + -Wno-atomic-implicit-seq-cst \ + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_MAC) diff --git a/3rdparty/lzma-21.03beta/C/warn_gcc.mak b/3rdparty/lzma-21.03beta/C/warn_gcc.mak new file mode 100644 index 0000000..7aab7a4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/warn_gcc.mak @@ -0,0 +1,51 @@ +CFLAGS_WARN_GCC_4_5 = \ + +CFLAGS_WARN_GCC_6 = \ + -Waddress \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wcast-align \ + -Wcomment \ + -Wdiv-by-zero \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Winit-self \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + +# -Wno-strict-aliasing + +CFLAGS_WARN_GCC_9 = \ + -Waddress \ + -Waddress-of-packed-member \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wbool-operation \ + -Wcast-align \ + -Wcast-align=strict \ + -Wcomment \ + -Wdangling-else \ + -Wdiv-by-zero \ + -Wduplicated-branches \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Wimplicit-fallthrough=5 \ + -Winit-self \ + -Wint-in-bool-context \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + -Wconversion \ + +# -Wno-sign-conversion \ + +CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ + -Wno-strict-aliasing \ + + +CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) \ + +# $(CFLAGS_WARN_GCC_PPMD_UNALIGNED) diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/7zip.mak b/3rdparty/lzma-21.03beta/CPP/7zip/7zip.mak new file mode 100644 index 0000000..7fbe2ad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/7zip.mak @@ -0,0 +1,240 @@ +OBJS = \ + $O\StdAfx.obj \ + $(CURRENT_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(WIN_CTRL_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(AGENT_OBJS) \ + $(CONSOLE_OBJS) \ + $(EXPLORER_OBJS) \ + $(FM_OBJS) \ + $(GUI_OBJS) \ + $(7Z_OBJS) \ + $(CAB_OBJS) \ + $(CHM_OBJS) \ + $(COM_OBJS) \ + $(ISO_OBJS) \ + $(NSIS_OBJS) \ + $(RAR_OBJS) \ + $(TAR_OBJS) \ + $(UDF_OBJS) \ + $(WIM_OBJS) \ + $(ZIP_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(C_OBJS) \ + $(ASM_OBJS) \ + $O\resource.res \ + +!include "../../../Build.mak" + +# MAK_SINGLE_FILE = 1 + +!IFDEF MAK_SINGLE_FILE + +!IFDEF CURRENT_OBJS +$(CURRENT_OBJS): ./$(*B).cpp + $(COMPL) +!ENDIF + + +!IFDEF COMMON_OBJS +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIN_OBJS +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIN_CTRL_OBJS +$(WIN_CTRL_OBJS): ../../../Windows/Control/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF 7ZIP_COMMON_OBJS +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AR_OBJS +$(AR_OBJS): ../../Archive/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AR_COMMON_OBJS +$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF 7Z_OBJS +$(7Z_OBJS): ../../Archive/7z/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CAB_OBJS +$(CAB_OBJS): ../../Archive/Cab/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CHM_OBJS +$(CHM_OBJS): ../../Archive/Chm/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF COM_OBJS +$(COM_OBJS): ../../Archive/Com/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF ISO_OBJS +$(ISO_OBJS): ../../Archive/Iso/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF NSIS_OBJS +$(NSIS_OBJS): ../../Archive/Nsis/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF RAR_OBJS +$(RAR_OBJS): ../../Archive/Rar/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF TAR_OBJS +$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF UDF_OBJS +$(UDF_OBJS): ../../Archive/Udf/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF WIM_OBJS +$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF ZIP_OBJS +$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF COMPRESS_OBJS +$(COMPRESS_OBJS): ../../Compress/$(*B).cpp + $(COMPL_O2) +!ENDIF + +!IFDEF CRYPTO_OBJS +$(CRYPTO_OBJS): ../../Crypto/$(*B).cpp + $(COMPL_O2) +!ENDIF + +!IFDEF UI_COMMON_OBJS +$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF AGENT_OBJS +$(AGENT_OBJS): ../../UI/Agent/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF CONSOLE_OBJS +$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF EXPLORER_OBJS +$(EXPLORER_OBJS): ../../UI/Explorer/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF FM_OBJS +$(FM_OBJS): ../../UI/FileManager/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF GUI_OBJS +$(GUI_OBJS): ../../UI/GUI/$(*B).cpp + $(COMPL) +!ENDIF + +!IFDEF C_OBJS +$(C_OBJS): ../../../../C/$(*B).c + $(COMPL_O2) +!ENDIF + + +!ELSE + +{.}.cpp{$O}.obj:: + $(COMPLB) +{../../../Common}.cpp{$O}.obj:: + $(COMPLB) +{../../../Windows}.cpp{$O}.obj:: + $(COMPLB) +{../../../Windows/Control}.cpp{$O}.obj:: + $(COMPLB) +{../../Common}.cpp{$O}.obj:: + $(COMPLB) + +{../../UI/Common}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Agent}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Console}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/Explorer}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/FileManager}.cpp{$O}.obj:: + $(COMPLB) +{../../UI/GUI}.cpp{$O}.obj:: + $(COMPLB) + + +{../../Archive}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Common}.cpp{$O}.obj:: + $(COMPLB) + +{../../Archive/7z}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Cab}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Chm}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Com}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Iso}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Nsis}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Rar}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Tar}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Udf}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Wim}.cpp{$O}.obj:: + $(COMPLB) +{../../Archive/Zip}.cpp{$O}.obj:: + $(COMPLB) + +{../../Compress}.cpp{$O}.obj:: + $(COMPLB_O2) +{../../Crypto}.cpp{$O}.obj:: + $(COMPLB_O2) +{../../../../C}.c{$O}.obj:: + $(CCOMPLB) + +!ENDIF + +!include "Asm.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/7zip_gcc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/7zip_gcc.mak new file mode 100644 index 0000000..5907421 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/7zip_gcc.mak @@ -0,0 +1,1195 @@ +# USE_CLANG=1 +# USE_ASM = 1 +# IS_X64 = 1 +# MY_ARCH = +# USE_ASM= + +MY_ARCH_2 = $(MY_ARCH) + +MY_ASM = jwasm +MY_ASM = asmc + +PROGPATH = $(O)/$(PROG) + + +ifneq ($(CC), xlc) +CFLAGS_WARN_WALL = -Wall -Werror -Wextra +endif + +# for object file +CFLAGS_BASE_LIST = -c +# CFLAGS_BASE_LIST = -S +CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ + -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ + -fPIC + +# -D_7ZIP_AFFINITY_DISABLE + + +ifdef SystemDrive +IS_MINGW = 1 +endif + +ifdef IS_MINGW +LDFLAGS_STATIC_2 = -static +else +ifndef DEF_FILE +ifndef IS_NOT_STANDALONE +ifndef MY_DYNAMIC_LINK +ifneq ($(CC), clang) +LDFLAGS_STATIC_2 = +# -static +# -static-libstdc++ -static-libgcc +endif +endif +endif +endif +endif + +LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) + +ifndef O + ifdef IS_MINGW + O=_o + else + O=_o + endif +endif + + +ifdef DEF_FILE + + +ifdef IS_MINGW +SHARED_EXT=.dll +LDFLAGS = -shared -DEF $(DEF_FILE) $(LDFLAGS_STATIC) +else +SHARED_EXT=.so +LDFLAGS = -shared -fPIC $(LDFLAGS_STATIC) +CC_SHARED=-fPIC +endif + + +else + +LDFLAGS = $(LDFLAGS_STATIC) +# -s is not required for clang, do we need it for GGC ??? +# -s + +#-static -static-libgcc -static-libstdc++ + +ifdef IS_MINGW +SHARED_EXT=.exe +else +SHARED_EXT= +endif + +endif + + +PROGPATH = $(O)/$(PROG)$(SHARED_EXT) + + +ifdef IS_MINGW + +RM = del +MY_MKDIR=mkdir +LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 + +CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE +# -Wno-delete-non-virtual-dtor + +DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll + +else + +RM = rm -f +MY_MKDIR=mkdir -p +# CFLAGS_BASE := $(CFLAGS_BASE) -D_7ZIP_ST +# CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + +# LOCAL_LIBS=-lpthread +# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl +LIB2 = -lpthread -ldl + + + +DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(OBJS) + +endif + + + +CFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(CC_SHARED) -o $@ + + +ifdef IS_MINGW +AFLAGS_ABI = -coff -DABI_CDECL +AFLAGS = $(AFLAGS_ABI) -Fo$(O)/$(basename $( predef_cc_log +# $(CC) $(CFLAGS) -E -dM - < /dev/null +predef_cxx: + $(CXX) $(CFLAGS) -E $(SHOW_PREDEF) ../../../Common/CrcReg.cpp > predef_cxx_log + +predef: predef_cc predef_cxx + + +clean: + -$(DEL_OBJ_EXE) diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Aes.mak b/3rdparty/lzma-21.03beta/CPP/7zip/Aes.mak new file mode 100644 index 0000000..7d8da2d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Aes.mak @@ -0,0 +1,10 @@ +C_OBJS = $(C_OBJS) \ + $O\Aes.obj + +!IF defined(USE_C_AES) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ + $O\AesOpt.obj +!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +ASM_OBJS = $(ASM_OBJS) \ + $O\AesOpt.obj +!ENDIF diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.cpp new file mode 100644 index 0000000..6774fc4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.cpp @@ -0,0 +1,3 @@ +// CompressionMethod.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.h new file mode 100644 index 0000000..44c9022 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -0,0 +1,78 @@ +// 7zCompressionMode.h + +#ifndef __7Z_COMPRESSION_MODE_H +#define __7Z_COMPRESSION_MODE_H + +#include "../../Common/MethodId.h" +#include "../../Common/MethodProps.h" + +namespace NArchive { +namespace N7z { + +struct CMethodFull: public CMethodProps +{ + CMethodId Id; + UInt32 NumStreams; + int CodecIndex; + + CMethodFull(): CodecIndex(-1) {} + bool IsSimpleCoder() const { return NumStreams == 1; } +}; + +struct CBond2 +{ + UInt32 OutCoder; + UInt32 OutStream; + UInt32 InCoder; +}; + +struct CCompressionMethodMode +{ + /* + if (Bonds.Empty()), then default bonds must be created + if (Filter_was_Inserted) + { + Methods[0] is filter method + Bonds don't contain bonds for filter (these bonds must be created) + } + */ + + CObjectVector Methods; + CRecordVector Bonds; + + bool IsThereBond_to_Coder(unsigned coderIndex) const + { + FOR_VECTOR(i, Bonds) + if (Bonds[i].InCoder == coderIndex) + return true; + return false; + } + + bool DefaultMethod_was_Inserted; + bool Filter_was_Inserted; + + #ifndef _7ZIP_ST + UInt32 NumThreads; + bool MultiThreadMixer; + #endif + + bool PasswordIsDefined; + UString Password; // _Wipe + + bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } + CCompressionMethodMode(): + DefaultMethod_was_Inserted(false) + , Filter_was_Inserted(false) + #ifndef _7ZIP_ST + , NumThreads(1) + , MultiThreadMixer(true) + #endif + , PasswordIsDefined(false) + {} + + ~CCompressionMethodMode() { Password.Wipe_and_Empty(); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.cpp new file mode 100644 index 0000000..c27c8fb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.cpp @@ -0,0 +1,583 @@ +// 7zDecode.cpp + +#include "StdAfx.h" + +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "7zDecode.h" + +namespace NArchive { +namespace N7z { + +class CDecProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr _progress; +public: + CDecProgress(ICompressProgressInfo *progress): _progress(progress) {} + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize) +{ + return _progress->SetRatioInfo(NULL, outSize); +} + +static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi) +{ + bi.Clear(); + + bi.Bonds.ClearAndSetSize(folder.Bonds.Size()); + unsigned i; + for (i = 0; i < folder.Bonds.Size(); i++) + { + NCoderMixer2::CBond &bond = bi.Bonds[i]; + const N7z::CBond &folderBond = folder.Bonds[i]; + bond.PackIndex = folderBond.PackIndex; + bond.UnpackIndex = folderBond.UnpackIndex; + } + + bi.Coders.ClearAndSetSize(folder.Coders.Size()); + bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size()); + for (i = 0; i < folder.Coders.Size(); i++) + { + const CCoderInfo &coderInfo = folder.Coders[i]; + bi.Coders[i].NumStreams = coderInfo.NumStreams; + bi.CoderMethodIDs[i] = coderInfo.MethodID; + } + + /* + if (!bi.SetUnpackCoder()) + throw 1112; + */ + bi.UnpackCoder = folder.UnpackCoder; + bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size()); + for (i = 0; i < folder.PackStreams.Size(); i++) + bi.PackStreams[i] = folder.PackStreams[i]; +} + +static inline bool AreCodersEqual( + const NCoderMixer2::CCoderStreamsInfo &a1, + const NCoderMixer2::CCoderStreamsInfo &a2) +{ + return (a1.NumStreams == a2.NumStreams); +} + +static inline bool AreBondsEqual( + const NCoderMixer2::CBond &a1, + const NCoderMixer2::CBond &a2) +{ + return + (a1.PackIndex == a2.PackIndex) && + (a1.UnpackIndex == a2.UnpackIndex); +} + +static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) +{ + if (a1.Coders.Size() != a2.Coders.Size()) + return false; + unsigned i; + for (i = 0; i < a1.Coders.Size(); i++) + if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) + return false; + + if (a1.Bonds.Size() != a2.Bonds.Size()) + return false; + for (i = 0; i < a1.Bonds.Size(); i++) + if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i])) + return false; + + for (i = 0; i < a1.CoderMethodIDs.Size(); i++) + if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) + return false; + + if (a1.PackStreams.Size() != a2.PackStreams.Size()) + return false; + for (i = 0; i < a1.PackStreams.Size(); i++) + if (a1.PackStreams[i] != a2.PackStreams[i]) + return false; + + /* + if (a1.UnpackCoder != a2.UnpackCoder) + return false; + */ + return true; +} + +CDecoder::CDecoder(bool useMixerMT): + _bindInfoPrev_Defined(false), + _useMixerMT(useMixerMT) +{} + + +struct CLockedInStream: + public IUnknown, + public CMyUnknownImp +{ + CMyComPtr Stream; + UInt64 Pos; + + MY_UNKNOWN_IMP + + #ifdef USE_MIXER_MT + NWindows::NSynchronization::CCriticalSection CriticalSection; + #endif +}; + + +#ifdef USE_MIXER_MT + +class CLockedSequentialInStreamMT: + public ISequentialInStream, + public CMyUnknownImp +{ + CLockedInStream *_glob; + UInt64 _pos; + CMyComPtr _globRef; +public: + void Init(CLockedInStream *lockedInStream, UInt64 startPos) + { + _globRef = lockedInStream; + _glob = lockedInStream; + _pos = startPos; + } + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection); + + if (_pos != _glob->Pos) + { + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); + _glob->Pos = _pos; + } + + UInt32 realProcessedSize = 0; + HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); + _pos += realProcessedSize; + _glob->Pos = _pos; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} + +#endif + + +#ifdef USE_MIXER_ST + +class CLockedSequentialInStreamST: + public ISequentialInStream, + public CMyUnknownImp +{ + CLockedInStream *_glob; + UInt64 _pos; + CMyComPtr _globRef; +public: + void Init(CLockedInStream *lockedInStream, UInt64 startPos) + { + _globRef = lockedInStream; + _glob = lockedInStream; + _pos = startPos; + } + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (_pos != _glob->Pos) + { + RINOK(_glob->Stream->Seek((Int64)_pos, STREAM_SEEK_SET, NULL)); + _glob->Pos = _pos; + } + + UInt32 realProcessedSize = 0; + HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize); + _pos += realProcessedSize; + _glob->Pos = _pos; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} + +#endif + + + +HRESULT CDecoder::Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + UInt64 startPos, + const CFolders &folders, unsigned folderIndex, + const UInt64 *unpackSize + + , ISequentialOutStream *outStream + , ICompressProgressInfo *compressProgress + + , ISequentialInStream ** + #ifdef USE_MIXER_ST + inStreamMainRes + #endif + + , bool &dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS_DECL + + #if !defined(_7ZIP_ST) + , bool mtMode, UInt32 numThreads, UInt64 memUsage + #endif + ) +{ + dataAfterEnd_Error = false; + + const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]]; + CFolderEx folderInfo; + folders.ParseFolderEx(folderIndex, folderInfo); + + if (!folderInfo.IsDecodingSupported()) + return E_NOTIMPL; + + CBindInfoEx bindInfo; + Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo); + if (!bindInfo.CalcMapsAndCheck()) + return E_NOTIMPL; + + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex); + bool fullUnpack = true; + if (unpackSize) + { + if (*unpackSize > folderUnpackSize) + return E_FAIL; + fullUnpack = (*unpackSize == folderUnpackSize); + } + + /* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only + + #ifndef _NO_CRYPTO + isEncrypted = false; + passwordIsDefined = false; + #endif + */ + + if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev)) + { + _bindInfoPrev_Defined = false; + _mixerRef.Release(); + + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_useMixerMT) + #endif + { + _mixerMT = new NCoderMixer2::CMixerMT(false); + _mixerRef = _mixerMT; + _mixer = _mixerMT; + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + _mixerST = new NCoderMixer2::CMixerST(false); + _mixerRef = _mixerST; + _mixer = _mixerST; + #endif + } + + RINOK(_mixer->SetBindInfo(bindInfo)); + + FOR_VECTOR(i, folderInfo.Coders) + { + const CCoderInfo &coderInfo = folderInfo.Coders[i]; + + #ifndef _SFX + // we don't support RAR codecs here + if ((coderInfo.MethodID >> 8) == 0x403) + return E_NOTIMPL; + #endif + + CCreatedCoder cod; + RINOK(CreateCoder_Id( + EXTERNAL_CODECS_LOC_VARS + coderInfo.MethodID, false, cod)); + + if (coderInfo.IsSimpleCoder()) + { + if (!cod.Coder) + return E_NOTIMPL; + // CMethodId m = coderInfo.MethodID; + // isFilter = (IsFilterMethod(m) || m == k_AES); + } + else + { + if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams) + return E_NOTIMPL; + } + _mixer->AddCoder(cod); + + // now there is no codec that uses another external codec + /* + #ifdef EXTERNAL_CODECS + CMyComPtr setCompressCodecsInfo; + decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + // we must use g_ExternalCodecs also + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); + } + #endif + */ + } + + _bindInfoPrev = bindInfo; + _bindInfoPrev_Defined = true; + } + + RINOK(_mixer->ReInit2()); + + UInt32 packStreamIndex = 0; + UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex]; + + unsigned i; + + #if !defined(_7ZIP_ST) + bool mt_wasUsed = false; + #endif + + for (i = 0; i < folderInfo.Coders.Size(); i++) + { + const CCoderInfo &coderInfo = folderInfo.Coders[i]; + IUnknown *decoder = _mixer->GetCoder(i).GetUnknown(); + + #if !defined(_7ZIP_ST) + if (!mt_wasUsed) + { + if (mtMode) + { + CMyComPtr setCoderMt; + decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); + if (setCoderMt) + { + mt_wasUsed = true; + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); + } + } + // if (memUsage != 0) + { + CMyComPtr setMemLimit; + decoder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit); + if (setMemLimit) + { + mt_wasUsed = true; + RINOK(setMemLimit->SetMemLimit(memUsage)); + } + } + } + #endif + + { + CMyComPtr setDecoderProperties; + decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); + if (setDecoderProperties) + { + const CByteBuffer &props = coderInfo.Props; + const UInt32 size32 = (UInt32)props.Size(); + if (props.Size() != size32) + return E_NOTIMPL; + HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32); + if (res == E_INVALIDARG) + res = E_NOTIMPL; + RINOK(res); + } + } + + #ifndef _NO_CRYPTO + { + CMyComPtr cryptoSetPassword; + decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword); + if (cryptoSetPassword) + { + isEncrypted = true; + if (!getTextPassword) + return E_NOTIMPL; + CMyComBSTR_Wipe passwordBSTR; + RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); + passwordIsDefined = true; + password.Wipe_and_Empty(); + size_t len = 0; + if (passwordBSTR) + { + password = passwordBSTR; + len = password.Len(); + } + CByteBuffer_Wipe buffer(len * 2); + for (size_t k = 0; k < len; k++) + { + wchar_t c = passwordBSTR[k]; + ((Byte *)buffer)[k * 2] = (Byte)c; + ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); + } + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size())); + } + } + #endif + + bool finishMode = false; + { + CMyComPtr setFinishMode; + decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + if (setFinishMode) + { + finishMode = fullUnpack; + RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode))); + } + } + + UInt32 numStreams = (UInt32)coderInfo.NumStreams; + + CObjArray packSizes(numStreams); + CObjArray packSizesPointers(numStreams); + + for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++) + { + int bond = folderInfo.FindBond_for_PackStream(packStreamIndex); + + if (bond >= 0) + packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex]; + else + { + int index = folderInfo.Find_in_PackStreams(packStreamIndex); + if (index < 0) + return E_NOTIMPL; + packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index]; + packSizesPointers[j] = &packSizes[j]; + } + } + + const UInt64 *unpackSizesPointer = + (unpackSize && i == bindInfo.UnpackCoder) ? + unpackSize : + &folders.CoderUnpackSizes[unpackStreamIndexStart + i]; + + _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode); + } + + if (outStream) + { + _mixer->SelectMainCoder(!fullUnpack); + } + + CObjectVector< CMyComPtr > inStreams; + + CLockedInStream *lockedInStreamSpec = new CLockedInStream; + CMyComPtr lockedInStream = lockedInStreamSpec; + + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + bool needMtLock = _useMixerMT; + #endif + #endif + + if (folderInfo.PackStreams.Size() > 1) + { + // lockedInStream.Pos = (UInt64)(Int64)-1; + // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos)); + RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)); + lockedInStreamSpec->Stream = inStream; + + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + /* + For ST-mixer mode: + If parallel input stream reading from pack streams is possible, + we must use MT-lock for packed streams. + Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode. + So we force to needMtLock mode only if there is unknown (external) decoder. + */ + if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex)) + needMtLock = true; + #endif + #endif + } + + for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++) + { + CMyComPtr packStream; + const UInt64 packPos = startPos + packPositions[j]; + + if (folderInfo.PackStreams.Size() == 1) + { + RINOK(inStream->Seek((Int64)packPos, STREAM_SEEK_SET, NULL)); + packStream = inStream; + } + else + { + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (needMtLock) + #endif + { + CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; + packStream = lockedStreamImpSpec; + lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; + packStream = lockedStreamImpSpec; + lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); + #endif + } + } + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + inStreams.AddNew() = streamSpec; + streamSpec->SetStream(packStream); + streamSpec->Init(packPositions[j + 1] - packPositions[j]); + } + + const unsigned num = inStreams.Size(); + CObjArray inStreamPointers(num); + for (i = 0; i < num; i++) + inStreamPointers[i] = inStreams[i]; + + if (outStream) + { + CMyComPtr progress2; + if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex)) + progress2 = new CDecProgress(compressProgress); + + ISequentialOutStream *outStreamPointer = outStream; + return _mixer->Code(inStreamPointers, &outStreamPointer, + progress2 ? (ICompressProgressInfo *)progress2 : compressProgress, + dataAfterEnd_Error); + } + + #ifdef USE_MIXER_ST + return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes); + #else + return E_FAIL; + #endif +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.h new file mode 100644 index 0000000..eeb146e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zDecode.h @@ -0,0 +1,70 @@ +// 7zDecode.h + +#ifndef __7Z_DECODE_H +#define __7Z_DECODE_H + +#include "../Common/CoderMixer2.h" + +#include "7zIn.h" + +namespace NArchive { +namespace N7z { + +struct CBindInfoEx: public NCoderMixer2::CBindInfo +{ + CRecordVector CoderMethodIDs; + + void Clear() + { + CBindInfo::Clear(); + CoderMethodIDs.Clear(); + } +}; + +class CDecoder +{ + bool _bindInfoPrev_Defined; + CBindInfoEx _bindInfoPrev; + + bool _useMixerMT; + + #ifdef USE_MIXER_ST + NCoderMixer2::CMixerST *_mixerST; + #endif + + #ifdef USE_MIXER_MT + NCoderMixer2::CMixerMT *_mixerMT; + #endif + + NCoderMixer2::CMixer *_mixer; + CMyComPtr _mixerRef; + +public: + + CDecoder(bool useMixerMT); + + HRESULT Decode( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + UInt64 startPos, + const CFolders &folders, unsigned folderIndex, + const UInt64 *unpackSize // if (!unpackSize), then full folder is required + // if (unpackSize), then only *unpackSize bytes from folder are required + + , ISequentialOutStream *outStream + , ICompressProgressInfo *compressProgress + + , ISequentialInStream **inStreamMainRes + , bool &dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS_DECL + + #if !defined(_7ZIP_ST) + , bool mtMode, UInt32 numThreads, UInt64 memUsage + #endif + ); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.cpp new file mode 100644 index 0000000..4996324 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.cpp @@ -0,0 +1,679 @@ +// 7zEncode.cpp + +#include "StdAfx.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/FilterCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/InOutTempBuffer.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "7zEncode.h" +#include "7zSpecStream.h" + +namespace NArchive { +namespace N7z { + +void CEncoder::InitBindConv() +{ + unsigned numIn = _bindInfo.Coders.Size(); + + _SrcIn_to_DestOut.ClearAndSetSize(numIn); + _DestOut_to_SrcIn.ClearAndSetSize(numIn); + + unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams(); + _SrcOut_to_DestIn.ClearAndSetSize(numOut); + // _DestIn_to_SrcOut.ClearAndSetSize(numOut); + + UInt32 destIn = 0; + UInt32 destOut = 0; + + for (unsigned i = _bindInfo.Coders.Size(); i != 0;) + { + i--; + + const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i]; + + numIn--; + numOut -= coder.NumStreams; + + _SrcIn_to_DestOut[numIn] = destOut; + _DestOut_to_SrcIn[destOut] = numIn; + + destOut++; + + for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++) + { + UInt32 index = numOut + j; + _SrcOut_to_DestIn[index] = destIn; + // _DestIn_to_SrcOut[destIn] = index; + } + } +} + +void CEncoder::SetFolder(CFolder &folder) +{ + folder.Bonds.SetSize(_bindInfo.Bonds.Size()); + + unsigned i; + + for (i = 0; i < _bindInfo.Bonds.Size(); i++) + { + CBond &fb = folder.Bonds[i]; + const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i]; + fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex]; + fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex]; + } + + folder.Coders.SetSize(_bindInfo.Coders.Size()); + + for (i = 0; i < _bindInfo.Coders.Size(); i++) + { + CCoderInfo &coderInfo = folder.Coders[i]; + const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i]; + + coderInfo.NumStreams = coderStreamsInfo.NumStreams; + coderInfo.MethodID = _decompressionMethods[i]; + // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty. + } + + folder.PackStreams.SetSize(_bindInfo.PackStreams.Size()); + + for (i = 0; i < _bindInfo.PackStreams.Size(); i++) + folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]]; +} + + + +static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) +{ + CMyComPtr setCoderProperties; + coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); + if (setCoderProperties) + return props.SetCoderProps(setCoderProperties, dataSizeReduce); + return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; +} + + + +void CMtEncMultiProgress::Init(ICompressProgressInfo *progress) +{ + _progress = progress; + OutSize = 0; +} + +STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + UInt64 outSize2; + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + #endif + outSize2 = OutSize; + } + + if (_progress) + return _progress->SetRatioInfo(inSize, &outSize2); + + return S_OK; +} + + + +HRESULT CEncoder::CreateMixerCoder( + DECL_EXTERNAL_CODECS_LOC_VARS + const UInt64 *inSizeForReduce) +{ + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_options.MultiThreadMixer) + #endif + { + _mixerMT = new NCoderMixer2::CMixerMT(true); + _mixerRef = _mixerMT; + _mixer = _mixerMT; + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + _mixerST = new NCoderMixer2::CMixerST(true); + _mixerRef = _mixerST; + _mixer = _mixerST; + #endif + } + + RINOK(_mixer->SetBindInfo(_bindInfo)); + + FOR_VECTOR (m, _options.Methods) + { + const CMethodFull &methodFull = _options.Methods[m]; + + CCreatedCoder cod; + + if (methodFull.CodecIndex >= 0) + { + RINOK(CreateCoder_Index( + EXTERNAL_CODECS_LOC_VARS + (unsigned)methodFull.CodecIndex, true, cod)); + } + else + { + RINOK(CreateCoder_Id( + EXTERNAL_CODECS_LOC_VARS + methodFull.Id, true, cod)); + } + + if (cod.NumStreams != methodFull.NumStreams) + return E_FAIL; + if (!cod.Coder && !cod.Coder2) + return E_FAIL; + + CMyComPtr encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2; + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); + } + } + #endif + + RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon)); + + /* + CMyComPtr resetSalt; + encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); + if (resetSalt) + { + resetSalt->ResetSalt(); + } + */ + + // now there is no codec that uses another external codec + /* + #ifdef EXTERNAL_CODECS + CMyComPtr setCompressCodecsInfo; + encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + // we must use g_ExternalCodecs also + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); + } + #endif + */ + + CMyComPtr cryptoSetPassword; + encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); + + if (cryptoSetPassword) + { + const unsigned sizeInBytes = _options.Password.Len() * 2; + CByteBuffer_Wipe buffer(sizeInBytes); + for (unsigned i = 0; i < _options.Password.Len(); i++) + { + wchar_t c = _options.Password[i]; + ((Byte *)buffer)[i * 2] = (Byte)c; + ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); + } + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes)); + } + + _mixer->AddCoder(cod); + } + return S_OK; +} + + + +class CSequentialOutTempBufferImp2: + public ISequentialOutStream, + public CMyUnknownImp +{ + CInOutTempBuffer *_buf; +public: + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {} + void Init(CInOutTempBuffer *buffer) { _buf = buffer; } + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed) +{ + HRESULT res = _buf->Write_HRESULT(data, size); + if (res != S_OK) + { + if (processed) + *processed = 0; + return res; + } + if (processed) + *processed = size; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return S_OK; +} + + +class CSequentialOutMtNotify: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CMyComPtr _stream; + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutMtNotify(): _mtProgresSpec(NULL) {} + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed) +{ + UInt32 realProcessed = 0; + HRESULT res = _stream->Write(data, size, &realProcessed); + if (processed) + *processed = realProcessed; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return res; +} + + + +HRESULT CEncoder::Encode( + DECL_EXTERNAL_CODECS_LOC_VARS + ISequentialInStream *inStream, + // const UInt64 *inStreamSize, + const UInt64 *inSizeForReduce, + CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, + ISequentialOutStream *outStream, + CRecordVector &packSizes, + ICompressProgressInfo *compressProgress) +{ + RINOK(EncoderConstr()); + + if (!_mixerRef) + { + RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); + } + + RINOK(_mixer->ReInit2()); + + CMtEncMultiProgress *mtProgressSpec = NULL; + CMyComPtr mtProgress; + + CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL; + CMyComPtr mtOutStreamNotify; + + CObjectVector inOutTempBuffers; + CObjectVector tempBufferSpecs; + CObjectVector > tempBuffers; + + unsigned numMethods = _bindInfo.Coders.Size(); + + unsigned i; + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + { + CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); + iotb.Create(); + iotb.InitWriting(); + } + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + { + CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2; + CMyComPtr tempBuffer = tempBufferSpec; + tempBufferSpec->Init(&inOutTempBuffers[i - 1]); + tempBuffers.Add(tempBuffer); + tempBufferSpecs.Add(tempBufferSpec); + } + + for (i = 0; i < numMethods; i++) + _mixer->SetCoderInfo(i, NULL, NULL, false); + + + /* inStreamSize can be used by BCJ2 to set optimal range of conversion. + But current BCJ2 encoder uses also another way to check exact size of current file. + So inStreamSize is not required. */ + + /* + if (inStreamSize) + _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); + */ + + + CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; + CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; + + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; + CMyComPtr outStreamSizeCount; + + inStreamSizeCountSpec->Init(inStream); + + ISequentialInStream *inStreamPointer = inStreamSizeCount; + CRecordVector outStreamPointers; + + SetFolder(folderItem); + + for (i = 0; i < numMethods; i++) + { + IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); + + CMyComPtr resetInitVector; + coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); + if (resetInitVector) + { + resetInitVector->ResetInitVector(); + } + + { + CMyComPtr optProps; + coder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps); + if (optProps) + { + PROPID propID = NCoderPropID::kExpectedDataSize; + NWindows::NCOM::CPropVariant prop = (UInt64)unpackSize; + RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1)); + } + } + + CMyComPtr writeCoderProperties; + coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + + CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props; + + if (writeCoderProperties) + { + CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; + CMyComPtr dynOutStream(outStreamSpec); + outStreamSpec->Init(); + RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream)); + outStreamSpec->CopyToBuffer(props); + } + else + props.Free(); + } + + _mixer->SelectMainCoder(false); + UInt32 mainCoder = _mixer->MainCoderIndex; + + bool useMtProgress = false; + if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder)) + { + #ifdef _7ZIP_ST + if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder)) + #endif + useMtProgress = true; + } + + if (useMtProgress) + { + mtProgressSpec = new CMtEncMultiProgress; + mtProgress = mtProgressSpec; + mtProgressSpec->Init(compressProgress); + + mtOutStreamNotifySpec = new CSequentialOutMtNotify; + mtOutStreamNotify = mtOutStreamNotifySpec; + mtOutStreamNotifySpec->_stream = outStream; + mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec; + + FOR_VECTOR(t, tempBufferSpecs) + { + tempBufferSpecs[t]->_mtProgresSpec = mtProgressSpec; + } + } + + + if (_bindInfo.PackStreams.Size() != 0) + { + outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + outStreamSizeCount = outStreamSizeCountSpec; + outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); + outStreamSizeCountSpec->Init(); + outStreamPointers.Add(outStreamSizeCount); + } + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + outStreamPointers.Add(tempBuffers[i - 1]); + + bool dataAfterEnd_Error; + + RINOK(_mixer->Code( + &inStreamPointer, + &outStreamPointers.Front(), + mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error)); + + if (_bindInfo.PackStreams.Size() != 0) + packSizes.Add(outStreamSizeCountSpec->GetSize()); + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + { + CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; + RINOK(inOutTempBuffer.WriteToStream(outStream)); + packSizes.Add(inOutTempBuffer.GetDataSize()); + } + + unpackSize = 0; + + for (i = 0; i < _bindInfo.Coders.Size(); i++) + { + int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]); + UInt64 streamSize; + if (bond < 0) + { + streamSize = inStreamSizeCountSpec->GetSize(); + unpackSize = streamSize; + } + else + streamSize = _mixer->GetBondStreamSize((unsigned)bond); + coderUnpackSizes.Add(streamSize); + } + + return S_OK; +} + + +CEncoder::CEncoder(const CCompressionMethodMode &options): + _constructed(false) +{ + if (options.IsEmpty()) + throw 1; + + _options = options; + + #ifdef USE_MIXER_ST + _mixerST = NULL; + #endif + + #ifdef USE_MIXER_MT + _mixerMT = NULL; + #endif + + _mixer = NULL; +} + + +HRESULT CEncoder::EncoderConstr() +{ + if (_constructed) + return S_OK; + if (_options.Methods.IsEmpty()) + { + // it has only password method; + if (!_options.PasswordIsDefined) + throw 1; + if (!_options.Bonds.IsEmpty()) + throw 1; + + CMethodFull method; + method.Id = k_AES; + method.NumStreams = 1; + _options.Methods.Add(method); + + NCoderMixer2::CCoderStreamsInfo coderStreamsInfo; + coderStreamsInfo.NumStreams = 1; + _bindInfo.Coders.Add(coderStreamsInfo); + + _bindInfo.PackStreams.Add(0); + _bindInfo.UnpackCoder = 0; + } + else + { + + UInt32 numOutStreams = 0; + unsigned i; + + for (i = 0; i < _options.Methods.Size(); i++) + { + const CMethodFull &methodFull = _options.Methods[i]; + NCoderMixer2::CCoderStreamsInfo cod; + + cod.NumStreams = methodFull.NumStreams; + + if (_options.Bonds.IsEmpty()) + { + // if there are no bonds in options, we create bonds via first streams of coders + if (i != _options.Methods.Size() - 1) + { + NCoderMixer2::CBond bond; + bond.PackIndex = numOutStreams; + bond.UnpackIndex = i + 1; // it's next coder + _bindInfo.Bonds.Add(bond); + } + else if (cod.NumStreams != 0) + _bindInfo.PackStreams.Insert(0, numOutStreams); + + for (UInt32 j = 1; j < cod.NumStreams; j++) + _bindInfo.PackStreams.Add(numOutStreams + j); + } + + numOutStreams += cod.NumStreams; + + _bindInfo.Coders.Add(cod); + } + + if (!_options.Bonds.IsEmpty()) + { + for (i = 0; i < _options.Bonds.Size(); i++) + { + NCoderMixer2::CBond mixerBond; + const CBond2 &bond = _options.Bonds[i]; + if (bond.InCoder >= _bindInfo.Coders.Size() + || bond.OutCoder >= _bindInfo.Coders.Size() + || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams) + return E_INVALIDARG; + mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream; + mixerBond.UnpackIndex = bond.InCoder; + _bindInfo.Bonds.Add(mixerBond); + } + + for (i = 0; i < numOutStreams; i++) + if (_bindInfo.FindBond_for_PackStream(i) == -1) + _bindInfo.PackStreams.Add(i); + } + + if (!_bindInfo.SetUnpackCoder()) + return E_INVALIDARG; + + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; + + if (_bindInfo.PackStreams.Size() != 1) + { + /* main_PackStream is pack stream of main path of coders tree. + We find main_PackStream, and place to start of list of out streams. + It allows to use more optimal memory usage for temp buffers, + if main_PackStream is largest stream. */ + + UInt32 ci = _bindInfo.UnpackCoder; + + for (;;) + { + if (_bindInfo.Coders[ci].NumStreams == 0) + break; + + UInt32 outIndex = _bindInfo.Coder_to_Stream[ci]; + int bond = _bindInfo.FindBond_for_PackStream(outIndex); + if (bond >= 0) + { + ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex; + continue; + } + + int si = _bindInfo.FindStream_in_PackStreams(outIndex); + if (si >= 0) + _bindInfo.PackStreams.MoveToFront((unsigned)si); + break; + } + } + + if (_options.PasswordIsDefined) + { + unsigned numCryptoStreams = _bindInfo.PackStreams.Size(); + + unsigned numInStreams = _bindInfo.Coders.Size(); + + for (i = 0; i < numCryptoStreams; i++) + { + NCoderMixer2::CBond bond; + bond.UnpackIndex = numInStreams + i; + bond.PackIndex = _bindInfo.PackStreams[i]; + _bindInfo.Bonds.Add(bond); + } + _bindInfo.PackStreams.Clear(); + + /* + if (numCryptoStreams == 0) + numCryptoStreams = 1; + */ + + for (i = 0; i < numCryptoStreams; i++) + { + CMethodFull method; + method.NumStreams = 1; + method.Id = k_AES; + _options.Methods.Add(method); + + NCoderMixer2::CCoderStreamsInfo cod; + cod.NumStreams = 1; + _bindInfo.Coders.Add(cod); + + _bindInfo.PackStreams.Add(numOutStreams++); + } + } + + } + + for (unsigned i = _options.Methods.Size(); i != 0;) + _decompressionMethods.Add(_options.Methods[--i].Id); + + if (_bindInfo.Coders.Size() > 16) + return E_INVALIDARG; + if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16) + return E_INVALIDARG; + + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; + + InitBindConv(); + _constructed = true; + return S_OK; +} + +CEncoder::~CEncoder() {} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.h new file mode 100644 index 0000000..6ea7f27 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zEncode.h @@ -0,0 +1,92 @@ +// 7zEncode.h + +#ifndef __7Z_ENCODE_H +#define __7Z_ENCODE_H + +#include "7zCompressionMode.h" + +#include "../Common/CoderMixer2.h" + +#include "7zItem.h" + +namespace NArchive { +namespace N7z { + +class CMtEncMultiProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr _progress; + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSection CriticalSection; + #endif + +public: + UInt64 OutSize; + + CMtEncMultiProgress(): OutSize(0) {} + + void Init(ICompressProgressInfo *progress); + + void AddOutSize(UInt64 addOutSize) + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + #endif + OutSize += addOutSize; + } + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +class CEncoder MY_UNCOPYABLE +{ + #ifdef USE_MIXER_ST + NCoderMixer2::CMixerST *_mixerST; + #endif + #ifdef USE_MIXER_MT + NCoderMixer2::CMixerMT *_mixerMT; + #endif + + NCoderMixer2::CMixer *_mixer; + CMyComPtr _mixerRef; + + CCompressionMethodMode _options; + NCoderMixer2::CBindInfo _bindInfo; + CRecordVector _decompressionMethods; + + CRecordVector _SrcIn_to_DestOut; + CRecordVector _SrcOut_to_DestIn; + // CRecordVector _DestIn_to_SrcOut; + CRecordVector _DestOut_to_SrcIn; + + void InitBindConv(); + void SetFolder(CFolder &folder); + + HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS + const UInt64 *inSizeForReduce); + + bool _constructed; +public: + + CEncoder(const CCompressionMethodMode &options); + ~CEncoder(); + HRESULT EncoderConstr(); + HRESULT Encode( + DECL_EXTERNAL_CODECS_LOC_VARS + ISequentialInStream *inStream, + // const UInt64 *inStreamSize, + const UInt64 *inSizeForReduce, + CFolder &folderItem, + CRecordVector &coderUnpackSizes, + UInt64 &unpackSize, + ISequentialOutStream *outStream, + CRecordVector &packSizes, + ICompressProgressInfo *compressProgress); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zExtract.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zExtract.cpp new file mode 100644 index 0000000..95eba9a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zExtract.cpp @@ -0,0 +1,428 @@ +// 7zExtract.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/ComTry.h" + +#include "../../Common/ProgressUtils.h" + +#include "7zDecode.h" +#include "7zHandler.h" + +// EXTERN_g_ExternalCodecs + +namespace NArchive { +namespace N7z { + +class CFolderOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; +public: + bool TestMode; + bool CheckCrc; +private: + bool _fileIsOpen; + bool _calcCrc; + UInt32 _crc; + UInt64 _rem; + + const UInt32 *_indexes; + unsigned _numFiles; + unsigned _fileIndex; + + HRESULT OpenFile(bool isCorrupted = false); + HRESULT CloseFile_and_SetResult(Int32 res); + HRESULT CloseFile(); + HRESULT ProcessEmptyFiles(); + +public: + MY_UNKNOWN_IMP1(ISequentialOutStream) + + const CDbEx *_db; + CMyComPtr ExtractCallback; + + bool ExtraWriteWasCut; + + CFolderOutStream(): + TestMode(false), + CheckCrc(true) + {} + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + + HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles); + HRESULT FlushCorrupted(Int32 callbackOperationResult); + + bool WasWritingFinished() const { return _numFiles == 0; } +}; + + +HRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles) +{ + _fileIndex = startIndex; + _indexes = indexes; + _numFiles = numFiles; + + _fileIsOpen = false; + ExtraWriteWasCut = false; + + return ProcessEmptyFiles(); +} + +HRESULT CFolderOutStream::OpenFile(bool isCorrupted) +{ + const CFileItem &fi = _db->Files[_fileIndex]; + UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex); + Int32 askMode = (_fileIndex == nextFileIndex) ? + (TestMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract) : + NExtract::NAskMode::kSkip; + + if (isCorrupted + && askMode == NExtract::NAskMode::kExtract + && !_db->IsItemAnti(_fileIndex) + && !fi.IsDir) + askMode = NExtract::NAskMode::kTest; + + CMyComPtr realOutStream; + RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode)); + + _stream = realOutStream; + _crc = CRC_INIT_VAL; + _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir); + + _fileIsOpen = true; + _rem = fi.Size; + + if (askMode == NExtract::NAskMode::kExtract + && !realOutStream + && !_db->IsItemAnti(_fileIndex) + && !fi.IsDir) + askMode = NExtract::NAskMode::kSkip; + return ExtractCallback->PrepareOperation(askMode); +} + +HRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res) +{ + _stream.Release(); + _fileIsOpen = false; + + if (!_indexes) + _numFiles--; + else if (*_indexes == _fileIndex) + { + _indexes++; + _numFiles--; + } + + _fileIndex++; + return ExtractCallback->SetOperationResult(res); +} + +HRESULT CFolderOutStream::CloseFile() +{ + const CFileItem &fi = _db->Files[_fileIndex]; + return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ? + NExtract::NOperationResult::kOK : + NExtract::NOperationResult::kCRCError); +} + +HRESULT CFolderOutStream::ProcessEmptyFiles() +{ + while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0) + { + RINOK(OpenFile()); + RINOK(CloseFile()); + } + return S_OK; +} + +STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + if (_calcCrc) + { + const UInt32 k_Step = (UInt32)1 << 20; + if (cur > k_Step) + cur = k_Step; + } + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, cur, &cur); + if (_calcCrc) + _crc = CrcUpdate(_crc, data, cur); + if (processedSize) + *processedSize += cur; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (_rem == 0) + { + RINOK(CloseFile()); + RINOK(ProcessEmptyFiles()); + } + RINOK(result); + if (cur == 0) + break; + continue; + } + + RINOK(ProcessEmptyFiles()); + if (_numFiles == 0) + { + // we support partial extracting + /* + if (processedSize) + *processedSize += size; + break; + */ + ExtraWriteWasCut = true; + // return S_FALSE; + return k_My_HRESULT_WritingWasCut; + } + RINOK(OpenFile()); + } + + return S_OK; +} + +HRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult) +{ + while (_numFiles != 0) + { + if (_fileIsOpen) + { + RINOK(CloseFile_and_SetResult(callbackOperationResult)); + } + else + { + RINOK(OpenFile(true)); + } + } + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) +{ + // for GCC + // CFolderOutStream *folderOutStream = new CFolderOutStream; + // CMyComPtr outStream(folderOutStream); + + COM_TRY_BEGIN + + CMyComPtr extractCallback = extractCallbackSpec; + + UInt64 importantTotalUnpacked = 0; + + // numItems = (UInt32)(Int32)-1; + + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _db.Files.Size(); + + if (numItems == 0) + return S_OK; + + { + CNum prevFolder = kNumNoIndex; + UInt32 nextFile = 0; + + UInt32 i; + + for (i = 0; i < numItems; i++) + { + UInt32 fileIndex = allFilesMode ? i : indices[i]; + CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex == kNumNoIndex) + continue; + if (folderIndex != prevFolder || fileIndex < nextFile) + nextFile = _db.FolderStartFileIndex[folderIndex]; + for (CNum index = nextFile; index <= fileIndex; index++) + importantTotalUnpacked += _db.Files[index].Size; + nextFile = fileIndex + 1; + prevFolder = folderIndex; + } + } + + RINOK(extractCallback->SetTotal(importantTotalUnpacked)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CDecoder decoder( + #if !defined(USE_MIXER_MT) + false + #elif !defined(USE_MIXER_ST) + true + #elif !defined(__7Z_SET_PROPERTIES) + #ifdef _7ZIP_ST + false + #else + true + #endif + #else + _useMultiThreadMixer + #endif + ); + + UInt64 curPacked, curUnpacked; + + CMyComPtr callbackMessage; + extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage, &callbackMessage); + + CFolderOutStream *folderOutStream = new CFolderOutStream; + CMyComPtr outStream(folderOutStream); + + folderOutStream->_db = &_db; + folderOutStream->ExtractCallback = extractCallback; + folderOutStream->TestMode = (testModeSpec != 0); + folderOutStream->CheckCrc = (_crcSize != 0); + + for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked) + { + RINOK(lps->SetCur()); + + if (i >= numItems) + break; + + curUnpacked = 0; + curPacked = 0; + + UInt32 fileIndex = allFilesMode ? i : indices[i]; + CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex]; + + UInt32 numSolidFiles = 1; + + if (folderIndex != kNumNoIndex) + { + curPacked = _db.GetFolderFullPackSize(folderIndex); + UInt32 nextFile = fileIndex + 1; + fileIndex = _db.FolderStartFileIndex[folderIndex]; + UInt32 k; + + for (k = i + 1; k < numItems; k++) + { + UInt32 fileIndex2 = allFilesMode ? k : indices[k]; + if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex + || fileIndex2 < nextFile) + break; + nextFile = fileIndex2 + 1; + } + + numSolidFiles = k - i; + + for (k = fileIndex; k < nextFile; k++) + curUnpacked += _db.Files[k].Size; + } + + { + HRESULT result = folderOutStream->Init(fileIndex, + allFilesMode ? NULL : indices + i, + numSolidFiles); + + i += numSolidFiles; + + RINOK(result); + } + + // to test solid block with zero unpacked size we disable that code + if (folderOutStream->WasWritingFinished()) + continue; + + #ifndef _NO_CRYPTO + CMyComPtr getTextPassword; + if (extractCallback) + extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + #endif + + try + { + #ifndef _NO_CRYPTO + bool isEncrypted = false; + bool passwordIsDefined = false; + UString_Wipe password; + #endif + + + bool dataAfterEnd_Error = false; + + HRESULT result = decoder.Decode( + EXTERNAL_CODECS_VARS + _inStream, + _db.ArcInfo.DataStartPosition, + _db, folderIndex, + &curUnpacked, + + outStream, + progress, + NULL // *inStreamMainRes + , dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS + #if !defined(_7ZIP_ST) + , true, _numThreads, _memUsage + #endif + ); + + if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error) + { + bool wasFinished = folderOutStream->WasWritingFinished(); + + int resOp = NExtract::NOperationResult::kDataError; + + if (result != S_FALSE) + { + if (result == E_NOTIMPL) + resOp = NExtract::NOperationResult::kUnsupportedMethod; + else if (wasFinished && dataAfterEnd_Error) + resOp = NExtract::NOperationResult::kDataAfterEnd; + } + + RINOK(folderOutStream->FlushCorrupted(resOp)); + + if (wasFinished) + { + // we don't show error, if it's after required files + if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage) + { + RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp)); + } + } + continue; + } + + if (result != S_OK) + return result; + + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + continue; + } + catch(...) + { + RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError)); + // continue; + // return E_FAIL; + throw; + } + } + + return S_OK; + + COM_TRY_END +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.cpp new file mode 100644 index 0000000..a68edf4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.cpp @@ -0,0 +1,139 @@ +// 7zFolderInStream.cpp + +#include "StdAfx.h" + +#include "7zFolderInStream.h" + +namespace NArchive { +namespace N7z { + +void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, + const UInt32 *indexes, unsigned numFiles) +{ + _updateCallback = updateCallback; + _indexes = indexes; + _numFiles = numFiles; + _index = 0; + + Processed.ClearAndReserve(numFiles); + CRCs.ClearAndReserve(numFiles); + Sizes.ClearAndReserve(numFiles); + + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + _stream.Release(); +} + +HRESULT CFolderInStream::OpenStream() +{ + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + while (_index < _numFiles) + { + CMyComPtr stream; + HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream); + if (result != S_OK) + { + if (result != S_FALSE) + return result; + } + + _stream = stream; + + if (stream) + { + CMyComPtr streamGetSize; + stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); + if (streamGetSize) + { + if (streamGetSize->GetSize(&_size) == S_OK) + _size_Defined = true; + } + return S_OK; + } + + _index++; + RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + AddFileInfo(result == S_OK); + } + return S_OK; +} + +void CFolderInStream::AddFileInfo(bool isProcessed) +{ + Processed.Add(isProcessed); + Sizes.Add(_pos); + CRCs.Add(CRC_GET_DIGEST(_crc)); +} + +STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + while (size != 0) + { + if (_stream) + { + UInt32 cur = size; + const UInt32 kMax = (UInt32)1 << 20; + if (cur > kMax) + cur = kMax; + RINOK(_stream->Read(data, cur, &cur)); + if (cur != 0) + { + _crc = CrcUpdate(_crc, data, cur); + _pos += cur; + if (processedSize) + *processedSize = cur; + return S_OK; + } + + _stream.Release(); + _index++; + AddFileInfo(true); + + _pos = 0; + _crc = CRC_INIT_VAL; + _size_Defined = false; + _size = 0; + + RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + + if (_index >= _numFiles) + break; + RINOK(OpenStream()); + } + return S_OK; +} + +STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + *value = 0; + if (subStream > Sizes.Size()) + return S_FALSE; // E_FAIL; + + unsigned index = (unsigned)subStream; + if (index < Sizes.Size()) + { + *value = Sizes[index]; + return S_OK; + } + + if (!_size_Defined) + { + *value = _pos; + return S_FALSE; + } + + *value = (_pos > _size ? _pos : _size); + return S_OK; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.h new file mode 100644 index 0000000..805db54 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zFolderInStream.h @@ -0,0 +1,61 @@ +// 7zFolderInStream.h + +#ifndef __7Z_FOLDER_IN_STREAM_H +#define __7Z_FOLDER_IN_STREAM_H + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + +#include "../../ICoder.h" +#include "../IArchive.h" + +namespace NArchive { +namespace N7z { + +class CFolderInStream: + public ISequentialInStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _pos; + UInt32 _crc; + bool _size_Defined; + UInt64 _size; + + const UInt32 *_indexes; + unsigned _numFiles; + unsigned _index; + + CMyComPtr _updateCallback; + + HRESULT OpenStream(); + void AddFileInfo(bool isProcessed); + +public: + CRecordVector Processed; + CRecordVector CRCs; + CRecordVector Sizes; + + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); + + void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles); + + bool WasFinished() const { return _index == _numFiles; } + + UInt64 GetFullSize() const + { + UInt64 size = 0; + FOR_VECTOR (i, Sizes) + size += Sizes[i]; + return size; + } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.cpp new file mode 100644 index 0000000..9e344c3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.cpp @@ -0,0 +1,778 @@ +// 7zHandler.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" + +#ifndef __7Z_SET_PROPERTIES +#include "../../../Windows/System.h" +#endif + +#include "../Common/ItemNameUtils.h" + +#include "7zHandler.h" +#include "7zProperties.h" + +#ifdef __7Z_SET_PROPERTIES +#ifdef EXTRACT_ONLY +#include "../Common/ParseProperties.h" +#endif +#endif + +using namespace NWindows; +using namespace NCOM; + +namespace NArchive { +namespace N7z { + +CHandler::CHandler() +{ + #ifndef _NO_CRYPTO + _isEncrypted = false; + _passwordIsDefined = false; + #endif + + #ifdef EXTRACT_ONLY + + _crcSize = 4; + + #ifdef __7Z_SET_PROPERTIES + _useMultiThreadMixer = true; + #endif + + #endif +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.Files.Size(); + return S_OK; +} + +#ifdef _SFX + +IMP_IInArchive_ArcProps_NO_Table + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) +{ + return E_NOTIMPL; +} + +#else + +static const Byte kArcProps[] = +{ + kpidHeadersSize, + kpidMethod, + kpidSolid, + kpidNumBlocks + // , kpidIsTree +}; + +IMP_IInArchive_ArcProps + +static inline char GetHex(unsigned value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static unsigned ConvertMethodIdToString_Back(char *s, UInt64 id) +{ + int len = 0; + do + { + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; + s[--len] = GetHex((unsigned)id & 0xF); id >>= 4; + } + while (id != 0); + return (unsigned)-len; +} + +static void ConvertMethodIdToString(AString &res, UInt64 id) +{ + const unsigned kLen = 32; + char s[kLen]; + unsigned len = kLen - 1; + s[len] = 0; + res += s + len - ConvertMethodIdToString_Back(s + len, id); +} + + +static char *GetStringForSizeValue(char *s, UInt32 val) +{ + unsigned i; + for (i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + { + if (i >= 10) + { + *s++= (char)('0' + i / 10); + i %= 10; + } + *s++ = (char)('0' + i); + *s = 0; + return s; + } + + char c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + s = ConvertUInt32ToString(val, s); + *s++ = c; + *s = 0; + return s; +} + + +static void GetLzma2String(char *s, unsigned d) +{ + if (d > 40) + { + *s = 0; + return; + // s = MyStpCpy(s, "unsup"); + } + else if ((d & 1) == 0) + d = (d >> 1) + 12; + else + { + // s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11)); + d = (d >> 1) + 1; + char c = 'k'; + if (d >= 10) + { + c = 'm'; + d -= 10; + } + s = ConvertUInt32ToString((UInt32)3 << d, s); + *s++ = c; + *s = 0; + return; + } + ConvertUInt32ToString(d, s); +} + + +/* +static inline void AddHexToString(UString &res, Byte value) +{ + res += GetHex((Byte)(value >> 4)); + res += GetHex((Byte)(value & 0xF)); +} +*/ + +static char *AddProp32(char *s, const char *name, UInt32 v) +{ + *s++ = ':'; + s = MyStpCpy(s, name); + return ConvertUInt32ToString(v, s); +} + +void CHandler::AddMethodName(AString &s, UInt64 id) +{ + AString name; + FindMethod(EXTERNAL_CODECS_VARS id, name); + if (name.IsEmpty()) + ConvertMethodIdToString(s, id); + else + s += name; +} + +#endif + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + #ifndef _SFX + COM_TRY_BEGIN + #endif + NCOM::CPropVariant prop; + switch (propID) + { + #ifndef _SFX + case kpidMethod: + { + AString s; + const CParsedMethods &pm = _db.ParsedMethods; + FOR_VECTOR (i, pm.IDs) + { + UInt64 id = pm.IDs[i]; + s.Add_Space_if_NotEmpty(); + char temp[16]; + if (id == k_LZMA2) + { + s += "LZMA2:"; + GetLzma2String(temp, pm.Lzma2Prop); + s += temp; + } + else if (id == k_LZMA) + { + s += "LZMA:"; + GetStringForSizeValue(temp, pm.LzmaDic); + s += temp; + } + else + AddMethodName(s, id); + } + prop = s; + break; + } + case kpidSolid: prop = _db.IsSolid(); break; + case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break; + case kpidHeadersSize: prop = _db.HeadersSize; break; + case kpidPhySize: prop = _db.PhySize; break; + case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break; + /* + case kpidIsTree: if (_db.IsTree) prop = true; break; + case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break; + case kpidIsAux: if (_db.IsTree) prop = true; break; + */ + // case kpidError: if (_db.ThereIsHeaderError) prop = "Header error"; break; + #endif + + case kpidWarningFlags: + { + UInt32 v = 0; + if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature; + if (v != 0) + prop = v; + break; + } + + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc; + if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError; + if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd; + // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported; + if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature; + prop = v; + break; + } + + case kpidReadOnly: + { + if (!_db.CanUpdate()) + prop = true; + break; + } + } + return prop.Detach(value); + #ifndef _SFX + COM_TRY_END + #endif +} + +static void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index) +{ + UInt64 value; + if (v.GetItem(index, value)) + PropVarEm_Set_FileTime64(prop, value); +} + +bool CHandler::IsFolderEncrypted(CNum folderIndex) const +{ + if (folderIndex == kNumNoIndex) + return false; + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + CNum numCoders = inByte.ReadNum(); + for (; numCoders != 0; numCoders--) + { + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + if (id64 == k_AES) + return true; + if ((mainByte & 0x20) != 0) + inByte.SkipDataNoCheck(inByte.ReadNum()); + } + return false; +} + +STDMETHODIMP CHandler::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = kpidNtSecure; + return S_OK; +} + +STDMETHODIMP CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) +{ + /* + const CFileItem &file = _db.Files[index]; + *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir); + *parent = (UInt32)(Int32)file.Parent; + */ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = NULL; + *dataSize = 0; + *propType = 0; + + if (/* _db.IsTree && propID == kpidName || + !_db.IsTree && */ propID == kpidPath) + { + if (_db.NameOffsets && _db.NamesBuf) + { + size_t offset = _db.NameOffsets[index]; + size_t size = (_db.NameOffsets[index + 1] - offset) * 2; + if (size < ((UInt32)1 << 31)) + { + *data = (const void *)(_db.NamesBuf + offset * 2); + *dataSize = (UInt32)size; + *propType = NPropDataType::kUtf16z; + } + } + return S_OK; + } + /* + if (propID == kpidNtSecure) + { + if (index < (UInt32)_db.SecureIDs.Size()) + { + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) + { + *data = _db.SecureBuf + offs; + *dataSize = (UInt32)size; + *propType = NPropDataType::kRaw; + } + } + } + */ + return S_OK; +} + +#ifndef _SFX + +HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const +{ + PropVariant_Clear(prop); + if (folderIndex == kNumNoIndex) + return S_OK; + // for (int ttt = 0; ttt < 1; ttt++) { + const unsigned kTempSize = 256; + char temp[kTempSize]; + unsigned pos = kTempSize; + temp[--pos] = 0; + + size_t startPos = _db.FoCodersDataOffset[folderIndex]; + const Byte *p = _db.CodersData + startPos; + size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; + CInByte2 inByte; + inByte.Init(p, size); + + // numCoders == 0 ??? + CNum numCoders = inByte.ReadNum(); + bool needSpace = false; + + for (; numCoders != 0; numCoders--, needSpace = true) + { + if (pos < 32) // max size of property + break; + Byte mainByte = inByte.ReadByte(); + unsigned idSize = (mainByte & 0xF); + const Byte *longID = inByte.GetPtr(); + UInt64 id64 = 0; + for (unsigned j = 0; j < idSize; j++) + id64 = ((id64 << 8) | longID[j]); + inByte.SkipDataNoCheck(idSize); + + if ((mainByte & 0x10) != 0) + { + inByte.ReadNum(); // NumInStreams + inByte.ReadNum(); // NumOutStreams + } + + CNum propsSize = 0; + const Byte *props = NULL; + if ((mainByte & 0x20) != 0) + { + propsSize = inByte.ReadNum(); + props = inByte.GetPtr(); + inByte.SkipDataNoCheck(propsSize); + } + + const char *name = NULL; + char s[32]; + s[0] = 0; + + if (id64 <= (UInt32)0xFFFFFFFF) + { + UInt32 id = (UInt32)id64; + if (id == k_LZMA) + { + name = "LZMA"; + if (propsSize == 5) + { + UInt32 dicSize = GetUi32((const Byte *)props + 1); + char *dest = GetStringForSizeValue(s, dicSize); + UInt32 d = props[0]; + if (d != 0x5D) + { + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) dest = AddProp32(dest, "lc", lc); + if (lp != 0) dest = AddProp32(dest, "lp", lp); + if (pb != 2) dest = AddProp32(dest, "pb", pb); + } + } + } + else if (id == k_LZMA2) + { + name = "LZMA2"; + if (propsSize == 1) + GetLzma2String(s, props[0]); + } + else if (id == k_PPMD) + { + name = "PPMD"; + if (propsSize == 5) + { + char *dest = s; + *dest++ = 'o'; + dest = ConvertUInt32ToString(*props, dest); + dest = MyStpCpy(dest, ":mem"); + GetStringForSizeValue(dest, GetUi32(props + 1)); + } + } + else if (id == k_Delta) + { + name = "Delta"; + if (propsSize == 1) + ConvertUInt32ToString((UInt32)props[0] + 1, s); + } + else if (id == k_BCJ2) name = "BCJ2"; + else if (id == k_BCJ) name = "BCJ"; + else if (id == k_AES) + { + name = "7zAES"; + if (propsSize >= 1) + { + Byte firstByte = props[0]; + UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + } + + if (name) + { + unsigned nameLen = MyStringLen(name); + unsigned propsLen = MyStringLen(s); + unsigned totalLen = nameLen + propsLen; + if (propsLen != 0) + totalLen++; + if (needSpace) + totalLen++; + if (totalLen + 5 >= pos) + break; + pos -= totalLen; + MyStringCopy(temp + pos, name); + if (propsLen != 0) + { + char *dest = temp + pos + nameLen; + *dest++ = ':'; + MyStringCopy(dest, s); + } + if (needSpace) + temp[pos + totalLen - 1] = ' '; + } + else + { + AString methodName; + FindMethod(EXTERNAL_CODECS_VARS id64, methodName); + if (needSpace) + temp[--pos] = ' '; + if (methodName.IsEmpty()) + pos -= ConvertMethodIdToString_Back(temp + pos, id64); + else + { + unsigned len = methodName.Len(); + if (len + 5 > pos) + break; + pos -= len; + for (unsigned i = 0; i < len; i++) + temp[pos + i] = methodName[i]; + } + } + } + + if (numCoders != 0 && pos >= 4) + { + temp[--pos] = ' '; + temp[--pos] = '.'; + temp[--pos] = '.'; + temp[--pos] = '.'; + } + + return PropVarEm_Set_Str(prop, temp + pos); + // } +} + +#endif + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + RINOK(PropVariant_Clear(value)); + // COM_TRY_BEGIN + // NCOM::CPropVariant prop; + + /* + const CRef2 &ref2 = _refs[index]; + if (ref2.Refs.IsEmpty()) + return E_FAIL; + const CRef &ref = ref2.Refs.Front(); + */ + + const CFileItem &item = _db.Files[index]; + const UInt32 index2 = index; + + switch (propID) + { + case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break; + case kpidSize: + { + PropVarEm_Set_UInt64(value, item.Size); + // prop = ref2.Size; + break; + } + case kpidPackSize: + { + // prop = ref2.PackSize; + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + { + if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) + PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex)); + /* + else + PropVarEm_Set_UInt64(value, 0); + */ + } + else + PropVarEm_Set_UInt64(value, 0); + } + break; + } + // case kpidIsAux: prop = _db.IsItemAux(index2); break; + case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; } + case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break; + case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break; + case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break; + case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break; + case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break; + case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break; + case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break; + /* + case kpidIsAltStream: prop = item.IsAltStream; break; + case kpidNtSecure: + { + int id = _db.SecureIDs[index]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + if (size >= 0) + { + prop.SetBlob(_db.SecureBuf + offs, (ULONG)size); + } + break; + } + */ + + case kpidPath: return _db.GetPath_Prop(index, value); + + #ifndef _SFX + + case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value); + case kpidBlock: + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + PropVarEm_Set_UInt32(value, (UInt32)folderIndex); + } + break; + /* + case kpidPackedSize0: + case kpidPackedSize1: + case kpidPackedSize2: + case kpidPackedSize3: + case kpidPackedSize4: + { + CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; + if (folderIndex != kNumNoIndex) + { + if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && + _db.FoStartPackStreamIndex[folderIndex + 1] - + _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0)) + { + PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0)); + } + } + else + PropVarEm_Set_UInt64(value, 0); + } + break; + */ + + #endif + } + // return prop.Detach(value); + return S_OK; + // COM_TRY_END +} + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + Close(); + #ifndef _SFX + _fileInfoPopIDs.Clear(); + #endif + + try + { + CMyComPtr openArchiveCallbackTemp = openArchiveCallback; + + #ifndef _NO_CRYPTO + CMyComPtr getTextPassword; + if (openArchiveCallback) + openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + #endif + + CInArchive archive( + #ifdef __7Z_SET_PROPERTIES + _useMultiThreadMixer + #else + true + #endif + ); + _db.IsArc = false; + RINOK(archive.Open(stream, maxCheckStartPosition)); + _db.IsArc = true; + + HRESULT result = archive.ReadDatabase( + EXTERNAL_CODECS_VARS + _db + #ifndef _NO_CRYPTO + , getTextPassword, _isEncrypted, _passwordIsDefined, _password + #endif + ); + RINOK(result); + + _inStream = stream; + } + catch(...) + { + Close(); + // return E_INVALIDARG; + // return S_FALSE; + // we must return out_of_memory here + return E_OUTOFMEMORY; + } + // _inStream = stream; + #ifndef _SFX + FillPopIDs(); + #endif + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + COM_TRY_BEGIN + _inStream.Release(); + _db.Clear(); + #ifndef _NO_CRYPTO + _isEncrypted = false; + _passwordIsDefined = false; + _password.Wipe_and_Empty(); + #endif + return S_OK; + COM_TRY_END +} + +#ifdef __7Z_SET_PROPERTIES +#ifdef EXTRACT_ONLY + +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) +{ + COM_TRY_BEGIN + + InitCommon(); + _useMultiThreadMixer = true; + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &value = values[i]; + UInt32 number; + unsigned index = ParseStringToUInt32(name, number); + if (index == 0) + { + if (name.IsEqualTo("mtf")) + { + RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer)); + continue; + } + { + HRESULT hres; + if (SetCommonProperty(name, value, hres)) + { + RINOK(hres); + continue; + } + } + return E_INVALIDARG; + } + } + return S_OK; + COM_TRY_END +} + +#endif +#endif + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.h new file mode 100644 index 0000000..cad1ae6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandler.h @@ -0,0 +1,185 @@ +// 7z/Handler.h + +#ifndef __7Z_HANDLER_H +#define __7Z_HANDLER_H + +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "../../Common/CreateCoder.h" + +#ifndef __7Z_SET_PROPERTIES + +#ifdef EXTRACT_ONLY + #if !defined(_7ZIP_ST) && !defined(_SFX) + #define __7Z_SET_PROPERTIES + #endif +#else + #define __7Z_SET_PROPERTIES +#endif + +#endif + +// #ifdef __7Z_SET_PROPERTIES +#include "../Common/HandlerOut.h" +// #endif + +#include "7zCompressionMode.h" +#include "7zIn.h" + +namespace NArchive { +namespace N7z { + + +#ifndef EXTRACT_ONLY + +class COutHandler: public CMultiMethodProps +{ + HRESULT SetSolidFromString(const UString &s); + HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value); +public: + UInt64 _numSolidFiles; + UInt64 _numSolidBytes; + bool _numSolidBytesDefined; + bool _solidExtension; + bool _useTypeSorting; + + bool _compressHeaders; + bool _encryptHeadersSpecified; + bool _encryptHeaders; + // bool _useParents; 9.26 + + CBoolPair Write_CTime; + CBoolPair Write_ATime; + CBoolPair Write_MTime; + CBoolPair Write_Attrib; + + bool _useMultiThreadMixer; + + bool _removeSfxBlock; + + // bool _volumeMode; + + void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } + void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } + void InitSolid() + { + InitSolidFiles(); + InitSolidSize(); + _solidExtension = false; + _numSolidBytesDefined = false; + } + + void InitProps7z(); + void InitProps(); + + COutHandler() { InitProps7z(); } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + +#endif + +class CHandler: + public IInArchive, + public IArchiveGetRawProps, + + #ifdef __7Z_SET_PROPERTIES + public ISetProperties, + #endif + + #ifndef EXTRACT_ONLY + public IOutArchive, + #endif + + PUBLIC_ISetCompressCodecsInfo + + public CMyUnknownImp, + + #ifndef EXTRACT_ONLY + public COutHandler + #else + public CCommonMethodProps + #endif +{ +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) + #ifdef __7Z_SET_PROPERTIES + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #endif + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutArchive) + #endif + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + INTERFACE_IArchiveGetRawProps(;) + + #ifdef __7Z_SET_PROPERTIES + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); + #endif + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + #endif + + DECL_ISetCompressCodecsInfo + + CHandler(); + ~CHandler() + { + Close(); + } + +private: + CMyComPtr _inStream; + NArchive::N7z::CDbEx _db; + + #ifndef _NO_CRYPTO + bool _isEncrypted; + bool _passwordIsDefined; + UString _password; // _Wipe + #endif + + #ifdef EXTRACT_ONLY + + #ifdef __7Z_SET_PROPERTIES + bool _useMultiThreadMixer; + #endif + + UInt32 _crcSize; + + #else + + CRecordVector _bonds; + + HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m); + HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod); + HRESULT SetMainMethod(CCompressionMethodMode &method + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ); + + + #endif + + bool IsFolderEncrypted(CNum folderIndex) const; + #ifndef _SFX + + CRecordVector _fileInfoPopIDs; + void FillPopIDs(); + void AddMethodName(AString &s, UInt64 id); + HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const; + + #endif + + DECL_EXTERNAL_CODECS_VARS +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandlerOut.cpp new file mode 100644 index 0000000..8bb8734 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -0,0 +1,968 @@ +// 7zHandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/Wildcard.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/ParseProperties.h" + +#include "7zHandler.h" +#include "7zOut.h" +#include "7zUpdate.h" + +#ifndef EXTRACT_ONLY + +using namespace NWindows; + +namespace NArchive { +namespace N7z { + +#define k_LZMA_Name "LZMA" +#define kDefaultMethodName "LZMA2" +#define k_Copy_Name "Copy" + +#define k_MatchFinder_ForHeaders "BT2" + +static const UInt32 k_NumFastBytes_ForHeaders = 273; +static const UInt32 k_Level_ForHeaders = 5; +static const UInt32 k_Dictionary_ForHeaders = + #ifdef UNDER_CE + 1 << 18; + #else + 1 << 20; + #endif + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kWindows; + return S_OK; +} + +HRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m) +{ + dest.CodecIndex = FindMethod_Index( + EXTERNAL_CODECS_VARS + m.MethodName, true, + dest.Id, dest.NumStreams); + if (dest.CodecIndex < 0) + return E_INVALIDARG; + (CProps &)dest = (CProps &)m; + return S_OK; +} + +HRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod) +{ + if (!_compressHeaders) + return S_OK; + COneMethodInfo m; + m.MethodName = k_LZMA_Name; + m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders); + m.AddProp_Level(k_Level_ForHeaders); + m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders); + m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders); + m.AddProp_NumThreads(1); + + CMethodFull &methodFull = headerMethod.Methods.AddNew(); + return PropsMethod_To_FullMethod(methodFull, m); +} + +HRESULT CHandler::SetMainMethod( + CCompressionMethodMode &methodMode + #ifndef _7ZIP_ST + , UInt32 numThreads + #endif + ) +{ + methodMode.Bonds = _bonds; + + CObjectVector methods = _methods; + + { + FOR_VECTOR (i, methods) + { + AString &methodName = methods[i].MethodName; + if (methodName.IsEmpty()) + methodName = kDefaultMethodName; + } + if (methods.IsEmpty()) + { + COneMethodInfo &m = methods.AddNew(); + m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName); + methodMode.DefaultMethod_was_Inserted = true; + } + } + + if (!_filterMethod.MethodName.IsEmpty()) + { + // if (methodMode.Bonds.IsEmpty()) + { + FOR_VECTOR (k, methodMode.Bonds) + { + CBond2 &bond = methodMode.Bonds[k]; + bond.InCoder++; + bond.OutCoder++; + } + methods.Insert(0, _filterMethod); + methodMode.Filter_was_Inserted = true; + } + } + + const UInt64 kSolidBytes_Min = (1 << 24); + const UInt64 kSolidBytes_Max = ((UInt64)1 << 32); + + bool needSolid = false; + + FOR_VECTOR (i, methods) + { + COneMethodInfo &oneMethodInfo = methods[i]; + + SetGlobalLevelTo(oneMethodInfo); + #ifndef _7ZIP_ST + CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads); + #endif + + CMethodFull &methodFull = methodMode.Methods.AddNew(); + RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo)); + + if (methodFull.Id != k_Copy) + needSolid = true; + + if (_numSolidBytesDefined) + continue; + + UInt64 dicSize; + switch (methodFull.Id) + { + case k_LZMA: + case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break; + case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break; + case k_Deflate: dicSize = (UInt32)1 << 15; break; + case k_Deflate64: dicSize = (UInt32)1 << 16; break; + case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break; + default: continue; + } + + if (methodFull.Id == k_LZMA2) + { + // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code + UInt64 cs = (UInt64)dicSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (cs < kMinSize) cs = kMinSize; + if (cs > kMaxSize) cs = kMaxSize; + if (cs < dicSize) cs = dicSize; + cs += (kMinSize - 1); + cs &= ~(UInt64)(kMinSize - 1); + // we want to use at least 64 chunks (threads) per one solid block. + _numSolidBytes = cs << 6; + const UInt64 kSolidBytes_Lzma2_Max = ((UInt64)1 << 34); + if (_numSolidBytes > kSolidBytes_Lzma2_Max) + _numSolidBytes = kSolidBytes_Lzma2_Max; + } + else + { + _numSolidBytes = (UInt64)dicSize << 7; + if (_numSolidBytes > kSolidBytes_Max) + _numSolidBytes = kSolidBytes_Max; + } + + if (_numSolidBytes < kSolidBytes_Min) + _numSolidBytes = kSolidBytes_Min; + _numSolidBytesDefined = true; + } + + if (!_numSolidBytesDefined) + { + if (needSolid) + _numSolidBytes = kSolidBytes_Max; + else + _numSolidBytes = 0; + } + _numSolidBytesDefined = true; + return S_OK; +} + +static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined) +{ + // ft = 0; + // ftDefined = false; + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(index, propID, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); + ftDefined = true; + } + else if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + else + { + ft = 0; + ftDefined = false; + } + return S_OK; +} + +/* + +#ifdef _WIN32 +static const wchar_t kDirDelimiter1 = L'\\'; +#endif +static const wchar_t kDirDelimiter2 = L'/'; + +static inline bool IsCharDirLimiter(wchar_t c) +{ + return ( + #ifdef _WIN32 + c == kDirDelimiter1 || + #endif + c == kDirDelimiter2); +} + +static int FillSortIndex(CObjectVector &treeFolders, int cur, int curSortIndex) +{ + CTreeFolder &tf = treeFolders[cur]; + tf.SortIndex = curSortIndex++; + for (int i = 0; i < tf.SubFolders.Size(); i++) + curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex); + tf.SortIndexEnd = curSortIndex; + return curSortIndex; +} + +static int FindSubFolder(const CObjectVector &treeFolders, int cur, const UString &name, int &insertPos) +{ + const CIntVector &subFolders = treeFolders[cur].SubFolders; + int left = 0, right = subFolders.Size(); + insertPos = -1; + for (;;) + { + if (left == right) + { + insertPos = left; + return -1; + } + int mid = (left + right) / 2; + int midFolder = subFolders[mid]; + int compare = CompareFileNames(name, treeFolders[midFolder].Name); + if (compare == 0) + return midFolder; + if (compare < 0) + right = mid; + else + left = mid + 1; + } +} + +static int AddFolder(CObjectVector &treeFolders, int cur, const UString &name) +{ + int insertPos; + int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos); + if (folderIndex < 0) + { + folderIndex = treeFolders.Size(); + CTreeFolder &newFolder = treeFolders.AddNew(); + newFolder.Parent = cur; + newFolder.Name = name; + treeFolders[cur].SubFolders.Insert(insertPos, folderIndex); + } + // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234; + return folderIndex; +} +*/ + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + COM_TRY_BEGIN + + const CDbEx *db = 0; + #ifdef _7Z_VOL + if (_volumes.Size() > 1) + return E_FAIL; + const CVolume *volume = 0; + if (_volumes.Size() == 1) + { + volume = &_volumes.Front(); + db = &volume->Database; + } + #else + if (_inStream != 0) + db = &_db; + #endif + + if (db && !db->CanUpdate()) + return E_NOTIMPL; + + /* + CMyComPtr getRawProps; + updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps); + + CUniqBlocks secureBlocks; + secureBlocks.AddUniq(NULL, 0); + + CObjectVector treeFolders; + { + CTreeFolder folder; + folder.Parent = -1; + treeFolders.Add(folder); + } + */ + + CObjectVector updateItems; + + bool need_CTime = (Write_CTime.Def && Write_CTime.Val); + bool need_ATime = (Write_ATime.Def && Write_ATime.Val); + bool need_MTime = (Write_MTime.Def ? Write_MTime.Val : true); + bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true); + + if (db && !db->Files.IsEmpty()) + { + if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty(); + if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty(); + if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty(); + if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty(); + } + + // UString s; + UString name; + + for (UInt32 i = 0; i < numItems; i++) + { + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)); + CUpdateItem ui; + ui.NewProps = IntToBool(newProps); + ui.NewData = IntToBool(newData); + ui.IndexInArchive = (int)indexInArchive; + ui.IndexInClient = i; + ui.IsAnti = false; + ui.Size = 0; + + name.Empty(); + // bool isAltStream = false; + if (ui.IndexInArchive != -1) + { + if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size()) + return E_INVALIDARG; + const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive]; + if (!ui.NewProps) + { + _db.GetPath((unsigned)ui.IndexInArchive, name); + } + ui.IsDir = fi.IsDir; + ui.Size = fi.Size; + // isAltStream = fi.IsAltStream; + ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive); + + if (!ui.NewProps) + { + ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime); + ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime); + ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime); + } + } + + if (ui.NewProps) + { + bool folderStatusIsDefined; + if (need_Attrib) + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + ui.AttribDefined = false; + else if (prop.vt != VT_UI4) + return E_INVALIDARG; + else + { + ui.Attrib = prop.ulVal; + ui.AttribDefined = true; + } + } + + // we need MTime to sort files. + if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined)); + if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined)); + if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined)); + + /* + if (getRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + + getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0 && propType != NPropDataType::kRaw) + return E_FAIL; + ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize); + } + */ + + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); + if (prop.vt == VT_EMPTY) + { + } + else if (prop.vt != VT_BSTR) + return E_INVALIDARG; + else + { + name = prop.bstrVal; + NItemName::ReplaceSlashes_OsToUnix(name); + } + } + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); + if (prop.vt == VT_EMPTY) + folderStatusIsDefined = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + { + ui.IsDir = (prop.boolVal != VARIANT_FALSE); + folderStatusIsDefined = true; + } + } + + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); + if (prop.vt == VT_EMPTY) + ui.IsAnti = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + ui.IsAnti = (prop.boolVal != VARIANT_FALSE); + } + + /* + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop)); + if (prop.vt == VT_EMPTY) + isAltStream = false; + else if (prop.vt != VT_BOOL) + return E_INVALIDARG; + else + isAltStream = (prop.boolVal != VARIANT_FALSE); + } + */ + + if (ui.IsAnti) + { + ui.AttribDefined = false; + + ui.CTimeDefined = false; + ui.ATimeDefined = false; + ui.MTimeDefined = false; + + ui.Size = 0; + } + + if (!folderStatusIsDefined && ui.AttribDefined) + ui.SetDirStatusFromAttrib(); + } + else + { + /* + if (_db.SecureIDs.IsEmpty()) + ui.SecureIndex = secureBlocks.AddUniq(NULL, 0); + else + { + int id = _db.SecureIDs[ui.IndexInArchive]; + size_t offs = _db.SecureOffsets[id]; + size_t size = _db.SecureOffsets[id + 1] - offs; + ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size); + } + */ + } + + /* + { + int folderIndex = 0; + if (_useParents) + { + int j; + s.Empty(); + for (j = 0; j < name.Len(); j++) + { + wchar_t c = name[j]; + if (IsCharDirLimiter(c)) + { + folderIndex = AddFolder(treeFolders, folderIndex, s); + s.Empty(); + continue; + } + s += c; + } + if (isAltStream) + { + int colonPos = s.Find(':'); + if (colonPos < 0) + { + // isAltStream = false; + return E_INVALIDARG; + } + UString mainName = s.Left(colonPos); + int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName); + if (treeFolders[newFolderIndex].UpdateItemIndex < 0) + { + for (int j = updateItems.Size() - 1; j >= 0; j--) + { + CUpdateItem &ui2 = updateItems[j]; + if (ui2.ParentFolderIndex == folderIndex + && ui2.Name == mainName) + { + ui2.TreeFolderIndex = newFolderIndex; + treeFolders[newFolderIndex].UpdateItemIndex = j; + } + } + } + folderIndex = newFolderIndex; + s.Delete(0, colonPos + 1); + } + ui.Name = s; + } + else + ui.Name = name; + ui.IsAltStream = isAltStream; + ui.ParentFolderIndex = folderIndex; + ui.TreeFolderIndex = -1; + if (ui.IsDir && !s.IsEmpty()) + { + ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s); + treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size(); + } + } + */ + ui.Name = name; + + if (ui.NewData) + { + ui.Size = 0; + if (!ui.IsDir) + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + ui.Size = (UInt64)prop.uhVal.QuadPart; + if (ui.Size != 0 && ui.IsAnti) + return E_INVALIDARG; + } + } + + updateItems.Add(ui); + } + + /* + FillSortIndex(treeFolders, 0, 0); + for (i = 0; i < (UInt32)updateItems.Size(); i++) + { + CUpdateItem &ui = updateItems[i]; + ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex; + ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd; + } + */ + + CCompressionMethodMode methodMode, headerMethod; + + HRESULT res = SetMainMethod(methodMode + #ifndef _7ZIP_ST + , _numThreads + #endif + ); + RINOK(res); + + RINOK(SetHeaderMethod(headerMethod)); + + #ifndef _7ZIP_ST + methodMode.NumThreads = _numThreads; + methodMode.MultiThreadMixer = _useMultiThreadMixer; + headerMethod.NumThreads = 1; + headerMethod.MultiThreadMixer = _useMultiThreadMixer; + #endif + + CMyComPtr getPassword2; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2); + + methodMode.PasswordIsDefined = false; + methodMode.Password.Wipe_and_Empty(); + if (getPassword2) + { + CMyComBSTR_Wipe password; + Int32 passwordIsDefined; + RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password)); + methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); + if (methodMode.PasswordIsDefined && password) + methodMode.Password = password; + } + + bool compressMainHeader = _compressHeaders; // check it + + bool encryptHeaders = false; + + #ifndef _NO_CRYPTO + if (!methodMode.PasswordIsDefined && _passwordIsDefined) + { + // if header is compressed, we use that password for updated archive + methodMode.PasswordIsDefined = true; + methodMode.Password = _password; + } + #endif + + if (methodMode.PasswordIsDefined) + { + if (_encryptHeadersSpecified) + encryptHeaders = _encryptHeaders; + #ifndef _NO_CRYPTO + else + encryptHeaders = _passwordIsDefined; + #endif + compressMainHeader = true; + if (encryptHeaders) + { + headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; + headerMethod.Password = methodMode.Password; + } + } + + if (numItems < 2) + compressMainHeader = false; + + int level = GetLevel(); + + CUpdateOptions options; + options.Method = &methodMode; + options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL; + options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted); + options.MaxFilter = (level >= 8); + options.AnalysisLevel = GetAnalysisLevel(); + + options.HeaderOptions.CompressMainHeader = compressMainHeader; + /* + options.HeaderOptions.WriteCTime = Write_CTime; + options.HeaderOptions.WriteATime = Write_ATime; + options.HeaderOptions.WriteMTime = Write_MTime; + options.HeaderOptions.WriteAttrib = Write_Attrib; + */ + + options.NumSolidFiles = _numSolidFiles; + options.NumSolidBytes = _numSolidBytes; + options.SolidExtension = _solidExtension; + options.UseTypeSorting = _useTypeSorting; + + options.RemoveSfxBlock = _removeSfxBlock; + // options.VolumeMode = _volumeMode; + + options.MultiThreadMixer = _useMultiThreadMixer; + + COutArchive archive; + CArchiveDatabaseOut newDatabase; + + CMyComPtr getPassword; + updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword); + + /* + if (secureBlocks.Sorted.Size() > 1) + { + secureBlocks.GetReverseMap(); + for (int i = 0; i < updateItems.Size(); i++) + { + int &secureIndex = updateItems[i].SecureIndex; + secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex]; + } + } + */ + + res = Update( + EXTERNAL_CODECS_VARS + #ifdef _7Z_VOL + volume ? volume->Stream: 0, + volume ? db : 0, + #else + _inStream, + db, + #endif + updateItems, + // treeFolders, + // secureBlocks, + archive, newDatabase, outStream, updateCallback, options + #ifndef _NO_CRYPTO + , getPassword + #endif + ); + + RINOK(res); + + updateItems.ClearAndFree(); + + return archive.WriteDatabase(EXTERNAL_CODECS_VARS + newDatabase, options.HeaderMethod, options.HeaderOptions); + + COM_TRY_END +} + +static HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream) +{ + stream = 0; + { + unsigned index = ParseStringToUInt32(srcString, coder); + if (index == 0) + return E_INVALIDARG; + srcString.DeleteFrontal(index); + } + if (srcString[0] == 's') + { + srcString.Delete(0); + unsigned index = ParseStringToUInt32(srcString, stream); + if (index == 0) + return E_INVALIDARG; + srcString.DeleteFrontal(index); + } + return S_OK; +} + +void COutHandler::InitProps7z() +{ + _removeSfxBlock = false; + _compressHeaders = true; + _encryptHeadersSpecified = false; + _encryptHeaders = false; + // _useParents = false; + + Write_CTime.Init(); + Write_ATime.Init(); + Write_MTime.Init(); + Write_Attrib.Init(); + + _useMultiThreadMixer = true; + + // _volumeMode = false; + + InitSolid(); + _useTypeSorting = false; +} + +void COutHandler::InitProps() +{ + CMultiMethodProps::Init(); + InitProps7z(); +} + + + +HRESULT COutHandler::SetSolidFromString(const UString &s) +{ + UString s2 = s; + s2.MakeLower_Ascii(); + for (unsigned i = 0; i < s2.Len();) + { + const wchar_t *start = ((const wchar_t *)s2) + i; + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(start, &end); + if (start == end) + { + if (s2[i++] != 'e') + return E_INVALIDARG; + _solidExtension = true; + continue; + } + i += (unsigned)(end - start); + if (i == s2.Len()) + return E_INVALIDARG; + wchar_t c = s2[i++]; + if (c == 'f') + { + if (v < 1) + v = 1; + _numSolidFiles = v; + } + else + { + unsigned numBits; + switch (c) + { + case 'b': numBits = 0; break; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return E_INVALIDARG; + } + _numSolidBytes = (v << numBits); + _numSolidBytesDefined = true; + /* + if (_numSolidBytes == 0) + _numSolidFiles = 1; + */ + } + } + return S_OK; +} + +HRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value) +{ + bool isSolid; + switch (value.vt) + { + case VT_EMPTY: isSolid = true; break; + case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; + case VT_BSTR: + if (StringToBool(value.bstrVal, isSolid)) + break; + return SetSolidFromString(value.bstrVal); + default: return E_INVALIDARG; + } + if (isSolid) + InitSolid(); + else + _numSolidFiles = 1; + return S_OK; +} + +static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest) +{ + RINOK(PROPVARIANT_to_bool(prop, dest.Val)); + dest.Def = true; + return S_OK; +} + +HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == L's') + { + name.Delete(0); + if (name.IsEmpty()) + return SetSolidFromPROPVARIANT(value); + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + return SetSolidFromString(name); + } + + UInt32 number; + unsigned index = ParseStringToUInt32(name, number); + // UString realName = name.Ptr(index); + if (index == 0) + { + if (name.IsEqualTo("rsfx")) return PROPVARIANT_to_bool(value, _removeSfxBlock); + if (name.IsEqualTo("hc")) return PROPVARIANT_to_bool(value, _compressHeaders); + // if (name.IsEqualToNoCase(L"HS")) return PROPVARIANT_to_bool(value, _useParents); + + if (name.IsEqualTo("hcf")) + { + bool compressHeadersFull = true; + RINOK(PROPVARIANT_to_bool(value, compressHeadersFull)); + return compressHeadersFull ? S_OK: E_INVALIDARG; + } + + if (name.IsEqualTo("he")) + { + RINOK(PROPVARIANT_to_bool(value, _encryptHeaders)); + _encryptHeadersSpecified = true; + return S_OK; + } + + if (name.IsEqualTo("tc")) return PROPVARIANT_to_BoolPair(value, Write_CTime); + if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime); + if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime); + + if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib); + + if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer); + + if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); + + // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); + } + return CMultiMethodProps::SetProperty(name, value); +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) +{ + COM_TRY_BEGIN + _bonds.Clear(); + InitProps(); + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &value = values[i]; + + if (name[0] == 'b') + { + if (value.vt != VT_EMPTY) + return E_INVALIDARG; + name.Delete(0); + + CBond2 bond; + RINOK(ParseBond(name, bond.OutCoder, bond.OutStream)); + if (name[0] != ':') + return E_INVALIDARG; + name.Delete(0); + UInt32 inStream = 0; + RINOK(ParseBond(name, bond.InCoder, inStream)); + if (inStream != 0) + return E_INVALIDARG; + if (!name.IsEmpty()) + return E_INVALIDARG; + _bonds.Add(bond); + continue; + } + + RINOK(SetProperty(name, value)); + } + + unsigned numEmptyMethods = GetNumEmptyMethods(); + if (numEmptyMethods > 0) + { + unsigned k; + for (k = 0; k < _bonds.Size(); k++) + { + const CBond2 &bond = _bonds[k]; + if (bond.InCoder < (UInt32)numEmptyMethods || + bond.OutCoder < (UInt32)numEmptyMethods) + return E_INVALIDARG; + } + for (k = 0; k < _bonds.Size(); k++) + { + CBond2 &bond = _bonds[k]; + bond.InCoder -= (UInt32)numEmptyMethods; + bond.OutCoder -= (UInt32)numEmptyMethods; + } + _methods.DeleteFrontal(numEmptyMethods); + } + + FOR_VECTOR (k, _bonds) + { + const CBond2 &bond = _bonds[k]; + if (bond.InCoder >= (UInt32)_methods.Size() || + bond.OutCoder >= (UInt32)_methods.Size()) + return E_INVALIDARG; + } + + return S_OK; + COM_TRY_END +} + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.cpp new file mode 100644 index 0000000..acff2fd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.cpp @@ -0,0 +1,19 @@ +// 7zHeader.cpp + +#include "StdAfx.h" + +#include "7zHeader.h" + +namespace NArchive { +namespace N7z { + +Byte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; +#ifdef _7Z_VOL +Byte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; +#endif + +// We can change signature. So file doesn't contain correct signature. +// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } }; +// static SignatureInitializer g_SignatureInitializer; + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.h new file mode 100644 index 0000000..e1bbc0a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zHeader.h @@ -0,0 +1,149 @@ +// 7z/7zHeader.h + +#ifndef __7Z_HEADER_H +#define __7Z_HEADER_H + +#include "../../../Common/MyTypes.h" + +namespace NArchive { +namespace N7z { + +const unsigned kSignatureSize = 6; +extern Byte kSignature[kSignatureSize]; + +// #define _7Z_VOL +// 7z-MultiVolume is not finished yet. +// It can work already, but I still do not like some +// things of that new multivolume format. +// So please keep it commented. + +#ifdef _7Z_VOL +extern Byte kFinishSignature[kSignatureSize]; +#endif + +struct CArchiveVersion +{ + Byte Major; + Byte Minor; +}; + +const Byte kMajorVersion = 0; + +struct CStartHeader +{ + UInt64 NextHeaderOffset; + UInt64 NextHeaderSize; + UInt32 NextHeaderCRC; +}; + +const UInt32 kStartHeaderSize = 20; + +#ifdef _7Z_VOL +struct CFinishHeader: public CStartHeader +{ + UInt64 ArchiveStartOffset; // data offset from end if that struct + UInt64 AdditionalStartBlockSize; // start signature & start header size +}; + +const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; +#endif + +namespace NID +{ + enum EEnum + { + kEnd, + + kHeader, + + kArchiveProperties, + + kAdditionalStreamsInfo, + kMainStreamsInfo, + kFilesInfo, + + kPackInfo, + kUnpackInfo, + kSubStreamsInfo, + + kSize, + kCRC, + + kFolder, + + kCodersUnpackSize, + kNumUnpackStream, + + kEmptyStream, + kEmptyFile, + kAnti, + + kName, + kCTime, + kATime, + kMTime, + kWinAttrib, + kComment, + + kEncodedHeader, + + kStartPos, + kDummy + + // kNtSecure, + // kParent, + // kIsAux + }; +} + + +const UInt32 k_Copy = 0; +const UInt32 k_Delta = 3; + +const UInt32 k_LZMA2 = 0x21; + +const UInt32 k_SWAP2 = 0x20302; +const UInt32 k_SWAP4 = 0x20304; + +const UInt32 k_LZMA = 0x30101; +const UInt32 k_PPMD = 0x30401; + +const UInt32 k_Deflate = 0x40108; +const UInt32 k_Deflate64 = 0x40109; +const UInt32 k_BZip2 = 0x40202; + +const UInt32 k_BCJ = 0x3030103; +const UInt32 k_BCJ2 = 0x303011B; +const UInt32 k_PPC = 0x3030205; +const UInt32 k_IA64 = 0x3030401; +const UInt32 k_ARM = 0x3030501; +const UInt32 k_ARMT = 0x3030701; +const UInt32 k_SPARC = 0x3030805; + +const UInt32 k_AES = 0x6F10701; + + +static inline bool IsFilterMethod(UInt64 m) +{ + if (m > (UInt64)0xFFFFFFFF) + return false; + switch ((UInt32)m) + { + case k_Delta: + case k_BCJ: + case k_BCJ2: + case k_PPC: + case k_IA64: + case k_ARM: + case k_ARMT: + case k_SPARC: + case k_SWAP2: + case k_SWAP4: + return true; + } + return false; +} + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.cpp new file mode 100644 index 0000000..7134595 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.cpp @@ -0,0 +1,1710 @@ +// 7zIn.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "../../../../C/7zCrc.h" +#include "../../../../C/CpuArch.h" + +// #include "../../../Common/UTFConvert.h" + +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "7zDecode.h" +#include "7zIn.h" + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) +#define Get64(p) GetUi64(p) + +// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader +#ifndef _SFX +#define FORMAT_7Z_RECOVERY +#endif + +using namespace NWindows; +using namespace NCOM; + +namespace NArchive { +namespace N7z { + +unsigned BoolVector_CountSum(const CBoolVector &v); +unsigned BoolVector_CountSum(const CBoolVector &v) +{ + unsigned sum = 0; + const unsigned size = v.Size(); + for (unsigned i = 0; i < size; i++) + if (v[i]) + sum++; + return sum; +} + +static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) +{ + return (i < v.Size() ? v[i] : false); +} + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) +{ + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; +} + + +class CInArchiveException {}; +class CUnsupportedFeatureException: public CInArchiveException {}; + +MY_ATTR_NORETURN +static void ThrowException() { throw CInArchiveException(); } +MY_ATTR_NORETURN +static inline void ThrowEndOfData() { ThrowException(); } +MY_ATTR_NORETURN +static inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); } +MY_ATTR_NORETURN +static inline void ThrowIncorrect() { ThrowException(); } + +class CStreamSwitch +{ + CInArchive *_archive; + bool _needRemove; + bool _needUpdatePos; +public: + CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {} + ~CStreamSwitch() { Remove(); } + void Remove(); + void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos); + void Set(CInArchive *archive, const CByteBuffer &byteBuffer); + void Set(CInArchive *archive, const CObjectVector *dataVector); +}; + +void CStreamSwitch::Remove() +{ + if (_needRemove) + { + if (_archive->_inByteBack->GetRem() != 0) + _archive->ThereIsHeaderError = true; + _archive->DeleteByteStream(_needUpdatePos); + _needRemove = false; + } +} + +void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos) +{ + Remove(); + _archive = archive; + _archive->AddByteStream(data, size); + _needRemove = true; + _needUpdatePos = needUpdatePos; +} + +void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) +{ + Set(archive, byteBuffer, byteBuffer.Size(), false); +} + +void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) +{ + Remove(); + Byte external = archive->ReadByte(); + if (external != 0) + { + if (!dataVector) + ThrowIncorrect(); + CNum dataIndex = archive->ReadNum(); + if (dataIndex >= dataVector->Size()) + ThrowIncorrect(); + Set(archive, (*dataVector)[dataIndex]); + } +} + +void CInArchive::AddByteStream(const Byte *buf, size_t size) +{ + if (_numInByteBufs == kNumBufLevelsMax) + ThrowIncorrect(); + _inByteBack = &_inByteVector[_numInByteBufs++]; + _inByteBack->Init(buf, size); +} + + +Byte CInByte2::ReadByte() +{ + if (_pos >= _size) + ThrowEndOfData(); + return _buffer[_pos++]; +} + +void CInByte2::ReadBytes(Byte *data, size_t size) +{ + if (size == 0) + return; + if (size > _size - _pos) + ThrowEndOfData(); + memcpy(data, _buffer + _pos, size); + _pos += size; +} + +void CInByte2::SkipData(UInt64 size) +{ + if (size > _size - _pos) + ThrowEndOfData(); + _pos += (size_t)size; +} + +void CInByte2::SkipData() +{ + SkipData(ReadNumber()); +} + +static UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed) +{ + if (size == 0) + { + processed = 0; + return 0; + } + + unsigned b = *p++; + size--; + + if ((b & 0x80) == 0) + { + processed = 1; + return b; + } + + if (size == 0) + { + processed = 0; + return 0; + } + + UInt64 value = (UInt64)*p; + p++; + size--; + + for (unsigned i = 1; i < 8; i++) + { + unsigned mask = (unsigned)0x80 >> i; + if ((b & mask) == 0) + { + UInt64 high = b & (mask - 1); + value |= (high << (i * 8)); + processed = i + 1; + return value; + } + + if (size == 0) + { + processed = 0; + return 0; + } + + value |= ((UInt64)*p << (i * 8)); + p++; + size--; + } + + processed = 9; + return value; +} + +UInt64 CInByte2::ReadNumber() +{ + size_t processed; + UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed); + if (processed == 0) + ThrowEndOfData(); + _pos += processed; + return res; +} + +CNum CInByte2::ReadNum() +{ + /* + if (_pos < _size) + { + Byte val = _buffer[_pos]; + if ((unsigned)val < 0x80) + { + _pos++; + return (unsigned)val; + } + } + */ + UInt64 value = ReadNumber(); + if (value > kNumMax) + ThrowUnsupported(); + return (CNum)value; +} + +UInt32 CInByte2::ReadUInt32() +{ + if (_pos + 4 > _size) + ThrowEndOfData(); + UInt32 res = Get32(_buffer + _pos); + _pos += 4; + return res; +} + +UInt64 CInByte2::ReadUInt64() +{ + if (_pos + 8 > _size) + ThrowEndOfData(); + UInt64 res = Get64(_buffer + _pos); + _pos += 8; + return res; +} + +#define CHECK_SIGNATURE if (p[0] != '7' || p[1] != 'z' || p[2] != 0xBC || p[3] != 0xAF || p[4] != 0x27 || p[5] != 0x1C) return false; + +static inline bool TestSignature(const Byte *p) +{ + CHECK_SIGNATURE + return CrcCalc(p + 12, 20) == Get32(p + 8); +} + +#ifdef FORMAT_7Z_RECOVERY +static inline bool TestSignature2(const Byte *p) +{ + CHECK_SIGNATURE; + if (CrcCalc(p + 12, 20) == Get32(p + 8)) + return true; + for (unsigned i = 8; i < kHeaderSize; i++) + if (p[i] != 0) + return false; + return (p[6] != 0 || p[7] != 0); +} +#else +#define TestSignature2(p) TestSignature(p) +#endif + +HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); + + if (TestSignature2(_header)) + return S_OK; + if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0) + return S_FALSE; + + const UInt32 kBufSize = 1 << 15; + CByteArr buf(kBufSize); + memcpy(buf, _header, kHeaderSize); + UInt64 offset = 0; + + for (;;) + { + UInt32 readSize = kBufSize - kHeaderSize; + if (searchHeaderSizeLimit) + { + UInt64 rem = *searchHeaderSizeLimit - offset; + if (readSize > rem) + readSize = (UInt32)rem; + if (readSize == 0) + return S_FALSE; + } + + UInt32 processed = 0; + RINOK(stream->Read(buf + kHeaderSize, readSize, &processed)); + if (processed == 0) + return S_FALSE; + + for (UInt32 pos = 0;;) + { + const Byte *p = buf + pos + 1; + const Byte *lim = buf + processed; + for (; p <= lim; p += 4) + { + if (p[0] == '7') break; + if (p[1] == '7') { p += 1; break; } + if (p[2] == '7') { p += 2; break; } + if (p[3] == '7') { p += 3; break; } + }; + if (p > lim) + break; + pos = (UInt32)(p - buf); + if (TestSignature(p)) + { + memcpy(_header, p, kHeaderSize); + _arhiveBeginStreamPosition += offset + pos; + return stream->Seek((Int64)(_arhiveBeginStreamPosition + kHeaderSize), STREAM_SEEK_SET, NULL); + } + } + + offset += processed; + memmove(buf, buf + processed, kHeaderSize); + } +} + +// S_FALSE means that file is not archive +HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) +{ + HeadersSize = 0; + Close(); + RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) + RINOK(stream->Seek(0, STREAM_SEEK_END, &_fileEndPosition)) + RINOK(stream->Seek((Int64)_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL)) + RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); + _stream = stream; + return S_OK; +} + +void CInArchive::Close() +{ + _numInByteBufs = 0; + _stream.Release(); + ThereIsHeaderError = false; +} + +void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) +{ + for (;;) + { + if (ReadID() == NID::kEnd) + break; + SkipData(); + } +} + +// CFolder &folder can be non empty. So we must set all fields + +void CInByte2::ParseFolder(CFolder &folder) +{ + UInt32 numCoders = ReadNum(); + + if (numCoders == 0) + ThrowUnsupported(); + + folder.Coders.SetSize(numCoders); + + UInt32 numInStreams = 0; + UInt32 i; + for (i = 0; i < numCoders; i++) + { + CCoderInfo &coder = folder.Coders[i]; + { + Byte mainByte = ReadByte(); + if ((mainByte & 0xC0) != 0) + ThrowUnsupported(); + unsigned idSize = (mainByte & 0xF); + if (idSize > 8 || idSize > GetRem()) + ThrowUnsupported(); + const Byte *longID = GetPtr(); + UInt64 id = 0; + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + SkipDataNoCheck(idSize); + coder.MethodID = id; + + if ((mainByte & 0x10) != 0) + { + coder.NumStreams = ReadNum(); + /* numOutStreams = */ ReadNum(); + } + else + { + coder.NumStreams = 1; + } + + if ((mainByte & 0x20) != 0) + { + CNum propsSize = ReadNum(); + coder.Props.Alloc((size_t)propsSize); + ReadBytes((Byte *)coder.Props, (size_t)propsSize); + } + else + coder.Props.Free(); + } + numInStreams += coder.NumStreams; + } + + UInt32 numBonds = numCoders - 1; + folder.Bonds.SetSize(numBonds); + for (i = 0; i < numBonds; i++) + { + CBond &bp = folder.Bonds[i]; + bp.PackIndex = ReadNum(); + bp.UnpackIndex = ReadNum(); + } + + if (numInStreams < numBonds) + ThrowUnsupported(); + UInt32 numPackStreams = numInStreams - numBonds; + folder.PackStreams.SetSize(numPackStreams); + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (folder.FindBond_for_PackStream(i) < 0) + { + folder.PackStreams[0] = i; + break; + } + if (i == numInStreams) + ThrowUnsupported(); + } + else + for (i = 0; i < numPackStreams; i++) + folder.PackStreams[i] = ReadNum(); +} + +void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const +{ + size_t startPos = FoCodersDataOffset[folderIndex]; + CInByte2 inByte; + inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); + inByte.ParseFolder(folder); + if (inByte.GetRem() != 0) + throw 20120424; +} + + +void CDatabase::GetPath(unsigned index, UString &path) const +{ + path.Empty(); + if (!NameOffsets || !NamesBuf) + return; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset; + + if (size >= (1 << 28)) + return; + + wchar_t *s = path.GetBuf((unsigned)size - 1); + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + + #if defined(_WIN32) && defined(MY_CPU_LE) + + wmemcpy(s, (const wchar_t *)(const void *)p, size); + + #else + + for (size_t i = 0; i < size; i++) + { + *s = Get16(p); + p += 2; + s++; + } + + #endif + + path.ReleaseBuf_SetLen((unsigned)size - 1); +} + +HRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw() +{ + PropVariant_Clear(path); + if (!NameOffsets || !NamesBuf) + return S_OK; + + size_t offset = NameOffsets[index]; + size_t size = NameOffsets[index + 1] - offset; + + if (size >= (1 << 14)) + return S_OK; + + // (size) includes null terminator + + /* + #if WCHAR_MAX > 0xffff + + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + size = Utf16LE__Get_Num_WCHARs(p, size - 1); + // (size) doesn't include null terminator + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size)); + wchar_t *s = path->bstrVal; + wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s); + *sEnd = 0; + if (s + size != sEnd) return E_FAIL; + + #else + */ + + RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1)); + wchar_t *s = path->bstrVal; + const Byte *p = ((const Byte *)NamesBuf + offset * 2); + // Utf16LE__To_WCHARs_Sep(p, size, s); + + for (size_t i = 0; i < size; i++) + { + wchar_t c = Get16(p); + p += 2; + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + else if (c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme + #endif + *s++ = c; + } + + // #endif + + return S_OK; + + /* + unsigned cur = index; + unsigned size = 0; + + for (int i = 0;; i++) + { + size_t len = NameOffsets[cur + 1] - NameOffsets[cur]; + size += (unsigned)len; + if (i > 256 || len > (1 << 14) || size > (1 << 14)) + return PropVarEm_Set_Str(path, "[TOO-LONG]"); + cur = Files[cur].Parent; + if (cur < 0) + break; + } + size--; + + RINOK(PropVarEm_Alloc_Bstr(path, size)); + wchar_t *s = path->bstrVal; + s += size; + *s = 0; + cur = index; + + for (;;) + { + unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1); + const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2; + for (; len != 0; len--) + { + p -= 2; + --s; + wchar_t c = Get16(p); + if (c == '/') + c = WCHAR_PATH_SEPARATOR; + *s = c; + } + + const CFileItem &file = Files[cur]; + cur = file.Parent; + if (cur < 0) + return S_OK; + *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR); + } + */ +} + +void CInArchive::WaitId(UInt64 id) +{ + for (;;) + { + UInt64 type = ReadID(); + if (type == id) + return; + if (type == NID::kEnd) + ThrowIncorrect(); + SkipData(); + } +} + + +void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v) +{ + unsigned numItems = v.Defs.Size(); + v.Vals.ClearAndSetSize(numItems); + UInt32 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; + for (unsigned i = 0; i < numItems; i++) + { + UInt32 a = 0; + if (defs[i]) + a = ReadUInt32(); + p[i] = a; + } +} + + +void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs) +{ + ReadBoolVector2(numItems, crcs.Defs); + Read_UInt32_Vector(crcs); +} + + +#define k_Scan_NumCoders_MAX 64 +#define k_Scan_NumCodersStreams_in_Folder_MAX 64 + +void CInArchive::ReadPackInfo(CFolders &f) +{ + CNum numPackStreams = ReadNum(); + + WaitId(NID::kSize); + f.PackPositions.Alloc(numPackStreams + 1); + f.NumPackStreams = numPackStreams; + UInt64 sum = 0; + for (CNum i = 0; i < numPackStreams; i++) + { + f.PackPositions[i] = sum; + UInt64 packSize = ReadNumber(); + sum += packSize; + if (sum < packSize) + ThrowIncorrect(); + } + f.PackPositions[numPackStreams] = sum; + + UInt64 type; + for (;;) + { + type = ReadID(); + if (type == NID::kEnd) + return; + if (type == NID::kCRC) + { + CUInt32DefVector PackCRCs; + ReadHashDigests(numPackStreams, PackCRCs); + continue; + } + SkipData(); + } +} + +void CInArchive::ReadUnpackInfo( + const CObjectVector *dataVector, + CFolders &folders) +{ + WaitId(NID::kFolder); + CNum numFolders = ReadNum(); + + CNum numCodersOutStreams = 0; + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, dataVector); + const Byte *startBufPtr = _inByteBack->GetPtr(); + folders.NumFolders = numFolders; + + folders.FoStartPackStreamIndex.Alloc(numFolders + 1); + folders.FoToMainUnpackSizeIndex.Alloc(numFolders); + folders.FoCodersDataOffset.Alloc(numFolders + 1); + folders.FoToCoderUnpackSizes.Alloc(numFolders + 1); + + CBoolVector StreamUsed; + CBoolVector CoderUsed; + + CNum packStreamIndex = 0; + CNum fo; + CInByte2 *inByte = _inByteBack; + + for (fo = 0; fo < numFolders; fo++) + { + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 0; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); + + CNum numInStreams = 0; + CNum numCoders = inByte->ReadNum(); + + if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX) + ThrowUnsupported(); + + for (CNum ci = 0; ci < numCoders; ci++) + { + Byte mainByte = inByte->ReadByte(); + if ((mainByte & 0xC0) != 0) + ThrowUnsupported(); + + unsigned idSize = (mainByte & 0xF); + if (idSize > 8) + ThrowUnsupported(); + if (idSize > inByte->GetRem()) + ThrowEndOfData(); + const Byte *longID = inByte->GetPtr(); + UInt64 id = 0; + for (unsigned j = 0; j < idSize; j++) + id = ((id << 8) | longID[j]); + inByte->SkipDataNoCheck(idSize); + if (folders.ParsedMethods.IDs.Size() < 128) + folders.ParsedMethods.IDs.AddToUniqueSorted(id); + + CNum coderInStreams = 1; + if ((mainByte & 0x10) != 0) + { + coderInStreams = inByte->ReadNum(); + if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) + ThrowUnsupported(); + if (inByte->ReadNum() != 1) + ThrowUnsupported(); + } + + numInStreams += coderInStreams; + if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) + ThrowUnsupported(); + + if ((mainByte & 0x20) != 0) + { + CNum propsSize = inByte->ReadNum(); + if (propsSize > inByte->GetRem()) + ThrowEndOfData(); + if (id == k_LZMA2 && propsSize == 1) + { + Byte v = *_inByteBack->GetPtr(); + if (folders.ParsedMethods.Lzma2Prop < v) + folders.ParsedMethods.Lzma2Prop = v; + } + else if (id == k_LZMA && propsSize == 5) + { + UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1); + if (folders.ParsedMethods.LzmaDic < dicSize) + folders.ParsedMethods.LzmaDic = dicSize; + } + inByte->SkipDataNoCheck((size_t)propsSize); + } + } + + if (numCoders == 1 && numInStreams == 1) + { + indexOfMainStream = 0; + numPackStreams = 1; + } + else + { + UInt32 i; + CNum numBonds = numCoders - 1; + if (numInStreams < numBonds) + ThrowUnsupported(); + + BoolVector_Fill_False(StreamUsed, numInStreams); + BoolVector_Fill_False(CoderUsed, numCoders); + + for (i = 0; i < numBonds; i++) + { + CNum index = ReadNum(); + if (index >= numInStreams || StreamUsed[index]) + ThrowUnsupported(); + StreamUsed[index] = true; + + index = ReadNum(); + if (index >= numCoders || CoderUsed[index]) + ThrowUnsupported(); + CoderUsed[index] = true; + } + + numPackStreams = numInStreams - numBonds; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + { + CNum index = inByte->ReadNum(); // PackStreams + if (index >= numInStreams || StreamUsed[index]) + ThrowUnsupported(); + StreamUsed[index] = true; + } + + for (i = 0; i < numCoders; i++) + if (!CoderUsed[i]) + { + indexOfMainStream = i; + break; + } + + if (i == numCoders) + ThrowUnsupported(); + } + + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + numCodersOutStreams += numCoders; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + if (numPackStreams > folders.NumPackStreams - packStreamIndex) + ThrowIncorrect(); + packStreamIndex += numPackStreams; + folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream; + } + + const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr); + folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; + folders.FoStartPackStreamIndex[fo] = packStreamIndex; + folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); + folders.CodersData.CopyFrom(startBufPtr, dataSize); + + // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); + } + + WaitId(NID::kCodersUnpackSize); + folders.CoderUnpackSizes.Alloc(numCodersOutStreams); + for (CNum i = 0; i < numCodersOutStreams; i++) + folders.CoderUnpackSizes[i] = ReadNumber(); + + for (;;) + { + UInt64 type = ReadID(); + if (type == NID::kEnd) + return; + if (type == NID::kCRC) + { + ReadHashDigests(numFolders, folders.FolderCRCs); + continue; + } + SkipData(); + } +} + +void CInArchive::ReadSubStreamsInfo( + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests) +{ + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + CNum i; + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = 1; + + UInt64 type; + + for (;;) + { + type = ReadID(); + if (type == NID::kNumUnpackStream) + { + for (i = 0; i < folders.NumFolders; i++) + folders.NumUnpackStreamsVector[i] = ReadNum(); + continue; + } + if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) + break; + SkipData(); + } + + if (type == NID::kSize) + { + for (i = 0; i < folders.NumFolders; i++) + { + // v3.13 incorrectly worked with empty folders + // v4.07: we check that folder is empty + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 0) + continue; + UInt64 sum = 0; + for (CNum j = 1; j < numSubstreams; j++) + { + UInt64 size = ReadNumber(); + unpackSizes.Add(size); + sum += size; + if (sum < size) + ThrowIncorrect(); + } + UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); + if (folderUnpackSize < sum) + ThrowIncorrect(); + unpackSizes.Add(folderUnpackSize - sum); + } + type = ReadID(); + } + else + { + for (i = 0; i < folders.NumFolders; i++) + { + /* v9.26 - v9.29 incorrectly worked: + if (folders.NumUnpackStreamsVector[i] == 0), it threw error */ + CNum val = folders.NumUnpackStreamsVector[i]; + if (val > 1) + ThrowIncorrect(); + if (val == 1) + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + } + } + + unsigned numDigests = 0; + for (i = 0; i < folders.NumFolders; i++) + { + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i)) + numDigests += numSubstreams; + } + + for (;;) + { + if (type == NID::kEnd) + break; + if (type == NID::kCRC) + { + // CUInt32DefVector digests2; + // ReadHashDigests(numDigests, digests2); + CBoolVector digests2; + ReadBoolVector2(numDigests, digests2); + + digests.ClearAndSetSize(unpackSizes.Size()); + + unsigned k = 0; + unsigned k2 = 0; + + for (i = 0; i < folders.NumFolders; i++) + { + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) + { + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + bool defined = digests2[k2++]; + digests.Defs[k] = defined; + UInt32 crc = 0; + if (defined) + crc = ReadUInt32(); + digests.Vals[k] = crc; + k++; + } + } + // if (k != unpackSizes.Size()) throw 1234567; + } + else + SkipData(); + + type = ReadID(); + } + + if (digests.Defs.Size() != unpackSizes.Size()) + { + digests.ClearAndSetSize(unpackSizes.Size()); + unsigned k = 0; + for (i = 0; i < folders.NumFolders; i++) + { + CNum numSubstreams = folders.NumUnpackStreamsVector[i]; + if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i)) + { + digests.Defs[k] = true; + digests.Vals[k] = folders.FolderCRCs.Vals[i]; + k++; + } + else for (CNum j = 0; j < numSubstreams; j++) + { + digests.Defs[k] = false; + digests.Vals[k] = 0; + k++; + } + } + } +} + + + +void CInArchive::ReadStreamsInfo( + const CObjectVector *dataVector, + UInt64 &dataOffset, + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests) +{ + UInt64 type = ReadID(); + + if (type == NID::kPackInfo) + { + dataOffset = ReadNumber(); + if (dataOffset > _rangeLimit) + ThrowIncorrect(); + ReadPackInfo(folders); + if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset) + ThrowIncorrect(); + type = ReadID(); + } + + if (type == NID::kUnpackInfo) + { + ReadUnpackInfo(dataVector, folders); + type = ReadID(); + } + + if (folders.NumFolders != 0 && !folders.PackPositions) + { + // if there are folders, we need PackPositions also + folders.PackPositions.Alloc(1); + folders.PackPositions[0] = 0; + } + + if (type == NID::kSubStreamsInfo) + { + ReadSubStreamsInfo(folders, unpackSizes, digests); + type = ReadID(); + } + else + { + folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); + /* If digests.Defs.Size() == 0, it means that there are no crcs. + So we don't need to fill digests with values. */ + // digests.Vals.ClearAndSetSize(folders.NumFolders); + // BoolVector_Fill_False(digests.Defs, folders.NumFolders); + for (CNum i = 0; i < folders.NumFolders; i++) + { + folders.NumUnpackStreamsVector[i] = 1; + unpackSizes.Add(folders.GetFolderUnpackSize(i)); + // digests.Vals[i] = 0; + } + } + + if (type != NID::kEnd) + ThrowIncorrect(); +} + +void CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v) +{ + v.ClearAndSetSize(numItems); + Byte b = 0; + Byte mask = 0; + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) + { + if (mask == 0) + { + b = ReadByte(); + mask = 0x80; + } + p[i] = ((b & mask) != 0); + mask = (Byte)(mask >> 1); + } +} + +void CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v) +{ + Byte allAreDefined = ReadByte(); + if (allAreDefined == 0) + { + ReadBoolVector(numItems, v); + return; + } + v.ClearAndSetSize(numItems); + bool *p = &v[0]; + for (unsigned i = 0; i < numItems; i++) + p[i] = true; +} + +void CInArchive::ReadUInt64DefVector(const CObjectVector &dataVector, + CUInt64DefVector &v, unsigned numItems) +{ + ReadBoolVector2(numItems, v.Defs); + + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + + v.Vals.ClearAndSetSize(numItems); + UInt64 *p = &v.Vals[0]; + const bool *defs = &v.Defs[0]; + + for (unsigned i = 0; i < numItems; i++) + { + UInt64 t = 0; + if (defs[i]) + t = ReadUInt64(); + p[i] = t; + } +} + +HRESULT CInArchive::ReadAndDecodePackedStreams( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 baseOffset, + UInt64 &dataOffset, CObjectVector &dataVector + _7Z_DECODER_CRYPRO_VARS_DECL + ) +{ + CFolders folders; + CRecordVector unpackSizes; + CUInt32DefVector digests; + + ReadStreamsInfo(NULL, + dataOffset, + folders, + unpackSizes, + digests); + + CDecoder decoder(_useMixerMT); + + for (CNum i = 0; i < folders.NumFolders; i++) + { + CByteBuffer &data = dataVector.AddNew(); + const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i); + const size_t unpackSize = (size_t)unpackSize64; + if (unpackSize != unpackSize64) + ThrowUnsupported(); + data.Alloc(unpackSize); + + CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr outStream = outStreamSpec; + outStreamSpec->Init(data, unpackSize); + + bool dataAfterEnd_Error = false; + + HRESULT result = decoder.Decode( + EXTERNAL_CODECS_LOC_VARS + _stream, baseOffset + dataOffset, + folders, i, + NULL, // &unpackSize64 + + outStream, + NULL, // *compressProgress + + NULL // **inStreamMainRes + , dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS + #if !defined(_7ZIP_ST) + , false // mtMode + , 1 // numThreads + , 0 // memUsage + #endif + ); + + RINOK(result); + + if (dataAfterEnd_Error) + ThereIsHeaderError = true; + + if (unpackSize != outStreamSpec->GetPos()) + ThrowIncorrect(); + + if (folders.FolderCRCs.ValidAndDefined(i)) + if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i]) + ThrowIncorrect(); + } + + if (folders.PackPositions) + HeadersSize += folders.PackPositions[folders.NumPackStreams]; + + return S_OK; +} + +HRESULT CInArchive::ReadHeader( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ) +{ + UInt64 type = ReadID(); + + if (type == NID::kArchiveProperties) + { + ReadArchiveProperties(db.ArcInfo); + type = ReadID(); + } + + CObjectVector dataVector; + + if (type == NID::kAdditionalStreamsInfo) + { + HRESULT result = ReadAndDecodePackedStreams( + EXTERNAL_CODECS_LOC_VARS + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, + dataVector + _7Z_DECODER_CRYPRO_VARS + ); + RINOK(result); + db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader; + type = ReadID(); + } + + CRecordVector unpackSizes; + CUInt32DefVector digests; + + if (type == NID::kMainStreamsInfo) + { + ReadStreamsInfo(&dataVector, + db.ArcInfo.DataStartPosition, + (CFolders &)db, + unpackSizes, + digests); + db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader; + type = ReadID(); + } + + if (type == NID::kFilesInfo) + { + + const CNum numFiles = ReadNum(); + + db.ArcInfo.FileInfoPopIDs.Add(NID::kSize); + // if (!db.PackSizes.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo); + if (numFiles > 0 && !digests.Defs.IsEmpty()) + db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC); + + CBoolVector emptyStreamVector; + CBoolVector emptyFileVector; + CBoolVector antiFileVector; + CNum numEmptyStreams = 0; + + for (;;) + { + const UInt64 type2 = ReadID(); + if (type2 == NID::kEnd) + break; + UInt64 size = ReadNumber(); + if (size > _inByteBack->GetRem()) + ThrowIncorrect(); + CStreamSwitch switchProp; + switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true); + bool addPropIdToList = true; + bool isKnownType = true; + if (type2 > ((UInt32)1 << 30)) + isKnownType = false; + else switch ((UInt32)type2) + { + case NID::kName: + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + size_t rem = _inByteBack->GetRem(); + db.NamesBuf.Alloc(rem); + ReadBytes(db.NamesBuf, rem); + db.NameOffsets.Alloc(numFiles + 1); + size_t pos = 0; + unsigned i; + for (i = 0; i < numFiles; i++) + { + const size_t curRem = (rem - pos) / 2; + const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); + size_t j; + for (j = 0; j < curRem && buf[j] != 0; j++); + if (j == curRem) + ThrowEndOfData(); + db.NameOffsets[i] = pos / 2; + pos += j * 2 + 2; + } + db.NameOffsets[i] = pos / 2; + if (pos != rem) + ThereIsHeaderError = true; + break; + } + + case NID::kWinAttrib: + { + ReadBoolVector2(numFiles, db.Attrib.Defs); + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + Read_UInt32_Vector(db.Attrib); + break; + } + + /* + case NID::kIsAux: + { + ReadBoolVector(numFiles, db.IsAux); + break; + } + case NID::kParent: + { + db.IsTree = true; + // CBoolVector boolVector; + // ReadBoolVector2(numFiles, boolVector); + // CStreamSwitch streamSwitch; + // streamSwitch.Set(this, &dataVector); + CBoolVector boolVector; + ReadBoolVector2(numFiles, boolVector); + + db.ThereAreAltStreams = false; + for (i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + // file.Parent = -1; + // if (boolVector[i]) + file.Parent = (int)ReadUInt32(); + file.IsAltStream = !boolVector[i]; + if (file.IsAltStream) + db.ThereAreAltStreams = true; + } + break; + } + */ + case NID::kEmptyStream: + { + ReadBoolVector(numFiles, emptyStreamVector); + numEmptyStreams = BoolVector_CountSum(emptyStreamVector); + emptyFileVector.Clear(); + antiFileVector.Clear(); + break; + } + case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; + case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; + case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break; + case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break; + case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break; + case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break; + case NID::kDummy: + { + for (UInt64 j = 0; j < size; j++) + if (ReadByte() != 0) + ThereIsHeaderError = true; + addPropIdToList = false; + break; + } + /* + case NID::kNtSecure: + { + try + { + { + CStreamSwitch streamSwitch; + streamSwitch.Set(this, &dataVector); + UInt32 numDescriptors = ReadUInt32(); + size_t offset = 0; + db.SecureOffsets.Clear(); + for (i = 0; i < numDescriptors; i++) + { + UInt32 size = ReadUInt32(); + db.SecureOffsets.Add(offset); + offset += size; + } + // ThrowIncorrect();; + db.SecureOffsets.Add(offset); + db.SecureBuf.SetCapacity(offset); + for (i = 0; i < numDescriptors; i++) + { + offset = db.SecureOffsets[i]; + ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset); + } + db.SecureIDs.Clear(); + for (unsigned i = 0; i < numFiles; i++) + { + db.SecureIDs.Add(ReadNum()); + // db.SecureIDs.Add(ReadUInt32()); + } + // ReadUInt32(); + if (_inByteBack->GetRem() != 0) + ThrowIncorrect();; + } + } + catch(CInArchiveException &) + { + ThereIsHeaderError = true; + addPropIdToList = isKnownType = false; + db.ClearSecure(); + } + break; + } + */ + default: + addPropIdToList = isKnownType = false; + } + if (isKnownType) + { + if (addPropIdToList) + db.ArcInfo.FileInfoPopIDs.Add(type2); + } + else + { + db.UnsupportedFeatureWarning = true; + _inByteBack->SkipRem(); + } + // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02) + if (_inByteBack->GetRem() != 0) + ThrowIncorrect(); + } + + type = ReadID(); // Read (NID::kEnd) end of headers + + if (numFiles - numEmptyStreams != unpackSizes.Size()) + ThrowUnsupported(); + + CNum emptyFileIndex = 0; + CNum sizeIndex = 0; + + const CNum numAntiItems = BoolVector_CountSum(antiFileVector); + + if (numAntiItems != 0) + db.IsAnti.ClearAndSetSize(numFiles); + + db.Files.ClearAndSetSize(numFiles); + + for (CNum i = 0; i < numFiles; i++) + { + CFileItem &file = db.Files[i]; + bool isAnti; + file.Crc = 0; + if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i)) + { + file.HasStream = true; + file.IsDir = false; + isAnti = false; + file.Size = unpackSizes[sizeIndex]; + file.CrcDefined = digests.ValidAndDefined(sizeIndex); + if (file.CrcDefined) + file.Crc = digests.Vals[sizeIndex]; + sizeIndex++; + } + else + { + file.HasStream = false; + file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex); + isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex); + emptyFileIndex++; + file.Size = 0; + file.CrcDefined = false; + } + if (numAntiItems != 0) + db.IsAnti[i] = isAnti; + } + + } + + db.FillLinks(); + + if (type != NID::kEnd || _inByteBack->GetRem() != 0) + { + db.UnsupportedFeatureWarning = true; + // ThrowIncorrect(); + } + + return S_OK; +} + + +void CDbEx::FillLinks() +{ + FolderStartFileIndex.Alloc(NumFolders); + FileIndexToFolderIndexMap.Alloc(Files.Size()); + + CNum folderIndex = 0; + CNum indexInFolder = 0; + unsigned i; + + for (i = 0; i < Files.Size(); i++) + { + bool emptyStream = !Files[i].HasStream; + if (indexInFolder == 0) + { + if (emptyStream) + { + FileIndexToFolderIndexMap[i] = kNumNoIndex; + continue; + } + // v3.13 incorrectly worked with empty folders + // v4.07: we skip empty folders + for (;;) + { + if (folderIndex >= NumFolders) + ThrowIncorrect(); + FolderStartFileIndex[folderIndex] = i; + if (NumUnpackStreamsVector[folderIndex] != 0) + break; + folderIndex++; + } + } + FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStream) + continue; + if (++indexInFolder >= NumUnpackStreamsVector[folderIndex]) + { + folderIndex++; + indexInFolder = 0; + } + } + + if (indexInFolder != 0) + { + folderIndex++; + // 18.06 + ThereIsHeaderError = true; + // ThrowIncorrect(); + } + + for (;;) + { + if (folderIndex >= NumFolders) + return; + FolderStartFileIndex[folderIndex] = i; + if (NumUnpackStreamsVector[folderIndex] != 0) + { + // 18.06 + ThereIsHeaderError = true; + // ThrowIncorrect(); + } + folderIndex++; + } +} + + +HRESULT CInArchive::ReadDatabase2( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ) +{ + db.Clear(); + db.ArcInfo.StartPosition = _arhiveBeginStreamPosition; + + db.ArcInfo.Version.Major = _header[6]; + db.ArcInfo.Version.Minor = _header[7]; + + if (db.ArcInfo.Version.Major != kMajorVersion) + { + // db.UnsupportedVersion = true; + return S_FALSE; + } + + UInt64 nextHeaderOffset = Get64(_header + 12); + UInt64 nextHeaderSize = Get64(_header + 20); + UInt32 nextHeaderCRC = Get32(_header + 28); + + #ifdef FORMAT_7Z_RECOVERY + UInt32 crcFromArc = Get32(_header + 8); + if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) + { + UInt64 cur, fileSize; + RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); + const unsigned kCheckSize = 512; + Byte buf[kCheckSize]; + RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize)); + const UInt64 rem = fileSize - cur; + unsigned checkSize = kCheckSize; + if (rem < kCheckSize) + checkSize = (unsigned)(rem); + if (checkSize < 3) + return S_FALSE; + RINOK(_stream->Seek((Int64)(fileSize - checkSize), STREAM_SEEK_SET, NULL)); + RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); + + if (buf[checkSize - 1] != 0) + return S_FALSE; + + unsigned i; + for (i = checkSize - 2;; i--) + { + if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) || + (buf[i] == NID::kHeader && buf[i + 1] == NID::kMainStreamsInfo)) + break; + if (i == 0) + return S_FALSE; + } + nextHeaderSize = checkSize - i; + nextHeaderOffset = rem - nextHeaderSize; + nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); + RINOK(_stream->Seek((Int64)cur, STREAM_SEEK_SET, NULL)); + db.StartHeaderWasRecovered = true; + } + else + #endif + { + // Crc was tested already at signature check + // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect(); + } + + db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; + db.PhySize = kHeaderSize; + + db.IsArc = false; + if ((Int64)nextHeaderOffset < 0 || + nextHeaderSize > ((UInt64)1 << 62)) + return S_FALSE; + + HeadersSize = kHeaderSize; + + if (nextHeaderSize == 0) + { + if (nextHeaderOffset != 0) + return S_FALSE; + db.IsArc = true; + db.HeadersSize = HeadersSize; + return S_OK; + } + + if (!db.StartHeaderWasRecovered) + db.IsArc = true; + + HeadersSize += nextHeaderSize; + // db.EndHeaderOffset = nextHeaderOffset; + _rangeLimit = nextHeaderOffset; + + db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; + if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize) + { + db.UnexpectedEnd = true; + return S_FALSE; + } + RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL)); + + size_t nextHeaderSize_t = (size_t)nextHeaderSize; + if (nextHeaderSize_t != nextHeaderSize) + return E_OUTOFMEMORY; + CByteBuffer buffer2(nextHeaderSize_t); + + RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t)); + + if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC) + ThrowIncorrect(); + + if (!db.StartHeaderWasRecovered) + db.PhySizeWasConfirmed = true; + + CStreamSwitch streamSwitch; + streamSwitch.Set(this, buffer2); + + CObjectVector dataVector; + + UInt64 type = ReadID(); + if (type != NID::kHeader) + { + if (type != NID::kEncodedHeader) + ThrowIncorrect(); + HRESULT result = ReadAndDecodePackedStreams( + EXTERNAL_CODECS_LOC_VARS + db.ArcInfo.StartPositionAfterHeader, + db.ArcInfo.DataStartPosition2, + dataVector + _7Z_DECODER_CRYPRO_VARS + ); + RINOK(result); + if (dataVector.Size() == 0) + return S_OK; + if (dataVector.Size() > 1) + ThrowIncorrect(); + streamSwitch.Remove(); + streamSwitch.Set(this, dataVector.Front()); + if (ReadID() != NID::kHeader) + ThrowIncorrect(); + } + + db.IsArc = true; + + db.HeadersSize = HeadersSize; + + return ReadHeader( + EXTERNAL_CODECS_LOC_VARS + db + _7Z_DECODER_CRYPRO_VARS + ); +} + + +HRESULT CInArchive::ReadDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ) +{ + try + { + HRESULT res = ReadDatabase2( + EXTERNAL_CODECS_LOC_VARS db + _7Z_DECODER_CRYPRO_VARS + ); + if (ThereIsHeaderError) + db.ThereIsHeaderError = true; + if (res == E_NOTIMPL) + ThrowUnsupported(); + return res; + } + catch(CUnsupportedFeatureException &) + { + db.UnsupportedFeatureError = true; + return S_FALSE; + } + catch(CInArchiveException &) + { + db.ThereIsHeaderError = true; + return S_FALSE; + } +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.h new file mode 100644 index 0000000..ffa1e4b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zIn.h @@ -0,0 +1,451 @@ +// 7zIn.h + +#ifndef __7Z_IN_H +#define __7Z_IN_H + +#include "../../../Common/MyCom.h" + +#include "../../../Windows/PropVariant.h" + +#include "../../IPassword.h" +#include "../../IStream.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/InBuffer.h" + +#include "7zItem.h" + +namespace NArchive { +namespace N7z { + +/* + We don't need to init isEncrypted and passwordIsDefined + We must upgrade them only */ + +#ifdef _NO_CRYPTO +#define _7Z_DECODER_CRYPRO_VARS_DECL +#define _7Z_DECODER_CRYPRO_VARS +#else +#define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password +#define _7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password +#endif + +struct CParsedMethods +{ + Byte Lzma2Prop; + UInt32 LzmaDic; + CRecordVector IDs; + + CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} +}; + +struct CFolderEx: public CFolder +{ + unsigned UnpackCoder; +}; + +struct CFolders +{ + CNum NumPackStreams; + CNum NumFolders; + + CObjArray PackPositions; // NumPackStreams + 1 + // CUInt32DefVector PackCRCs; // we don't use PackCRCs now + + CUInt32DefVector FolderCRCs; // NumFolders + CObjArray NumUnpackStreamsVector; // NumFolders + + CObjArray CoderUnpackSizes; // including unpack sizes of bond coders + CObjArray FoToCoderUnpackSizes; // NumFolders + 1 + CObjArray FoStartPackStreamIndex; // NumFolders + 1 + CObjArray FoToMainUnpackSizeIndex; // NumFolders + + CObjArray FoCodersDataOffset; // NumFolders + 1 + CByteBuffer CodersData; + + CParsedMethods ParsedMethods; + + void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; + void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const + { + ParseFolderInfo(folderIndex, folder); + folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex]; + } + + unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const + { + return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]); + } + + UInt64 GetFolderUnpackSize(unsigned folderIndex) const + { + return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; + } + + UInt64 GetStreamPackSize(unsigned index) const + { + return PackPositions[index + 1] - PackPositions[index]; + } + + CFolders(): NumPackStreams(0), NumFolders(0) {} + + void Clear() + { + NumPackStreams = 0; + PackPositions.Free(); + // PackCRCs.Clear(); + + NumFolders = 0; + FolderCRCs.Clear(); + NumUnpackStreamsVector.Free(); + CoderUnpackSizes.Free(); + FoToCoderUnpackSizes.Free(); + FoStartPackStreamIndex.Free(); + FoToMainUnpackSizeIndex.Free(); + FoCodersDataOffset.Free(); + CodersData.Free(); + } +}; + +struct CDatabase: public CFolders +{ + CRecordVector Files; + + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CUInt32DefVector Attrib; + CBoolVector IsAnti; + /* + CBoolVector IsAux; + CByteBuffer SecureBuf; + CRecordVector SecureIDs; + */ + + CByteBuffer NamesBuf; + CObjArray NameOffsets; // numFiles + 1, offsets of utf-16 symbols + + /* + void ClearSecure() + { + SecureBuf.Free(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + CFolders::Clear(); + // ClearSecure(); + + NamesBuf.Free(); + NameOffsets.Free(); + + Files.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + Attrib.Clear(); + IsAnti.Clear(); + // IsAux.Clear(); + } + + bool IsSolid() const + { + for (CNum i = 0; i < NumFolders; i++) + if (NumUnpackStreamsVector[i] > 1) + return true; + return false; + } + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + /* + const void* GetName(unsigned index) const + { + if (!NameOffsets || !NamesBuf) + return NULL; + return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); + }; + */ + void GetPath(unsigned index, UString &path) const; + HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); +}; + + +struct CInArchiveInfo +{ + CArchiveVersion Version; + UInt64 StartPosition; // in stream + UInt64 StartPositionAfterHeader; // in stream + UInt64 DataStartPosition; // in stream + UInt64 DataStartPosition2; // in stream. it's for headers + CRecordVector FileInfoPopIDs; + + void Clear() + { + StartPosition = 0; + StartPositionAfterHeader = 0; + DataStartPosition = 0; + DataStartPosition2 = 0; + FileInfoPopIDs.Clear(); + } +}; + + +struct CDbEx: public CDatabase +{ + CInArchiveInfo ArcInfo; + + CObjArray FolderStartFileIndex; + CObjArray FileIndexToFolderIndexMap; + + UInt64 HeadersSize; + UInt64 PhySize; + // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes) + + /* + CRecordVector SecureOffsets; + bool IsTree; + bool ThereAreAltStreams; + */ + + bool IsArc; + bool PhySizeWasConfirmed; + + bool ThereIsHeaderError; + bool UnexpectedEnd; + // bool UnsupportedVersion; + + bool StartHeaderWasRecovered; + bool UnsupportedFeatureWarning; + bool UnsupportedFeatureError; + + /* + void ClearSecureEx() + { + ClearSecure(); + SecureOffsets.Clear(); + } + */ + + void Clear() + { + IsArc = false; + PhySizeWasConfirmed = false; + + ThereIsHeaderError = false; + UnexpectedEnd = false; + // UnsupportedVersion = false; + + StartHeaderWasRecovered = false; + UnsupportedFeatureError = false; + UnsupportedFeatureWarning = false; + + /* + IsTree = false; + ThereAreAltStreams = false; + */ + + CDatabase::Clear(); + + // SecureOffsets.Clear(); + ArcInfo.Clear(); + FolderStartFileIndex.Free(); + FileIndexToFolderIndexMap.Free(); + + HeadersSize = 0; + PhySize = 0; + // EndHeaderOffset = 0; + } + + bool CanUpdate() const + { + if (ThereIsHeaderError + || UnexpectedEnd + || StartHeaderWasRecovered + || UnsupportedFeatureError) + return false; + return true; + } + + void FillLinks(); + + UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const + { + return ArcInfo.DataStartPosition + + PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; + } + + UInt64 GetFolderFullPackSize(CNum folderIndex) const + { + return + PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - + PackPositions[FoStartPackStreamIndex[folderIndex]]; + } + + UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const + { + size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; + return PackPositions[i + 1] - PackPositions[i]; + } + + UInt64 GetFilePackSize(CNum fileIndex) const + { + CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex != kNumNoIndex) + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + return 0; + } +}; + +const unsigned kNumBufLevelsMax = 4; + +struct CInByte2 +{ + const Byte *_buffer; +public: + size_t _size; + size_t _pos; + + size_t GetRem() const { return _size - _pos; } + const Byte *GetPtr() const { return _buffer + _pos; } + void Init(const Byte *buffer, size_t size) + { + _buffer = buffer; + _size = size; + _pos = 0; + } + Byte ReadByte(); + void ReadBytes(Byte *data, size_t size); + void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } + void SkipData(UInt64 size); + + void SkipData(); + void SkipRem() { _pos = _size; } + UInt64 ReadNumber(); + CNum ReadNum(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + + void ParseFolder(CFolder &folder); +}; + +class CStreamSwitch; + +const UInt32 kHeaderSize = 32; + +class CInArchive +{ + friend class CStreamSwitch; + + CMyComPtr _stream; + + unsigned _numInByteBufs; + CInByte2 _inByteVector[kNumBufLevelsMax]; + + CInByte2 *_inByteBack; + bool ThereIsHeaderError; + + UInt64 _arhiveBeginStreamPosition; + UInt64 _fileEndPosition; + + UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) + + Byte _header[kHeaderSize]; + + UInt64 HeadersSize; + + bool _useMixerMT; + + void AddByteStream(const Byte *buffer, size_t size); + + void DeleteByteStream(bool needUpdatePos) + { + _numInByteBufs--; + if (_numInByteBufs > 0) + { + _inByteBack = &_inByteVector[_numInByteBufs - 1]; + if (needUpdatePos) + _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; + } + } + + HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); + + void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } + Byte ReadByte() { return _inByteBack->ReadByte(); } + UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } + CNum ReadNum() { return _inByteBack->ReadNum(); } + UInt64 ReadID() { return _inByteBack->ReadNumber(); } + UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } + UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } + void SkipData(UInt64 size) { _inByteBack->SkipData(size); } + void SkipData() { _inByteBack->SkipData(); } + void WaitId(UInt64 id); + + void Read_UInt32_Vector(CUInt32DefVector &v); + + void ReadArchiveProperties(CInArchiveInfo &archiveInfo); + void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); + + void ReadPackInfo(CFolders &f); + + void ReadUnpackInfo( + const CObjectVector *dataVector, + CFolders &folders); + + void ReadSubStreamsInfo( + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests); + + void ReadStreamsInfo( + const CObjectVector *dataVector, + UInt64 &dataOffset, + CFolders &folders, + CRecordVector &unpackSizes, + CUInt32DefVector &digests); + + void ReadBoolVector(unsigned numItems, CBoolVector &v); + void ReadBoolVector2(unsigned numItems, CBoolVector &v); + void ReadUInt64DefVector(const CObjectVector &dataVector, + CUInt64DefVector &v, unsigned numItems); + HRESULT ReadAndDecodePackedStreams( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 baseOffset, UInt64 &dataOffset, + CObjectVector &dataVector + _7Z_DECODER_CRYPRO_VARS_DECL + ); + HRESULT ReadHeader( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ); + HRESULT ReadDatabase2( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ); +public: + CInArchive(bool useMixerMT): + _numInByteBufs(0), + _useMixerMT(useMixerMT) + {} + + HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive + void Close(); + + HRESULT ReadDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + CDbEx &db + _7Z_DECODER_CRYPRO_VARS_DECL + ); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zItem.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zItem.h new file mode 100644 index 0000000..0f9fdad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zItem.h @@ -0,0 +1,202 @@ +// 7zItem.h + +#ifndef __7Z_ITEM_H +#define __7Z_ITEM_H + +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyString.h" + +#include "../../Common/MethodId.h" + +#include "7zHeader.h" + +namespace NArchive { +namespace N7z { + +typedef UInt32 CNum; +const CNum kNumMax = 0x7FFFFFFF; +const CNum kNumNoIndex = 0xFFFFFFFF; + +struct CCoderInfo +{ + CMethodId MethodID; + CByteBuffer Props; + UInt32 NumStreams; + + bool IsSimpleCoder() const { return NumStreams == 1; } +}; + + +struct CBond +{ + UInt32 PackIndex; + UInt32 UnpackIndex; +}; + + +struct CFolder +{ + CLASS_NO_COPY(CFolder) +public: + CObjArray2 Coders; + CObjArray2 Bonds; + CObjArray2 PackStreams; + + CFolder() {} + + bool IsDecodingSupported() const { return Coders.Size() <= 32; } + + int Find_in_PackStreams(UInt32 packStream) const + { + FOR_VECTOR(i, PackStreams) + if (PackStreams[i] == packStream) + return (int)i; + return -1; + } + + int FindBond_for_PackStream(UInt32 packStream) const + { + FOR_VECTOR(i, Bonds) + if (Bonds[i].PackIndex == packStream) + return (int)i; + return -1; + } + + /* + int FindBond_for_UnpackStream(UInt32 unpackStream) const + { + FOR_VECTOR(i, Bonds) + if (Bonds[i].UnpackIndex == unpackStream) + return i; + return -1; + } + + int FindOutCoder() const + { + for (int i = (int)Coders.Size() - 1; i >= 0; i--) + if (FindBond_for_UnpackStream(i) < 0) + return i; + return -1; + } + */ + + bool IsEncrypted() const + { + FOR_VECTOR(i, Coders) + if (Coders[i].MethodID == k_AES) + return true; + return false; + } +}; + + +struct CUInt32DefVector +{ + CBoolVector Defs; + CRecordVector Vals; + + void ClearAndSetSize(unsigned newSize) + { + Defs.ClearAndSetSize(newSize); + Vals.ClearAndSetSize(newSize); + } + + void Clear() + { + Defs.Clear(); + Vals.Clear(); + } + + void ReserveDown() + { + Defs.ReserveDown(); + Vals.ReserveDown(); + } + + bool GetItem(unsigned index, UInt32 &value) const + { + if (index < Defs.Size() && Defs[index]) + { + value = Vals[index]; + return true; + } + value = 0; + return false; + } + + bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; } + + bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } + + void SetItem(unsigned index, bool defined, UInt32 value); +}; + + +struct CUInt64DefVector +{ + CBoolVector Defs; + CRecordVector Vals; + + void Clear() + { + Defs.Clear(); + Vals.Clear(); + } + + void ReserveDown() + { + Defs.ReserveDown(); + Vals.ReserveDown(); + } + + bool GetItem(unsigned index, UInt64 &value) const + { + if (index < Defs.Size() && Defs[index]) + { + value = Vals[index]; + return true; + } + value = 0; + return false; + } + + bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } + + void SetItem(unsigned index, bool defined, UInt64 value); +}; + + +struct CFileItem +{ + UInt64 Size; + UInt32 Crc; + /* + int Parent; + bool IsAltStream; + */ + bool HasStream; // Test it !!! it means that there is + // stream in some folder. It can be empty stream + bool IsDir; + bool CrcDefined; + + /* + void Clear() + { + HasStream = true; + IsDir = false; + CrcDefined = false; + } + + CFileItem(): + // Parent(-1), + // IsAltStream(false), + HasStream(true), + IsDir(false), + CrcDefined(false), + {} + */ +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.cpp new file mode 100644 index 0000000..2786bf2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.cpp @@ -0,0 +1,961 @@ +// 7zOut.cpp + +#include "StdAfx.h" + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/AutoPtr.h" +// #include "../../../Common/UTFConvert.h" + +#include "../../Common/StreamObjects.h" + +#include "7zOut.h" + +namespace NArchive { +namespace N7z { + +HRESULT COutArchive::WriteSignature() +{ + Byte buf[8]; + memcpy(buf, kSignature, kSignatureSize); + buf[kSignatureSize] = kMajorVersion; + buf[kSignatureSize + 1] = 4; + return WriteDirect(buf, 8); +} + +#ifdef _7Z_VOL +HRESULT COutArchive::WriteFinishSignature() +{ + RINOK(WriteDirect(kFinishSignature, kSignatureSize)); + CArchiveVersion av; + av.Major = kMajorVersion; + av.Minor = 2; + RINOK(WriteDirectByte(av.Major)); + return WriteDirectByte(av.Minor); +} +#endif + +static void SetUInt32(Byte *p, UInt32 d) +{ + for (int i = 0; i < 4; i++, d >>= 8) + p[i] = (Byte)d; +} + +static void SetUInt64(Byte *p, UInt64 d) +{ + for (int i = 0; i < 8; i++, d >>= 8) + p[i] = (Byte)d; +} + +HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) +{ + Byte buf[24]; + SetUInt64(buf + 4, h.NextHeaderOffset); + SetUInt64(buf + 12, h.NextHeaderSize); + SetUInt32(buf + 20, h.NextHeaderCRC); + SetUInt32(buf, CrcCalc(buf + 4, 20)); + return WriteDirect(buf, 24); +} + +#ifdef _7Z_VOL +HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) +{ + CCRC crc; + crc.UpdateUInt64(h.NextHeaderOffset); + crc.UpdateUInt64(h.NextHeaderSize); + crc.UpdateUInt32(h.NextHeaderCRC); + crc.UpdateUInt64(h.ArchiveStartOffset); + crc.UpdateUInt64(h.AdditionalStartBlockSize); + RINOK(WriteDirectUInt32(crc.GetDigest())); + RINOK(WriteDirectUInt64(h.NextHeaderOffset)); + RINOK(WriteDirectUInt64(h.NextHeaderSize)); + RINOK(WriteDirectUInt32(h.NextHeaderCRC)); + RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); + return WriteDirectUInt64(h.AdditionalStartBlockSize); +} +#endif + +HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) +{ + Close(); + #ifdef _7Z_VOL + // endMarker = false; + _endMarker = endMarker; + #endif + SeqStream = stream; + if (!endMarker) + { + SeqStream.QueryInterface(IID_IOutStream, &Stream); + if (!Stream) + { + return E_NOTIMPL; + // endMarker = true; + } + } + #ifdef _7Z_VOL + if (endMarker) + { + /* + CStartHeader sh; + sh.NextHeaderOffset = (UInt32)(Int32)-1; + sh.NextHeaderSize = (UInt32)(Int32)-1; + sh.NextHeaderCRC = 0; + WriteStartHeader(sh); + */ + } + else + #endif + { + if (!Stream) + return E_FAIL; + RINOK(WriteSignature()); + RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); + } + return S_OK; +} + +void COutArchive::Close() +{ + SeqStream.Release(); + Stream.Release(); +} + +HRESULT COutArchive::SkipPrefixArchiveHeader() +{ + #ifdef _7Z_VOL + if (_endMarker) + return S_OK; + #endif + Byte buf[24]; + memset(buf, 0, 24); + return WriteDirect(buf, 24); +} + +UInt64 COutArchive::GetPos() const +{ + if (_countMode) + return _countSize; + if (_writeToStream) + return _outByte.GetProcessedSize(); + return _outByte2.GetPos(); +} + +void COutArchive::WriteBytes(const void *data, size_t size) +{ + if (_countMode) + _countSize += size; + else if (_writeToStream) + { + _outByte.WriteBytes(data, size); + _crc = CrcUpdate(_crc, data, size); + } + else + _outByte2.WriteBytes(data, size); +} + +void COutArchive::WriteByte(Byte b) +{ + if (_countMode) + _countSize++; + else if (_writeToStream) + { + _outByte.WriteByte(b); + _crc = CRC_UPDATE_BYTE(_crc, b); + } + else + _outByte2.WriteByte(b); +} + +void COutArchive::WriteUInt32(UInt32 value) +{ + for (int i = 0; i < 4; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +void COutArchive::WriteUInt64(UInt64 value) +{ + for (int i = 0; i < 8; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +void COutArchive::WriteNumber(UInt64 value) +{ + Byte firstByte = 0; + Byte mask = 0x80; + int i; + for (i = 0; i < 8; i++) + { + if (value < ((UInt64(1) << ( 7 * (i + 1))))) + { + firstByte |= Byte(value >> (8 * i)); + break; + } + firstByte |= mask; + mask = (Byte)(mask >> 1); + } + WriteByte(firstByte); + for (; i > 0; i--) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +static unsigned GetBigNumberSize(UInt64 value) +{ + unsigned i; + for (i = 1; i < 9; i++) + if (value < (((UInt64)1 << (i * 7)))) + break; + return i; +} + +#ifdef _7Z_VOL +UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) +{ + UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; + if (nameLength != 0) + { + nameLength = (nameLength + 1) * 2; + result += nameLength + GetBigNumberSize(nameLength) + 2; + } + if (props) + { + result += 20; + } + if (result >= 128) + result++; + result += kSignatureSize + 2 + kFinishHeaderSize; + return result; +} + +UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) +{ + UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); + int testSize; + if (volSize > headersSizeBase) + testSize = volSize - headersSizeBase; + else + testSize = 1; + UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); + UInt64 pureSize = 1; + if (volSize > headersSize) + pureSize = volSize - headersSize; + return pureSize; +} +#endif + +void COutArchive::WriteFolder(const CFolder &folder) +{ + WriteNumber(folder.Coders.Size()); + unsigned i; + + for (i = 0; i < folder.Coders.Size(); i++) + { + const CCoderInfo &coder = folder.Coders[i]; + { + UInt64 id = coder.MethodID; + unsigned idSize; + for (idSize = 1; idSize < sizeof(id); idSize++) + if ((id >> (8 * idSize)) == 0) + break; + // idSize &= 0xF; // idSize is smaller than 16 already + Byte temp[16]; + for (unsigned t = idSize; t != 0; t--, id >>= 8) + temp[t] = (Byte)(id & 0xFF); + + unsigned b = idSize; + const bool isComplex = !coder.IsSimpleCoder(); + b |= (isComplex ? 0x10 : 0); + + const size_t propsSize = coder.Props.Size(); + b |= ((propsSize != 0) ? 0x20 : 0); + temp[0] = (Byte)b; + WriteBytes(temp, idSize + 1); + if (isComplex) + { + WriteNumber(coder.NumStreams); + WriteNumber(1); // NumOutStreams; + } + if (propsSize == 0) + continue; + WriteNumber(propsSize); + WriteBytes(coder.Props, propsSize); + } + } + + for (i = 0; i < folder.Bonds.Size(); i++) + { + const CBond &bond = folder.Bonds[i]; + WriteNumber(bond.PackIndex); + WriteNumber(bond.UnpackIndex); + } + + if (folder.PackStreams.Size() > 1) + for (i = 0; i < folder.PackStreams.Size(); i++) + WriteNumber(folder.PackStreams[i]); +} + +void COutArchive::WriteBoolVector(const CBoolVector &boolVector) +{ + Byte b = 0; + Byte mask = 0x80; + FOR_VECTOR (i, boolVector) + { + if (boolVector[i]) + b |= mask; + mask = (Byte)(mask >> 1); + if (mask == 0) + { + WriteByte(b); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) + WriteByte(b); +} + +static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; } + +void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector) +{ + WriteByte(id); + WriteNumber(Bv_GetSizeInBytes(boolVector)); + WriteBoolVector(boolVector); +} + +unsigned BoolVector_CountSum(const CBoolVector &v); + +void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) +{ + const unsigned numDefined = BoolVector_CountSum(digests.Defs); + if (numDefined == 0) + return; + + WriteByte(NID::kCRC); + if (numDefined == digests.Defs.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(digests.Defs); + } + + for (unsigned i = 0; i < digests.Defs.Size(); i++) + if (digests.Defs[i]) + WriteUInt32(digests.Vals[i]); +} + +void COutArchive::WritePackInfo( + UInt64 dataOffset, + const CRecordVector &packSizes, + const CUInt32DefVector &packCRCs) +{ + if (packSizes.IsEmpty()) + return; + WriteByte(NID::kPackInfo); + WriteNumber(dataOffset); + WriteNumber(packSizes.Size()); + WriteByte(NID::kSize); + FOR_VECTOR (i, packSizes) + WriteNumber(packSizes[i]); + + WriteHashDigests(packCRCs); + + WriteByte(NID::kEnd); +} + +void COutArchive::WriteUnpackInfo(const CObjectVector &folders, const COutFolders &outFolders) +{ + if (folders.IsEmpty()) + return; + + WriteByte(NID::kUnpackInfo); + + WriteByte(NID::kFolder); + WriteNumber(folders.Size()); + { + WriteByte(0); + FOR_VECTOR (i, folders) + WriteFolder(folders[i]); + } + + WriteByte(NID::kCodersUnpackSize); + FOR_VECTOR (i, outFolders.CoderUnpackSizes) + WriteNumber(outFolders.CoderUnpackSizes[i]); + + WriteHashDigests(outFolders.FolderUnpackCRCs); + + WriteByte(NID::kEnd); +} + +void COutArchive::WriteSubStreamsInfo(const CObjectVector &folders, + const COutFolders &outFolders, + const CRecordVector &unpackSizes, + const CUInt32DefVector &digests) +{ + const CRecordVector &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector; + WriteByte(NID::kSubStreamsInfo); + + unsigned i; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + if (numUnpackStreamsInFolders[i] != 1) + { + WriteByte(NID::kNumUnpackStream); + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + WriteNumber(numUnpackStreamsInFolders[i]); + break; + } + + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + if (numUnpackStreamsInFolders[i] > 1) + { + WriteByte(NID::kSize); + CNum index = 0; + for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) + { + CNum num = numUnpackStreamsInFolders[i]; + for (CNum j = 0; j < num; j++) + { + if (j + 1 != num) + WriteNumber(unpackSizes[index]); + index++; + } + } + break; + } + + CUInt32DefVector digests2; + + unsigned digestIndex = 0; + for (i = 0; i < folders.Size(); i++) + { + unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i]; + if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i)) + digestIndex++; + else + for (unsigned j = 0; j < numSubStreams; j++, digestIndex++) + { + digests2.Defs.Add(digests.Defs[digestIndex]); + digests2.Vals.Add(digests.Vals[digestIndex]); + } + } + WriteHashDigests(digests2); + WriteByte(NID::kEnd); +} + +// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. + +void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts) +{ + if (!_useAlign) + return; + + const unsigned alignSize = (unsigned)1 << alignShifts; + pos += (unsigned)GetPos(); + pos &= (alignSize - 1); + if (pos == 0) + return; + unsigned skip = alignSize - pos; + if (skip < 2) + skip += alignSize; + skip -= 2; + WriteByte(NID::kDummy); + WriteByte((Byte)skip); + for (unsigned i = 0; i < skip; i++) + WriteByte(0); +} + +void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts) +{ + const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v); + const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2; + SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts); + + WriteByte(type); + WriteNumber(dataSize); + if (numDefined == v.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(v); + } + WriteByte(0); // 0 means no switching to external stream +} + +void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) +{ + const unsigned numDefined = BoolVector_CountSum(v.Defs); + if (numDefined == 0) + return; + + WriteAlignedBools(v.Defs, numDefined, type, 3); + + for (unsigned i = 0; i < v.Defs.Size(); i++) + if (v.Defs[i]) + WriteUInt64(v.Vals[i]); +} + +HRESULT COutArchive::EncodeStream( + DECL_EXTERNAL_CODECS_LOC_VARS + CEncoder &encoder, const CByteBuffer &data, + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders) +{ + CBufInStream *streamSpec = new CBufInStream; + CMyComPtr stream = streamSpec; + streamSpec->Init(data, data.Size()); + outFolders.FolderUnpackCRCs.Defs.Add(true); + outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); + // outFolders.NumUnpackStreamsVector.Add(1); + UInt64 dataSize64 = data.Size(); + UInt64 unpackSize = data.Size(); + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + stream, + // NULL, + &dataSize64, + folders.AddNew(), outFolders.CoderUnpackSizes, unpackSize, SeqStream, packSizes, NULL)) + return S_OK; +} + +void COutArchive::WriteHeader( + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, + UInt64 &headerOffset) +{ + /* + bool thereIsSecure = (db.SecureBuf.Size() != 0); + */ + _useAlign = true; + + { + UInt64 packSize = 0; + FOR_VECTOR (i, db.PackSizes) + packSize += db.PackSizes[i]; + headerOffset = packSize; + } + + + WriteByte(NID::kHeader); + + /* + { + // It's example for per archive properies writing + + WriteByte(NID::kArchiveProperties); + + // you must use random 40-bit number that will identify you + // then you can use same kDeveloperID for any properties and methods + const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number + + #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID) + + { + const UInt64 kSubID = 0x1; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 3; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i & 0xFF)); + } + { + const UInt64 kSubID = 0x2; // you can use small number for subID + const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID); + WriteNumber(kID); + const unsigned kPropsSize = 5; // it's example size + WriteNumber(kPropsSize); + for (unsigned i = 0; i < kPropsSize; i++) + WriteByte((Byte)(i + 16)); + } + WriteByte(NID::kEnd); + } + */ + + if (db.Folders.Size() > 0) + { + WriteByte(NID::kMainStreamsInfo); + WritePackInfo(0, db.PackSizes, db.PackCRCs); + WriteUnpackInfo(db.Folders, (const COutFolders &)db); + + CRecordVector unpackSizes; + CUInt32DefVector digests; + FOR_VECTOR (i, db.Files) + { + const CFileItem &file = db.Files[i]; + if (!file.HasStream) + continue; + unpackSizes.Add(file.Size); + digests.Defs.Add(file.CrcDefined); + digests.Vals.Add(file.Crc); + } + + WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests); + WriteByte(NID::kEnd); + } + + if (db.Files.IsEmpty()) + { + WriteByte(NID::kEnd); + return; + } + + WriteByte(NID::kFilesInfo); + WriteNumber(db.Files.Size()); + + { + /* ---------- Empty Streams ---------- */ + CBoolVector emptyStreamVector; + emptyStreamVector.ClearAndSetSize(db.Files.Size()); + unsigned numEmptyStreams = 0; + { + FOR_VECTOR (i, db.Files) + if (db.Files[i].HasStream) + emptyStreamVector[i] = false; + else + { + emptyStreamVector[i] = true; + numEmptyStreams++; + } + } + + if (numEmptyStreams != 0) + { + WritePropBoolVector(NID::kEmptyStream, emptyStreamVector); + + CBoolVector emptyFileVector, antiVector; + emptyFileVector.ClearAndSetSize(numEmptyStreams); + antiVector.ClearAndSetSize(numEmptyStreams); + bool thereAreEmptyFiles = false, thereAreAntiItems = false; + unsigned cur = 0; + + FOR_VECTOR (i, db.Files) + { + const CFileItem &file = db.Files[i]; + if (file.HasStream) + continue; + emptyFileVector[cur] = !file.IsDir; + if (!file.IsDir) + thereAreEmptyFiles = true; + bool isAnti = db.IsItemAnti(i); + antiVector[cur] = isAnti; + if (isAnti) + thereAreAntiItems = true; + cur++; + } + + if (thereAreEmptyFiles) + WritePropBoolVector(NID::kEmptyFile, emptyFileVector); + if (thereAreAntiItems) + WritePropBoolVector(NID::kAnti, antiVector); + } + } + + + { + /* ---------- Names ---------- */ + + unsigned numDefined = 0; + size_t namesDataSize = 0; + FOR_VECTOR (i, db.Files) + { + const UString &name = db.Names[i]; + if (!name.IsEmpty()) + numDefined++; + const size_t numUtfChars = + /* + #if WCHAR_MAX > 0xffff + Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); + #else + */ + name.Len(); + // #endif + namesDataSize += (numUtfChars + 1) * 2; + } + + if (numDefined > 0) + { + namesDataSize++; + SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); + + WriteByte(NID::kName); + WriteNumber(namesDataSize); + WriteByte(0); + FOR_VECTOR (i, db.Files) + { + const UString &name = db.Names[i]; + for (unsigned t = 0; t <= name.Len(); t++) + { + wchar_t c = name[t]; + + /* + #if WCHAR_MAX > 0xffff + if (c >= 0x10000) + { + c -= 0x10000; + if (c < (1 << 20)) + { + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + WriteByte((Byte)c0); + WriteByte((Byte)(c0 >> 8)); + c = 0xdc00 + (c & 0x3FF); + } + else + c = '_'; // we change character unsupported by UTF16 + } + #endif + */ + + WriteByte((Byte)c); + WriteByte((Byte)(c >> 8)); + } + } + } + } + + /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); + /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); + /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); + WriteUInt64DefVector(db.StartPos, NID::kStartPos); + + { + /* ---------- Write Attrib ---------- */ + const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); + + if (numDefined != 0) + { + WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); + FOR_VECTOR (i, db.Attrib.Defs) + { + if (db.Attrib.Defs[i]) + WriteUInt32(db.Attrib.Vals[i]); + } + } + } + + /* + { + // ---------- Write IsAux ---------- + if (BoolVector_CountSum(db.IsAux) != 0) + WritePropBoolVector(NID::kIsAux, db.IsAux); + } + + { + // ---------- Write Parent ---------- + CBoolVector boolVector; + boolVector.Reserve(db.Files.Size()); + unsigned numIsDir = 0; + unsigned numParentLinks = 0; + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + bool defined = !file.IsAltStream; + boolVector.Add(defined); + if (defined) + numIsDir++; + if (file.Parent >= 0) + numParentLinks++; + } + if (numParentLinks > 0) + { + // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2); + const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector); + const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1; + SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2); + + WriteByte(NID::kParent); + WriteNumber(dataSize); + if (numIsDir == boolVector.Size()) + WriteByte(1); + else + { + WriteByte(0); + WriteBoolVector(boolVector); + } + for (i = 0; i < db.Files.Size(); i++) + { + const CFileItem &file = db.Files[i]; + // if (file.Parent >= 0) + WriteUInt32(file.Parent); + } + } + } + + if (thereIsSecure) + { + UInt64 secureDataSize = 1 + 4 + + db.SecureBuf.Size() + + db.SecureSizes.Size() * 4; + // secureDataSize += db.SecureIDs.Size() * 4; + for (i = 0; i < db.SecureIDs.Size(); i++) + secureDataSize += GetBigNumberSize(db.SecureIDs[i]); + SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2); + WriteByte(NID::kNtSecure); + WriteNumber(secureDataSize); + WriteByte(0); + WriteUInt32(db.SecureSizes.Size()); + for (i = 0; i < db.SecureSizes.Size(); i++) + WriteUInt32(db.SecureSizes[i]); + WriteBytes(db.SecureBuf, db.SecureBuf.Size()); + for (i = 0; i < db.SecureIDs.Size(); i++) + { + WriteNumber(db.SecureIDs[i]); + // WriteUInt32(db.SecureIDs[i]); + } + } + */ + + WriteByte(NID::kEnd); // for files + WriteByte(NID::kEnd); // for headers +} + +HRESULT COutArchive::WriteDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + const CArchiveDatabaseOut &db, + const CCompressionMethodMode *options, + const CHeaderOptions &headerOptions) +{ + if (!db.CheckNumFiles()) + return E_FAIL; + + UInt64 headerOffset; + UInt32 headerCRC; + UInt64 headerSize; + if (db.IsEmpty()) + { + headerSize = 0; + headerOffset = 0; + headerCRC = CrcCalc(0, 0); + } + else + { + bool encodeHeaders = false; + if (options != 0) + if (options->IsEmpty()) + options = 0; + if (options != 0) + if (options->PasswordIsDefined || headerOptions.CompressMainHeader) + encodeHeaders = true; + + _outByte.SetStream(SeqStream); + _outByte.Init(); + _crc = CRC_INIT_VAL; + _countMode = encodeHeaders; + _writeToStream = true; + _countSize = 0; + WriteHeader(db, /* headerOptions, */ headerOffset); + + if (encodeHeaders) + { + CByteBuffer buf(_countSize); + _outByte2.Init((Byte *)buf, _countSize); + + _countMode = false; + _writeToStream = false; + WriteHeader(db, /* headerOptions, */ headerOffset); + + if (_countSize != _outByte2.GetPos()) + return E_FAIL; + + CCompressionMethodMode encryptOptions; + encryptOptions.PasswordIsDefined = options->PasswordIsDefined; + encryptOptions.Password = options->Password; + CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); + CRecordVector packSizes; + CObjectVector folders; + COutFolders outFolders; + + RINOK(EncodeStream( + EXTERNAL_CODECS_LOC_VARS + encoder, buf, + packSizes, folders, outFolders)); + + _writeToStream = true; + + if (folders.Size() == 0) + throw 1; + + WriteID(NID::kEncodedHeader); + WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); + WriteUnpackInfo(folders, outFolders); + WriteByte(NID::kEnd); + FOR_VECTOR (i, packSizes) + headerOffset += packSizes[i]; + } + RINOK(_outByte.Flush()); + headerCRC = CRC_GET_DIGEST(_crc); + headerSize = _outByte.GetProcessedSize(); + } + #ifdef _7Z_VOL + if (_endMarker) + { + CFinishHeader h; + h.NextHeaderSize = headerSize; + h.NextHeaderCRC = headerCRC; + h.NextHeaderOffset = + UInt64(0) - (headerSize + + 4 + kFinishHeaderSize); + h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; + h.AdditionalStartBlockSize = 0; + RINOK(WriteFinishHeader(h)); + return WriteFinishSignature(); + } + else + #endif + { + CStartHeader h; + h.NextHeaderSize = headerSize; + h.NextHeaderCRC = headerCRC; + h.NextHeaderOffset = headerOffset; + RINOK(Stream->Seek((Int64)_prefixHeaderPos, STREAM_SEEK_SET, NULL)); + return WriteStartHeader(h); + } +} + +void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value) +{ + while (index >= Defs.Size()) + Defs.Add(false); + Defs[index] = defined; + if (!defined) + return; + while (index >= Vals.Size()) + Vals.Add(0); + Vals[index] = value; +} + +void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value) +{ + while (index >= Defs.Size()) + Defs.Add(false); + Defs[index] = defined; + if (!defined) + return; + while (index >= Vals.Size()) + Vals.Add(0); + Vals[index] = value; +} + +void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name) +{ + unsigned index = Files.Size(); + CTime.SetItem(index, file2.CTimeDefined, file2.CTime); + ATime.SetItem(index, file2.ATimeDefined, file2.ATime); + MTime.SetItem(index, file2.MTimeDefined, file2.MTime); + StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); + Attrib.SetItem(index, file2.AttribDefined, file2.Attrib); + SetItem_Anti(index, file2.IsAnti); + // SetItem_Aux(index, file2.IsAux); + Names.Add(name); + Files.Add(file); +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.h new file mode 100644 index 0000000..1ebad56 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zOut.h @@ -0,0 +1,335 @@ +// 7zOut.h + +#ifndef __7Z_OUT_H +#define __7Z_OUT_H + +#include "7zCompressionMode.h" +#include "7zEncode.h" +#include "7zHeader.h" +#include "7zItem.h" + +#include "../../Common/OutBuffer.h" +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace N7z { + +class CWriteBufferLoc +{ + Byte *_data; + size_t _size; + size_t _pos; +public: + CWriteBufferLoc(): _size(0), _pos(0) {} + void Init(Byte *data, size_t size) + { + _data = data; + _size = size; + _pos = 0; + } + void WriteBytes(const void *data, size_t size) + { + if (size == 0) + return; + if (size > _size - _pos) + throw 1; + memcpy(_data + _pos, data, size); + _pos += size; + } + void WriteByte(Byte b) + { + if (_size == _pos) + throw 1; + _data[_pos++] = b; + } + size_t GetPos() const { return _pos; } +}; + + +struct CHeaderOptions +{ + bool CompressMainHeader; + /* + bool WriteCTime; + bool WriteATime; + bool WriteMTime; + */ + + CHeaderOptions(): + CompressMainHeader(true) + /* + , WriteCTime(false) + , WriteATime(false) + , WriteMTime(true) + */ + {} +}; + + +struct CFileItem2 +{ + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + UInt64 StartPos; + UInt32 Attrib; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool StartPosDefined; + bool AttribDefined; + bool IsAnti; + // bool IsAux; + + /* + void Init() + { + CTimeDefined = false; + ATimeDefined = false; + MTimeDefined = false; + StartPosDefined = false; + AttribDefined = false; + IsAnti = false; + // IsAux = false; + } + */ +}; + + +struct COutFolders +{ + CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. + + CRecordVector NumUnpackStreamsVector; + CRecordVector CoderUnpackSizes; // including unpack sizes of bond coders + + void OutFoldersClear() + { + FolderUnpackCRCs.Clear(); + NumUnpackStreamsVector.Clear(); + CoderUnpackSizes.Clear(); + } + + void OutFoldersReserveDown() + { + FolderUnpackCRCs.ReserveDown(); + NumUnpackStreamsVector.ReserveDown(); + CoderUnpackSizes.ReserveDown(); + } +}; + + +struct CArchiveDatabaseOut: public COutFolders +{ + CRecordVector PackSizes; + CUInt32DefVector PackCRCs; + CObjectVector Folders; + + CRecordVector Files; + UStringVector Names; + CUInt64DefVector CTime; + CUInt64DefVector ATime; + CUInt64DefVector MTime; + CUInt64DefVector StartPos; + CUInt32DefVector Attrib; + CBoolVector IsAnti; + + /* + CBoolVector IsAux; + + CByteBuffer SecureBuf; + CRecordVector SecureSizes; + CRecordVector SecureIDs; + + void ClearSecure() + { + SecureBuf.Free(); + SecureSizes.Clear(); + SecureIDs.Clear(); + } + */ + + void Clear() + { + OutFoldersClear(); + + PackSizes.Clear(); + PackCRCs.Clear(); + Folders.Clear(); + + Files.Clear(); + Names.Clear(); + CTime.Clear(); + ATime.Clear(); + MTime.Clear(); + StartPos.Clear(); + Attrib.Clear(); + IsAnti.Clear(); + + /* + IsAux.Clear(); + ClearSecure(); + */ + } + + void ReserveDown() + { + OutFoldersReserveDown(); + + PackSizes.ReserveDown(); + PackCRCs.ReserveDown(); + Folders.ReserveDown(); + + Files.ReserveDown(); + Names.ReserveDown(); + CTime.ReserveDown(); + ATime.ReserveDown(); + MTime.ReserveDown(); + StartPos.ReserveDown(); + Attrib.ReserveDown(); + IsAnti.ReserveDown(); + + /* + IsAux.ReserveDown(); + */ + } + + bool IsEmpty() const + { + return ( + PackSizes.IsEmpty() && + NumUnpackStreamsVector.IsEmpty() && + Folders.IsEmpty() && + Files.IsEmpty()); + } + + bool CheckNumFiles() const + { + unsigned size = Files.Size(); + return ( + CTime.CheckSize(size) + && ATime.CheckSize(size) + && MTime.CheckSize(size) + && StartPos.CheckSize(size) + && Attrib.CheckSize(size) + && (size == IsAnti.Size() || IsAnti.Size() == 0)); + } + + bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } + // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } + + void SetItem_Anti(unsigned index, bool isAnti) + { + while (index >= IsAnti.Size()) + IsAnti.Add(false); + IsAnti[index] = isAnti; + } + /* + void SetItem_Aux(unsigned index, bool isAux) + { + while (index >= IsAux.Size()) + IsAux.Add(false); + IsAux[index] = isAux; + } + */ + + void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); +}; + + +class COutArchive +{ + UInt64 _prefixHeaderPos; + + HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } + + UInt64 GetPos() const; + void WriteBytes(const void *data, size_t size); + void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } + void WriteByte(Byte b); + void WriteUInt32(UInt32 value); + void WriteUInt64(UInt64 value); + void WriteNumber(UInt64 value); + void WriteID(UInt64 value) { WriteNumber(value); } + + void WriteFolder(const CFolder &folder); + HRESULT WriteFileHeader(const CFileItem &itemInfo); + void WriteBoolVector(const CBoolVector &boolVector); + void WritePropBoolVector(Byte id, const CBoolVector &boolVector); + + void WriteHashDigests(const CUInt32DefVector &digests); + + void WritePackInfo( + UInt64 dataOffset, + const CRecordVector &packSizes, + const CUInt32DefVector &packCRCs); + + void WriteUnpackInfo( + const CObjectVector &folders, + const COutFolders &outFolders); + + void WriteSubStreamsInfo( + const CObjectVector &folders, + const COutFolders &outFolders, + const CRecordVector &unpackSizes, + const CUInt32DefVector &digests); + + void SkipToAligned(unsigned pos, unsigned alignShifts); + void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); + void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); + + HRESULT EncodeStream( + DECL_EXTERNAL_CODECS_LOC_VARS + CEncoder &encoder, const CByteBuffer &data, + CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders); + void WriteHeader( + const CArchiveDatabaseOut &db, + // const CHeaderOptions &headerOptions, + UInt64 &headerOffset); + + bool _countMode; + bool _writeToStream; + size_t _countSize; + UInt32 _crc; + COutBuffer _outByte; + CWriteBufferLoc _outByte2; + + #ifdef _7Z_VOL + bool _endMarker; + #endif + + bool _useAlign; + + HRESULT WriteSignature(); + #ifdef _7Z_VOL + HRESULT WriteFinishSignature(); + #endif + HRESULT WriteStartHeader(const CStartHeader &h); + #ifdef _7Z_VOL + HRESULT WriteFinishHeader(const CFinishHeader &h); + #endif + CMyComPtr Stream; +public: + + COutArchive() { _outByte.Create(1 << 16); } + CMyComPtr SeqStream; + HRESULT Create(ISequentialOutStream *stream, bool endMarker); + void Close(); + HRESULT SkipPrefixArchiveHeader(); + HRESULT WriteDatabase( + DECL_EXTERNAL_CODECS_LOC_VARS + const CArchiveDatabaseOut &db, + const CCompressionMethodMode *options, + const CHeaderOptions &headerOptions); + + #ifdef _7Z_VOL + static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); + static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); + #endif + +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.cpp new file mode 100644 index 0000000..4cb5a5e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.cpp @@ -0,0 +1,174 @@ +// 7zProperties.cpp + +#include "StdAfx.h" + +#include "7zProperties.h" +#include "7zHeader.h" +#include "7zHandler.h" + +// #define _MULTI_PACK + +namespace NArchive { +namespace N7z { + +struct CPropMap +{ + UInt32 FilePropID; + CStatProp StatProp; +}; + +static const CPropMap kPropMap[] = +{ + { NID::kName, { NULL, kpidPath, VT_BSTR } }, + { NID::kSize, { NULL, kpidSize, VT_UI8 } }, + { NID::kPackInfo, { NULL, kpidPackSize, VT_UI8 } }, + + #ifdef _MULTI_PACK + { 100, { "Pack0", kpidPackedSize0, VT_UI8 } }, + { 101, { "Pack1", kpidPackedSize1, VT_UI8 } }, + { 102, { "Pack2", kpidPackedSize2, VT_UI8 } }, + { 103, { "Pack3", kpidPackedSize3, VT_UI8 } }, + { 104, { "Pack4", kpidPackedSize4, VT_UI8 } }, + #endif + + { NID::kCTime, { NULL, kpidCTime, VT_FILETIME } }, + { NID::kMTime, { NULL, kpidMTime, VT_FILETIME } }, + { NID::kATime, { NULL, kpidATime, VT_FILETIME } }, + { NID::kWinAttrib, { NULL, kpidAttrib, VT_UI4 } }, + { NID::kStartPos, { NULL, kpidPosition, VT_UI8 } }, + + { NID::kCRC, { NULL, kpidCRC, VT_UI4 } }, + +// { NID::kIsAux, { NULL, kpidIsAux, VT_BOOL } }, + { NID::kAnti, { NULL, kpidIsAnti, VT_BOOL } } + + #ifndef _SFX + , + { 97, { NULL, kpidEncrypted, VT_BOOL } }, + { 98, { NULL, kpidMethod, VT_BSTR } }, + { 99, { NULL, kpidBlock, VT_UI4 } } + #endif +}; + +static void CopyOneItem(CRecordVector &src, + CRecordVector &dest, UInt32 item) +{ + FOR_VECTOR (i, src) + if (src[i] == item) + { + dest.Add(item); + src.Delete(i); + return; + } +} + +static void RemoveOneItem(CRecordVector &src, UInt32 item) +{ + FOR_VECTOR (i, src) + if (src[i] == item) + { + src.Delete(i); + return; + } +} + +static void InsertToHead(CRecordVector &dest, UInt32 item) +{ + FOR_VECTOR (i, dest) + if (dest[i] == item) + { + dest.Delete(i); + break; + } + dest.Insert(0, item); +} + +#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id); + +void CHandler::FillPopIDs() +{ + _fileInfoPopIDs.Clear(); + + #ifdef _7Z_VOL + if (_volumes.Size() < 1) + return; + const CVolume &volume = _volumes.Front(); + const CArchiveDatabaseEx &_db = volume.Database; + #endif + + CRecordVector fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs; + + RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); + RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); + /* + RemoveOneItem(fileInfoPopIDs, NID::kParent); + RemoveOneItem(fileInfoPopIDs, NID::kNtSecure); + */ + + COPY_ONE_ITEM(kName); + COPY_ONE_ITEM(kAnti); + COPY_ONE_ITEM(kSize); + COPY_ONE_ITEM(kPackInfo); + COPY_ONE_ITEM(kCTime); + COPY_ONE_ITEM(kMTime); + COPY_ONE_ITEM(kATime); + COPY_ONE_ITEM(kWinAttrib); + COPY_ONE_ITEM(kCRC); + COPY_ONE_ITEM(kComment); + + _fileInfoPopIDs += fileInfoPopIDs; + + #ifndef _SFX + _fileInfoPopIDs.Add(97); + _fileInfoPopIDs.Add(98); + _fileInfoPopIDs.Add(99); + #endif + + #ifdef _MULTI_PACK + _fileInfoPopIDs.Add(100); + _fileInfoPopIDs.Add(101); + _fileInfoPopIDs.Add(102); + _fileInfoPopIDs.Add(103); + _fileInfoPopIDs.Add(104); + #endif + + #ifndef _SFX + InsertToHead(_fileInfoPopIDs, NID::kMTime); + InsertToHead(_fileInfoPopIDs, NID::kPackInfo); + InsertToHead(_fileInfoPopIDs, NID::kSize); + InsertToHead(_fileInfoPopIDs, NID::kName); + #endif +} + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) +{ + *numProps = _fileInfoPopIDs.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if (index >= _fileInfoPopIDs.Size()) + return E_INVALIDARG; + UInt64 id = _fileInfoPopIDs[index]; + for (unsigned i = 0; i < ARRAY_SIZE(kPropMap); i++) + { + const CPropMap &pr = kPropMap[i]; + if (pr.FilePropID == id) + { + const CStatProp &st = pr.StatProp; + *propID = st.PropID; + *varType = st.vt; + /* + if (st.lpwstrName) + *name = ::SysAllocString(st.lpwstrName); + else + */ + *name = NULL; + return S_OK; + } + } + return E_INVALIDARG; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.h new file mode 100644 index 0000000..6618179 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zProperties.h @@ -0,0 +1,22 @@ +// 7zProperties.h + +#ifndef __7Z_PROPERTIES_H +#define __7Z_PROPERTIES_H + +#include "../../PropID.h" + +namespace NArchive { +namespace N7z { + +enum +{ + kpidPackedSize0 = kpidUserDefined, + kpidPackedSize1, + kpidPackedSize2, + kpidPackedSize3, + kpidPackedSize4 +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zRegister.cpp new file mode 100644 index 0000000..389b540 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zRegister.cpp @@ -0,0 +1,21 @@ +// 7zRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "7zHandler.h" + +namespace NArchive { +namespace N7z { + +static Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +REGISTER_ARC_IO_DECREMENT_SIG( + "7z", "7z", NULL, 7, + k_Signature_Dec, + 0, + NArcInfoFlags::kFindSignature, + NULL); + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.cpp new file mode 100644 index 0000000..8e45d98 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.cpp @@ -0,0 +1,22 @@ +// 7zSpecStream.cpp + +#include "StdAfx.h" + +#include "7zSpecStream.h" + +STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + if (!_getSubStreamSize) + return E_NOTIMPL; + return _getSubStreamSize->GetSubStreamSize(subStream, value); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.h new file mode 100644 index 0000000..2115506 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zSpecStream.h @@ -0,0 +1,35 @@ +// 7zSpecStream.h + +#ifndef __7Z_SPEC_STREAM_H +#define __7Z_SPEC_STREAM_H + +#include "../../../Common/MyCom.h" + +#include "../../ICoder.h" + +class CSequentialInStreamSizeCount2: + public ISequentialInStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + CMyComPtr _stream; + CMyComPtr _getSubStreamSize; + UInt64 _size; +public: + void Init(ISequentialInStream *stream) + { + _size = 0; + _getSubStreamSize.Release(); + _stream = stream; + _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); + } + UInt64 GetSize() const { return _size; } + + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.cpp new file mode 100644 index 0000000..b641d93 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -0,0 +1,2514 @@ +// 7zUpdate.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/Wildcard.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "../Common/ItemNameUtils.h" + +#include "7zDecode.h" +#include "7zEncode.h" +#include "7zFolderInStream.h" +#include "7zHandler.h" +#include "7zOut.h" +#include "7zUpdate.h" + +namespace NArchive { +namespace N7z { + + +#define k_X86 k_BCJ + +struct CFilterMode +{ + UInt32 Id; + UInt32 Delta; + + CFilterMode(): Id(0), Delta(0) {} + + void SetDelta() + { + if (Id == k_IA64) + Delta = 16; + else if (Id == k_ARM || Id == k_PPC || Id == k_SPARC) + Delta = 4; + else if (Id == k_ARMT) + Delta = 2; + else + Delta = 0; + } +}; + + +/* ---------- PE ---------- */ + +#define MZ_SIG 0x5A4D + +#define PE_SIG 0x00004550 +#define PE_OptHeader_Magic_32 0x10B +#define PE_OptHeader_Magic_64 0x20B +// #define PE_SectHeaderSize 40 +// #define PE_SECT_EXECUTE 0x20000000 + +static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + if (size < 512 || GetUi16(buf) != MZ_SIG) + return 0; + + const Byte *p; + UInt32 peOffset, optHeaderSize, filterId; + + peOffset = GetUi32(buf + 0x3C); + if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0) + return 0; + p = buf + peOffset; + if (GetUi32(p) != PE_SIG) + return 0; + p += 4; + + switch (GetUi16(p)) + { + case 0x014C: + case 0x8664: filterId = k_X86; break; + + /* + IMAGE_FILE_MACHINE_ARM 0x01C0 // ARM LE + IMAGE_FILE_MACHINE_THUMB 0x01C2 // ARM Thumb / Thumb-2 LE + IMAGE_FILE_MACHINE_ARMNT 0x01C4 // ARM Thumb-2, LE + Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2). + */ + + case 0x01C0: // WinCE old + case 0x01C2: filterId = k_ARM; break; // WinCE new + case 0x01C4: filterId = k_ARMT; break; // WinRT + + case 0x0200: filterId = k_IA64; break; + default: return 0; + } + + optHeaderSize = GetUi16(p + 16); + if (optHeaderSize > (1 << 10)) + return 0; + + p += 20; /* headerSize */ + + switch (GetUi16(p)) + { + case PE_OptHeader_Magic_32: + case PE_OptHeader_Magic_64: + break; + default: + return 0; + } + + filterMode->Id = filterId; + return 1; +} + + +/* ---------- ELF ---------- */ + +#define ELF_SIG 0x464C457F + +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 + +#define ELF_DATA_2LSB 1 +#define ELF_DATA_2MSB 2 + +static UInt16 Get16(const Byte *p, BoolInt be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); } +static UInt32 Get32(const Byte *p, BoolInt be) { if (be) return GetBe32(p); return GetUi32(p); } +// static UInt64 Get64(const Byte *p, BoolInt be) { if (be) return GetBe64(p); return GetUi64(p); } + +static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + BoolInt /* is32, */ be; + UInt32 filterId; + + if (size < 512 || buf[6] != 1) /* ver */ + return 0; + + if (GetUi32(buf) != ELF_SIG) + return 0; + + switch (buf[4]) + { + case ELF_CLASS_32: /* is32 = True; */ break; + case ELF_CLASS_64: /* is32 = False; */ break; + default: return 0; + } + + switch (buf[5]) + { + case ELF_DATA_2LSB: be = False; break; + case ELF_DATA_2MSB: be = True; break; + default: return 0; + } + + switch (Get16(buf + 0x12, be)) + { + case 3: + case 6: + case 62: filterId = k_X86; break; + case 2: + case 18: + case 43: filterId = k_SPARC; break; + case 20: + case 21: if (!be) return 0; filterId = k_PPC; break; + case 40: if ( be) return 0; filterId = k_ARM; break; + + /* Some IA-64 ELF exacutable have size that is not aligned for 16 bytes. + So we don't use IA-64 filter for IA-64 ELF */ + // case 50: if ( be) return 0; filterId = k_IA64; break; + + default: return 0; + } + + filterMode->Id = filterId; + return 1; +} + + + +/* ---------- Mach-O ---------- */ + +#define MACH_SIG_BE_32 0xCEFAEDFE +#define MACH_SIG_BE_64 0xCFFAEDFE +#define MACH_SIG_LE_32 0xFEEDFACE +#define MACH_SIG_LE_64 0xFEEDFACF + +#define MACH_ARCH_ABI64 (1 << 24) +#define MACH_MACHINE_386 7 +#define MACH_MACHINE_ARM 12 +#define MACH_MACHINE_SPARC 14 +#define MACH_MACHINE_PPC 18 +#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC) +#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386) + +static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + UInt32 filterId, numCommands, commandsSize; + + if (size < 512) + return 0; + + BoolInt /* mode64, */ be; + switch (GetUi32(buf)) + { + case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break; + case MACH_SIG_BE_64: /* mode64 = True; */ be = True; break; + case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break; + case MACH_SIG_LE_64: /* mode64 = True; */ be = False; break; + default: return 0; + } + + switch (Get32(buf + 4, be)) + { + case MACH_MACHINE_386: + case MACH_MACHINE_AMD64: filterId = k_X86; break; + case MACH_MACHINE_ARM: if ( be) return 0; filterId = k_ARM; break; + case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break; + case MACH_MACHINE_PPC: + case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break; + default: return 0; + } + + numCommands = Get32(buf + 0x10, be); + commandsSize = Get32(buf + 0x14, be); + + if (commandsSize > (1 << 24) || numCommands > (1 << 18)) + return 0; + + filterMode->Id = filterId; + return 1; +} + + +/* ---------- WAV ---------- */ + +#define WAV_SUBCHUNK_fmt 0x20746D66 +#define WAV_SUBCHUNK_data 0x61746164 + +#define RIFF_SIG 0x46464952 + +static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + UInt32 subChunkSize, pos; + if (size < 0x2C) + return False; + + if (GetUi32(buf + 0) != RIFF_SIG || + GetUi32(buf + 8) != 0x45564157 || // WAVE + GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt) + return False; + subChunkSize = GetUi32(buf + 0x10); + /* [0x14 = format] = 1 (PCM) */ + if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1) + return False; + + const unsigned numChannels = GetUi16(buf + 0x16); + const unsigned bitsPerSample = GetUi16(buf + 0x22); + if ((bitsPerSample & 0x7) != 0) + return False; + const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3); + if (delta == 0 || delta > 256) + return False; + + pos = 0x14 + subChunkSize; + + const int kNumSubChunksTests = 10; + // Do we need to scan more than 3 sub-chunks? + for (int i = 0; i < kNumSubChunksTests; i++) + { + if (pos + 8 > size) + return False; + subChunkSize = GetUi32(buf + pos + 4); + if (GetUi32(buf + pos) == WAV_SUBCHUNK_data) + { + filterMode->Id = k_Delta; + filterMode->Delta = delta; + return True; + } + if (subChunkSize > (1 << 16)) + return False; + pos += subChunkSize + 8; + } + return False; +} + +static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode) +{ + filterMode->Id = 0; + filterMode->Delta = 0; + + if (Parse_EXE(buf, size, filterMode)) return True; + if (Parse_ELF(buf, size, filterMode)) return True; + if (Parse_MACH(buf, size, filterMode)) return True; + return Parse_WAV(buf, size, filterMode); +} + + + + +struct CFilterMode2: public CFilterMode +{ + bool Encrypted; + unsigned GroupIndex; + + CFilterMode2(): Encrypted(false) {} + + int Compare(const CFilterMode2 &m) const + { + if (!Encrypted) + { + if (m.Encrypted) + return -1; + } + else if (!m.Encrypted) + return 1; + + if (Id < m.Id) return -1; + if (Id > m.Id) return 1; + + if (Delta < m.Delta) return -1; + if (Delta > m.Delta) return 1; + + return 0; + } + + bool operator ==(const CFilterMode2 &m) const + { + return Id == m.Id && Delta == m.Delta && Encrypted == m.Encrypted; + } +}; + +static unsigned GetGroup(CRecordVector &filters, const CFilterMode2 &m) +{ + unsigned i; + for (i = 0; i < filters.Size(); i++) + { + const CFilterMode2 &m2 = filters[i]; + if (m == m2) + return i; + /* + if (m.Encrypted != m2.Encrypted) + { + if (!m.Encrypted) + break; + continue; + } + + if (m.Id < m2.Id) break; + if (m.Id != m2.Id) continue; + + if (m.Delta < m2.Delta) break; + if (m.Delta != m2.Delta) continue; + */ + } + // filters.Insert(i, m); + // return i; + return filters.Add(m); +} + +static inline bool Is86Filter(CMethodId m) +{ + return (m == k_BCJ || m == k_BCJ2); +} + +static inline bool IsExeFilter(CMethodId m) +{ + switch (m) + { + case k_BCJ: + case k_BCJ2: + case k_ARM: + case k_ARMT: + case k_PPC: + case k_SPARC: + case k_IA64: + return true; + } + return false; +} + +static unsigned Get_FilterGroup_for_Folder( + CRecordVector &filters, const CFolderEx &f, bool extractFilter) +{ + CFilterMode2 m; + m.Id = 0; + m.Delta = 0; + m.Encrypted = f.IsEncrypted(); + + if (extractFilter) + { + const CCoderInfo &coder = f.Coders[f.UnpackCoder]; + + if (coder.MethodID == k_Delta) + { + if (coder.Props.Size() == 1) + { + m.Delta = (unsigned)coder.Props[0] + 1; + m.Id = k_Delta; + } + } + else if (IsExeFilter(coder.MethodID)) + { + m.Id = (UInt32)coder.MethodID; + if (m.Id == k_BCJ2) + m.Id = k_BCJ; + m.SetDelta(); + } + } + + return GetGroup(filters, m); +} + + + + +static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, + UInt64 position, UInt64 size, ICompressProgressInfo *progress) +{ + RINOK(inStream->Seek((Int64)position, STREAM_SEEK_SET, 0)); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStreamLimited(streamSpec); + streamSpec->SetStream(inStream); + streamSpec->Init(size); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); + return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); +} + +/* +unsigned CUpdateItem::GetExtensionPos() const +{ + int slashPos = Name.ReverseFind_PathSepar(); + int dotPos = Name.ReverseFind_Dot(); + if (dotPos <= slashPos) + return Name.Len(); + return dotPos + 1; +} + +UString CUpdateItem::GetExtension() const +{ + return Name.Ptr(GetExtensionPos()); +} +*/ + +#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } + +#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b)) + +/* +static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) +{ + size_t c1 = a1.GetCapacity(); + size_t c2 = a2.GetCapacity(); + RINOZ_COMP(c1, c2); + for (size_t i = 0; i < c1; i++) + RINOZ_COMP(a1[i], a2[i]); + return 0; +} + +static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) +{ + RINOZ_COMP(c1.NumInStreams, c2.NumInStreams); + RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams); + RINOZ_COMP(c1.MethodID, c2.MethodID); + return CompareBuffers(c1.Props, c2.Props); +} + +static int CompareBonds(const CBond &b1, const CBond &b2) +{ + RINOZ_COMP(b1.InIndex, b2.InIndex); + return MyCompare(b1.OutIndex, b2.OutIndex); +} + +static int CompareFolders(const CFolder &f1, const CFolder &f2) +{ + int s1 = f1.Coders.Size(); + int s2 = f2.Coders.Size(); + RINOZ_COMP(s1, s2); + int i; + for (i = 0; i < s1; i++) + RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); + s1 = f1.Bonds.Size(); + s2 = f2.Bonds.Size(); + RINOZ_COMP(s1, s2); + for (i = 0; i < s1; i++) + RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i])); + return 0; +} +*/ + +/* +static int CompareFiles(const CFileItem &f1, const CFileItem &f2) +{ + return CompareFileNames(f1.Name, f2.Name); +} +*/ + +struct CFolderRepack +{ + unsigned FolderIndex; + CNum NumCopyFiles; +}; + +/* +static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *) +{ + int i1 = p1->FolderIndex; + int i2 = p2->FolderIndex; + // In that version we don't want to parse folders here, so we don't compare folders + // probably it must be improved in future + // const CDbEx &db = *(const CDbEx *)param; + // RINOZ(CompareFolders( + // db.Folders[i1], + // db.Folders[i2])); + + return MyCompare(i1, i2); + + // RINOZ_COMP( + // db.NumUnpackStreamsVector[i1], + // db.NumUnpackStreamsVector[i2]); + // if (db.NumUnpackStreamsVector[i1] == 0) + // return 0; + // return CompareFiles( + // db.Files[db.FolderStartFileIndex[i1]], + // db.Files[db.FolderStartFileIndex[i2]]); +} +*/ + +/* + we sort empty files and dirs in such order: + - Dir.NonAnti (name sorted) + - File.NonAnti (name sorted) + - File.Anti (name sorted) + - Dir.Anti (reverse name sorted) +*/ + +static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param) +{ + const CObjectVector &updateItems = *(const CObjectVector *)param; + const CUpdateItem &u1 = updateItems[*p1]; + const CUpdateItem &u2 = updateItems[*p2]; + // NonAnti < Anti + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); + if (u1.IsDir != u2.IsDir) + { + // Dir.NonAnti < File < Dir.Anti + if (u1.IsDir) + return (u1.IsAnti ? 1 : -1); + return (u2.IsAnti ? -1 : 1); + } + int n = CompareFileNames(u1.Name, u2.Name); + return (u1.IsDir && u1.IsAnti) ? -n : n; +} + +static const char *g_Exts = + " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" + " zip jar ear war msi" + " 3gp avi mov mpeg mpg mpe wmv" + " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" + " swf" + " chm hxi hxs" + " gif jpeg jpg jp2 png tiff bmp ico psd psp" + " awg ps eps cgm dxf svg vrml wmf emf ai md" + " cad dwg pps key sxi" + " max 3ds" + " iso bin nrg mdf img pdi tar cpio xpi" + " vfd vhd vud vmc vsv" + " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" + " inl inc idl acf asa" + " h hpp hxx c cpp cxx m mm go swift" + " rc java cs rs pas bas vb cls ctl frm dlg def" + " f77 f f90 f95" + " asm s" + " sql manifest dep" + " mak clw csproj vcproj sln dsp dsw" + " class" + " bat cmd bash sh" + " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" + " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs" + " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" + " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" + " abw afp cwk lwp wpd wps wpt wrf wri" + " abf afm bdf fon mgf otf pcf pfa snf ttf" + " dbf mdb nsf ntf wdb db fdb gdb" + " exe dll ocx vbx sfx sys tlb awx com obj lib out o so" + " pdb pch idb ncb opt"; + +static unsigned GetExtIndex(const char *ext) +{ + unsigned extIndex = 1; + const char *p = g_Exts; + for (;;) + { + char c = *p++; + if (c == 0) + return extIndex; + if (c == ' ') + continue; + unsigned pos = 0; + for (;;) + { + char c2 = ext[pos++]; + if (c2 == 0 && (c == 0 || c == ' ')) + return extIndex; + if (c != c2) + break; + c = *p++; + } + extIndex++; + for (;;) + { + if (c == 0) + return extIndex; + if (c == ' ') + break; + c = *p++; + } + } +} + +struct CRefItem +{ + const CUpdateItem *UpdateItem; + UInt32 Index; + unsigned ExtensionPos; + unsigned NamePos; + unsigned ExtensionIndex; + + CRefItem() {}; + CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): + UpdateItem(&ui), + Index(index), + ExtensionPos(0), + NamePos(0), + ExtensionIndex(0) + { + if (sortByType) + { + int slashPos = ui.Name.ReverseFind_PathSepar(); + NamePos = (unsigned)(slashPos + 1); + int dotPos = ui.Name.ReverseFind_Dot(); + if (dotPos <= slashPos) + ExtensionPos = ui.Name.Len(); + else + { + ExtensionPos = (unsigned)(dotPos + 1); + if (ExtensionPos != ui.Name.Len()) + { + AString s; + for (unsigned pos = ExtensionPos;; pos++) + { + wchar_t c = ui.Name[pos]; + if (c >= 0x80) + break; + if (c == 0) + { + ExtensionIndex = GetExtIndex(s); + break; + } + s += (char)MyCharLower_Ascii((char)c); + } + } + } + } + } +}; + +struct CSortParam +{ + // const CObjectVector *TreeFolders; + bool SortByType; +}; + +/* + we sort files in such order: + - Dir.NonAnti (name sorted) + - alt streams + - Dirs + - Dir.Anti (reverse name sorted) +*/ + + +static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) +{ + const CRefItem &a1 = *p1; + const CRefItem &a2 = *p2; + const CUpdateItem &u1 = *a1.UpdateItem; + const CUpdateItem &u2 = *a2.UpdateItem; + + /* + if (u1.IsAltStream != u2.IsAltStream) + return u1.IsAltStream ? 1 : -1; + */ + + // Actually there are no dirs that time. They were stored in other steps + // So that code is unused? + if (u1.IsDir != u2.IsDir) + return u1.IsDir ? 1 : -1; + if (u1.IsDir) + { + if (u1.IsAnti != u2.IsAnti) + return (u1.IsAnti ? 1 : -1); + int n = CompareFileNames(u1.Name, u2.Name); + return -n; + } + + // bool sortByType = *(bool *)param; + const CSortParam *sortParam = (const CSortParam *)param; + bool sortByType = sortParam->SortByType; + if (sortByType) + { + RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos))); + RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos))); + if (!u1.MTimeDefined && u2.MTimeDefined) return 1; + if (u1.MTimeDefined && !u2.MTimeDefined) return -1; + if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime); + RINOZ_COMP(u1.Size, u2.Size); + } + /* + int par1 = a1.UpdateItem->ParentFolderIndex; + int par2 = a2.UpdateItem->ParentFolderIndex; + const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1]; + const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2]; + + int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd; + int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd; + if (b1 < b2) + { + if (e1 <= b2) + return -1; + // p2 in p1 + int par = par2; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par1) + { + RINOZ(CompareFileNames(u1.Name, tf.Name)); + break; + } + } + } + else if (b2 < b1) + { + if (e2 <= b1) + return 1; + // p1 in p2 + int par = par1; + for (;;) + { + const CTreeFolder &tf = (*sortParam->TreeFolders)[par]; + par = tf.Parent; + if (par == par2) + { + RINOZ(CompareFileNames(tf.Name, u2.Name)); + break; + } + } + } + */ + // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex); + RINOK(CompareFileNames(u1.Name, u2.Name)); + RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient); + RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive); + return 0; +} + +struct CSolidGroup +{ + CRecordVector Indices; + + CRecordVector folderRefs; +}; + +static const char * const g_ExeExts[] = +{ + "dll" + , "exe" + , "ocx" + , "sfx" + , "sys" +}; + +static bool IsExeExt(const wchar_t *ext) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_ExeExts); i++) + if (StringsAreEqualNoCase_Ascii(ext, g_ExeExts[i])) + return true; + return false; +} + +struct CAnalysis +{ + CMyComPtr Callback; + CByteBuffer Buffer; + + bool ParseWav; + bool ParseExe; + bool ParseAll; + + CAnalysis(): + ParseWav(true), + ParseExe(false), + ParseAll(false) + {} + + HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode); +}; + +static const size_t kAnalysisBufSize = 1 << 14; + +HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode) +{ + filterMode.Id = 0; + filterMode.Delta = 0; + + CFilterMode filterModeTemp = filterMode; + + int slashPos = ui.Name.ReverseFind_PathSepar(); + int dotPos = ui.Name.ReverseFind_Dot(); + + // if (dotPos > slashPos) + { + bool needReadFile = ParseAll; + + bool probablyIsSameIsa = false; + + if (!needReadFile || !Callback) + { + const wchar_t *ext; + if (dotPos > slashPos) + ext = ui.Name.Ptr((unsigned)(dotPos + 1)); + else + ext = ui.Name.RightPtr(0); + + // p7zip uses the trick to store posix attributes in high 16 bits + if (ui.Attrib & 0x8000) + { + unsigned st_mode = ui.Attrib >> 16; + // st_mode = 00111; + if ((st_mode & 00111) && (ui.Size >= 2048)) + { + #ifndef _WIN32 + probablyIsSameIsa = true; + #endif + needReadFile = true; + } + } + + if (IsExeExt(ext)) + { + needReadFile = true; + #ifdef _WIN32 + probablyIsSameIsa = true; + needReadFile = ParseExe; + #endif + } + else if (StringsAreEqualNoCase_Ascii(ext, "wav")) + { + needReadFile = ParseWav; + } + /* + else if (!needReadFile && ParseUnixExt) + { + if (StringsAreEqualNoCase_Ascii(ext, "so") + || StringsAreEqualNoCase_Ascii(ext, "")) + + needReadFile = true; + } + */ + } + + if (needReadFile && Callback) + { + if (Buffer.Size() != kAnalysisBufSize) + { + Buffer.Alloc(kAnalysisBufSize); + } + { + CMyComPtr stream; + HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze); + if (result == S_OK && stream) + { + size_t size = kAnalysisBufSize; + result = ReadStream(stream, Buffer, &size); + stream.Release(); + // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK)); + if (result == S_OK) + { + BoolInt parseRes = ParseFile(Buffer, size, &filterModeTemp); + if (parseRes && filterModeTemp.Delta == 0) + { + filterModeTemp.SetDelta(); + if (filterModeTemp.Delta != 0 && filterModeTemp.Id != k_Delta) + { + if (ui.Size % filterModeTemp.Delta != 0) + { + parseRes = false; + } + } + } + if (!parseRes) + { + filterModeTemp.Id = 0; + filterModeTemp.Delta = 0; + } + } + } + } + } + else if ((needReadFile && !Callback) || probablyIsSameIsa) + { + #ifdef MY_CPU_X86_OR_AMD64 + if (probablyIsSameIsa) + filterModeTemp.Id = k_X86; + #endif + } + } + + filterMode = filterModeTemp; + return S_OK; +} + +static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m) +{ + m.Id = methodID; + m.NumStreams = numStreams; +} + +static HRESULT AddBondForFilter(CCompressionMethodMode &mode) +{ + for (unsigned c = 1; c < mode.Methods.Size(); c++) + { + if (!mode.IsThereBond_to_Coder(c)) + { + CBond2 bond; + bond.OutCoder = 0; + bond.OutStream = 0; + bond.InCoder = c; + mode.Bonds.Add(bond); + return S_OK; + } + } + return E_INVALIDARG; +} + +static HRESULT AddFilterBond(CCompressionMethodMode &mode) +{ + if (!mode.Bonds.IsEmpty()) + return AddBondForFilter(mode); + return S_OK; +} + +static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) +{ + // mode.Methods[0] must be k_BCJ2 method ! + + CMethodFull m; + GetMethodFull(k_LZMA, 1, m); + + m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20); + m.AddProp32(NCoderPropID::kNumFastBytes, 128); + m.AddProp32(NCoderPropID::kNumThreads, 1); + m.AddProp32(NCoderPropID::kLitPosBits, 2); + m.AddProp32(NCoderPropID::kLitContextBits, 0); + // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); + + unsigned methodIndex = mode.Methods.Size(); + + if (mode.Bonds.IsEmpty()) + { + for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++) + { + CBond2 bond; + bond.OutCoder = i; + bond.OutStream = 0; + bond.InCoder = i + 1; + mode.Bonds.Add(bond); + } + } + + mode.Methods.Add(m); + mode.Methods.Add(m); + + RINOK(AddBondForFilter(mode)); + CBond2 bond; + bond.OutCoder = 0; + bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); + bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); + return S_OK; +} + +static HRESULT MakeExeMethod(CCompressionMethodMode &mode, + const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) +{ + if (mode.Filter_was_Inserted) + { + const CMethodFull &m = mode.Methods[0]; + CMethodId id = m.Id; + if (id == k_BCJ2) + return AddBcj2Methods(mode); + if (!m.IsSimpleCoder()) + return E_NOTIMPL; + // if (Bonds.IsEmpty()) we can create bonds later + return AddFilterBond(mode); + } + + if (filterMode.Id == 0) + return S_OK; + + CMethodFull &m = mode.Methods.InsertNew(0); + + { + FOR_VECTOR(k, mode.Bonds) + { + CBond2 &bond = mode.Bonds[k]; + bond.InCoder++; + bond.OutCoder++; + } + } + + HRESULT res; + + if (bcj2Filter && Is86Filter(filterMode.Id)) + { + GetMethodFull(k_BCJ2, 4, m); + res = AddBcj2Methods(mode); + } + else + { + GetMethodFull(filterMode.Id, 1, m); + if (filterMode.Id == k_Delta) + m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); + res = AddFilterBond(mode); + + int alignBits = -1; + if (filterMode.Id == k_Delta || filterMode.Delta != 0) + { + if (filterMode.Delta == 1) alignBits = 0; + else if (filterMode.Delta == 2) alignBits = 1; + else if (filterMode.Delta == 4) alignBits = 2; + else if (filterMode.Delta == 8) alignBits = 3; + else if (filterMode.Delta == 16) alignBits = 4; + } + else + { + // alignBits = GetAlignForFilterMethod(filterMode.Id); + } + + if (res == S_OK && alignBits >= 0) + { + unsigned nextCoder = 1; + if (!mode.Bonds.IsEmpty()) + { + nextCoder = mode.Bonds.Back().InCoder; + } + if (nextCoder < mode.Methods.Size()) + { + CMethodFull &nextMethod = mode.Methods[nextCoder]; + if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) + { + if (!nextMethod.Are_Lzma_Model_Props_Defined()) + { + if (alignBits != 0) + { + if (alignBits > 2 || filterMode.Id == k_Delta) + nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); + unsigned lc = 0; + if (alignBits < 3) + lc = (unsigned)(3 - alignBits); + nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); + nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); + } + } + } + } + } + } + + return res; +} + + +static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2) +{ + file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined; + file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; + file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; + file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; + file2.IsAnti = ui.IsAnti; + // file2.IsAux = false; + file2.StartPosDefined = false; + // file2.StartPos = 0; +} + + +static void UpdateItem_To_FileItem(const CUpdateItem &ui, + CFileItem &file, CFileItem2 &file2) +{ + UpdateItem_To_FileItem2(ui, file2); + + file.Size = ui.Size; + file.IsDir = ui.IsDir; + file.HasStream = ui.HasStream(); + // file.IsAltStream = ui.IsAltStream; +} + + + +class CRepackInStreamWithSizes: + public ISequentialInStream, + public ICompressGetSubStreamSize, + public CMyUnknownImp +{ + CMyComPtr _stream; + // UInt64 _size; + const CBoolVector *_extractStatuses; + UInt32 _startIndex; +public: + const CDbEx *_db; + + void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses) + { + _startIndex = startIndex; + _extractStatuses = extractStatuses; + // _size = 0; + _stream = stream; + } + // UInt64 GetSize() const { return _size; } + + MY_UNKNOWN_IMP2(ISequentialInStream, ICompressGetSubStreamSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); +}; + +STDMETHODIMP CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + return _stream->Read(data, size, processedSize); + /* + UInt32 realProcessedSize; + HRESULT result = _stream->Read(data, size, &realProcessedSize); + _size += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return result; + */ +} + +STDMETHODIMP CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value) +{ + *value = 0; + if (subStream >= _extractStatuses->Size()) + return S_FALSE; // E_FAIL; + unsigned index = (unsigned)subStream; + if ((*_extractStatuses)[index]) + { + const CFileItem &fi = _db->Files[_startIndex + index]; + if (fi.HasStream) + *value = fi.Size; + } + return S_OK; +} + + +class CRepackStreamBase +{ +protected: + bool _needWrite; + bool _fileIsOpen; + bool _calcCrc; + UInt32 _crc; + UInt64 _rem; + + const CBoolVector *_extractStatuses; + UInt32 _startIndex; + unsigned _currentIndex; + + HRESULT OpenFile(); + HRESULT CloseFile(); + HRESULT ProcessEmptyFiles(); + +public: + const CDbEx *_db; + CMyComPtr _opCallback; + CMyComPtr _extractCallback; + + HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses); + HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; } +}; + +HRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses) +{ + _startIndex = startIndex; + _extractStatuses = extractStatuses; + + _currentIndex = 0; + _fileIsOpen = false; + + return ProcessEmptyFiles(); +} + +HRESULT CRepackStreamBase::OpenFile() +{ + UInt32 arcIndex = _startIndex + _currentIndex; + const CFileItem &fi = _db->Files[arcIndex]; + + _needWrite = (*_extractStatuses)[_currentIndex]; + if (_opCallback) + { + RINOK(_opCallback->ReportOperation( + NEventIndexType::kInArcIndex, arcIndex, + _needWrite ? + NUpdateNotifyOp::kRepack : + NUpdateNotifyOp::kSkip)); + } + + _crc = CRC_INIT_VAL; + _calcCrc = (fi.CrcDefined && !fi.IsDir); + + _fileIsOpen = true; + _rem = fi.Size; + return S_OK; +} + +const HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002; + +HRESULT CRepackStreamBase::CloseFile() +{ + UInt32 arcIndex = _startIndex + _currentIndex; + const CFileItem &fi = _db->Files[arcIndex]; + _fileIsOpen = false; + _currentIndex++; + if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) + return S_OK; + + if (_extractCallback) + { + RINOK(_extractCallback->ReportExtractResult( + NEventIndexType::kInArcIndex, arcIndex, + NExtract::NOperationResult::kCRCError)); + } + // return S_FALSE; + return k_My_HRESULT_CRC_ERROR; +} + +HRESULT CRepackStreamBase::ProcessEmptyFiles() +{ + while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0) + { + RINOK(OpenFile()); + RINOK(CloseFile()); + } + return S_OK; +} + + + +#ifndef _7ZIP_ST + +class CFolderOutStream2: + public CRepackStreamBase, + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CMyComPtr _stream; + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + HRESULT result = S_OK; + if (_needWrite) + result = _stream->Write(data, cur, &cur); + if (_calcCrc) + _crc = CrcUpdate(_crc, data, cur); + if (processedSize) + *processedSize += cur; + data = (const Byte *)data + cur; + size -= cur; + _rem -= cur; + if (_rem == 0) + { + RINOK(CloseFile()); + RINOK(ProcessEmptyFiles()); + } + RINOK(result); + if (cur == 0) + break; + continue; + } + + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + // we don't support write cut here + return E_FAIL; + } + RINOK(OpenFile()); + } + + return S_OK; +} + +#endif + + + +static const UInt32 kTempBufSize = 1 << 16; + +class CFolderInStream2: + public CRepackStreamBase, + public ISequentialInStream, + public CMyUnknownImp +{ + Byte *_buf; +public: + CMyComPtr _inStream; + HRESULT Result; + + MY_UNKNOWN_IMP + + CFolderInStream2(): + Result(S_OK) + { + _buf = new Byte[kTempBufSize]; + } + + ~CFolderInStream2() + { + delete []_buf; + } + + void Init() { Result = S_OK; } + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_fileIsOpen) + { + UInt32 cur = (size < _rem ? size : (UInt32)_rem); + + void *buf; + if (_needWrite) + buf = data; + else + { + buf = _buf; + if (cur > kTempBufSize) + cur = kTempBufSize; + } + + HRESULT result = _inStream->Read(buf, cur, &cur); + _crc = CrcUpdate(_crc, buf, cur); + _rem -= cur; + + if (_needWrite) + { + data = (Byte *)data + cur; + size -= cur; + if (processedSize) + *processedSize += cur; + } + + if (result != S_OK) + Result = result; + + if (_rem == 0) + { + RINOK(CloseFile()); + RINOK(ProcessEmptyFiles()); + } + + RINOK(result); + + if (cur == 0) + return E_FAIL; + + continue; + } + + RINOK(ProcessEmptyFiles()); + if (_currentIndex == _extractStatuses->Size()) + { + return S_OK; + } + RINOK(OpenFile()); + } + + return S_OK; +} + + +class CThreadDecoder + #ifndef _7ZIP_ST + : public CVirtThread + #endif +{ +public: + CDecoder Decoder; + + CThreadDecoder(bool multiThreadMixer): + Decoder(multiThreadMixer) + { + #ifndef _7ZIP_ST + if (multiThreadMixer) + { + MtMode = false; + NumThreads = 1; + FosSpec = new CFolderOutStream2; + Fos = FosSpec; + Result = E_FAIL; + } + #endif + // UnpackSize = 0; + // send_UnpackSize = false; + } + + #ifndef _7ZIP_ST + + bool dataAfterEnd_Error; + HRESULT Result; + CMyComPtr InStream; + + CFolderOutStream2 *FosSpec; + CMyComPtr Fos; + + UInt64 StartPos; + const CFolders *Folders; + unsigned FolderIndex; + + // bool send_UnpackSize; + // UInt64 UnpackSize; + + #ifndef _NO_CRYPTO + CMyComPtr getTextPassword; + #endif + + DECL_EXTERNAL_CODECS_LOC_VARS2; + + #ifndef _7ZIP_ST + bool MtMode; + UInt32 NumThreads; + #endif + + + ~CThreadDecoder() { CVirtThread::WaitThreadFinish(); } + virtual void Execute(); + + #endif +}; + +#ifndef _7ZIP_ST + +void CThreadDecoder::Execute() +{ + try + { + #ifndef _NO_CRYPTO + bool isEncrypted = false; + bool passwordIsDefined = false; + UString password; + #endif + + dataAfterEnd_Error = false; + + Result = Decoder.Decode( + EXTERNAL_CODECS_LOC_VARS + InStream, + StartPos, + *Folders, FolderIndex, + + // send_UnpackSize ? &UnpackSize : NULL, + NULL, // unpackSize : FULL unpack + + Fos, + NULL, // compressProgress + + NULL // *inStreamMainRes + , dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS + #ifndef _7ZIP_ST + , MtMode, NumThreads, + 0 // MemUsage + #endif + + ); + } + catch(...) + { + Result = E_FAIL; + } + + /* + if (Result == S_OK) + Result = FosSpec->CheckFinishedState(); + */ + FosSpec->_stream.Release(); +} + +#endif + +#ifndef _NO_CRYPTO + +class CCryptoGetTextPassword: + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + UString Password; + + MY_UNKNOWN_IMP + STDMETHOD(CryptoGetTextPassword)(BSTR *password); +}; + +STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password) +{ + return StringToBstr(Password, password); +} + +#endif + + +static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2) +{ + file = inDb.Files[index]; + file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime); + file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime); + file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime); + file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos); + file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib); + file2.IsAnti = inDb.IsItemAnti(index); + // file2.IsAux = inDb.IsItemAux(index); +} + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + const CDbEx *db, + const CObjectVector &updateItems, + // const CObjectVector &treeFolders, + // const CUniqBlocks &secureBlocks, + COutArchive &archive, + CArchiveDatabaseOut &newDatabase, + ISequentialOutStream *seqOutStream, + IArchiveUpdateCallback *updateCallback, + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ) +{ + UInt64 numSolidFiles = options.NumSolidFiles; + if (numSolidFiles == 0) + numSolidFiles = 1; + + CMyComPtr opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + + CMyComPtr extractCallback; + updateCallback->QueryInterface(IID_IArchiveExtractCallbackMessage, (void **)&extractCallback); + + // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes(); + + /* + CMyComPtr outStream; + RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); + if (!outStream) + return E_NOTIMPL; + */ + + UInt64 startBlockSize = db ? db->ArcInfo.StartPosition: 0; + if (startBlockSize > 0 && !options.RemoveSfxBlock) + { + RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); + } + + CIntArr fileIndexToUpdateIndexMap; + UInt64 complexity = 0; + UInt64 inSizeForReduce2 = 0; + bool needEncryptedRepack = false; + + CRecordVector filters; + CObjectVector groups; + + #ifndef _7ZIP_ST + bool thereAreRepacks = false; + #endif + + bool useFilters = options.UseFilters; + if (useFilters) + { + const CCompressionMethodMode &method = *options.Method; + + FOR_VECTOR (i, method.Methods) + if (IsFilterMethod(method.Methods[i].Id)) + { + useFilters = false; + break; + } + } + + if (db) + { + fileIndexToUpdateIndexMap.Alloc(db->Files.Size()); + unsigned i; + + for (i = 0; i < db->Files.Size(); i++) + fileIndexToUpdateIndexMap[i] = -1; + + for (i = 0; i < updateItems.Size(); i++) + { + int index = updateItems[i].IndexInArchive; + if (index != -1) + fileIndexToUpdateIndexMap[(unsigned)index] = (int)i; + } + + for (i = 0; i < db->NumFolders; i++) + { + CNum indexInFolder = 0; + CNum numCopyItems = 0; + CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; + UInt64 repackSize = 0; + + for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++) + { + if (fi >= db->Files.Size()) + return E_FAIL; + + const CFileItem &file = db->Files[fi]; + if (file.HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) + { + numCopyItems++; + repackSize += file.Size; + } + } + } + + if (numCopyItems == 0) + continue; + + CFolderRepack rep; + rep.FolderIndex = i; + rep.NumCopyFiles = numCopyItems; + CFolderEx f; + db->ParseFolderEx(i, f); + + const bool isEncrypted = f.IsEncrypted(); + const bool needCopy = (numCopyItems == numUnpackStreams); + const bool extractFilter = (useFilters || needCopy); + + unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter); + + while (groupIndex >= groups.Size()) + groups.AddNew(); + + groups[groupIndex].folderRefs.Add(rep); + + if (needCopy) + complexity += db->GetFolderFullPackSize(i); + else + { + #ifndef _7ZIP_ST + thereAreRepacks = true; + #endif + complexity += repackSize; + if (inSizeForReduce2 < repackSize) + inSizeForReduce2 = repackSize; + if (isEncrypted) + needEncryptedRepack = true; + } + } + } + + UInt64 inSizeForReduce = 0; + { + bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); + FOR_VECTOR (i, updateItems) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + { + complexity += ui.Size; + if (isSolid) + inSizeForReduce += ui.Size; + else if (inSizeForReduce < ui.Size) + inSizeForReduce = ui.Size; + } + } + } + + if (inSizeForReduce < inSizeForReduce2) + inSizeForReduce = inSizeForReduce2; + + RINOK(updateCallback->SetTotal(complexity)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + #ifndef _7ZIP_ST + + CStreamBinder sb; + /* + if (options.MultiThreadMixer) + { + RINOK(sb.CreateEvents()); + } + */ + + #endif + + CThreadDecoder threadDecoder(options.MultiThreadMixer); + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer && thereAreRepacks) + { + #ifdef EXTERNAL_CODECS + threadDecoder.__externalCodecs = __externalCodecs; + #endif + WRes wres = threadDecoder.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + #endif + + { + CAnalysis analysis; + if (options.AnalysisLevel == 0) + { + analysis.ParseWav = false; + analysis.ParseExe = false; + analysis.ParseAll = false; + } + else + { + analysis.Callback = opCallback; + if (options.AnalysisLevel > 0) + { + analysis.ParseWav = true; + if (options.AnalysisLevel >= 7) + { + analysis.ParseExe = true; + if (options.AnalysisLevel >= 9) + analysis.ParseAll = true; + } + } + } + + // ---------- Split files to groups ---------- + + const CCompressionMethodMode &method = *options.Method; + + FOR_VECTOR (i, updateItems) + { + const CUpdateItem &ui = updateItems[i]; + if (!ui.NewData || !ui.HasStream()) + continue; + + CFilterMode2 fm; + if (useFilters) + { + RINOK(analysis.GetFilterGroup(i, ui, fm)); + } + fm.Encrypted = method.PasswordIsDefined; + + unsigned groupIndex = GetGroup(filters, fm); + while (groupIndex >= groups.Size()) + groups.AddNew(); + groups[groupIndex].Indices.Add(i); + } + } + + + #ifndef _NO_CRYPTO + + CCryptoGetTextPassword *getPasswordSpec = NULL; + CMyComPtr getTextPassword; + if (needEncryptedRepack) + { + getPasswordSpec = new CCryptoGetTextPassword; + getTextPassword = getPasswordSpec; + + #ifndef _7ZIP_ST + threadDecoder.getTextPassword = getPasswordSpec; + #endif + + if (options.Method->PasswordIsDefined) + getPasswordSpec->Password = options.Method->Password; + else + { + if (!getDecoderPassword) + return E_NOTIMPL; + CMyComBSTR password; + RINOK(getDecoderPassword->CryptoGetTextPassword(&password)); + if (password) + getPasswordSpec->Password = password; + } + } + + #endif + + + // ---------- Compress ---------- + + RINOK(archive.Create(seqOutStream, false)); + RINOK(archive.SkipPrefixArchiveHeader()); + + /* + CIntVector treeFolderToArcIndex; + treeFolderToArcIndex.Reserve(treeFolders.Size()); + for (i = 0; i < treeFolders.Size(); i++) + treeFolderToArcIndex.Add(-1); + // ---------- Write Tree (only AUX dirs) ---------- + for (i = 1; i < treeFolders.Size(); i++) + { + const CTreeFolder &treeFolder = treeFolders[i]; + CFileItem file; + CFileItem2 file2; + file2.Init(); + int secureID = 0; + if (treeFolder.UpdateItemIndex < 0) + { + // we can store virtual dir item wuthout attrib, but we want all items have attrib. + file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY); + file2.IsAux = true; + } + else + { + const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex]; + // if item is not dir, then it's parent for alt streams. + // we will write such items later + if (!ui.IsDir) + continue; + secureID = ui.SecureIndex; + if (ui.NewProps) + UpdateItem_To_FileItem(ui, file, file2); + else + GetFile(*db, ui.IndexInArchive, file, file2); + } + file.Size = 0; + file.HasStream = false; + file.IsDir = true; + file.Parent = treeFolder.Parent; + + treeFolderToArcIndex[i] = newDatabase.Files.Size(); + newDatabase.AddFile(file, file2, treeFolder.Name); + + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(secureID); + } + */ + + { + /* ---------- Write non-AUX dirs and Empty files ---------- */ + CUIntVector emptyRefs; + + unsigned i; + + for (i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &ui = updateItems[i]; + if (ui.NewData) + { + if (ui.HasStream()) + continue; + } + else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream) + continue; + /* + if (ui.TreeFolderIndex >= 0) + continue; + */ + emptyRefs.Add(i); + } + + emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); + + for (i = 0; i < emptyRefs.Size(); i++) + { + const CUpdateItem &ui = updateItems[emptyRefs[i]]; + CFileItem file; + CFileItem2 file2; + UString name; + if (ui.NewProps) + { + UpdateItem_To_FileItem(ui, file, file2); + file.CrcDefined = false; + name = ui.Name; + } + else + { + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); + } + + /* + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + file.Parent = ui.ParentFolderIndex; + */ + newDatabase.AddFile(file, file2, name); + } + } + + lps->ProgressOffset = 0; + + { + // ---------- Sort Filters ---------- + + FOR_VECTOR (i, filters) + { + filters[i].GroupIndex = i; + } + filters.Sort2(); + } + + for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++) + { + const CFilterMode2 &filterMode = filters[groupIndex]; + + CCompressionMethodMode method = *options.Method; + { + HRESULT res = MakeExeMethod(method, filterMode, + #ifdef _7ZIP_ST + false + #else + options.MaxFilter && options.MultiThreadMixer + #endif + ); + + RINOK(res); + } + + if (filterMode.Encrypted) + { + if (!method.PasswordIsDefined) + { + #ifndef _NO_CRYPTO + if (getPasswordSpec) + method.Password = getPasswordSpec->Password; + #endif + method.PasswordIsDefined = true; + } + } + else + { + method.PasswordIsDefined = false; + method.Password.Empty(); + } + + CEncoder encoder(method); + + // ---------- Repack and copy old solid blocks ---------- + + const CSolidGroup &group = groups[filterMode.GroupIndex]; + + FOR_VECTOR(folderRefIndex, group.folderRefs) + { + const CFolderRepack &rep = group.folderRefs[folderRefIndex]; + + unsigned folderIndex = rep.FolderIndex; + + CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; + + if (rep.NumCopyFiles == numUnpackStreams) + { + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NUpdateNotifyOp::kReplicate)); + + // ---------- Copy old solid block ---------- + { + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + if (db->Files[fi].HasStream) + { + indexInFolder++; + RINOK(opCallback->ReportOperation( + NEventIndexType::kInArcIndex, (UInt32)fi, + NUpdateNotifyOp::kReplicate)); + } + } + } + } + + UInt64 packSize = db->GetFolderFullPackSize(folderIndex); + RINOK(WriteRange(inStream, archive.SeqStream, + db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); + lps->ProgressOffset += packSize; + + CFolder &folder = newDatabase.Folders.AddNew(); + db->ParseFolderInfo(folderIndex, folder); + CNum startIndex = db->FoStartPackStreamIndex[folderIndex]; + FOR_VECTOR(j, folder.PackStreams) + { + newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j)); + // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); + // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); + } + + size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; + size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; + for (; indexStart < indexEnd; indexStart++) + newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); + } + else + { + // ---------- Repack old solid block ---------- + + CBoolVector extractStatuses; + + CNum indexInFolder = 0; + + if (opCallback) + { + RINOK(opCallback->ReportOperation( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NUpdateNotifyOp::kRepack)) + } + + /* We could reduce data size of decoded folder, if we don't need to repack + last files in folder. But the gain in speed is small in most cases. + So we unpack full folder. */ + + UInt64 sizeToEncode = 0; + + /* + UInt64 importantUnpackSize = 0; + unsigned numImportantFiles = 0; + UInt64 decodeSize = 0; + */ + + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + bool needExtract = false; + const CFileItem &file = db->Files[fi]; + + if (file.HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData) + needExtract = true; + // decodeSize += file.Size; + } + + extractStatuses.Add(needExtract); + if (needExtract) + { + sizeToEncode += file.Size; + /* + numImportantFiles = extractStatuses.Size(); + importantUnpackSize = decodeSize; + */ + } + } + + // extractStatuses.DeleteFrom(numImportantFiles); + + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curUnpackSize; + { + + CMyComPtr sbInStream; + CRepackStreamBase *repackBase; + CFolderInStream2 *FosSpec2 = NULL; + + CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes; + CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; + { + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + repackBase = threadDecoder.FosSpec; + CMyComPtr sbOutStream; + sb.CreateStreams2(sbInStream, sbOutStream); + RINOK(sb.Create_ReInit()); + + threadDecoder.FosSpec->_stream = sbOutStream; + + threadDecoder.InStream = inStream; + threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0); + threadDecoder.Folders = (const CFolders *)db; + threadDecoder.FolderIndex = folderIndex; + + // threadDecoder.UnpackSize = importantUnpackSize; + // threadDecoder.send_UnpackSize = true; + } + else + #endif + { + FosSpec2 = new CFolderInStream2; + FosSpec2->Init(); + sbInStream = FosSpec2; + repackBase = FosSpec2; + + #ifndef _NO_CRYPTO + bool isEncrypted = false; + bool passwordIsDefined = false; + UString password; + #endif + + CMyComPtr decodedStream; + bool dataAfterEnd_Error = false; + + HRESULT res = threadDecoder.Decoder.Decode( + EXTERNAL_CODECS_LOC_VARS + inStream, + db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);, + *db, folderIndex, + // &importantUnpackSize, // *unpackSize + NULL, // *unpackSize : FULL unpack + + NULL, // *outStream + NULL, // *compressProgress + + &decodedStream + , dataAfterEnd_Error + + _7Z_DECODER_CRYPRO_VARS + #ifndef _7ZIP_ST + , false // mtMode + , 1 // numThreads + , 0 // memUsage + #endif + ); + + RINOK(res); + if (!decodedStream) + return E_FAIL; + + FosSpec2->_inStream = decodedStream; + } + + repackBase->_db = db; + repackBase->_opCallback = opCallback; + repackBase->_extractCallback = extractCallback; + + UInt32 startIndex = db->FolderStartFileIndex[folderIndex]; + RINOK(repackBase->Init(startIndex, &extractStatuses)); + + inStreamSizeCountSpec->_db = db; + inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses); + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + WRes wres = threadDecoder.Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + #endif + } + + curUnpackSize = sizeToEncode; + + HRESULT encodeRes = encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + inStreamSizeCount, + // NULL, + &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curUnpackSize, + archive.SeqStream, newDatabase.PackSizes, progress); + + if (encodeRes == k_My_HRESULT_CRC_ERROR) + return E_FAIL; + + #ifndef _7ZIP_ST + if (options.MultiThreadMixer) + { + // 16.00: hang was fixed : for case if decoding was not finished. + // We close CBinderInStream and it calls CStreamBinder::CloseRead() + inStreamSizeCount.Release(); + sbInStream.Release(); + + { + WRes wres = threadDecoder.WaitExecuteFinish(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + + HRESULT decodeRes = threadDecoder.Result; + // if (res == k_My_HRESULT_CRC_ERROR) + if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error) + { + if (extractCallback) + { + RINOK(extractCallback->ReportExtractResult( + NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex], + // NEventIndexType::kBlockIndex, (UInt32)folderIndex, + (decodeRes != S_OK ? + NExtract::NOperationResult::kDataError : + NExtract::NOperationResult::kDataAfterEnd))); + } + if (decodeRes != S_OK) + return E_FAIL; + } + RINOK(decodeRes); + if (encodeRes == S_OK) + if (sb.ProcessedSize != sizeToEncode) + encodeRes = E_FAIL; + } + else + #endif + { + if (FosSpec2->Result == S_FALSE) + { + if (extractCallback) + { + RINOK(extractCallback->ReportExtractResult( + NEventIndexType::kBlockIndex, (UInt32)folderIndex, + NExtract::NOperationResult::kDataError)); + } + return E_FAIL; + } + RINOK(FosSpec2->Result); + } + + RINOK(encodeRes); + RINOK(repackBase->CheckFinishedState()); + + if (curUnpackSize != sizeToEncode) + return E_FAIL; + } + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + lps->InSize += curUnpackSize; + } + + newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles); + + CNum indexInFolder = 0; + for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) + { + if (db->Files[fi].HasStream) + { + indexInFolder++; + int updateIndex = fileIndexToUpdateIndexMap[fi]; + if (updateIndex >= 0) + { + const CUpdateItem &ui = updateItems[(unsigned)updateIndex]; + if (ui.NewData) + continue; + + UString name; + CFileItem file; + CFileItem2 file2; + GetFile(*db, fi, file, file2); + + if (ui.NewProps) + { + UpdateItem_To_FileItem2(ui, file2); + file.IsDir = ui.IsDir; + name = ui.Name; + } + else + db->GetPath(fi, name); + + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); + } + } + } + } + + + // ---------- Compress files to new solid blocks ---------- + + unsigned numFiles = group.Indices.Size(); + if (numFiles == 0) + continue; + CRecordVector refItems; + refItems.ClearAndSetSize(numFiles); + // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1 + bool sortByType = options.UseTypeSorting; + + unsigned i; + + for (i = 0; i < numFiles; i++) + refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); + + CSortParam sortParam; + // sortParam.TreeFolders = &treeFolders; + sortParam.SortByType = sortByType; + refItems.Sort(CompareUpdateItems, (void *)&sortParam); + + CObjArray indices(numFiles); + + for (i = 0; i < numFiles; i++) + { + UInt32 index = refItems[i].Index; + indices[i] = index; + /* + const CUpdateItem &ui = updateItems[index]; + CFileItem file; + if (ui.NewProps) + UpdateItem_To_FileItem(ui, file); + else + file = db.Files[ui.IndexInArchive]; + if (file.IsAnti || file.IsDir) + return E_FAIL; + newDatabase.Files.Add(file); + */ + } + + for (i = 0; i < numFiles;) + { + UInt64 totalSize = 0; + unsigned numSubFiles; + + const wchar_t *prevExtension = NULL; + + for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) + { + const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; + totalSize += ui.Size; + if (totalSize > options.NumSolidBytes) + break; + if (options.SolidExtension) + { + int slashPos = ui.Name.ReverseFind_PathSepar(); + int dotPos = ui.Name.ReverseFind_Dot(); + const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1)); + if (numSubFiles == 0) + prevExtension = ext; + else if (!StringsAreEqualNoCase(ext, prevExtension)) + break; + } + } + + if (numSubFiles < 1) + numSubFiles = 1; + + RINOK(lps->SetCur()); + + CFolderInStream *inStreamSpec = new CFolderInStream; + CMyComPtr solidInStream(inStreamSpec); + inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); + + unsigned startPackIndex = newDatabase.PackSizes.Size(); + UInt64 curFolderUnpackSize = totalSize; + // curFolderUnpackSize = (UInt64)(Int64)-1; + + RINOK(encoder.Encode( + EXTERNAL_CODECS_LOC_VARS + solidInStream, + // NULL, + &inSizeForReduce, + newDatabase.Folders.AddNew(), newDatabase.CoderUnpackSizes, curFolderUnpackSize, + archive.SeqStream, newDatabase.PackSizes, progress)); + + if (!inStreamSpec->WasFinished()) + return E_FAIL; + + for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) + lps->OutSize += newDatabase.PackSizes[startPackIndex]; + + lps->InSize += curFolderUnpackSize; + // for () + // newDatabase.PackCRCsDefined.Add(false); + // newDatabase.PackCRCs.Add(0); + + CNum numUnpackStreams = 0; + UInt64 skippedSize = 0; + + for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++) + { + const CUpdateItem &ui = updateItems[indices[i + subIndex]]; + CFileItem file; + CFileItem2 file2; + UString name; + if (ui.NewProps) + { + UpdateItem_To_FileItem(ui, file, file2); + name = ui.Name; + } + else + { + GetFile(*db, (unsigned)ui.IndexInArchive, file, file2); + db->GetPath((unsigned)ui.IndexInArchive, name); + } + if (file2.IsAnti || file.IsDir) + return E_FAIL; + + /* + CFileItem &file = newDatabase.Files[ + startFileIndexInDatabase + i + subIndex]; + */ + if (!inStreamSpec->Processed[subIndex]) + { + skippedSize += ui.Size; + continue; + // file.Name += ".locked"; + } + + file.Crc = inStreamSpec->CRCs[subIndex]; + file.Size = inStreamSpec->Sizes[subIndex]; + + // if (file.Size >= 0) // test purposes + if (file.Size != 0) + { + file.CrcDefined = true; + file.HasStream = true; + numUnpackStreams++; + } + else + { + file.CrcDefined = false; + file.HasStream = false; + } + + /* + file.Parent = ui.ParentFolderIndex; + if (ui.TreeFolderIndex >= 0) + treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size(); + if (totalSecureDataSize != 0) + newDatabase.SecureIDs.Add(ui.SecureIndex); + */ + newDatabase.AddFile(file, file2, name); + } + + // numUnpackStreams = 0 is very bad case for locked files + // v3.13 doesn't understand it. + newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); + i += numSubFiles; + + if (skippedSize != 0 && complexity >= skippedSize) + { + complexity -= skippedSize; + RINOK(updateCallback->SetTotal(complexity)); + } + } + } + + RINOK(lps->SetCur()); + + /* + fileIndexToUpdateIndexMap.ClearAndFree(); + groups.ClearAndFree(); + */ + + /* + for (i = 0; i < newDatabase.Files.Size(); i++) + { + CFileItem &file = newDatabase.Files[i]; + file.Parent = treeFolderToArcIndex[file.Parent]; + } + + if (totalSecureDataSize != 0) + { + newDatabase.SecureBuf.SetCapacity(totalSecureDataSize); + size_t pos = 0; + newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size()); + for (i = 0; i < secureBlocks.Sorted.Size(); i++) + { + const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]]; + size_t size = buf.GetCapacity(); + if (size != 0) + memcpy(newDatabase.SecureBuf + pos, buf, size); + newDatabase.SecureSizes.Add((UInt32)size); + pos += size; + } + } + */ + newDatabase.ReserveDown(); + + if (opCallback) + RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader)); + + return S_OK; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.h new file mode 100644 index 0000000..7c0f78a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/7zUpdate.h @@ -0,0 +1,139 @@ +// 7zUpdate.h + +#ifndef __7Z_UPDATE_H +#define __7Z_UPDATE_H + +#include "../IArchive.h" + +// #include "../../Common/UniqBlocks.h" + +#include "7zCompressionMode.h" +#include "7zIn.h" +#include "7zOut.h" + +namespace NArchive { +namespace N7z { + +/* +struct CTreeFolder +{ + UString Name; + int Parent; + CIntVector SubFolders; + int UpdateItemIndex; + int SortIndex; + int SortIndexEnd; + + CTreeFolder(): UpdateItemIndex(-1) {} +}; +*/ + +struct CUpdateItem +{ + int IndexInArchive; + unsigned IndexInClient; + + UInt64 CTime; + UInt64 ATime; + UInt64 MTime; + + UInt64 Size; + UString Name; + /* + bool IsAltStream; + int ParentFolderIndex; + int TreeFolderIndex; + */ + + // that code is not used in 9.26 + // int ParentSortIndex; + // int ParentSortIndexEnd; + + UInt32 Attrib; + + bool NewData; + bool NewProps; + + bool IsAnti; + bool IsDir; + + bool AttribDefined; + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + // int SecureIndex; // 0 means (no_security) + + bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } + // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes + + CUpdateItem(): + // ParentSortIndex(-1), + // IsAltStream(false), + IsAnti(false), + IsDir(false), + AttribDefined(false), + CTimeDefined(false), + ATimeDefined(false), + MTimeDefined(false) + // SecureIndex(0) + {} + void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); } + + // unsigned GetExtensionPos() const; + // UString GetExtension() const; +}; + +struct CUpdateOptions +{ + const CCompressionMethodMode *Method; + const CCompressionMethodMode *HeaderMethod; + bool UseFilters; // use additional filters for some files + bool MaxFilter; // use BCJ2 filter instead of BCJ + int AnalysisLevel; + + CHeaderOptions HeaderOptions; + + UInt64 NumSolidFiles; + UInt64 NumSolidBytes; + bool SolidExtension; + + bool UseTypeSorting; + + bool RemoveSfxBlock; + bool MultiThreadMixer; + + CUpdateOptions(): + Method(NULL), + HeaderMethod(NULL), + UseFilters(false), + MaxFilter(false), + AnalysisLevel(-1), + NumSolidFiles((UInt64)(Int64)(-1)), + NumSolidBytes((UInt64)(Int64)(-1)), + SolidExtension(false), + UseTypeSorting(true), + RemoveSfxBlock(false), + MultiThreadMixer(true) + {} +}; + +HRESULT Update( + DECL_EXTERNAL_CODECS_LOC_VARS + IInStream *inStream, + const CDbEx *db, + const CObjectVector &updateItems, + // const CObjectVector &treeFolders, // treeFolders[0] is root + // const CUniqBlocks &secureBlocks, + COutArchive &archive, + CArchiveDatabaseOut &newDatabase, + ISequentialOutStream *seqOutStream, + IArchiveUpdateCallback *updateCallback, + const CUpdateOptions &options + #ifndef _NO_CRYPTO + , ICryptoGetTextPassword *getDecoderPassword + #endif + ); +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/7z/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive.def b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive.def new file mode 100644 index 0000000..145516d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive.def @@ -0,0 +1,12 @@ +EXPORTS + CreateObject PRIVATE + + GetHandlerProperty PRIVATE + GetNumberOfFormats PRIVATE + GetHandlerProperty2 PRIVATE + GetIsArc PRIVATE + + SetCodecs PRIVATE + + SetLargePageMode PRIVATE + SetCaseSensitive PRIVATE diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive2.def b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive2.def new file mode 100644 index 0000000..c758274 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Archive2.def @@ -0,0 +1,19 @@ +EXPORTS + CreateObject PRIVATE + + GetHandlerProperty PRIVATE + GetNumberOfFormats PRIVATE + GetHandlerProperty2 PRIVATE + GetIsArc PRIVATE + + GetNumberOfMethods PRIVATE + GetMethodProperty PRIVATE + CreateDecoder PRIVATE + CreateEncoder PRIVATE + + GetHashers PRIVATE + + SetCodecs PRIVATE + + SetLargePageMode PRIVATE + SetCaseSensitive PRIVATE diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/ArchiveExports.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/ArchiveExports.cpp new file mode 100644 index 0000000..6549b3d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/ArchiveExports.cpp @@ -0,0 +1,156 @@ +// ArchiveExports.cpp + +#include "StdAfx.h" + +#include "../../../C/7zVersion.h" + +#include "../../Common/ComTry.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/RegisterArc.h" + +static const unsigned kNumArcsMax = 64; +static unsigned g_NumArcs = 0; +static unsigned g_DefaultArcIndex = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; + +void RegisterArc(const CArcInfo *arcInfo) throw() +{ + if (g_NumArcs < kNumArcsMax) + { + const char *p = arcInfo->Name; + if (p[0] == '7' && p[1] == 'z' && p[2] == 0) + g_DefaultArcIndex = g_NumArcs; + g_Arcs[g_NumArcs++] = arcInfo; + } +} + +DEFINE_GUID(CLSID_CArchiveHandler, + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + +#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) + +static inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value) +{ + if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) + value->vt = VT_BSTR; + return S_OK; +} + +static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) +{ + return SetPropStrFromBin((const char *)&guid, sizeof(guid), value); +} + +static int FindFormatCalssId(const GUID *clsid) +{ + GUID cls = *clsid; + CLS_ARC_ID_ITEM(cls) = 0; + if (cls != CLSID_CArchiveHandler) + return -1; + Byte id = CLS_ARC_ID_ITEM(*clsid); + for (unsigned i = 0; i < g_NumArcs; i++) + if (g_Arcs[i]->Id == id) + return (int)i; + return -1; +} + +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) +{ + COM_TRY_BEGIN + { + int needIn = (*iid == IID_IInArchive); + int needOut = (*iid == IID_IOutArchive); + if (!needIn && !needOut) + return E_NOINTERFACE; + int formatIndex = FindFormatCalssId(clsid); + if (formatIndex < 0) + return CLASS_E_CLASSNOTAVAILABLE; + + const CArcInfo &arc = *g_Arcs[formatIndex]; + if (needIn) + { + *outObject = arc.CreateInArchive(); + ((IInArchive *)*outObject)->AddRef(); + } + else + { + if (!arc.CreateOutArchive) + return CLASS_E_CLASSNOTAVAILABLE; + *outObject = arc.CreateOutArchive(); + ((IOutArchive *)*outObject)->AddRef(); + } + } + COM_TRY_END + return S_OK; +} + +STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value); +STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::PropVariant_Clear(value); + if (formatIndex >= g_NumArcs) + return E_INVALIDARG; + const CArcInfo &arc = *g_Arcs[formatIndex]; + NWindows::NCOM::CPropVariant prop; + switch (propID) + { + case NArchive::NHandlerPropID::kName: prop = arc.Name; break; + case NArchive::NHandlerPropID::kClassID: + { + GUID clsId = CLSID_CArchiveHandler; + CLS_ARC_ID_ITEM(clsId) = arc.Id; + return SetPropGUID(clsId, value); + } + case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break; + case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break; + case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break; + case NArchive::NHandlerPropID::kKeepName: prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break; + case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break; + case NArchive::NHandlerPropID::kNtSecure: prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break; + case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break; + case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break; + // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break; + + case NArchive::NHandlerPropID::kSignature: + if (arc.SignatureSize != 0 && !arc.IsMultiSignature()) + return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); + break; + case NArchive::NHandlerPropID::kMultiSignature: + if (arc.SignatureSize != 0 && arc.IsMultiSignature()) + return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value); + break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value); +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) +{ + return GetHandlerProperty2(g_DefaultArcIndex, propID, value); +} + +STDAPI GetNumberOfFormats(UINT32 *numFormats); +STDAPI GetNumberOfFormats(UINT32 *numFormats) +{ + *numFormats = g_NumArcs; + return S_OK; +} + +STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc); +STDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc) +{ + *isArc = NULL; + if (formatIndex >= g_NumArcs) + return E_INVALIDARG; + *isArc = g_Arcs[formatIndex]->IsArc; + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.cpp new file mode 100644 index 0000000..c8b67bd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -0,0 +1,1142 @@ +// CoderMixer2.cpp + +#include "StdAfx.h" + +#include "CoderMixer2.h" + +#ifdef USE_MIXER_ST + +STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size != 0 && realProcessed == 0) + _wasFinished = true; + if (processedSize) + *processedSize = realProcessed; + return result; +} + + +STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + _size += size; + if (processedSize) + *processedSize = size; + return result; +} + +STDMETHODIMP COutStreamCalcSize::OutStreamFinish() +{ + HRESULT result = S_OK; + if (_stream) + { + CMyComPtr outStreamFinish; + _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish); + if (outStreamFinish) + result = outStreamFinish->OutStreamFinish(); + } + return result; +} + +#endif + + + + +namespace NCoderMixer2 { + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) +{ + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; +} + + +HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const +{ + if (Coder) + { + if (PackSizePointers.IsEmpty() || !PackSizePointers[0]) + return S_OK; + CMyComPtr getInStreamProcessedSize; + Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); + // if (!getInStreamProcessedSize) return E_FAIL; + if (getInStreamProcessedSize) + { + UInt64 processed; + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)); + if (processed != (UInt64)(Int64)-1) + { + const UInt64 size = PackSizes[0]; + if (processed < size && Finish) + dataAfterEnd_Error = true; + if (processed > size) + { + // InternalPackSizeError = true; + // return S_FALSE; + } + } + } + } + else if (Coder2) + { + CMyComPtr getInStreamProcessedSize2; + Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2); + if (getInStreamProcessedSize2) + FOR_VECTOR (i, PackSizePointers) + { + if (!PackSizePointers[i]) + continue; + UInt64 processed; + RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed)); + if (processed != (UInt64)(Int64)-1) + { + const UInt64 size = PackSizes[i]; + if (processed < size && Finish) + dataAfterEnd_Error = true; + else if (processed > size) + { + // InternalPackSizeError = true; + // return S_FALSE; + } + } + } + } + + return S_OK; +} + + + +class CBondsChecks +{ + CBoolVector _coderUsed; + + bool Init(); + bool CheckCoder(unsigned coderIndex); +public: + const CBindInfo *BindInfo; + + bool Check(); +}; + +bool CBondsChecks::CheckCoder(unsigned coderIndex) +{ + const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex]; + + if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex]) + return false; + _coderUsed[coderIndex] = true; + + const UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; + + for (unsigned i = 0; i < coder.NumStreams; i++) + { + UInt32 ind = start + i; + + if (BindInfo->IsStream_in_PackStreams(ind)) + continue; + + const int bond = BindInfo->FindBond_for_PackStream(ind); + if (bond < 0) + return false; + if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex)) + return false; + } + + return true; +} + +bool CBondsChecks::Check() +{ + BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size()); + + if (!CheckCoder(BindInfo->UnpackCoder)) + return false; + + FOR_VECTOR(i, _coderUsed) + if (!_coderUsed[i]) + return false; + + return true; +} + +void CBindInfo::ClearMaps() +{ + Coder_to_Stream.Clear(); + Stream_to_Coder.Clear(); +} + +bool CBindInfo::CalcMapsAndCheck() +{ + ClearMaps(); + + UInt32 numStreams = 0; + + if (Coders.Size() == 0) + return false; + if (Coders.Size() - 1 != Bonds.Size()) + return false; + + FOR_VECTOR(i, Coders) + { + Coder_to_Stream.Add(numStreams); + + const CCoderStreamsInfo &c = Coders[i]; + + for (unsigned j = 0; j < c.NumStreams; j++) + Stream_to_Coder.Add(i); + + numStreams += c.NumStreams; + } + + if (numStreams != GetNum_Bonds_and_PackStreams()) + return false; + + CBondsChecks bc; + bc.BindInfo = this; + return bc.Check(); +} + + +void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) +{ + Finish = finish; + + if (unpackSize) + { + UnpackSize = *unpackSize; + UnpackSizePointer = &UnpackSize; + } + else + { + UnpackSize = 0; + UnpackSizePointer = NULL; + } + + PackSizes.ClearAndSetSize((unsigned)NumStreams); + PackSizePointers.ClearAndSetSize((unsigned)NumStreams); + + for (unsigned i = 0; i < NumStreams; i++) + { + if (packSizes && packSizes[i]) + { + PackSizes[i] = *(packSizes[i]); + PackSizePointers[i] = &PackSizes[i]; + } + else + { + PackSizes[i] = 0; + PackSizePointers[i] = NULL; + } + } +} + +bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) +{ + if (coderIndex == _bi.UnpackCoder) + return true; + + const int bond = _bi.FindBond_for_UnpackStream(coderIndex); + if (bond < 0) + throw 20150213; + + /* + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex); + */ + const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex]; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_UnpackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) +{ + if (_bi.IsStream_in_PackStreams(streamIndex)) + return true; + + const int bond = _bi.FindBond_for_PackStream(streamIndex); + if (bond < 0) + throw 20150213; + + const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_PackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) +{ + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + if (!Is_PackSize_Correct_for_Stream(startIndex + i)) + return false; + return true; +} + +bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) +{ + if (IsExternal_Vector[coderIndex]) + return true; + const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + { + const UInt32 si = startIndex + i; + if (_bi.IsStream_in_PackStreams(si)) + continue; + + const int bond = _bi.FindBond_for_PackStream(si); + if (bond < 0) + throw 20150213; + + if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex)) + return true; + } + return false; +} + + + + +#ifdef USE_MIXER_ST + +CMixerST::CMixerST(bool encodeMode): + CMixer(encodeMode) + {} + +CMixerST::~CMixerST() {} + +void CMixerST::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderST &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; + + /* + if (isFilter) + { + c2.CanRead = true; + c2.CanWrite = true; + } + else + */ + { + IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2); + { + CMyComPtr s; + unk->QueryInterface(IID_ISequentialInStream, (void**)&s); + c2.CanRead = (s != NULL); + } + { + CMyComPtr s; + unk->QueryInterface(IID_ISequentialOutStream, (void**)&s); + c2.CanWrite = (s != NULL); + } + } +} + +CCoder &CMixerST::GetCoder(unsigned index) +{ + return _coders[index]; +} + +HRESULT CMixerST::ReInit2() { return S_OK; } + +HRESULT CMixerST::GetInStream2( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes) +{ + UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0; + + if (EncodeMode) + { + _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex); + if (coderStreamIndex != 0) + return E_NOTIMPL; + } + + const CCoder &coder = _coders[coderIndex]; + + CMyComPtr seqInStream; + coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream); + if (!seqInStream) + return E_NOTIMPL; + + UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; + UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex]; + + bool isSet = false; + + if (numInStreams == 1) + { + CMyComPtr setStream; + coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); + if (setStream) + { + CMyComPtr seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)); + RINOK(setStream->SetInStream(seqInStream2)); + isSet = true; + } + } + + if (!isSet && numInStreams != 0) + { + CMyComPtr setStream2; + coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + + for (UInt32 i = 0; i < numInStreams; i++) + { + CMyComPtr seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2)); + RINOK(setStream2->SetInStream2(i, seqInStream2)); + } + } + + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + + +HRESULT CMixerST::GetInStream( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes) +{ + CMyComPtr seqInStream; + + { + int index = -1; + if (EncodeMode) + { + if (_bi.UnpackCoder == inStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(inStreamIndex); + + if (index >= 0) + { + seqInStream = inStreams[(unsigned)index]; + *inStreamRes = seqInStream.Detach(); + return S_OK; + } + } + + const int bond = FindBond_for_Stream( + true, // forInputStream + inStreamIndex); + if (bond < 0) + return E_INVALIDARG; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream)); + + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[(unsigned)bond]; + + if (bs.StreamRef || bs.InStreamSpec) + return E_NOTIMPL; + + CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize; + bs.StreamRef = spec; + bs.InStreamSpec = spec; + + spec->SetStream(seqInStream); + spec->Init(); + + seqInStream = bs.InStreamSpec; + + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + + +HRESULT CMixerST::GetOutStream( + ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) +{ + CMyComPtr seqOutStream; + + { + int index = -1; + if (!EncodeMode) + { + if (_bi.UnpackCoder == outStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(outStreamIndex); + + if (index >= 0) + { + seqOutStream = outStreams[(unsigned)index]; + *outStreamRes = seqOutStream.Detach(); + return S_OK; + } + } + + const int bond = FindBond_for_Stream( + false, // forInputStream + outStreamIndex); + if (bond < 0) + return E_INVALIDARG; + + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; + + /* + if (!coder.Coder) + return E_NOTIMPL; + */ + + coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); + if (!seqOutStream) + return E_NOTIMPL; + + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; + + bool isSet = false; + + if (numOutStreams == 1) + { + CMyComPtr setOutStream; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (setOutStream) + { + CMyComPtr seqOutStream2; + RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + isSet = true; + } + } + + if (!isSet && numOutStreams != 0) + { + return E_NOTIMPL; + /* + CMyComPtr setStream2; + coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + for (UInt32 i = 0; i < numOutStreams; i++) + { + CMyComPtr seqOutStream2; + RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2)); + RINOK(setStream2->SetOutStream2(i, seqOutStream2)); + } + */ + } + + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[(unsigned)bond]; + + if (bs.StreamRef || bs.OutStreamSpec) + return E_NOTIMPL; + + COutStreamCalcSize *spec = new COutStreamCalcSize; + bs.StreamRef = (ISequentialOutStream *)spec; + bs.OutStreamSpec = spec; + + spec->SetStream(seqOutStream); + spec->Init(); + + seqOutStream = bs.OutStreamSpec; + + *outStreamRes = seqOutStream.Detach(); + return S_OK; +} + + +static HRESULT GetError(HRESULT res, HRESULT res2) +{ + if (res == res2) + return res; + if (res == S_OK) + return res2; + if (res == k_My_HRESULT_WritingWasCut) + { + if (res2 != S_OK) + return res2; + } + return res; +} + + +HRESULT CMixerST::FinishStream(UInt32 streamIndex) +{ + { + int index = -1; + if (!EncodeMode) + { + if (_bi.UnpackCoder == streamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(streamIndex); + + if (index >= 0) + return S_OK; + } + + const int bond = FindBond_for_Stream( + false, // forInputStream + streamIndex); + if (bond < 0) + return E_INVALIDARG; + + UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; + CMyComPtr finish; + coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish); + HRESULT res = S_OK; + if (finish) + { + res = finish->OutStreamFinish(); + } + return GetError(res, FinishCoder(coderIndex)); +} + + +HRESULT CMixerST::FinishCoder(UInt32 coderIndex) +{ + CCoder &coder = _coders[coderIndex]; + + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; + + HRESULT res = S_OK; + for (unsigned i = 0; i < numOutStreams; i++) + res = GetError(res, FinishStream(startIndex + i)); + return res; +} + + +void CMixerST::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + int firstNonFilter = -1; + unsigned firstAllowed = ci; + + for (;;) + { + const CCoderST &coder = _coders[ci]; + // break; + + if (ci != _bi.UnpackCoder) + if (EncodeMode ? !coder.CanWrite : !coder.CanRead) + { + firstAllowed = ci; + firstNonFilter = -2; + } + + if (coder.NumStreams != 1) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + const int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + + if (EncodeMode ? !coder.CanRead : !coder.CanWrite) + break; + + if (firstNonFilter == -1 && !IsFilter_Vector[ci]) + firstNonFilter = (int)ci; + + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; + } + + if (useFirst) + ci = firstAllowed; + else if (firstNonFilter >= 0) + ci = (unsigned)firstNonFilter; + + MainCoderIndex = ci; +} + + +HRESULT CMixerST::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) +{ + // InternalPackSizeError = false; + dataAfterEnd_Error = false; + + _binderStreams.Clear(); + unsigned ci = MainCoderIndex; + + const CCoder &mainCoder = _coders[MainCoderIndex]; + + CObjectVector< CMyComPtr > seqInStreams; + CObjectVector< CMyComPtr > seqOutStreams; + + UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; + UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; + + UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + + UInt32 i; + + for (i = 0; i < numInStreams; i++) + { + CMyComPtr seqInStream; + RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); + seqInStreams.Add(seqInStream); + } + + for (i = 0; i < numOutStreams; i++) + { + CMyComPtr seqOutStream; + RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)); + seqOutStreams.Add(seqOutStream); + } + + CRecordVector< ISequentialInStream * > seqInStreamsSpec; + CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; + + for (i = 0; i < numInStreams; i++) + seqInStreamsSpec.Add(seqInStreams[i]); + for (i = 0; i < numOutStreams; i++) + seqOutStreamsSpec.Add(seqOutStreams[i]); + + for (i = 0; i < _coders.Size(); i++) + { + if (i == ci) + continue; + + CCoder &coder = _coders[i]; + + if (EncodeMode) + { + CMyComPtr initEncoder; + coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder); + if (initEncoder) + RINOK(initEncoder->InitEncoder()); + } + else + { + CMyComPtr setOutStreamSize; + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); + if (setOutStreamSize) + RINOK(setOutStreamSize->SetOutStreamSize( + EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer)); + } + } + + const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front(); + const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer; + + HRESULT res; + if (mainCoder.Coder) + { + res = mainCoder.Coder->Code( + seqInStreamsSpec[0], seqOutStreamsSpec[0], + isSizes2[0], outSizes2[0], + progress); + } + else + { + res = mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), isSizes2, numInStreams, + &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, + progress); + } + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + + if (res == S_OK || res == S_FALSE) + { + res = GetError(res, FinishCoder(ci)); + } + + for (i = 0; i < _binderStreams.Size(); i++) + { + const CStBinderStream &bs = _binderStreams[i]; + if (bs.InStreamSpec) + bs.InStreamSpec->ReleaseStream(); + else + bs.OutStreamSpec->ReleaseStream(); + } + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + + if (res != S_OK) + return res; + + for (i = 0; i < _coders.Size(); i++) + { + RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */)); + } + + return S_OK; +} + + +HRESULT CMixerST::GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes) +{ + CMyComPtr seqInStream; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.UnpackCoder, &seqInStream)) + + FOR_VECTOR (i, _coders) + { + CCoder &coder = _coders[i]; + CMyComPtr setOutStreamSize; + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); + if (setOutStreamSize) + { + RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)); + } + } + + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + + +UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const +{ + const CStBinderStream &bs = _binderStreams[bondIndex]; + if (bs.InStreamSpec) + return bs.InStreamSpec->GetSize(); + return bs.OutStreamSpec->GetSize(); +} + +#endif + + + + + + +#ifdef USE_MIXER_MT + + +void CCoderMT::Execute() +{ + try + { + Code(NULL); + } + catch(...) + { + Result = E_FAIL; + } +} + +void CCoderMT::Code(ICompressProgressInfo *progress) +{ + unsigned numInStreams = EncodeMode ? 1 : NumStreams; + unsigned numOutStreams = EncodeMode ? NumStreams : 1; + + InStreamPointers.ClearAndReserve(numInStreams); + OutStreamPointers.ClearAndReserve(numOutStreams); + + unsigned i; + + for (i = 0; i < numInStreams; i++) + InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); + + for (i = 0; i < numOutStreams; i++) + OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); + + // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers. + /* + if (UnpackSizePointer) + UnpackSizePointer = &UnpackSize; + for (i = 0; i < NumStreams; i++) + if (PackSizePointers[i]) + PackSizePointers[i] = &PackSizes[i]; + */ + + CReleaser releaser(*this); + + if (Coder) + Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], + EncodeMode ? UnpackSizePointer : PackSizePointers[0], + EncodeMode ? PackSizePointers[0] : UnpackSizePointer, + progress); + else + Result = Coder2->Code( + &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, + &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, + progress); +} + +HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) +{ + CMixer::SetBindInfo(bindInfo); + + _streamBinders.Clear(); + FOR_VECTOR (i, _bi.Bonds) + { + // RINOK(_streamBinders.AddNew().CreateEvents()); + _streamBinders.AddNew(); + } + return S_OK; +} + +void CMixerMT::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderMT &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; + c2.EncodeMode = EncodeMode; +} + +CCoder &CMixerMT::GetCoder(unsigned index) +{ + return _coders[index]; +} + +HRESULT CMixerMT::ReInit2() +{ + FOR_VECTOR (i, _streamBinders) + { + RINOK(_streamBinders[i].Create_ReInit()); + } + return S_OK; +} + +void CMixerMT::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + if (!useFirst) + for (;;) + { + if (_coders[ci].NumStreams != 1) + break; + if (!IsFilter_Vector[ci]) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + const int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + ci = _bi.Bonds[(unsigned)bond].UnpackIndex; + } + + MainCoderIndex = ci; +} + +HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) +{ + unsigned i; + + for (i = 0; i < _coders.Size(); i++) + { + CCoderMT &coderInfo = _coders[i]; + const CCoderStreamsInfo &csi = _bi.Coders[i]; + + UInt32 j; + + unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; + unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1; + + coderInfo.InStreams.Clear(); + for (j = 0; j < numInStreams; j++) + coderInfo.InStreams.AddNew(); + + coderInfo.OutStreams.Clear(); + for (j = 0; j < numOutStreams; j++) + coderInfo.OutStreams.AddNew(); + } + + for (i = 0; i < _bi.Bonds.Size(); i++) + { + const CBond &bond = _bi.Bonds[i]; + + UInt32 inCoderIndex, inCoderStreamIndex; + UInt32 outCoderIndex, outCoderStreamIndex; + + { + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex); + + inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex; + outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex; + + inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex; + outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; + } + + _streamBinders[i].CreateStreams2( + _coders[inCoderIndex].InStreams[inCoderStreamIndex], + _coders[outCoderIndex].OutStreams[outCoderStreamIndex]); + + CMyComPtr inSetSize, outSetSize; + _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); + _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); + if (inSetSize && outSetSize) + { + const UInt32 kBufSize = 1 << 19; + inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); + outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); + } + } + + { + CCoderMT &cod = _coders[_bi.UnpackCoder]; + if (EncodeMode) + cod.InStreams[0] = inStreams[0]; + else + cod.OutStreams[0] = outStreams[0]; + } + + for (i = 0; i < _bi.PackStreams.Size(); i++) + { + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex); + CCoderMT &cod = _coders[coderIndex]; + if (EncodeMode) + cod.OutStreams[coderStreamIndex] = outStreams[i]; + else + cod.InStreams[coderStreamIndex] = inStreams[i]; + } + + return S_OK; +} + +HRESULT CMixerMT::ReturnIfError(HRESULT code) +{ + FOR_VECTOR (i, _coders) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +HRESULT CMixerMT::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) +{ + // InternalPackSizeError = false; + dataAfterEnd_Error = false; + + Init(inStreams, outStreams); + + unsigned i; + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) + { + const WRes wres = _coders[i].Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) + { + const WRes wres = _coders[i].Start(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + + _coders[MainCoderIndex].Code(progress); + + WRes wres = 0; + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) + { + WRes wres2 = _coders[i].WaitExecuteFinish(); + if (wres == 0) + wres = wres2; + } + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + + RINOK(ReturnIfError(E_ABORT)); + RINOK(ReturnIfError(E_OUTOFMEMORY)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK + && result != k_My_HRESULT_WritingWasCut + && result != S_FALSE + && result != E_FAIL) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK && result != k_My_HRESULT_WritingWasCut) + return result; + } + + for (i = 0; i < _coders.Size(); i++) + { + RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */)); + } + + return S_OK; +} + +UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const +{ + return _streamBinders[bondIndex].ProcessedSize; +} + +#endif + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.h new file mode 100644 index 0000000..f099ac3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/CoderMixer2.h @@ -0,0 +1,453 @@ +// CoderMixer2.h + +#ifndef __CODER_MIXER2_H +#define __CODER_MIXER2_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + +#include "../../ICoder.h" + +#include "../../Common/CreateCoder.h" + +#ifdef _7ZIP_ST + #define USE_MIXER_ST +#else + #define USE_MIXER_MT + #ifndef _SFX + #define USE_MIXER_ST + #endif +#endif + +#ifdef USE_MIXER_MT +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" +#endif + + + +#ifdef USE_MIXER_ST + +class CSequentialInStreamCalcSize: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr _stream; + UInt64 _size; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + } + void ReleaseStream() { _stream.Release(); } + UInt64 GetSize() const { return _size; } + bool WasFinished() const { return _wasFinished; } +}; + + +class COutStreamCalcSize: + public ISequentialOutStream, + public IOutStreamFinish, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; +public: + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(OutStreamFinish)(); + + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + UInt64 GetSize() const { return _size; } +}; + +#endif + + + +namespace NCoderMixer2 { + +struct CBond +{ + UInt32 PackIndex; + UInt32 UnpackIndex; + + UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } + UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } +}; + + +struct CCoderStreamsInfo +{ + UInt32 NumStreams; +}; + + +struct CBindInfo +{ + CRecordVector Coders; + CRecordVector Bonds; + CRecordVector PackStreams; + unsigned UnpackCoder; + + unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } + + int FindBond_for_PackStream(UInt32 packStream) const + { + FOR_VECTOR (i, Bonds) + if (Bonds[i].PackIndex == packStream) + return (int)i; + return -1; + } + + int FindBond_for_UnpackStream(UInt32 unpackStream) const + { + FOR_VECTOR (i, Bonds) + if (Bonds[i].UnpackIndex == unpackStream) + return (int)i; + return -1; + } + + bool SetUnpackCoder() + { + bool isOk = false; + FOR_VECTOR(i, Coders) + { + if (FindBond_for_UnpackStream(i) < 0) + { + if (isOk) + return false; + UnpackCoder = i; + isOk = true; + } + } + return isOk; + } + + bool IsStream_in_PackStreams(UInt32 streamIndex) const + { + return FindStream_in_PackStreams(streamIndex) >= 0; + } + + int FindStream_in_PackStreams(UInt32 streamIndex) const + { + FOR_VECTOR(i, PackStreams) + if (PackStreams[i] == streamIndex) + return (int)i; + return -1; + } + + + // that function is used before Maps is calculated + + UInt32 GetStream_for_Coder(UInt32 coderIndex) const + { + UInt32 streamIndex = 0; + for (UInt32 i = 0; i < coderIndex; i++) + streamIndex += Coders[i].NumStreams; + return streamIndex; + } + + // ---------- Maps Section ---------- + + CRecordVector Coder_to_Stream; + CRecordVector Stream_to_Coder; + + void ClearMaps(); + bool CalcMapsAndCheck(); + + // ---------- End of Maps Section ---------- + + void Clear() + { + Coders.Clear(); + Bonds.Clear(); + PackStreams.Clear(); + + ClearMaps(); + } + + void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const + { + coderIndex = Stream_to_Coder[streamIndex]; + coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; + } +}; + + + +class CCoder +{ + CLASS_NO_COPY(CCoder); +public: + CMyComPtr Coder; + CMyComPtr Coder2; + UInt32 NumStreams; + + UInt64 UnpackSize; + const UInt64 *UnpackSizePointer; + + CRecordVector PackSizes; + CRecordVector PackSizePointers; + + bool Finish; + + CCoder(): Finish(false) {} + + void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish); + + HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const; + + IUnknown *GetUnknown() const + { + return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; + } + + HRESULT QueryInterface(REFGUID iid, void** pp) const + { + return GetUnknown()->QueryInterface(iid, pp); + } +}; + + + +class CMixer +{ + bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); + +protected: + CBindInfo _bi; + + int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const + { + if (EncodeMode == forInputStream) + return _bi.FindBond_for_UnpackStream(streamIndex); + else + return _bi.FindBond_for_PackStream(streamIndex); + } + + CBoolVector IsFilter_Vector; + CBoolVector IsExternal_Vector; + bool EncodeMode; +public: + unsigned MainCoderIndex; + + // bool InternalPackSizeError; + + CMixer(bool encodeMode): + EncodeMode(encodeMode), + MainCoderIndex(0) + // , InternalPackSizeError(false) + {} + + virtual ~CMixer() {}; + /* + Sequence of calling: + + SetBindInfo(); + for each coder + AddCoder(); + SelectMainCoder(); + + for each file + { + ReInit() + for each coder + SetCoderInfo(); + Code(); + } + */ + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) + { + _bi = bindInfo; + IsFilter_Vector.Clear(); + MainCoderIndex = 0; + return S_OK; + } + + virtual void AddCoder(const CCreatedCoder &cod) = 0; + virtual CCoder &GetCoder(unsigned index) = 0; + virtual void SelectMainCoder(bool useFirst) = 0; + virtual HRESULT ReInit2() = 0; + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error) = 0; + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; + + bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); + bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); + bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); +}; + + + + +#ifdef USE_MIXER_ST + +struct CCoderST: public CCoder +{ + bool CanRead; + bool CanWrite; + + CCoderST(): CanRead(false), CanWrite(false) {} +}; + + +struct CStBinderStream +{ + CSequentialInStreamCalcSize *InStreamSpec; + COutStreamCalcSize *OutStreamSpec; + CMyComPtr StreamRef; + + CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} +}; + + +class CMixerST: + public IUnknown, + public CMixer, + public CMyUnknownImp +{ + CLASS_NO_COPY(CMixerST) + + HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); + + HRESULT FinishStream(UInt32 streamIndex); + HRESULT FinishCoder(UInt32 coderIndex); + +public: + CObjectVector _coders; + + CObjectVector _binderStreams; + + MY_UNKNOWN_IMP + + CMixerST(bool encodeMode); + ~CMixerST(); + + virtual void AddCoder(const CCreatedCoder &cod); + virtual CCoder &GetCoder(unsigned index); + virtual void SelectMainCoder(bool useFirst); + virtual HRESULT ReInit2(); + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error); + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; + + HRESULT GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes); +}; + +#endif + + + + +#ifdef USE_MIXER_MT + +class CCoderMT: public CCoder, public CVirtThread +{ + CLASS_NO_COPY(CCoderMT) + CRecordVector InStreamPointers; + CRecordVector OutStreamPointers; + +private: + void Execute(); +public: + bool EncodeMode; + HRESULT Result; + CObjectVector< CMyComPtr > InStreams; + CObjectVector< CMyComPtr > OutStreams; + + void Release() + { + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + unsigned i; + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); + } + + class CReleaser + { + CLASS_NO_COPY(CReleaser) + CCoderMT &_c; + public: + CReleaser(CCoderMT &c): _c(c) {} + ~CReleaser() { _c.Release(); } + }; + + CCoderMT(): EncodeMode(false) {} + virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + + void Code(ICompressProgressInfo *progress); +}; + + +class CMixerMT: + public IUnknown, + public CMixer, + public CMyUnknownImp +{ + CLASS_NO_COPY(CMixerMT) + + CObjectVector _streamBinders; + + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); + HRESULT ReturnIfError(HRESULT code); + + // virtual ~CMixerMT() {}; +public: + CObjectVector _coders; + + MY_UNKNOWN_IMP + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); + virtual void AddCoder(const CCreatedCoder &cod); + virtual CCoder &GetCoder(unsigned index); + virtual void SelectMainCoder(bool useFirst); + virtual HRESULT ReInit2(); + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress, + bool &dataAfterEnd_Error); + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; + + CMixerMT(bool encodeMode): CMixer(encodeMode) {} +}; + +#endif + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.cpp new file mode 100644 index 0000000..7c4f548 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.cpp @@ -0,0 +1,17 @@ +// DummyOutStream.cpp + +#include "StdAfx.h" + +#include "DummyOutStream.h" + +STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = size; + HRESULT res = S_OK; + if (_stream) + res = _stream->Write(data, size, &realProcessedSize); + _size += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.h new file mode 100644 index 0000000..b5a51fc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/DummyOutStream.h @@ -0,0 +1,25 @@ +// DummyOutStream.h + +#ifndef __DUMMY_OUT_STREAM_H +#define __DUMMY_OUT_STREAM_H + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class CDummyOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; +public: + void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetSize() const { return _size; } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.cpp new file mode 100644 index 0000000..972a766 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -0,0 +1,232 @@ +// HandlerOut.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringToInt.h" + +#include "../Common/ParseProperties.h" + +#include "HandlerOut.h" + +namespace NArchive { + +bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res) +{ + if (*s == 0) + { + switch (prop.vt) + { + case VT_UI4: res = prop.ulVal; return true; + case VT_UI8: res = prop.uhVal.QuadPart; return true; + case VT_BSTR: + s = prop.bstrVal; + break; + default: return false; + } + } + else if (prop.vt != VT_EMPTY) + return false; + + const wchar_t *end; + UInt64 v = ConvertStringToUInt64(s, &end); + if (s == end) + return false; + wchar_t c = *end; + if (c == 0) + { + res = v; + return true; + } + if (end[1] != 0) + return false; + + if (c == '%') + { + res = percentsBase / 100 * v; + return true; + } + + unsigned numBits; + switch (MyCharLower_Ascii(c)) + { + case 'b': numBits = 0; break; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + UInt64 val2 = v << numBits; + if ((val2 >> numBits) != v) + return false; + res = val2; + return true; +} + +bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres) +{ + hres = S_OK; + + if (name.IsPrefixedBy_Ascii_NoCase("mt")) + { + #ifndef _7ZIP_ST + hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads); + #endif + return true; + } + + if (name.IsPrefixedBy_Ascii_NoCase("memuse")) + { + if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage)) + hres = E_INVALIDARG; + return true; + } + + return false; +} + + +#ifndef EXTRACT_ONLY + +static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value) +{ + if (m.FindProp(propID) < 0) + m.AddProp32(propID, value); +} + +void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const +{ + UInt32 level = _level; + if (level != (UInt32)(Int32)-1) + SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); +} + +#ifndef _7ZIP_ST +void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads) +{ + SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); +} +#endif + +void CMultiMethodProps::InitMulti() +{ + _level = (UInt32)(Int32)-1; + _analysisLevel = -1; + _crcSize = 4; + _autoFilter = true; +} + +void CMultiMethodProps::Init() +{ + InitCommon(); + InitMulti(); + _methods.Clear(); + _filterMethod.Clear(); +} + + +HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + if (name[0] == 'x') + { + name.Delete(0); + _level = 9; + return ParsePropToUInt32(name, value, _level); + } + + if (name.IsPrefixedBy_Ascii_NoCase("yx")) + { + name.Delete(0, 2); + UInt32 v = 9; + RINOK(ParsePropToUInt32(name, value, v)); + _analysisLevel = (int)v; + return S_OK; + } + + if (name.IsPrefixedBy_Ascii_NoCase("crc")) + { + name.Delete(0, 3); + _crcSize = 4; + return ParsePropToUInt32(name, value, _crcSize); + } + + { + HRESULT hres; + if (SetCommonProperty(name, value, hres)) + return hres; + } + + UInt32 number; + unsigned index = ParseStringToUInt32(name, number); + UString realName = name.Ptr(index); + if (index == 0) + { + if (name.IsEqualTo("f")) + { + HRESULT res = PROPVARIANT_to_bool(value, _autoFilter); + if (res == S_OK) + return res; + if (value.vt != VT_BSTR) + return E_INVALIDARG; + return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value); + } + number = 0; + } + if (number > 64) + return E_FAIL; + for (unsigned j = _methods.Size(); j <= number; j++) + _methods.AddNew(); + return _methods[number].ParseMethodFromPROPVARIANT(realName, value); +} + + + +void CSingleMethodProps::Init() +{ + InitCommon(); + InitSingle(); + Clear(); +} + + +HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) +{ + Init(); + + for (UInt32 i = 0; i < numProps; i++) + { + UString name = names[i]; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + const PROPVARIANT &value = values[i]; + if (name[0] == L'x') + { + UInt32 a = 9; + RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); + _level = a; + AddProp_Level(a); + continue; + } + { + HRESULT hres; + if (SetCommonProperty(name, value, hres)) + { + RINOK(hres) + continue; + } + } + RINOK(ParseMethodFromPROPVARIANT(names[i], value)); + } + + return S_OK; +} + +#endif + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.h new file mode 100644 index 0000000..bbb4336 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/HandlerOut.h @@ -0,0 +1,110 @@ +// HandlerOut.h + +#ifndef __HANDLER_OUT_H +#define __HANDLER_OUT_H + +#include "../../../Windows/System.h" + +#include "../../Common/MethodProps.h" + +namespace NArchive { + +bool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res); + +class CCommonMethodProps +{ +protected: + void InitCommon() + { + #ifndef _7ZIP_ST + _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); + #endif + + UInt64 memAvail = (UInt64)(sizeof(size_t)) << 28; + _memAvail = memAvail; + _memUsage = memAvail; + if (NWindows::NSystem::GetRamSize(memAvail)) + { + _memAvail = memAvail; + _memUsage = memAvail / 32 * 17; + } + } + +public: + #ifndef _7ZIP_ST + UInt32 _numThreads; + UInt32 _numProcessors; + #endif + + UInt64 _memUsage; + UInt64 _memAvail; + + bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres); + + CCommonMethodProps() { InitCommon(); } +}; + + +#ifndef EXTRACT_ONLY + +class CMultiMethodProps: public CCommonMethodProps +{ + UInt32 _level; + int _analysisLevel; + + void InitMulti(); +public: + UInt32 _crcSize; + CObjectVector _methods; + COneMethodInfo _filterMethod; + bool _autoFilter; + + + void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const; + + #ifndef _7ZIP_ST + static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads); + #endif + + + unsigned GetNumEmptyMethods() const + { + unsigned i; + for (i = 0; i < _methods.Size(); i++) + if (!_methods[i].IsEmpty()) + break; + return i; + } + + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + int GetAnalysisLevel() const { return _analysisLevel; } + + void Init(); + CMultiMethodProps() { InitMulti(); } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); +}; + + +class CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps +{ + UInt32 _level; + + void InitSingle() + { + _level = (UInt32)(Int32)-1; + } + +public: + void Init(); + CSingleMethodProps() { InitSingle(); } + + int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); +}; + +#endif + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.cpp new file mode 100644 index 0000000..a2d6883 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.cpp @@ -0,0 +1,46 @@ +// InStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "InStreamWithCRC.h" + +STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size != 0 && realProcessed == 0) + _wasFinished = true; + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; + return result; +} + +STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + /* + if (size != 0 && realProcessed == 0) + _wasFinished = true; + */ + _crc = CrcUpdate(_crc, data, realProcessed); + if (processedSize) + *processedSize = realProcessed; + return result; +} + +STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin != STREAM_SEEK_SET || offset != 0) + return E_FAIL; + _size = 0; + _crc = CRC_INIT_VAL; + return _stream->Seek(offset, seekOrigin, newPosition); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.h new file mode 100644 index 0000000..31b761e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/InStreamWithCRC.h @@ -0,0 +1,67 @@ +// InStreamWithCRC.h + +#ifndef __IN_STREAM_WITH_CRC_H +#define __IN_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class CSequentialInStreamWithCRC: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr _stream; + UInt64 _size; + UInt32 _crc; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + _crc = CRC_INIT_VAL; + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } + UInt64 GetSize() const { return _size; } + bool WasFinished() const { return _wasFinished; } +}; + +class CInStreamWithCRC: + public IInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +private: + CMyComPtr _stream; + UInt64 _size; + UInt32 _crc; + // bool _wasFinished; +public: + void SetStream(IInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + // _wasFinished = false; + _crc = CRC_INIT_VAL; + } + void ReleaseStream() { _stream.Release(); } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } + UInt64 GetSize() const { return _size; } + // bool WasFinished() const { return _wasFinished; } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.cpp new file mode 100644 index 0000000..905a863 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.cpp @@ -0,0 +1,112 @@ +// Archive/Common/ItemNameUtils.cpp + +#include "StdAfx.h" + +#include "ItemNameUtils.h" + +namespace NArchive { +namespace NItemName { + +static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR; + +#if WCHAR_PATH_SEPARATOR != L'/' +static const wchar_t kUnixPathSepar = L'/'; +#endif + +void ReplaceSlashes_OsToUnix +#if WCHAR_PATH_SEPARATOR != L'/' + (UString &name) + { + name.Replace(kOsPathSepar, kUnixPathSepar); + } +#else + (UString &) {} +#endif + + +UString GetOsPath(const UString &name) +{ + #if WCHAR_PATH_SEPARATOR != L'/' + UString newName = name; + newName.Replace(kUnixPathSepar, kOsPathSepar); + return newName; + #else + return name; + #endif +} + + +UString GetOsPath_Remove_TailSlash(const UString &name) +{ + if (name.IsEmpty()) + return UString(); + UString newName = GetOsPath(name); + if (newName.Back() == kOsPathSepar) + newName.DeleteBack(); + return newName; +} + + +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool + #if WCHAR_PATH_SEPARATOR != L'/' + useBackslashReplacement + #endif + ) +{ + if (name.IsEmpty()) + return; + + #if WCHAR_PATH_SEPARATOR != L'/' + { + // name.Replace(kUnixPathSepar, kOsPathSepar); + const unsigned len = name.Len(); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = name[i]; + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + else if (useBackslashReplacement && c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme + else + continue; + name.ReplaceOneCharAtPos(i, c); + } + } + #endif + + if (name.Back() == kOsPathSepar) + name.DeleteBack(); +} + + +bool HasTailSlash(const AString &name, UINT + #if defined(_WIN32) && !defined(UNDER_CE) + codePage + #endif + ) +{ + if (name.IsEmpty()) + return false; + char c; + #if defined(_WIN32) && !defined(UNDER_CE) + if (codePage != CP_UTF8) + c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0); + else + #endif + { + c = name.Back(); + } + return (c == '/'); +} + + +#ifndef _WIN32 +UString WinPathToOsPath(const UString &name) +{ + UString newName = name; + newName.Replace(L'\\', WCHAR_PATH_SEPARATOR); + return newName; +} +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.h new file mode 100644 index 0000000..6a4d6c7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ItemNameUtils.h @@ -0,0 +1,28 @@ +// Archive/Common/ItemNameUtils.h + +#ifndef __ARCHIVE_ITEM_NAME_UTILS_H +#define __ARCHIVE_ITEM_NAME_UTILS_H + +#include "../../../Common/MyString.h" + +namespace NArchive { +namespace NItemName { + +void ReplaceSlashes_OsToUnix(UString &name); + +UString GetOsPath(const UString &name); +UString GetOsPath_Remove_TailSlash(const UString &name); + +void ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false); + +bool HasTailSlash(const AString &name, UINT codePage); + +#ifdef _WIN32 + inline UString WinPathToOsPath(const UString &name) { return name; } +#else + UString WinPathToOsPath(const UString &name); +#endif + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.cpp new file mode 100644 index 0000000..162fc92 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.cpp @@ -0,0 +1,191 @@ +// MultiStream.cpp + +#include "StdAfx.h" + +#include "MultiStream.h" + +STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= _totalLength) + return S_OK; + + { + unsigned left = 0, mid = _streamIndex, right = Streams.Size(); + for (;;) + { + CSubStreamInfo &m = Streams[mid]; + if (_pos < m.GlobalOffset) + right = mid; + else if (_pos >= m.GlobalOffset + m.Size) + left = mid + 1; + else + { + _streamIndex = mid; + break; + } + mid = (left + right) / 2; + } + _streamIndex = mid; + } + + CSubStreamInfo &s = Streams[_streamIndex]; + UInt64 localPos = _pos - s.GlobalOffset; + if (localPos != s.LocalPos) + { + RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos)); + } + UInt64 rem = s.Size - localPos; + if (size > rem) + size = (UInt32)rem; + HRESULT result = s.Stream->Read(data, size, &size); + _pos += size; + s.LocalPos += size; + if (processedSize) + *processedSize = size; + return result; +} + +STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _totalLength; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} + + +/* +class COutVolumeStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + unsigned _volIndex; + UInt64 _volSize; + UInt64 _curPos; + CMyComPtr _volumeStream; + COutArchive _archive; + CCRC _crc; + +public: + MY_UNKNOWN_IMP + + CFileItem _file; + CUpdateOptions _options; + CMyComPtr VolumeCallback; + void Init(IArchiveUpdateCallback2 *volumeCallback, + const UString &name) + { + _file.Name = name; + _file.IsStartPosDefined = true; + _file.StartPos = 0; + + VolumeCallback = volumeCallback; + _volIndex = 0; + _volSize = 0; + } + + HRESULT Flush(); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +HRESULT COutVolumeStream::Flush() +{ + if (_volumeStream) + { + _file.UnPackSize = _curPos; + _file.FileCRC = _crc.GetDigest(); + RINOK(WriteVolumeHeader(_archive, _file, _options)); + _archive.Close(); + _volumeStream.Release(); + _file.StartPos += _file.UnPackSize; + } + return S_OK; +} +*/ + +/* +STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + while (size > 0) + { + if (_streamIndex >= Streams.Size()) + { + CSubStreamInfo subStream; + RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); + RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); + subStream.Pos = 0; + Streams.Add(subStream); + continue; + } + CSubStreamInfo &subStream = Streams[_streamIndex]; + if (_offsetPos >= subStream.Size) + { + _offsetPos -= subStream.Size; + _streamIndex++; + continue; + } + if (_offsetPos != subStream.Pos) + { + CMyComPtr outStream; + RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); + subStream.Pos = _offsetPos; + } + + UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); + UInt32 realProcessed; + RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); + data = (void *)((Byte *)data + realProcessed); + size -= realProcessed; + subStream.Pos += realProcessed; + _offsetPos += realProcessed; + _absPos += realProcessed; + if (_absPos > _length) + _length = _absPos; + if (processedSize) + *processedSize += realProcessed; + if (subStream.Pos == subStream.Size) + { + _streamIndex++; + _offsetPos = 0; + } + if (realProcessed != curSize && realProcessed == 0) + return E_FAIL; + } + return S_OK; +} + +STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _absPos; break; + case STREAM_SEEK_END: offset += _length; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _absPos = offset; + _offsetPos = _absPos; + _streamIndex = 0; + if (newPosition) + *newPosition = offset; + return S_OK; +} +*/ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.h new file mode 100644 index 0000000..c10cd45 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/MultiStream.h @@ -0,0 +1,89 @@ +// MultiStream.h + +#ifndef __MULTI_STREAM_H +#define __MULTI_STREAM_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyVector.h" + +#include "../../IStream.h" + +class CMultiStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _pos; + UInt64 _totalLength; + unsigned _streamIndex; + +public: + + struct CSubStreamInfo + { + CMyComPtr Stream; + UInt64 Size; + UInt64 GlobalOffset; + UInt64 LocalPos; + + CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {} + }; + + CObjectVector Streams; + + HRESULT Init() + { + UInt64 total = 0; + FOR_VECTOR (i, Streams) + { + CSubStreamInfo &s = Streams[i]; + s.GlobalOffset = total; + total += Streams[i].Size; + RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos)); + } + _totalLength = total; + _pos = 0; + _streamIndex = 0; + return S_OK; + } + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +/* +class COutMultiStream: + public IOutStream, + public CMyUnknownImp +{ + unsigned _streamIndex; // required stream + UInt64 _offsetPos; // offset from start of _streamIndex index + UInt64 _absPos; + UInt64 _length; + + struct CSubStreamInfo + { + CMyComPtr Stream; + UInt64 Size; + UInt64 Pos; + }; + CObjectVector Streams; +public: + CMyComPtr VolumeCallback; + void Init() + { + _streamIndex = 0; + _offsetPos = 0; + _absPos = 0; + _length = 0; + } + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp new file mode 100644 index 0000000..f955c22 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp @@ -0,0 +1,18 @@ +// OutStreamWithCRC.cpp + +#include "StdAfx.h" + +#include "OutStreamWithCRC.h" + +STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _crc = CrcUpdate(_crc, data, size); + _size += size; + if (processedSize != NULL) + *processedSize = size; + return result; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.h new file mode 100644 index 0000000..09b899b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/OutStreamWithCRC.h @@ -0,0 +1,37 @@ +// OutStreamWithCRC.h + +#ifndef __OUT_STREAM_WITH_CRC_H +#define __OUT_STREAM_WITH_CRC_H + +#include "../../../../C/7zCrc.h" + +#include "../../../Common/MyCom.h" + +#include "../../IStream.h" + +class COutStreamWithCRC: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + UInt32 _crc; + bool _calculate; +public: + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + _size = 0; + _calculate = calculate; + _crc = CRC_INIT_VAL; + } + void EnableCalc(bool calculate) { _calculate = calculate; } + void InitCRC() { _crc = CRC_INIT_VAL; } + UInt64 GetSize() const { return _size; } + UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.cpp new file mode 100644 index 0000000..63e4f3e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.cpp @@ -0,0 +1,3 @@ +// ParseProperties.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.h new file mode 100644 index 0000000..1038a8c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/ParseProperties.h @@ -0,0 +1,6 @@ +// ParseProperties.h + +#ifndef __PARSE_PROPERTIES_H +#define __PARSE_PROPERTIES_H + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Common/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/DllExports2.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/DllExports2.cpp new file mode 100644 index 0000000..967a7cb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/DllExports2.cpp @@ -0,0 +1,157 @@ +// DLLExports2.cpp + +#include "StdAfx.h" + +#include "../../Common/MyWindows.h" + +#include "../../Common/MyInitGuid.h" + +#if defined(_7ZIP_LARGE_PAGES) +#include "../../../C/Alloc.h" +#endif + +#include "../../Common/ComTry.h" + +#include "../../Windows/NtCheck.h" +#include "../../Windows/PropVariant.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +#include "../Common/CreateCoder.h" + +#include "IArchive.h" + + +#ifdef _WIN32 + +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION return FALSE; +#endif + +HINSTANCE g_hInstance; + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID /*lpReserved*/); + +extern "C" +BOOL WINAPI DllMain( + #ifdef UNDER_CE + HANDLE + #else + HINSTANCE + #endif + hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + // OutputDebugStringA("7z.dll DLL_PROCESS_ATTACH"); + g_hInstance = (HINSTANCE)hInstance; + NT_CHECK; + } + /* + if (dwReason == DLL_PROCESS_DETACH) + { + OutputDebugStringA("7z.dll DLL_PROCESS_DETACH"); + } + */ + return TRUE; +} + +#else // _WIN32 + +#include "../../Common/StringConvert.h" +// #include + +// STDAPI LibStartup(); +static __attribute__((constructor)) void Init_ForceToUTF8(); +static __attribute__((constructor)) void Init_ForceToUTF8() +{ + g_ForceToUTF8 = IsNativeUTF8(); + // printf("\nDLLExports2.cpp::Init_ForceToUTF8 =%d\n", g_ForceToUTF8 ? 1 : 0); +} + +#endif // _WIN32 + + +DEFINE_GUID(CLSID_CArchiveHandler, + k_7zip_GUID_Data1, + k_7zip_GUID_Data2, + k_7zip_GUID_Data3_Common, + 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateHasher(const GUID *clsid, IHasher **hasher); +STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject); + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + // COM_TRY_BEGIN + *outObject = 0; + if (*iid == IID_ICompressCoder || + *iid == IID_ICompressCoder2 || + *iid == IID_ICompressFilter) + return CreateCoder(clsid, iid, outObject); + if (*iid == IID_IHasher) + return CreateHasher(clsid, (IHasher **)outObject); + return CreateArchiver(clsid, iid, outObject); + // COM_TRY_END +} + +STDAPI SetLargePageMode(); +STDAPI SetLargePageMode() +{ + #if defined(_7ZIP_LARGE_PAGES) + #ifdef _WIN32 + SetLargePageSize(); + #endif + #endif + return S_OK; +} + +extern bool g_CaseSensitive; + +STDAPI SetCaseSensitive(Int32 caseSensitive); +STDAPI SetCaseSensitive(Int32 caseSensitive) +{ + g_CaseSensitive = (caseSensitive != 0); + return S_OK; +} + +#ifdef EXTERNAL_CODECS + +CExternalCodecs g_ExternalCodecs; + +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo); +STDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo) +{ + COM_TRY_BEGIN + + // OutputDebugStringA(compressCodecsInfo ? "SetCodecs" : "SetCodecs NULL"); + if (compressCodecsInfo) + { + g_ExternalCodecs.GetCodecs = compressCodecsInfo; + return g_ExternalCodecs.Load(); + } + g_ExternalCodecs.ClearAndRelease(); + return S_OK; + + COM_TRY_END +} + +#else + +STDAPI SetCodecs(ICompressCodecsInfo *); +STDAPI SetCodecs(ICompressCodecsInfo *) +{ + return S_OK; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/IArchive.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/IArchive.h new file mode 100644 index 0000000..8290c73 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/IArchive.h @@ -0,0 +1,633 @@ +// IArchive.h + +#ifndef __IARCHIVE_H +#define __IARCHIVE_H + +#include "../IProgress.h" +#include "../IStream.h" +#include "../PropID.h" + +#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) +#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) + +/* +How the function in 7-Zip returns object for output parameter via pointer + +1) The caller sets the value of variable before function call: + PROPVARIANT : vt = VT_EMPTY + BSTR : NULL + IUnknown* and derived interfaces : NULL + another scalar types : any non-initialized value is allowed + +2) The callee in current 7-Zip code now can free input object for output parameter: + PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input + value stored in variable + another types : the callee ignores stored value. + +3) The callee writes new value to variable for output parameter and + returns execution to caller. + +4) The caller must free or release object returned by the callee: + PROPVARIANT : VariantClear(&propvaiant) + BSTR : SysFreeString(bstr) + IUnknown* and derived interfaces : if (ptr) ptr->Relase() +*/ + + +namespace NFileTimeType +{ + enum EEnum + { + kWindows, + kUnix, + kDOS + }; +} + +namespace NArcInfoFlags +{ + const UInt32 kKeepName = 1 << 0; // keep name of file in archive name + const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams + const UInt32 kNtSecure = 1 << 2; // the handler supports NT security + const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive + const UInt32 kMultiSignature = 1 << 4; // there are several signatures + const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset + const UInt32 kStartOpen = 1 << 6; // call handler for each start position + const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file + const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward + const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) + const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links + const UInt32 kHardLinks = 1 << 11; // the handler supports hard links + const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches +} + +namespace NArchive +{ + namespace NHandlerPropID + { + enum + { + kName = 0, // VT_BSTR + kClassID, // binary GUID in VT_BSTR + kExtension, // VT_BSTR + kAddExtension, // VT_BSTR + kUpdate, // VT_BOOL + kKeepName, // VT_BOOL + kSignature, // binary in VT_BSTR + kMultiSignature, // binary in VT_BSTR + kSignatureOffset, // VT_UI4 + kAltStreams, // VT_BOOL + kNtSecure, // VT_BOOL + kFlags // VT_UI4 + // kVersion // VT_UI4 ((VER_MAJOR << 8) | VER_MINOR) + }; + } + + namespace NExtract + { + namespace NAskMode + { + enum + { + kExtract = 0, + kTest, + kSkip + }; + } + + namespace NOperationResult + { + enum + { + kOK = 0, + kUnsupportedMethod, + kDataError, + kCRCError, + kUnavailable, + kUnexpectedEnd, + kDataAfterEnd, + kIsNotArc, + kHeadersError, + kWrongPassword + }; + } + } + + namespace NEventIndexType + { + enum + { + kNoIndex = 0, + kInArcIndex, + kBlockIndex, + kOutArcIndex + }; + } + + namespace NUpdate + { + namespace NOperationResult + { + enum + { + kOK = 0 + // , kError + }; + } + } +} + +#define INTERFACE_IArchiveOpenCallback(x) \ + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ + +ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) +{ + INTERFACE_IArchiveOpenCallback(PURE); +}; + +/* +IArchiveExtractCallback:: + +7-Zip doesn't call IArchiveExtractCallback functions + GetStream() + PrepareOperation() + SetOperationResult() +from different threads simultaneously. +But 7-Zip can call functions for IProgress or ICompressProgressInfo functions +from another threads simultaneously with calls for IArchiveExtractCallback interface. + +IArchiveExtractCallback::GetStream() + UInt32 index - index of item in Archive + Int32 askExtractMode (Extract::NAskMode) + if (askMode != NExtract::NAskMode::kExtract) + { + then the callee doesn't write data to stream: (*outStream == NULL) + } + + Out: + (*outStream == NULL) - for directories + (*outStream == NULL) - if link (hard link or symbolic link) was created + if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract) + { + then the caller must skip extracting of that file. + } + + returns: + S_OK : OK + S_FALSE : data error (for decoders) + +if (IProgress::SetTotal() was called) +{ + IProgress::SetCompleted(completeValue) uses + packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd). + unpackSize - for another formats. +} +else +{ + IProgress::SetCompleted(completeValue) uses packSize. +} + +SetOperationResult() + 7-Zip calls SetOperationResult at the end of extracting, + so the callee can close the file, set attributes, timestamps and security information. + + Int32 opRes (NExtract::NOperationResult) +*/ + +#define INTERFACE_IArchiveExtractCallback(x) \ + INTERFACE_IProgress(x) \ + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ + STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult)(Int32 opRes) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) +{ + INTERFACE_IArchiveExtractCallback(PURE) +}; + + + +/* +IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object + by Extract() or UpdateItems() functions to report about extracting errors +ReportExtractResult() + UInt32 indexType (NEventIndexType) + UInt32 index + Int32 opRes (NExtract::NOperationResult) +*/ + +#define INTERFACE_IArchiveExtractCallbackMessage(x) \ + STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21) +{ + INTERFACE_IArchiveExtractCallbackMessage(PURE) +}; + + +#define INTERFACE_IArchiveOpenVolumeCallback(x) \ + STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ + +ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) +{ + INTERFACE_IArchiveOpenVolumeCallback(PURE); +}; + + +ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) +{ + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; +}; + + +ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) +{ + STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; +}; + + +/* +IInArchive::Open + stream + if (kUseGlobalOffset), stream current position can be non 0. + if (!kUseGlobalOffset), stream current position is 0. + if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream + if (*maxCheckStartPosition == 0), the handler must check only current position as archive start + +IInArchive::Extract: + indices must be sorted + numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files" + testMode != 0 means "test files without writing to outStream" + +IInArchive::GetArchiveProperty: + kpidOffset - start offset of archive. + VT_EMPTY : means offset = 0. + VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed + kpidPhySize - size of archive. VT_EMPTY means unknown size. + kpidPhySize is allowed to be larger than file size. In that case it must show + supposed size. + + kpidIsDeleted: + kpidIsAltStream: + kpidIsAux: + kpidINode: + must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty. + + +Notes: + Don't call IInArchive functions for same IInArchive object from different threads simultaneously. + Some IInArchive handlers will work incorrectly in that case. +*/ + +#ifdef _MSC_VER + #define MY_NO_THROW_DECL_ONLY throw() +#else + #define MY_NO_THROW_DECL_ONLY +#endif + +#define INTERFACE_IInArchive(x) \ + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ + +ARCHIVE_INTERFACE(IInArchive, 0x60) +{ + INTERFACE_IInArchive(PURE) +}; + +namespace NParentType +{ + enum + { + kDir = 0, + kAltStream + }; +}; + +namespace NPropDataType +{ + const UInt32 kMask_ZeroEnd = 1 << 4; + // const UInt32 kMask_BigEndian = 1 << 5; + const UInt32 kMask_Utf = 1 << 6; + const UInt32 kMask_Utf8 = kMask_Utf | 0; + const UInt32 kMask_Utf16 = kMask_Utf | 1; + // const UInt32 kMask_Utf32 = kMask_Utf | 2; + + const UInt32 kNotDefined = 0; + const UInt32 kRaw = 1; + + const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd; + const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; +}; + +// UTF string (pointer to wchar_t) with zero end and little-endian. +#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1)) + +/* +GetRawProp: + Result: + S_OK - even if property is not set +*/ + +#define INTERFACE_IArchiveGetRawProps(x) \ + STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \ + STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \ + STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x; + +ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70) +{ + INTERFACE_IArchiveGetRawProps(PURE) +}; + +#define INTERFACE_IArchiveGetRootProps(x) \ + STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ + +ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71) +{ + INTERFACE_IArchiveGetRootProps(PURE) +}; + +ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) +{ + STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; +}; + +/* + OpenForSize + Result: + S_FALSE - is not archive + ? - DATA error +*/ + +/* +const UInt32 kOpenFlags_RealPhySize = 1 << 0; +const UInt32 kOpenFlags_NoSeek = 1 << 1; +// const UInt32 kOpenFlags_BeforeExtract = 1 << 2; +*/ + +/* +Flags: + 0 - opens archive with IInStream, if IInStream interface is supported + - if phySize is not available, it doesn't try to make full parse to get phySize + kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available + kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file + + if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified, + the handler can return S_OK, but it doesn't check even Signature. + So next Extract can be called for that sequential stream. +*/ + +/* +ARCHIVE_INTERFACE(IArchiveOpen2, 0x62) +{ + STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE; +}; +*/ + +// ---------- UPDATE ---------- + +/* +GetUpdateItemInfo outs: +*newData *newProps + 0 0 - Copy data and properties from archive + 0 1 - Copy data from archive, request new properties + 1 0 - that combination is unused now + 1 1 - Request new data and new properties. It can be used even for folders + + indexInArchive = -1 if there is no item in archive, or if it doesn't matter. + + +GetStream out: + Result: + S_OK: + (*inStream == NULL) - only for directories + - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file + (*inStream != NULL) - for any file, even for empty file or anti-file + S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason) + (*inStream == NULL) + +The order of calling for hard links: + - GetStream() + - GetProperty(kpidHardLink) + +SetOperationResult() + Int32 opRes (NExtract::NOperationResult::kOK) +*/ + +#define INTERFACE_IArchiveUpdateCallback(x) \ + INTERFACE_IProgress(x); \ + STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ + STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) +{ + INTERFACE_IArchiveUpdateCallback(PURE); +}; + +#define INTERFACE_IArchiveUpdateCallback2(x) \ + INTERFACE_IArchiveUpdateCallback(x) \ + STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ + STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) +{ + INTERFACE_IArchiveUpdateCallback2(PURE); +}; + +namespace NUpdateNotifyOp +{ + enum + { + kAdd = 0, + kUpdate, + kAnalyze, + kReplicate, + kRepack, + kSkip, + kDelete, + kHeader + + // kNumDefined + }; +}; + +/* +IArchiveUpdateCallbackFile::ReportOperation + UInt32 indexType (NEventIndexType) + UInt32 index + UInt32 notifyOp (NUpdateNotifyOp) +*/ + +#define INTERFACE_IArchiveUpdateCallbackFile(x) \ + STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \ + STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \ + +ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83) +{ + INTERFACE_IArchiveUpdateCallbackFile(PURE); +}; + + +/* +UpdateItems() +------------- + + outStream: output stream. (the handler) MUST support the case when + Seek position in outStream is not ZERO. + but the caller calls with empty outStream and seek position is ZERO?? + + archives with stub: + + If archive is open and the handler and (Offset > 0), then the handler + knows about stub size. + UpdateItems(): + 1) the handler MUST copy that stub to outStream + 2) the caller MUST NOT copy the stub to outStream, if + "rsfx" property is set with SetProperties + + the handler must support the case where + ISequentialOutStream *outStream +*/ + + +#define INTERFACE_IOutArchive(x) \ + STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ + STDMETHOD(GetFileTimeType)(UInt32 *type) x; + +ARCHIVE_INTERFACE(IOutArchive, 0xA0) +{ + INTERFACE_IOutArchive(PURE) +}; + + +/* +ISetProperties::SetProperties() + PROPVARIANT values[i].vt: + VT_EMPTY + VT_BOOL + VT_UI4 - if 32-bit number + VT_UI8 - if 64-bit number + VT_BSTR +*/ + +ARCHIVE_INTERFACE(ISetProperties, 0x03) +{ + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE; +}; + +ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04) +{ + STDMETHOD(KeepModeForNextOpen)() PURE; +}; + +/* Exe handler: the handler for executable format (PE, ELF, Mach-O). + SFX archive: executable stub + some tail data. + before 9.31: exe handler didn't parse SFX archives as executable format. + for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */ + +ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05) +{ + STDMETHOD(AllowTail)(Int32 allowTail) PURE; +}; + + +#define IMP_IInArchive_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \ + + +struct CStatProp +{ + const char *Name; + UInt32 PropID; + VARTYPE vt; +}; + +namespace NWindows { +namespace NCOM { +// PropVariant.cpp +BSTR AllocBstrFromAscii(const char *s) throw(); +}} + +#define IMP_IInArchive_GetProp_WITH_NAME(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ + const CStatProp &prop = k[index]; \ + *propID = (PROPID)prop.PropID; *varType = prop.vt; \ + *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \ + +#define IMP_IInArchive_Props \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) + +#define IMP_IInArchive_Props_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) + + +#define IMP_IInArchive_ArcProps \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) + +#define IMP_IInArchive_ArcProps_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) + +#define IMP_IInArchive_ArcProps_NO_Table \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ + { *numProps = 0; return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ + { return E_NOTIMPL; } \ + +#define IMP_IInArchive_ArcProps_NO \ + IMP_IInArchive_ArcProps_NO_Table \ + STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ + { value->vt = VT_EMPTY; return S_OK; } + + + +#define k_IsArc_Res_NO 0 +#define k_IsArc_Res_YES 1 +#define k_IsArc_Res_NEED_MORE 2 +// #define k_IsArc_Res_YES_LOW_PROB 3 + +#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI +#define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI + +extern "C" +{ + typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject); + + typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size); + typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc); + + typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats); + typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); + + typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); + typedef HRESULT (WINAPI *Func_SetLargePageMode)(); + + typedef IOutArchive * (*Func_CreateOutArchive)(); + typedef IInArchive * (*Func_CreateInArchive)(); +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Icons/7z.ico b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/Icons/7z.ico new file mode 100644 index 0000000000000000000000000000000000000000..319753a1772db054fd0c04de24a105769a5a0da2 GIT binary patch literal 4710 zcmZQzU}RunP*7k1gB2VM3~mez3<3gRE<*+@1H(HG5Fa9-!N|Z6#>c>*pa9{&U}9jX z<7Z&dU|?VX8R5VHGLHkSxq$^tVIdkA7#bKD7#bQN6hi}u$#CGn0fqy24lsN;wTyv< zg@u8GgM)#GhlfE>P>?}POpHNBMutI2Nr^#IQ_0?FnlS@IS{egG+Drz9v@;A0Y5yVGW*Rdv%uHiom^qVyVdfbIhME7tMlqZ* zW?(pz#=vl9CIiEnGYkx8{xdNAPh(*CKa+vs{~55&#ta~s#$e1alfjq)B=(;HY`w8D zgRyZMgR${U24mwh493R)Ax=s&W-v}mV=zve$zYszhQT=PKg5|cjTww*rZE`LoXKE3 z^9+OW%>NLlpD|`IK9j~^d}bzt@tHFW#%KOB82>kBF#ey$VElh3gE7b*|NnzS0OX1^ z1`wRdkj8L^A&ucb1K7*P#tdo3X$)z`Ga1s1&oHDJ|Az!anlVFKS{g%I+DwMDv@?)k znQ6?BHZzSOZRSjdw3#5W|B#?MW6Y3tW+p@0nKKM&Xa0kOF73ZDL)!nD3~B$*Fq~od z&+wn&3?vARXEH$G8E~x3GzNuE8pBLu5dS|UsMCxYW*Vn4%uJifFf;88!%XA<3^QjM zGt8Ws#xQf{Ooo{=L1z7jLloeT{Bjg1-p8>cb+H=fDx-}nr}f8+m<wrZN1VIg{c4%rgxCXZ{BzJBI&fj2Zr)Nn`kb zW+ub`GiMn7pZU-5|GzQAng3}F|NqZq`2YV5Ls}Xrj?x&?{)6lQnGI5t#-PZslp#Jo zo}s+FoT06)jbYlfX$+@NpJv#!X%oZs>(?3X-o4B4`0-Lf=EMDBHIrZ0TCc=V9RDfO_{X-Vn0k0WGM(Q02>AJ1WX>H z6{HS?q55Y*?FR`#0|6of5&#*2Zazqy1r3114f*%9^^NOeijIYCJ!%xdfLf2E?Ud1W3VIm_;-i+!TwDf+LA47Q&ze;U;v-dwFg{Z4W^fo(WWy^n z76cz$0u#YMeE9HTuzrvRXgvYu|7T(O&%$N!@$lgVETAGDRFkl9flG0SJgDFY`2o2! z{||1jF)%cM%0^_2tEdEZ=NK3mK;`Wp21tJpQO-g-f*?8U+Hse&gxZtX&0}CNh5!cZ z-C%%ByMTc8?%n?X|Ns92rd@E*U;Muq8yoxo|L^jJdG~JrFD@=$7{L7hUle{uQ$AH_Tue^mY#m;WxXkaYPEa?yVmW=KeGhVh{Z*uVwq9tN<2 e%?xlpIK>-45~Yia3oQOXrhza-8-k>Fy9)sB6V>kk literal 0 HcmV?d00001 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/LzmaHandler.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/LzmaHandler.cpp new file mode 100644 index 0000000..ba547c8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/LzmaHandler.cpp @@ -0,0 +1,624 @@ +// LzmaHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/FilterCoder.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/BcjCoder.h" +#include "../Compress/LzmaDecoder.h" + +#include "Common/DummyOutStream.h" + +using namespace NWindows; + +namespace NArchive { +namespace NLzma { + +static bool CheckDicSize(const Byte *p) +{ + UInt32 dicSize = GetUi32(p); + if (dicSize == 1) + return true; + for (unsigned i = 0; i <= 30; i++) + if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) + return true; + return (dicSize == 0xFFFFFFFF); +} + +static const Byte kProps[] = +{ + kpidSize, + kpidPackSize, + kpidMethod +}; + +static const Byte kArcProps[] = +{ + kpidNumStreams, + kpidMethod +}; + +struct CHeader +{ + UInt64 Size; + Byte FilterID; + Byte LzmaProps[5]; + + Byte GetProp() const { return LzmaProps[0]; } + UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } + bool HasSize() const { return (Size != (UInt64)(Int64)-1); } + bool Parse(const Byte *buf, bool isThereFilter); +}; + +bool CHeader::Parse(const Byte *buf, bool isThereFilter) +{ + FilterID = 0; + if (isThereFilter) + FilterID = buf[0]; + const Byte *sig = buf + (isThereFilter ? 1 : 0); + for (int i = 0; i < 5; i++) + LzmaProps[i] = sig[i]; + Size = GetUi64(sig + 5); + return + LzmaProps[0] < 5 * 5 * 9 && + FilterID < 2 && + (!HasSize() || Size < ((UInt64)1 << 56)) + && CheckDicSize(LzmaProps + 1); +} + +class CDecoder +{ + CMyComPtr _bcjStream; + CFilterCoder *_filterCoder; + CMyComPtr _lzmaDecoder; +public: + NCompress::NLzma::CDecoder *_lzmaDecoderSpec; + + ~CDecoder(); + HRESULT Create(bool filtered, ISequentialInStream *inStream); + + HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + + UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); } + + void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); } + + HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) + { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } +}; + +HRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) +{ + if (!_lzmaDecoder) + { + _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; + _lzmaDecoderSpec->FinishStream = true; + _lzmaDecoder = _lzmaDecoderSpec; + } + + if (filteredMode) + { + if (!_bcjStream) + { + _filterCoder = new CFilterCoder(false); + CMyComPtr coder = _filterCoder; + _filterCoder->Filter = new NCompress::NBcj::CCoder(false); + _bcjStream = _filterCoder; + } + } + + return _lzmaDecoderSpec->SetInStream(inStream); +} + +CDecoder::~CDecoder() +{ + ReleaseInStream(); +} + +HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, + ICompressProgressInfo *progress) +{ + if (header.FilterID > 1) + return E_NOTIMPL; + + RINOK(_lzmaDecoderSpec->SetDecoderProperties2(header.LzmaProps, 5)); + + bool filteredMode = (header.FilterID == 1); + + if (filteredMode) + { + RINOK(_filterCoder->SetOutStream(outStream)); + outStream = _bcjStream; + RINOK(_filterCoder->SetOutStreamSize(NULL)); + } + + const UInt64 *Size = header.HasSize() ? &header.Size : NULL; + HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); + + if (filteredMode) + { + { + HRESULT res2 = _filterCoder->OutStreamFinish(); + if (res == S_OK) + res = res2; + } + HRESULT res2 = _filterCoder->ReleaseOutStream(); + if (res == S_OK) + res = res2; + } + + RINOK(res); + + if (header.HasSize()) + if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) + return S_FALSE; + + return S_OK; +} + + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public CMyUnknownImp +{ + CHeader _header; + bool _lzma86; + CMyComPtr _stream; + CMyComPtr _seqStream; + + bool _isArc; + bool _needSeekToStart; + bool _dataAfterEnd; + bool _needMoreInput; + + bool _packSize_Defined; + bool _unpackSize_Defined; + bool _numStreams_Defined; + + bool _unsupported; + bool _dataError; + + UInt64 _packSize; + UInt64 _unpackSize; + UInt64 _numStreams; + + void GetMethod(NCOM::CPropVariant &prop); + +public: + MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq) + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + + CHandler(bool lzma86) { _lzma86 = lzma86; } + + unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } + +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch (propID) + { + case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; + case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; + case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; + case kpidMethod: GetMethod(prop); break; + case kpidErrorFlags: + { + UInt32 v = 0; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;; + if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; + if (_dataError) v |= kpv_ErrorFlags_DataError; + prop = v; + break; + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + + +static char * DictSizeToString(UInt32 val, char *s) +{ + for (unsigned i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + return ::ConvertUInt32ToString(i, s); + char c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + s = ::ConvertUInt32ToString(val, s); + *s++ = c; + *s = 0; + return s; +} + +static char *AddProp32(char *s, const char *name, UInt32 v) +{ + *s++ = ':'; + s = MyStpCpy(s, name); + return ::ConvertUInt32ToString(v, s); +} + +void CHandler::GetMethod(NCOM::CPropVariant &prop) +{ + if (!_stream) + return; + + char sz[64]; + char *s = sz; + if (_header.FilterID != 0) + s = MyStpCpy(s, "BCJ "); + s = MyStpCpy(s, "LZMA:"); + s = DictSizeToString(_header.GetDicSize(), s); + + UInt32 d = _header.GetProp(); + // if (d != 0x5D) + { + UInt32 lc = d % 9; + d /= 9; + UInt32 pb = d / 5; + UInt32 lp = d % 5; + if (lc != 3) s = AddProp32(s, "lc", lc); + if (lp != 0) s = AddProp32(s, "lp", lp); + if (pb != 2) s = AddProp32(s, "pb", pb); + } + prop = sz; +} + + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch (propID) + { + case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; + case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; + case kpidMethod: GetMethod(prop); break; + } + prop.Detach(value); + return S_OK; +} + +API_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) +{ + const UInt32 kHeaderSize = 1 + 4 + 8; + if (size < kHeaderSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] >= 5 * 5 * 9) + return k_IsArc_Res_NO; + const UInt64 unpackSize = GetUi64(p + 1 + 4); + if (unpackSize != (UInt64)(Int64)-1) + { + if (unpackSize >= ((UInt64)1 << 56)) + return k_IsArc_Res_NO; + } + if (unpackSize != 0) + { + if (size < kHeaderSize + 2) + return k_IsArc_Res_NEED_MORE; + if (p[kHeaderSize] != 0) + return k_IsArc_Res_NO; + if (unpackSize != (UInt64)(Int64)-1) + { + if ((p[kHeaderSize + 1] & 0x80) != 0) + return k_IsArc_Res_NO; + } + } + if (!CheckDicSize(p + 1)) + // return k_IsArc_Res_YES_LOW_PROB; + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} +} + +API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size) +{ + if (size < 1) + return k_IsArc_Res_NEED_MORE; + Byte filterID = p[0]; + if (filterID != 0 && filterID != 1) + return k_IsArc_Res_NO; + return IsArc_Lzma(p + 1, size - 1); +} +} + + + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *) +{ + Close(); + + const unsigned headerSize = GetHeaderSize(); + const UInt32 kBufSize = 1 << 7; + Byte buf[kBufSize]; + size_t processedSize = kBufSize; + RINOK(ReadStream(inStream, buf, &processedSize)); + if (processedSize < headerSize + 2) + return S_FALSE; + if (!_header.Parse(buf, _lzma86)) + return S_FALSE; + const Byte *start = buf + headerSize; + if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80 + return S_FALSE; + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize)); + + SizeT srcLen = processedSize - headerSize; + + if (srcLen > 10 + && _header.Size == 0 + // && _header.FilterID == 0 + && _header.LzmaProps[0] == 0 + ) + return S_FALSE; + + CDecoder state; + const UInt32 outLimit = 1 << 11; + Byte outBuf[outLimit]; + + SizeT outSize = outLimit; + if (outSize > _header.Size) + outSize = (SizeT)_header.Size; + SizeT destLen = outSize; + ELzmaStatus status; + + SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen, + _header.LzmaProps, 5, LZMA_FINISH_ANY, + &status, &g_Alloc); + + if (res != SZ_OK) + if (res != SZ_ERROR_INPUT_EOF) + return S_FALSE; + + _isArc = true; + _stream = inStream; + _seqStream = inStream; + _needSeekToStart = true; + return S_OK; +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _isArc = true; + _seqStream = stream; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + _isArc = false; + _packSize_Defined = false; + _unpackSize_Defined = false; + _numStreams_Defined = false; + + _dataAfterEnd = false; + _needMoreInput = false; + _unsupported = false; + _dataError = false; + + _packSize = 0; + + _needSeekToStart = false; + + _stream.Release(); + _seqStream.Release(); + return S_OK; +} + +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr Callback; +public: + UInt64 Offset; + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + const UInt64 files = 0; + const UInt64 val = Offset + *inSize; + return Callback->SetCompleted(&files, &val); + } + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + if (_packSize_Defined) + extractCallback->SetTotal(_packSize); + + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, true); + + if (_needSeekToStart) + { + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + else + _needSeekToStart = true; + + CDecoder decoder; + HRESULT result = decoder.Create(_lzma86, _seqStream); + RINOK(result); + + bool firstItem = true; + + UInt64 packSize = 0; + UInt64 unpackSize = 0; + UInt64 numStreams = 0; + + bool dataAfterEnd = false; + + for (;;) + { + lps->InSize = packSize; + lps->OutSize = unpackSize; + RINOK(lps->SetCur()); + + const UInt32 kBufSize = 1 + 5 + 8; + Byte buf[kBufSize]; + const UInt32 headerSize = GetHeaderSize(); + UInt32 processed; + RINOK(decoder.ReadInput(buf, headerSize, &processed)); + if (processed != headerSize) + { + if (processed != 0) + dataAfterEnd = true; + break; + } + + CHeader st; + if (!st.Parse(buf, _lzma86)) + { + dataAfterEnd = true; + break; + } + numStreams++; + firstItem = false; + + result = decoder.Code(st, outStream, progress); + + packSize = decoder.GetInputProcessedSize(); + unpackSize = outStreamSpec->GetSize(); + + if (result == E_NOTIMPL) + { + _unsupported = true; + result = S_FALSE; + break; + } + if (result == S_FALSE) + break; + RINOK(result); + } + + if (firstItem) + { + _isArc = false; + result = S_FALSE; + } + else if (result == S_OK || result == S_FALSE) + { + if (dataAfterEnd) + _dataAfterEnd = true; + else if (decoder._lzmaDecoderSpec->NeedsMoreInput()) + _needMoreInput = true; + + _packSize = packSize; + _unpackSize = unpackSize; + _numStreams = numStreams; + + _packSize_Defined = true; + _unpackSize_Defined = true; + _numStreams_Defined = true; + } + + Int32 opResult = NExtract::NOperationResult::kOK; + + if (!_isArc) + opResult = NExtract::NOperationResult::kIsNotArc; + else if (_needMoreInput) + opResult = NExtract::NOperationResult::kUnexpectedEnd; + else if (_unsupported) + opResult = NExtract::NOperationResult::kUnsupportedMethod; + else if (_dataAfterEnd) + opResult = NExtract::NOperationResult::kDataAfterEnd; + else if (result == S_FALSE) + opResult = NExtract::NOperationResult::kDataError; + else if (result == S_OK) + opResult = NExtract::NOperationResult::kOK; + else + return result; + + outStream.Release(); + return extractCallback->SetOperationResult(opResult); + + COM_TRY_END +} + +namespace NLzmaAr { + +// 2, { 0x5D, 0x00 }, + +REGISTER_ARC_I_CLS_NO_SIG( + CHandler(false), + "lzma", "lzma", 0, 0xA, + 0, + NArcInfoFlags::kStartOpen | + NArcInfoFlags::kKeepName, + IsArc_Lzma) + +} + +namespace NLzma86Ar { + +REGISTER_ARC_I_CLS_NO_SIG( + CHandler(true), + "lzma86", "lzma86", 0, 0xB, + 0, + NArcInfoFlags::kKeepName, + IsArc_Lzma86) + +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/SplitHandler.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/SplitHandler.cpp new file mode 100644 index 0000000..6705aee --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/SplitHandler.cpp @@ -0,0 +1,359 @@ +// SplitHandler.cpp + +#include "StdAfx.h" + +#include "../../Common/ComTry.h" +#include "../../Common/MyString.h" + +#include "../../Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/MultiStream.h" + +using namespace NWindows; + +namespace NArchive { +namespace NSplit { + +static const Byte kProps[] = +{ + kpidPath, + kpidSize +}; + +static const Byte kArcProps[] = +{ + kpidNumVolumes, + kpidTotalPhySize +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + CObjectVector > _streams; + CRecordVector _sizes; + UString _subName; + UInt64 _totalSize; + + HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch (propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; + case kpidTotalPhySize: prop = _totalSize; break; + case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; + } + prop.Detach(value); + return S_OK; +} + +struct CSeqName +{ + UString _unchangedPart; + UString _changedPart; + bool _splitStyle; + + bool GetNextName(UString &s) + { + { + unsigned i = _changedPart.Len(); + for (;;) + { + wchar_t c = _changedPart[--i]; + + if (_splitStyle) + { + if (c == 'z') + { + _changedPart.ReplaceOneCharAtPos(i, L'a'); + if (i == 0) + return false; + continue; + } + else if (c == 'Z') + { + _changedPart.ReplaceOneCharAtPos(i, L'A'); + if (i == 0) + return false; + continue; + } + } + else + { + if (c == '9') + { + _changedPart.ReplaceOneCharAtPos(i, L'0'); + if (i == 0) + { + _changedPart.InsertAtFront(L'1'); + break; + } + continue; + } + } + + c++; + _changedPart.ReplaceOneCharAtPos(i, c); + break; + } + } + + s = _unchangedPart + _changedPart; + return true; + } +}; + +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) +{ + Close(); + if (!callback) + return S_FALSE; + + CMyComPtr volumeCallback; + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback); + if (!volumeCallback) + return S_FALSE; + + UString name; + { + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + return S_FALSE; + name = prop.bstrVal; + } + + int dotPos = name.ReverseFind_Dot(); + const UString prefix = name.Left((unsigned)(dotPos + 1)); + const UString ext = name.Ptr((unsigned)(dotPos + 1)); + UString ext2 = ext; + ext2.MakeLower_Ascii(); + + CSeqName seqName; + + unsigned numLetters = 2; + bool splitStyle = false; + + if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) + { + splitStyle = true; + while (numLetters < ext2.Len()) + { + if (ext2[ext2.Len() - numLetters - 1] != 'a') + break; + numLetters++; + } + } + else if (ext.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "01")) + { + while (numLetters < ext2.Len()) + { + if (ext2[ext2.Len() - numLetters - 1] != '0') + break; + numLetters++; + } + if (numLetters != ext.Len()) + return S_FALSE; + } + else + return S_FALSE; + + seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); + seqName._changedPart = ext.RightPtr(numLetters); + seqName._splitStyle = splitStyle; + + if (prefix.Len() < 1) + _subName = "file"; + else + _subName.SetFrom(prefix, prefix.Len() - 1); + + UInt64 size; + { + /* + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + */ + RINOK(stream->Seek(0, STREAM_SEEK_END, &size)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + _totalSize += size; + _sizes.Add(size); + _streams.Add(stream); + + { + const UInt64 numFiles = _streams.Size(); + RINOK(callback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + UString fullName; + if (!seqName.GetNextName(fullName)) + break; + CMyComPtr nextStream; + HRESULT result = volumeCallback->GetStream(fullName, &nextStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!nextStream) + break; + { + /* + NCOM::CPropVariant prop; + RINOK(volumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + */ + RINOK(nextStream->Seek(0, STREAM_SEEK_END, &size)); + RINOK(nextStream->Seek(0, STREAM_SEEK_SET, NULL)); + } + _totalSize += size; + _sizes.Add(size); + _streams.Add(nextStream); + { + const UInt64 numFiles = _streams.Size(); + RINOK(callback->SetCompleted(&numFiles, NULL)); + } + } + + if (_streams.Size() == 1) + { + if (splitStyle) + return S_FALSE; + } + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + HRESULT res = Open2(stream, callback); + if (res != S_OK) + Close(); + return res; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _totalSize = 0; + _subName.Empty(); + _streams.Clear(); + _sizes.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _streams.IsEmpty() ? 0 : 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch (propID) + { + case kpidPath: prop = _subName; break; + case kpidSize: + case kpidPackSize: + prop = _totalSize; + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + UInt64 currentTotalSize = 0; + RINOK(extractCallback->SetTotal(_totalSize)); + CMyComPtr outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) + return S_OK; + RINOK(extractCallback->PrepareOperation(askMode)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + FOR_VECTOR (i, _streams) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + IInStream *inStream = _streams[i]; + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + currentTotalSize += copyCoderSpec->TotalSize; + } + outStream.Release(); + return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + if (index != 0) + return E_INVALIDARG; + *stream = 0; + CMultiStream *streamSpec = new CMultiStream; + CMyComPtr streamTemp = streamSpec; + FOR_VECTOR (i, _streams) + { + CMultiStream::CSubStreamInfo subStreamInfo; + subStreamInfo.Stream = _streams[i]; + subStreamInfo.Size = _sizes[i]; + streamSpec->Streams.Add(subStreamInfo); + } + streamSpec->Init(); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +REGISTER_ARC_I_NO_SIG( + "Split", "001", 0, 0xEA, + 0, + 0, + NULL) + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/StdAfx.h new file mode 100644 index 0000000..1cbd7fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.cpp new file mode 100644 index 0000000..2803f6a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.cpp @@ -0,0 +1,1361 @@ +// XzHandler.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../../Common/ComTry.h" +#include "../../Common/Defs.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/StringToInt.h" + +#include "../../Windows/PropVariant.h" +#include "../../Windows/System.h" + +#include "../Common/CWrappers.h" +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" +#include "../Common/StreamUtils.h" + +#include "../Compress/CopyCoder.h" +#include "../Compress/XzDecoder.h" +#include "../Compress/XzEncoder.h" + +#include "IArchive.h" + +#include "Common/HandlerOut.h" + +using namespace NWindows; + +namespace NArchive { +namespace NXz { + +#define k_LZMA2_Name "LZMA2" + + +struct CBlockInfo +{ + unsigned StreamFlags; + UInt64 PackPos; + UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros + UInt64 UnpackPos; +}; + + +class CHandler: + public IInArchive, + public IArchiveOpenSeq, + public IInArchiveGetStream, + public ISetProperties, + + #ifndef EXTRACT_ONLY + public IOutArchive, + #endif + + public CMyUnknownImp, + + #ifndef EXTRACT_ONLY + public CMultiMethodProps + #else + public CCommonMethodProps + #endif +{ + CXzStatInfo _stat; // it's stat from backward parsing + CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called + SRes _stat2_decode_SRes; + bool _stat_defined; + bool _stat2_defined; + + const CXzStatInfo *GetStat() const + { + if (_stat_defined) return &_stat; + if (_stat2_defined) return &_stat2; + return NULL; + } + + bool _isArc; + bool _needSeekToStart; + bool _firstBlockWasRead; + + AString _methodsString; + + + #ifndef EXTRACT_ONLY + + UInt32 _filterId; + UInt64 _numSolidBytes; + + void InitXz() + { + _filterId = 0; + _numSolidBytes = XZ_PROPS__BLOCK_SIZE__AUTO; + } + + #endif + + + void Init() + { + #ifndef EXTRACT_ONLY + InitXz(); + CMultiMethodProps::Init(); + #else + CCommonMethodProps::InitCommon(); + #endif + } + + HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); + + HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); + + HRESULT Decode(NCompress::NXz::CDecoder &decoder, + ISequentialInStream *seqInStream, + ISequentialOutStream *outStream, + ICompressProgressInfo *progress) + { + #ifndef _7ZIP_ST + decoder._numThreads = _numThreads; + #endif + decoder._memUsage = _memUsage; + + HRESULT hres = decoder.Decode(seqInStream, outStream, + NULL, // *outSizeLimit + true, // finishStream + progress); + + if (decoder.MainDecodeSRes_wasUsed + && decoder.MainDecodeSRes != SZ_ERROR_MEM + && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) + { + // if (!_stat2_defined) + { + _stat2_decode_SRes = decoder.MainDecodeSRes; + _stat2 = decoder.Stat; + _stat2_defined = true; + } + } + + return hres; + } + +public: + MY_QUERYINTERFACE_BEGIN2(IInArchive) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq) + MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) + MY_QUERYINTERFACE_ENTRY(ISetProperties) + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY(IOutArchive) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IInArchive(;) + STDMETHOD(OpenSeq)(ISequentialInStream *stream); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); + + #ifndef EXTRACT_ONLY + INTERFACE_IOutArchive(;) + #endif + + CBlockInfo *_blocks; + size_t _blocksArraySize; + UInt64 _maxBlocksSize; + CMyComPtr _stream; + CMyComPtr _seqStream; + + CXzBlock _firstBlock; + + CHandler(); + ~CHandler(); + + HRESULT SeekToPackPos(UInt64 pos) + { + return _stream->Seek((Int64)pos, STREAM_SEEK_SET, NULL); + } +}; + + +CHandler::CHandler(): + _blocks(NULL), + _blocksArraySize(0) +{ + #ifndef EXTRACT_ONLY + InitXz(); + #endif +} + +CHandler::~CHandler() +{ + MyFree(_blocks); +} + + +static const Byte kProps[] = +{ + kpidSize, + kpidPackSize, + kpidMethod +}; + +static const Byte kArcProps[] = +{ + kpidMethod, + kpidNumStreams, + kpidNumBlocks, + kpidClusterSize, + kpidCharacts +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static inline char GetHex(unsigned value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static inline void AddHexToString(AString &s, Byte value) +{ + s += GetHex(value >> 4); + s += GetHex(value & 0xF); +} + +static void Lzma2PropToString(AString &s, unsigned prop) +{ + char c = 0; + UInt32 size; + if ((prop & 1) == 0) + size = prop / 2 + 12; + else + { + c = 'k'; + size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); + if (prop > 17) + { + size >>= 10; + c = 'm'; + } + } + s.Add_UInt32(size); + if (c != 0) + s += c; +} + +struct CMethodNamePair +{ + UInt32 Id; + const char *Name; +}; + +static const CMethodNamePair g_NamePairs[] = +{ + { XZ_ID_Subblock, "SB" }, + { XZ_ID_Delta, "Delta" }, + { XZ_ID_X86, "BCJ" }, + { XZ_ID_PPC, "PPC" }, + { XZ_ID_IA64, "IA64" }, + { XZ_ID_ARM, "ARM" }, + { XZ_ID_ARMT, "ARMT" }, + { XZ_ID_SPARC, "SPARC" }, + { XZ_ID_LZMA2, "LZMA2" } +}; + +static void AddMethodString(AString &s, const CXzFilter &f) +{ + const char *p = NULL; + for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++) + if (g_NamePairs[i].Id == f.id) + { + p = g_NamePairs[i].Name; + break; + } + char temp[32]; + if (!p) + { + ::ConvertUInt64ToString(f.id, temp); + p = temp; + } + + s += p; + + if (f.propsSize > 0) + { + s += ':'; + if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) + Lzma2PropToString(s, f.props[0]); + else if (f.id == XZ_ID_Delta && f.propsSize == 1) + s.Add_UInt32((UInt32)f.props[0] + 1); + else + { + s += '['; + for (UInt32 bi = 0; bi < f.propsSize; bi++) + AddHexToString(s, f.props[bi]); + s += ']'; + } + } +} + +static const char * const kChecks[] = +{ + "NoCheck" + , "CRC32" + , NULL + , NULL + , "CRC64" + , NULL + , NULL + , NULL + , NULL + , NULL + , "SHA256" + , NULL + , NULL + , NULL + , NULL + , NULL +}; + +static void AddCheckString(AString &s, const CXzs &xzs) +{ + size_t i; + UInt32 mask = 0; + for (i = 0; i < xzs.num; i++) + mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); + for (i = 0; i <= XZ_CHECK_MASK; i++) + if (((mask >> i) & 1) != 0) + { + s.Add_Space_if_NotEmpty(); + if (kChecks[i]) + s += kChecks[i]; + else + { + s += "Check-"; + s.Add_UInt32((UInt32)i); + } + } +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + + const CXzStatInfo *stat = GetStat(); + + switch (propID) + { + case kpidPhySize: if (stat) prop = stat->InSize; break; + case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; + case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; + case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; + case kpidCharacts: + if (_firstBlockWasRead) + { + AString s; + if (XzBlock_HasPackSize(&_firstBlock)) + s.Add_OptSpaced("BlockPackSize"); + if (XzBlock_HasUnpackSize(&_firstBlock)) + s.Add_OptSpaced("BlockUnpackSize"); + if (!s.IsEmpty()) + prop = s; + } + break; + + + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + case kpidErrorFlags: + { + UInt32 v = 0; + SRes sres = _stat2_decode_SRes; + if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; + if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; + if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; + if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; + if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; + if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; + if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; + if (v != 0) + prop = v; + break; + } + + case kpidMainSubfile: + { + // debug only, comment it: + // if (_blocks) prop = (UInt32)0; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + const CXzStatInfo *stat = GetStat(); + NCOM::CPropVariant prop; + switch (propID) + { + case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; + case kpidPackSize: if (stat) prop = stat->InSize; break; + case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + + +struct COpenCallbackWrap +{ + ICompressProgress vt; + IArchiveOpenCallback *OpenCallback; + HRESULT Res; + + // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() + void Init(IArchiveOpenCallback *progress); +}; + +static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */) +{ + COpenCallbackWrap *p = CONTAINER_FROM_VTBL(pp, COpenCallbackWrap, vt); + if (p->OpenCallback) + p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); + return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); +} + +void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) +{ + vt.Progress = OpenCallbackProgress; + OpenCallback = callback; + Res = SZ_OK; +} + + +struct CXzsCPP +{ + CXzs p; + CXzsCPP() { Xzs_Construct(&p); } + ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } +}; + +#define kInputBufSize ((size_t)1 << 10) + +struct CLookToRead2_CPP: public CLookToRead2 +{ + CLookToRead2_CPP() + { + buf = NULL; + LookToRead2_CreateVTable(this, + True // Lookahead ? + ); + } + void Alloc(size_t allocSize) + { + buf = (Byte *)MyAlloc(allocSize); + if (buf) + this->bufSize = allocSize; + } + ~CLookToRead2_CPP() + { + MyFree(buf); + } +}; + + +static HRESULT SRes_to_Open_HRESULT(SRes res) +{ + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PROGRESS: return E_ABORT; + /* + case SZ_ERROR_UNSUPPORTED: + case SZ_ERROR_CRC: + case SZ_ERROR_DATA: + case SZ_ERROR_ARCHIVE: + case SZ_ERROR_NO_ARCHIVE: + return S_FALSE; + */ + } + return S_FALSE; +} + + + +HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) +{ + _needSeekToStart = true; + + { + CXzStreamFlags st; + CSeqInStreamWrap inStreamWrap; + + inStreamWrap.Init(inStream); + + SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; + if (res != SZ_OK) + return SRes_to_Open_HRESULT(res); + + { + CXzBlock block; + BoolInt isIndex; + UInt32 headerSizeRes; + + SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); + + if (inStreamWrap.Res != S_OK) + return inStreamWrap.Res; + + if (res2 != SZ_OK) + { + if (res2 == SZ_ERROR_INPUT_EOF) + { + _stat2_decode_SRes = res2; + _stream = inStream; + _seqStream = inStream; + _isArc = true; + return S_OK; + } + + if (res2 == SZ_ERROR_ARCHIVE) + return S_FALSE; + } + else if (!isIndex) + { + _firstBlockWasRead = true; + _firstBlock = block; + + unsigned numFilters = XzBlock_GetNumFilters(&block); + for (unsigned i = 0; i < numFilters; i++) + { + _methodsString.Add_Space_if_NotEmpty(); + AddMethodString(_methodsString, block.filters[i]); + } + } + } + } + + RINOK(inStream->Seek(0, STREAM_SEEK_END, &_stat.InSize)); + if (callback) + { + RINOK(callback->SetTotal(NULL, &_stat.InSize)); + } + + CSeekInStreamWrap inStreamImp; + + inStreamImp.Init(inStream); + + CLookToRead2_CPP lookStream; + + lookStream.Alloc(kInputBufSize); + + if (!lookStream.buf) + return E_OUTOFMEMORY; + + lookStream.realStream = &inStreamImp.vt; + LookToRead2_Init(&lookStream); + + COpenCallbackWrap openWrap; + openWrap.Init(callback); + + CXzsCPP xzs; + Int64 startPosition; + SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc); + if (res == SZ_ERROR_PROGRESS) + return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; + /* + if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) + res = SZ_OK; + */ + if (res == SZ_OK && startPosition == 0) + { + _stat_defined = true; + + _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); + _stat.UnpackSize_Defined = true; + + _stat.NumStreams = xzs.p.num; + _stat.NumStreams_Defined = true; + + _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); + _stat.NumBlocks_Defined = true; + + AddCheckString(_methodsString, xzs.p); + + const size_t numBlocks = (size_t)_stat.NumBlocks + 1; + const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo); + + if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1) + { + _blocks = (CBlockInfo *)MyAlloc(bytesAlloc); + if (_blocks) + { + unsigned blockIndex = 0; + UInt64 unpackPos = 0; + + for (size_t si = xzs.p.num; si != 0;) + { + si--; + const CXzStream &str = xzs.p.streams[si]; + UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE; + + for (size_t bi = 0; bi < str.numBlocks; bi++) + { + const CXzBlockSizes &bs = str.blocks[bi]; + const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3); + + if (bs.unpackSize != 0) + { + if (blockIndex >= _stat.NumBlocks) + return E_FAIL; + + CBlockInfo &block = _blocks[blockIndex++]; + block.StreamFlags = str.flags; + block.PackSize = bs.totalSize; // packSizeAligned; + block.PackPos = packPos; + block.UnpackPos = unpackPos; + } + packPos += packSizeAligned; + unpackPos += bs.unpackSize; + if (_maxBlocksSize < bs.unpackSize) + _maxBlocksSize = bs.unpackSize; + } + } + + /* + if (blockIndex != _stat.NumBlocks) + { + // there are Empty blocks; + } + */ + if (_stat.OutSize != unpackPos) + return E_FAIL; + CBlockInfo &block = _blocks[blockIndex++]; + block.StreamFlags = 0; + block.PackSize = 0; + block.PackPos = 0; + block.UnpackPos = unpackPos; + _blocksArraySize = blockIndex; + } + } + } + else + { + res = SZ_OK; + } + + RINOK(SRes_to_Open_HRESULT(res)); + + _stream = inStream; + _seqStream = inStream; + _isArc = true; + return S_OK; +} + + + +STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + { + Close(); + return Open2(inStream, callback); + } + COM_TRY_END +} + +STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) +{ + Close(); + _seqStream = stream; + _isArc = true; + _needSeekToStart = false; + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + XzStatInfo_Clear(&_stat); + XzStatInfo_Clear(&_stat2); + _stat_defined = false; + _stat2_defined = false; + _stat2_decode_SRes = SZ_OK; + + _isArc = false; + _needSeekToStart = false; + _firstBlockWasRead = false; + + _methodsString.Empty(); + _stream.Release(); + _seqStream.Release(); + + MyFree(_blocks); + _blocks = NULL; + _blocksArraySize = 0; + _maxBlocksSize = 0; + + return S_OK; +} + + +struct CXzUnpackerCPP2 +{ + Byte *InBuf; + // Byte *OutBuf; + CXzUnpacker p; + + CXzUnpackerCPP2(); + ~CXzUnpackerCPP2(); +}; + +CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL) + // , OutBuf(NULL) +{ + XzUnpacker_Construct(&p, &g_Alloc); +} + +CXzUnpackerCPP2::~CXzUnpackerCPP2() +{ + XzUnpacker_Free(&p); + MidFree(InBuf); + // MidFree(OutBuf); +} + + +class CInStream: + public IInStream, + public CMyUnknownImp +{ +public: + UInt64 _virtPos; + UInt64 Size; + UInt64 _cacheStartPos; + size_t _cacheSize; + CByteBuffer _cache; + // UInt64 _startPos; + CXzUnpackerCPP2 xz; + + void InitAndSeek() + { + _virtPos = 0; + _cacheStartPos = 0; + _cacheSize = 0; + // _startPos = startPos; + } + + CHandler *_handlerSpec; + CMyComPtr _handler; + + MY_UNKNOWN_IMP1(IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + ~CInStream(); +}; + + +CInStream::~CInStream() +{ + // _cache.Free(); +} + + +static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) +{ + size_t left = 0, right = numBlocks; + for (;;) + { + size_t mid = (left + right) / 2; + if (mid == left) + return left; + if (pos < blocks[mid].UnpackPos) + right = mid; + else + left = mid; + } +} + + + +static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu, + ISequentialInStream *seqInStream, + unsigned streamFlags, + UInt64 packSize, // pure size from Index record, it doesn't include pad zeros + size_t unpackSize, Byte *dest + // , ICompressProgressInfo *progress + ) +{ + const size_t kInBufSize = (size_t)1 << 16; + + XzUnpacker_Init(&xzu.p); + + if (!xzu.InBuf) + { + xzu.InBuf = (Byte *)MidAlloc(kInBufSize); + if (!xzu.InBuf) + return E_OUTOFMEMORY; + } + + xzu.p.streamFlags = (UInt16)streamFlags; + XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p); + + XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize); + + const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); + UInt64 packRem = packSizeAligned; + + UInt32 inSize = 0; + SizeT inPos = 0; + SizeT outPos = 0; + + HRESULT readRes = S_OK; + + for (;;) + { + if (inPos == inSize && readRes == S_OK) + { + inPos = 0; + inSize = 0; + UInt32 rem = kInBufSize; + if (rem > packRem) + rem = (UInt32)packRem; + if (rem != 0) + readRes = seqInStream->Read(xzu.InBuf, rem, &inSize); + } + + SizeT inLen = inSize - inPos; + SizeT outLen = unpackSize - outPos; + + ECoderStatus status; + + SRes res = XzUnpacker_Code(&xzu.p, + // dest + outPos, + NULL, + &outLen, + xzu.InBuf + inPos, &inLen, + (inLen == 0), // srcFinished + CODER_FINISH_END, &status); + + // return E_OUTOFMEMORY; + // res = SZ_ERROR_CRC; + + if (res != SZ_OK) + { + if (res == SZ_ERROR_CRC) + return S_FALSE; + return SResToHRESULT(res); + } + + inPos += inLen; + outPos += outLen; + + packRem -= inLen; + + BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p); + + if ((inLen == 0 && outLen == 0) || blockFinished) + { + if (packRem != 0 || !blockFinished || unpackSize != outPos) + return S_FALSE; + if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize) + return S_FALSE; + return S_OK; + } + } +} + + +STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + COM_TRY_BEGIN + + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + + { + if (_virtPos >= Size) + return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; + { + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } + } + + if (size == 0) + return S_OK; + + if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize) + { + size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos); + const CBlockInfo &block = _handlerSpec->_blocks[bi]; + const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos; + if (_cache.Size() < unpackSize) + return E_FAIL; + + _cacheSize = 0; + + RINOK(_handlerSpec->SeekToPackPos(block.PackPos)); + RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize, + (size_t)unpackSize, _cache)); + _cacheStartPos = block.UnpackPos; + _cacheSize = (size_t)unpackSize; + } + + { + size_t offset = (size_t)(_virtPos - _cacheStartPos); + size_t rem = _cacheSize - offset; + if (size > rem) + size = (UInt32)rem; + memcpy(data, _cache + offset, size); + _virtPos += size; + if (processedSize) + *processedSize = size; + return S_OK; + } + + COM_TRY_END +} + + +STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} + + + +static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40; + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + + *stream = NULL; + + if (index != 0) + return E_INVALIDARG; + + if (!_stat.UnpackSize_Defined + || _maxBlocksSize == 0 // 18.02 + || _maxBlocksSize > kMaxBlockSize_for_GetStream + || _maxBlocksSize != (size_t)_maxBlocksSize) + return S_FALSE; + + UInt64 memSize; + if (!NSystem::GetRamSize(memSize)) + memSize = (UInt64)(sizeof(size_t)) << 28; + { + if (_maxBlocksSize > memSize / 4) + return S_FALSE; + } + + CInStream *spec = new CInStream; + CMyComPtr specStream = spec; + spec->_cache.Alloc((size_t)_maxBlocksSize); + spec->_handlerSpec = this; + spec->_handler = (IInArchive *)this; + spec->Size = _stat.OutSize; + spec->InitAndSeek(); + + *stream = specStream.Detach(); + return S_OK; + + COM_TRY_END +} + + +static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) +{ + Int32 opRes; + SRes sres = decoder.MainDecodeSRes; + if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) + opRes = NExtract::NOperationResult::kIsNotArc; + else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) + opRes = NExtract::NOperationResult::kUnexpectedEnd; + else if (decoder.Stat.DataAfterEnd) + opRes = NExtract::NOperationResult::kDataAfterEnd; + else if (sres == SZ_ERROR_CRC) // (CrcError) + opRes = NExtract::NOperationResult::kCRCError; + else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported) + opRes = NExtract::NOperationResult::kUnsupportedMethod; + else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError) + opRes = NExtract::NOperationResult::kDataError; + else if (sres == SZ_ERROR_DATA) // (DataError) + opRes = NExtract::NOperationResult::kDataError; + else if (sres != SZ_OK) + opRes = NExtract::NOperationResult::kDataError; + else + opRes = NExtract::NOperationResult::kOK; + return opRes; +} + + + + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + const CXzStatInfo *stat = GetStat(); + + if (stat) + extractCallback->SetTotal(stat->InSize); + + UInt64 currentTotalPacked = 0; + RINOK(extractCallback->SetCompleted(¤tTotalPacked)); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + if (!testMode && !realOutStream) + return S_OK; + + extractCallback->PrepareOperation(askMode); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr lpsRef = lps; + lps->Init(extractCallback, true); + + if (_needSeekToStart) + { + if (!_stream) + return E_FAIL; + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + else + _needSeekToStart = true; + + + NCompress::NXz::CDecoder decoder; + + HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef); + + if (!decoder.MainDecodeSRes_wasUsed) + return hres == S_OK ? E_FAIL : hres; + + Int32 opRes = Get_Extract_OperationResult(decoder); + if (opRes == NExtract::NOperationResult::kOK + && hres != S_OK) + opRes = NExtract::NOperationResult::kDataError; + + realOutStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + + + +#ifndef EXTRACT_ONLY + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kUnix; + return S_OK; +} + + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + COM_TRY_BEGIN + + if (numItems == 0) + { + CSeqOutStreamWrap seqOutStream; + seqOutStream.Init(outStream); + SRes res = Xz_EncodeEmpty(&seqOutStream.vt); + return SResToHRESULT(res); + } + + if (numItems != 1) + return E_INVALIDARG; + + Int32 newData, newProps; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)); + + if (IntToBool(newProps)) + { + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)); + if (prop.vt != VT_EMPTY) + if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) + return E_INVALIDARG; + } + } + + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(updateCallback->GetProperty(0, kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + RINOK(updateCallback->SetTotal(size)); + } + + NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; + CMyComPtr encoder = encoderSpec; + + CXzProps &xzProps = encoderSpec->xzProps; + CLzma2EncProps &lzma2Props = xzProps.lzma2Props; + + lzma2Props.lzmaProps.level = GetLevel(); + + xzProps.reduceSize = size; + /* + { + NCOM::CPropVariant prop = (UInt64)size; + RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop)); + } + */ + + #ifndef _7ZIP_ST + xzProps.numTotalThreads = (int)_numThreads; + #endif + + xzProps.blockSize = _numSolidBytes; + if (_numSolidBytes == XZ_PROPS__BLOCK_SIZE__SOLID) + { + xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS__BLOCK_SIZE__SOLID; + } + + RINOK(encoderSpec->SetCheckSize(_crcSize)); + + { + CXzFilterProps &filter = xzProps.filterProps; + + if (_filterId == XZ_ID_Delta) + { + bool deltaDefined = false; + FOR_VECTOR (j, _filterMethod.Props) + { + const CProp &prop = _filterMethod.Props[j]; + if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) + { + UInt32 delta = (UInt32)prop.Value.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + filter.delta = delta; + deltaDefined = true; + } + else + return E_INVALIDARG; + } + if (!deltaDefined) + return E_INVALIDARG; + } + filter.id = _filterId; + } + + FOR_VECTOR (i, _methods) + { + COneMethodInfo &m = _methods[i]; + + FOR_VECTOR (j, m.Props) + { + const CProp &prop = m.Props[j]; + RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value)); + } + } + + CMyComPtr fileInStream; + RINOK(updateCallback->GetStream(0, &fileInStream)); + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + RINOK(encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress)); + + return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); + } + + if (indexInArchive != 0) + return E_INVALIDARG; + + CMyComPtr opCallback; + updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback); + if (opCallback) + { + RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) + } + + if (_stream) + { + const CXzStatInfo *stat = GetStat(); + if (stat) + RINOK(updateCallback->SetTotal(stat->InSize)); + RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(updateCallback, true); + + return NCompress::CopyStream(_stream, outStream, progress); + + COM_TRY_END +} + +#endif + + +HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) +{ + UString name = nameSpec; + name.MakeLower_Ascii(); + if (name.IsEmpty()) + return E_INVALIDARG; + + #ifndef EXTRACT_ONLY + + if (name[0] == L's') + { + const wchar_t *s = name.Ptr(1); + if (*s == 0) + { + bool useStr = false; + bool isSolid; + switch (value.vt) + { + case VT_EMPTY: isSolid = true; break; + case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; + case VT_BSTR: + if (!StringToBool(value.bstrVal, isSolid)) + useStr = true; + break; + default: return E_INVALIDARG; + } + if (!useStr) + { + _numSolidBytes = (isSolid ? XZ_PROPS__BLOCK_SIZE__SOLID : XZ_PROPS__BLOCK_SIZE__AUTO); + return S_OK; + } + } + return ParseSizeString(s, value, + 0, // percentsBase + _numSolidBytes) ? S_OK: E_INVALIDARG; + } + + return CMultiMethodProps::SetProperty(name, value); + + #else + + { + HRESULT hres; + if (SetCommonProperty(name, value, hres)) + return hres; + } + + return E_INVALIDARG; + + #endif +} + + + +STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) +{ + COM_TRY_BEGIN + + Init(); + + for (UInt32 i = 0; i < numProps; i++) + { + RINOK(SetProperty(names[i], values[i])); + } + + #ifndef EXTRACT_ONLY + + if (!_filterMethod.MethodName.IsEmpty()) + { + unsigned k; + for (k = 0; k < ARRAY_SIZE(g_NamePairs); k++) + { + const CMethodNamePair &pair = g_NamePairs[k]; + if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) + { + _filterId = pair.Id; + break; + } + } + if (k == ARRAY_SIZE(g_NamePairs)) + return E_INVALIDARG; + } + + _methods.DeleteFrontal(GetNumEmptyMethods()); + if (_methods.Size() > 1) + return E_INVALIDARG; + if (_methods.Size() == 1) + { + AString &methodName = _methods[0].MethodName; + if (methodName.IsEmpty()) + methodName = k_LZMA2_Name; + else if ( + !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name) + && !methodName.IsEqualTo_Ascii_NoCase("xz")) + return E_INVALIDARG; + } + + #endif + + return S_OK; + + COM_TRY_END +} + + +REGISTER_ARC_IO( + "xz", "xz txz", "* .tar", 0xC, + XZ_SIG, + 0, + NArcInfoFlags::kKeepName, + NULL) + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.h b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.h new file mode 100644 index 0000000..24e8eeb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Archive/XzHandler.h @@ -0,0 +1,11 @@ +// XzHandler.h + +#ifndef __XZ_HANDLER_H +#define __XZ_HANDLER_H + +namespace NArchive { +namespace NXz { + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Asm.mak b/3rdparty/lzma-21.03beta/CPP/7zip/Asm.mak new file mode 100644 index 0000000..c4073e8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Asm.mak @@ -0,0 +1,9 @@ +!IFDEF ASM_OBJS +!IF "$(CPU)" == "ARM" +$(ASM_OBJS): ../../../../Asm/Arm/$(*B).asm + $(COMPL_ASM) +!ELSEIF "$(CPU)" != "IA64" && "$(CPU)" != "MIPS" && "$(CPU)" != "ARM64" +$(ASM_OBJS): ../../../../Asm/x86/$(*B).asm + $(COMPL_ASM) +!ENDIF +!ENDIF diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsp new file mode 100644 index 0000000..a15a5bf --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsp @@ -0,0 +1,1979 @@ +# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Alone - Win32 DebugU +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Alone.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") +!MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Alone - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gr /MT /W4 /WX /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseU" +# PROP BASE Intermediate_Dir "ReleaseU" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseU" +# PROP Intermediate_Dir "ReleaseU" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gr /MD /W4 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugU" +# PROP BASE Intermediate_Dir "DebugU" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugU" +# PROP Intermediate_Dir "DebugU" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /Gr /MDd /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "_7ZIP_LARGE_PAGES" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Alone - Win32 Release" +# Name "Alone - Win32 Debug" +# Name "Alone - Win32 ReleaseU" +# Name "Alone - Win32 DebugU" +# Begin Group "Console" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Console\ArError.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\BenchCon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\BenchCon.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\CompressionMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ExtractCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\HashCon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\HashCon.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\List.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\List.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\Main.cpp +# ADD CPP /D "PROG_VARIANT_R" +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\MainAr.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\OpenCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\PercentPrinter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\PercentPrinter.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UpdateCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UserInputUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UserInputUtils.h +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\AutoPtr.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\ComTry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\DynamicBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\ListFileUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\ListFileUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\LzFindPrepare.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyCom.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyException.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyGuidDef.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyInitGuid.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyUnknown.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Sha256Reg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Types.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\XzCrc64Init.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\XzCrc64Reg.cpp +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Device.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileLink.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileMapping.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileSystem.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileSystem.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Handle.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\MemoryLock.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\MemoryLock.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Thread.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\TimeUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\TimeUtils.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InOutTempBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InOutTempBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodId.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterArc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterCodec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\UniqBlocks.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Coder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Coder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\XzEncoder.h +# End Source File +# End Group +# Begin Group "Archive" + +# PROP Default_Filter "" +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\7z\7zCompressionMode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zEncode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zEncode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zFolderInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zProperties.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zSpecStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zUpdate.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\DummyOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ParseProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ParseProperties.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\LzmaHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\XzHandler.cpp +# End Source File +# End Group +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveCommandLine.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Bench.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Bench.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\EnumDirItems.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\EnumDirItems.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\HashCalc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\HashCalc.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Property.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\PropIDUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\SetProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\SetProperties.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\SortUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\SortUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\TempFiles.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\TempFiles.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Update.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Update.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateAction.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateAction.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdatePair.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdatePair.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateProduce.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\UpdateProduce.h +# End Source File +# End Group +# Begin Group "7-zip" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\IMyUnknown.h +# End Source File +# Begin Source File + +SOURCE=..\..\IPassword.h +# End Source File +# Begin Source File + +SOURCE=..\..\IProgress.h +# End Source File +# Begin Source File + +SOURCE=..\..\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\PropID.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Group "Xz" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Xz.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzCrc64Opt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzDec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\XzIn.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zStream.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\AesOpt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2Enc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindOpt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Enc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.c + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +# SUBTRACT CPP /YX /Yc /Yu + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Types.h +# End Source File +# End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAesRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAesReg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\RandGen.h +# End Source File +# End Group +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsw new file mode 100644 index 0000000..65eca43 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/Alone.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Alone"=.\Alone.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile new file mode 100644 index 0000000..0a68e14 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile @@ -0,0 +1,160 @@ +PROG = 7zr.exe + +# USE_C_AES = 1 + +CFLAGS = $(CFLAGS) -DPROG_VARIANT_R + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\CrcReg.obj \ + $O\IntToString.obj \ + $O\ListFileUtils.obj \ + $O\LzFindPrepare.obj \ + $O\NewHandler.obj \ + $O\StdInStream.obj \ + $O\StdOutStream.obj \ + $O\MyString.obj \ + $O\Sha256Reg.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\UTFConvert.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + $O\XzCrc64Init.obj \ + $O\XzCrc64Reg.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileLink.obj \ + $O\FileName.obj \ + $O\FileSystem.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConv.obj \ + $O\Registry.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\SystemInfo.obj \ + $O\TimeUtils.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\InBuffer.obj \ + $O\InOutTempBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\LzmaHandler.obj \ + $O\SplitHandler.obj \ + $O\XzHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\DummyOutStream.obj \ + $O\HandlerOut.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zEncode.obj \ + $O\7zExtract.obj \ + $O\7zFolderInStream.obj \ + $O\7zHandler.obj \ + $O\7zHandlerOut.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zOut.obj \ + $O\7zProperties.obj \ + $O\7zRegister.obj \ + $O\7zSpecStream.obj \ + $O\7zUpdate.obj \ + +COMPRESS_OBJS = \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + $O\XzDecoder.obj \ + $O\XzEncoder.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + $O\MyAesReg.obj \ + $O\RandGen.obj \ + +C_OBJS = \ + $O\7zStream.obj \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\MtDec.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + $O\Xz.obj \ + $O\XzDec.obj \ + $O\XzEnc.obj \ + $O\XzIn.obj \ + +!include "../../UI/Console/Console.mak" + +!include "../../Aes.mak" +!include "../../Crc.mak" +!include "../../Crc64.mak" +!include "../../LzFindOpt.mak" +!include "../../LzmaDec.mak" +!include "../../Sha256.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile.gcc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile.gcc new file mode 100644 index 0000000..c1d6ac5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/makefile.gcc @@ -0,0 +1,268 @@ +PROG = 7zr + +CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_R + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/LzFindMt.o \ + $O/LzFindOpt.o \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/Threads.o \ + + + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + $(LOCAL_FLAGS_SYS) \ + +# -D_LZMA_PROB32 + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/ListFileUtils.o \ + $O/LzFindPrepare.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/Sha256Prepare.o \ + $O/Sha256Reg.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + $O/XzCrc64Init.o \ + $O/XzCrc64Reg.o \ + +WIN_OBJS = \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileLink.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + $O/System.o \ + $O/SystemInfo.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +AR_OBJS = \ + $O/LzmaHandler.o \ + $O/SplitHandler.o \ + $O/XzHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/DummyOutStream.o \ + $O/HandlerOut.o \ + $O/InStreamWithCRC.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + $O/ParseProperties.o \ + +7Z_OBJS = \ + $O/7zCompressionMode.o \ + $O/7zDecode.o \ + $O/7zEncode.o \ + $O/7zExtract.o \ + $O/7zFolderInStream.o \ + $O/7zHandler.o \ + $O/7zHandlerOut.o \ + $O/7zHeader.o \ + $O/7zIn.o \ + $O/7zOut.o \ + $O/7zProperties.o \ + $O/7zRegister.o \ + $O/7zSpecStream.o \ + $O/7zUpdate.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/ByteSwap.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/DeltaFilter.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Encoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + $O/XzDecoder.o \ + $O/XzEncoder.o \ + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/MyAes.o \ + $O/MyAesReg.o \ + $O/RandGen.o \ + +C_OBJS = \ + $O/7zStream.o \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bcj2Enc.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/CpuArch.o \ + $O/Delta.o \ + $O/LzFind.o \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/Lzma2Enc.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/MtCoder.o \ + $O/MtDec.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/Sort.o \ + $O/Xz.o \ + $O/XzDec.o \ + $O/XzEnc.o \ + $O/XzIn.o \ + $O/XzCrc64.o \ + $O/XzCrc64Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/resource.rc new file mode 100644 index 0000000..5937850 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Alone7z/resource.rc @@ -0,0 +1,7 @@ +#include "../../../../C/7zVersion.rc" + +MY_VERSION_INFO_APP("7-Zip Reduced Standalone Console", "7zr") + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "../../UI/Console/Console.manifest" +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/makefile new file mode 100644 index 0000000..756c8ae --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/makefile @@ -0,0 +1,96 @@ +PROG = 7zxr.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) \ + -DEXTRACT_ONLY \ + -D_NO_CRYPTO + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\CrcReg.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\PropVariant.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\InBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\ArchiveExports.obj \ + $O\DllExports2.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\HandlerOut.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zHandler.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zProperties.obj \ + $O\7zRegister.obj \ + + +COMPRESS_OBJS = \ + $O\CodecExports.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\LzmaDec.obj \ + $O\MtDec.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" +!include "../../LzmaDec.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/resource.rc new file mode 100644 index 0000000..149f58c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zExtractR/resource.rc @@ -0,0 +1,5 @@ +#include "../../../../C/7zVersion.rc" + +MY_VERSION_INFO_DLL("7z Extracting Reduced Standalone Plugin", "7zxr") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/makefile new file mode 100644 index 0000000..c223715 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/makefile @@ -0,0 +1,118 @@ +PROG = 7zra.dll +DEF_FILE = ../../Archive/Archive2.def +CFLAGS = $(CFLAGS) \ + -D_NO_CRYPTO + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\CrcReg.obj \ + $O\IntToString.obj \ + $O\LzFindPrepare.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\InBuffer.obj \ + $O\InOutTempBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\MethodId.obj \ + $O\MethodProps.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ + $O\VirtThread.obj \ + +AR_OBJS = \ + $O\ArchiveExports.obj \ + $O\DllExports2.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\HandlerOut.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + + +7Z_OBJS = \ + $O\7zCompressionMode.obj \ + $O\7zDecode.obj \ + $O\7zEncode.obj \ + $O\7zExtract.obj \ + $O\7zFolderInStream.obj \ + $O\7zHandler.obj \ + $O\7zHandlerOut.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zOut.obj \ + $O\7zProperties.obj \ + $O\7zSpecStream.obj \ + $O\7zUpdate.obj \ + $O\7zRegister.obj \ + + +COMPRESS_OBJS = \ + $O\CodecExports.obj \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\ByteSwap.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Encoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bcj2Enc.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\Lzma2Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\MtCoder.obj \ + $O\MtDec.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" +!include "../../LzFindOpt.mak" +!include "../../LzmaDec.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/resource.rc new file mode 100644 index 0000000..a8baa59 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/Format7zR/resource.rc @@ -0,0 +1,5 @@ +#include "../../../../C/7zVersion.rc" + +MY_VERSION_INFO_DLL("7z Reduced Standalone Plugin", "7zr") + +101 ICON "../../Archive/Icons/7z.ico" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp new file mode 100644 index 0000000..a08d9c0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp @@ -0,0 +1,810 @@ +// LzmaAlone.cpp + +#include "StdAfx.h" + +// #include + +#include "../../../../C/CpuArch.h" + +#if (defined(_WIN32) || defined(OS2) || defined(MSDOS)) && !defined(UNDER_CE) +#include +#include +#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) +#else +#define MY_SET_BINARY_MODE(file) +#endif + +#include "../../../Common/MyWindows.h" +#include "../../../Common/MyInitGuid.h" + +#include "../../../../C/7zVersion.h" +#include "../../../../C/Alloc.h" +#include "../../../../C/Lzma86.h" + +#include "../../../Windows/NtCheck.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/System.h" +#endif + +#include "../../../Common/IntToString.h" +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/LzmaDecoder.h" +#include "../../Compress/LzmaEncoder.h" + +#include "../../UI/Console/BenchCon.h" +#include "../../UI/Console/ConsoleClose.h" + +bool g_LargePagesMode = false; + +using namespace NCommandLineParser; + +static const unsigned kDictSizeLog = 24; + +#define kCopyrightString "\nLZMA " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n" + +static const char * const kHelpString = + "Usage: lzma [inputFile] [outputFile] [...]\n" + "\n" + "\n" + " e : Encode file\n" + " d : Decode file\n" + " b : Benchmark\n" + "\n" + " -a{N} : set compression mode : [0, 1] : default = 1 (max)\n" + " -d{N} : set dictionary size : [12, 30] : default = 24 (16 MiB)\n" + " -fb{N} : set number of fast bytes : [5, 273] : default = 128\n" + " -mc{N} : set number of cycles for match finder\n" + " -lc{N} : set number of literal context bits : [0, 8] : default = 3\n" + " -lp{N} : set number of literal pos bits : [0, 4] : default = 0\n" + " -pb{N} : set number of pos bits : [0, 4] : default = 2\n" + " -mf{M} : set match finder: [hc4, bt2, bt3, bt4] : default = bt4\n" + " -mt{N} : set number of CPU threads\n" + " -eos : write end of stream marker\n" + " -si : read data from stdin\n" + " -so : write data to stdout\n"; + + +static const char * const kCantAllocate = "Cannot allocate memory"; +static const char * const kReadError = "Read error"; +static const char * const kWriteError = "Write error"; + + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kMethod, + kLevel, + kAlgo, + kDict, + kFb, + kMc, + kLc, + kLp, + kPb, + kMatchFinder, + kMultiThread, + kEOS, + kStdIn, + kStdOut, + kFilter86 +}; +} + +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL + +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_STRING SWFRM_1(NSwitchType::kString) + +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) + +static const CSwitchForm kSwitchForms[] = +{ + { "?", SWFRM_SIMPLE }, + { "H", SWFRM_SIMPLE }, + { "MM", SWFRM_STRING_SINGL(1) }, + { "X", SWFRM_STRING_SINGL(1) }, + { "A", SWFRM_STRING_SINGL(1) }, + { "D", SWFRM_STRING_SINGL(1) }, + { "FB", SWFRM_STRING_SINGL(1) }, + { "MC", SWFRM_STRING_SINGL(1) }, + { "LC", SWFRM_STRING_SINGL(1) }, + { "LP", SWFRM_STRING_SINGL(1) }, + { "PB", SWFRM_STRING_SINGL(1) }, + { "MF", SWFRM_STRING_SINGL(1) }, + { "MT", SWFRM_STRING }, + { "EOS", SWFRM_SIMPLE }, + { "SI", SWFRM_SIMPLE }, + { "SO", SWFRM_SIMPLE }, + { "F86", NSwitchType::kChar, false, 0, "+" } +}; + + +static void Convert_UString_to_AString(const UString &s, AString &temp) +{ + int codePage = CP_OEMCP; + /* + int g_CodePage = -1; + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + */ + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); +} + +static void PrintErr(const char *s) +{ + fputs(s, stderr); +} + +static void PrintErr_LF(const char *s) +{ + PrintErr(s); + fputc('\n', stderr); +} + + +static void PrintError(const char *s) +{ + PrintErr("\nERROR: "); + PrintErr_LF(s); +} + +static void PrintError2(const char *s1, const UString &s2) +{ + PrintError(s1); + AString a; + Convert_UString_to_AString(s2, a); + PrintErr_LF(a); +} + +static void PrintError_int(const char *s, int code) +{ + PrintError(s); + char temp[32]; + ConvertInt64ToString(code, temp); + PrintErr("Error code = "); + PrintErr_LF(temp); +} + + + +static void Print(const char *s) +{ + fputs(s, stdout); +} + +static void Print_UInt64(UInt64 v) +{ + char temp[32]; + ConvertUInt64ToString(v, temp); + Print(temp); +} + +static void Print_MB(UInt64 v) +{ + Print_UInt64(v); + Print(" MiB"); +} + +static void Print_Size(const char *s, UInt64 v) +{ + Print(s); + Print_UInt64(v); + Print(" ("); + Print_MB(v >> 20); + Print(")\n"); +} + +static void PrintTitle() +{ + Print(kCopyrightString); +} + +static void PrintHelp() +{ + PrintTitle(); + Print(kHelpString); +} + +class CProgressPrint: + public ICompressProgressInfo, + public CMyUnknownImp +{ + UInt64 _size1; + UInt64 _size2; +public: + CProgressPrint(): _size1(0), _size2(0) {} + + void ClosePrint(); + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#define BACK_STR \ +"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" +static const char * const kBackSpaces = +BACK_STR +" " +BACK_STR; + + +void CProgressPrint::ClosePrint() +{ + Print(kBackSpaces); +} + +STDMETHODIMP CProgressPrint::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + if (inSize) + { + UInt64 v1 = *inSize >> 20; + UInt64 v2 = _size2; + if (outSize) + v2 = *outSize >> 20; + if (v1 != _size1 || v2 != _size2) + { + _size1 = v1; + _size2 = v2; + ClosePrint(); + Print_MB(_size1); + Print(" -> "); + Print_MB(_size2); + } + } + return S_OK; +} + + +MY_ATTR_NORETURN +static void IncorrectCommand() +{ + throw "Incorrect command"; +} + +static UInt32 GetNumber(const wchar_t *s) +{ + const wchar_t *end; + UInt32 v = ConvertStringToUInt32(s, &end); + if (*end != 0) + IncorrectCommand(); + return v; +} + +static void ParseUInt32(const CParser &parser, unsigned index, UInt32 &res) +{ + if (parser[index].ThereIs) + res = GetNumber(parser[index].PostStrings[0]); +} + + +static int Error_HRESULT(const char *s, HRESULT res) +{ + if (res == E_ABORT) + { + Print("\n\nBreak signaled\n"); + return 255; + } + + PrintError(s); + + if (res == E_OUTOFMEMORY) + { + PrintErr_LF(kCantAllocate); + return 8; + } + if (res == E_INVALIDARG) + { + PrintErr_LF("Ununsupported parameter"); + } + else + { + char temp[32]; + ConvertUInt32ToHex(res, temp); + PrintErr("Error code = 0x"); + PrintErr_LF(temp); + } + return 1; +} + +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; +#endif + +static void AddProp(CObjectVector &props2, const char *name, const wchar_t *val) +{ + CProperty &prop = props2.AddNew(); + prop.Name = name; + prop.Value = val; +} + +static int main2(int numArgs, const char *args[]) +{ + NT_CHECK + + if (numArgs == 1) + { + PrintHelp(); + return 0; + } + + /* + bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 8); + if (unsupportedTypes) + throw "Unsupported base types. Edit Common/Types.h and recompile"; + */ + + UStringVector commandStrings; + for (int i = 1; i < numArgs; i++) + commandStrings.Add(MultiByteToUnicodeString(args[i])); + + CParser parser; + try + { + if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings)) + { + PrintError2(parser.ErrorMessage, parser.ErrorLine); + return 1; + } + } + catch(...) + { + IncorrectCommand(); + } + + if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + { + PrintHelp(); + return 0; + } + + bool stdInMode = parser[NKey::kStdIn].ThereIs; + bool stdOutMode = parser[NKey::kStdOut].ThereIs; + + if (!stdOutMode) + PrintTitle(); + + const UStringVector ¶ms = parser.NonSwitchStrings; + + unsigned paramIndex = 0; + if (paramIndex >= params.Size()) + IncorrectCommand(); + const UString &command = params[paramIndex++]; + + CObjectVector props2; + bool dictDefined = false; + UInt32 dict = (UInt32)(Int32)-1; + + if (parser[NKey::kDict].ThereIs) + { + UInt32 dictLog; + const UString &s = parser[NKey::kDict].PostStrings[0]; + dictLog = GetNumber(s); + dict = 1 << dictLog; + dictDefined = true; + AddProp(props2, "d", s); + } + + if (parser[NKey::kLevel].ThereIs) + { + const UString &s = parser[NKey::kLevel].PostStrings[0]; + /* UInt32 level = */ GetNumber(s); + AddProp(props2, "x", s); + } + + UString mf ("BT4"); + if (parser[NKey::kMatchFinder].ThereIs) + mf = parser[NKey::kMatchFinder].PostStrings[0]; + + UInt32 numThreads = (UInt32)(Int32)-1; + + #ifndef _7ZIP_ST + + if (parser[NKey::kMultiThread].ThereIs) + { + const UString &s = parser[NKey::kMultiThread].PostStrings[0]; + if (s.IsEmpty()) + numThreads = NWindows::NSystem::GetNumberOfProcessors(); + else + numThreads = GetNumber(s); + AddProp(props2, "mt", s); + } + + #endif + + + if (parser[NKey::kMethod].ThereIs) + { + const UString &s = parser[NKey::kMethod].PostStrings[0]; + if (s.IsEmpty() || s[0] != '=') + IncorrectCommand(); + AddProp(props2, "m", s.Ptr(1)); + } + + if (StringsAreEqualNoCase_Ascii(command, "b")) + { + UInt32 numIterations = 1; + if (paramIndex < params.Size()) + numIterations = GetNumber(params[paramIndex++]); + if (params.Size() != paramIndex) + IncorrectCommand(); + + HRESULT res = BenchCon(props2, numIterations, stdout); + + if (res == S_OK) + return 0; + return Error_HRESULT("Benchmark error", res); + } + + { + UInt32 needParams = 3; + if (stdInMode) needParams--; + if (stdOutMode) needParams--; + if (needParams != params.Size()) + IncorrectCommand(); + } + + if (numThreads == (UInt32)(Int32)-1) + numThreads = 1; + + bool encodeMode = false; + + if (StringsAreEqualNoCase_Ascii(command, "e")) + encodeMode = true; + else if (!StringsAreEqualNoCase_Ascii(command, "d")) + IncorrectCommand(); + + CMyComPtr inStream; + CInFileStream *inStreamSpec = NULL; + + if (stdInMode) + { + inStream = new CStdInFileStream; + MY_SET_BINARY_MODE(stdin); + } + else + { + const UString &inputName = params[paramIndex++]; + inStreamSpec = new CInFileStream; + inStream = inStreamSpec; + if (!inStreamSpec->Open(us2fs(inputName))) + { + PrintError2("Cannot open input file", inputName); + return 1; + } + } + + CMyComPtr outStream; + COutFileStream *outStreamSpec = NULL; + + if (stdOutMode) + { + outStream = new CStdOutFileStream; + MY_SET_BINARY_MODE(stdout); + } + else + { + const UString &outputName = params[paramIndex++]; + outStreamSpec = new COutFileStream; + outStream = outStreamSpec; + if (!outStreamSpec->Create(us2fs(outputName), true)) + { + PrintError2("Cannot open output file", outputName); + return 1; + } + } + + bool fileSizeDefined = false; + UInt64 fileSize = 0; + + if (inStreamSpec) + { + if (!inStreamSpec->File.GetLength(fileSize)) + throw "Cannot get file length"; + fileSizeDefined = true; + if (!stdOutMode) + Print_Size("Input size: ", fileSize); + } + + if (encodeMode && !dictDefined) + { + dict = 1 << kDictSizeLog; + if (fileSizeDefined) + { + unsigned i; + for (i = 16; i < kDictSizeLog; i++) + if ((UInt32)((UInt32)1 << i) >= fileSize) + break; + dict = (UInt32)1 << i; + } + } + + if (parser[NKey::kFilter86].ThereIs) + { + /* -f86 switch is for x86 filtered mode: BCJ + LZMA. + It uses modified header format. + It's not recommended to use -f86 mode now. + You can use xz format instead, if you want to use filters */ + + if (parser[NKey::kEOS].ThereIs || stdInMode) + throw "Cannot use stdin in this mode"; + + size_t inSize = (size_t)fileSize; + + if (inSize != fileSize) + throw "File is too big"; + + Byte *inBuffer = NULL; + + if (inSize != 0) + { + inBuffer = (Byte *)MyAlloc((size_t)inSize); + if (!inBuffer) + throw kCantAllocate; + } + + if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) + throw "Cannot read"; + + Byte *outBuffer = NULL; + size_t outSize; + + if (encodeMode) + { + // we allocate 105% of original size for output buffer + UInt64 outSize64 = fileSize / 20 * 21 + (1 << 16); + + outSize = (size_t)outSize64; + + if (outSize != outSize64) + throw "File is too big"; + + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc((size_t)outSize); + if (!outBuffer) + throw kCantAllocate; + } + + int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, + 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); + + if (res != 0) + { + PrintError_int("Encode error", (int)res); + return 1; + } + } + else + { + UInt64 outSize64; + + if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) + throw "data error"; + + outSize = (size_t)outSize64; + if (outSize != outSize64) + throw "Unpack size is too big"; + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc(outSize); + if (!outBuffer) + throw kCantAllocate; + } + + int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); + + if (inSize != (size_t)fileSize) + throw "incorrect processed size"; + if (res != 0) + { + PrintError_int("Decode error", (int)res); + return 1; + } + } + + if (WriteStream(outStream, outBuffer, outSize) != S_OK) + throw kWriteError; + + MyFree(outBuffer); + MyFree(inBuffer); + } + else + { + + CProgressPrint *progressSpec = NULL; + CMyComPtr progress; + + if (!stdOutMode) + { + progressSpec = new CProgressPrint; + progress = progressSpec; + } + + if (encodeMode) + { + NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; + CMyComPtr encoder = encoderSpec; + + UInt32 pb = 2; + UInt32 lc = 3; // = 0; for 32-bit data + UInt32 lp = 0; // = 2; for 32-bit data + UInt32 algo = 1; + UInt32 fb = 128; + UInt32 mc = 16 + fb / 2; + bool mcDefined = false; + + bool eos = parser[NKey::kEOS].ThereIs || stdInMode; + + ParseUInt32(parser, NKey::kAlgo, algo); + ParseUInt32(parser, NKey::kFb, fb); + ParseUInt32(parser, NKey::kLc, lc); + ParseUInt32(parser, NKey::kLp, lp); + ParseUInt32(parser, NKey::kPb, pb); + + mcDefined = parser[NKey::kMc].ThereIs; + if (mcDefined) + mc = GetNumber(parser[NKey::kMc].PostStrings[0]); + + const PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker, + NCoderPropID::kNumThreads, + NCoderPropID::kMatchFinderCycles, + }; + + const unsigned kNumPropsMax = ARRAY_SIZE(propIDs); + + PROPVARIANT props[kNumPropsMax]; + for (int p = 0; p < 6; p++) + props[p].vt = VT_UI4; + + props[0].ulVal = (UInt32)dict; + props[1].ulVal = (UInt32)pb; + props[2].ulVal = (UInt32)lc; + props[3].ulVal = (UInt32)lp; + props[4].ulVal = (UInt32)algo; + props[5].ulVal = (UInt32)fb; + + props[6].vt = VT_BSTR; + props[6].bstrVal = const_cast((const wchar_t *)mf); + + props[7].vt = VT_BOOL; + props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; + + props[8].vt = VT_UI4; + props[8].ulVal = (UInt32)numThreads; + + // it must be last in property list + props[9].vt = VT_UI4; + props[9].ulVal = (UInt32)mc; + + unsigned numProps = kNumPropsMax; + if (!mcDefined) + numProps--; + + HRESULT res = encoderSpec->SetCoderProperties(propIDs, props, numProps); + if (res != S_OK) + return Error_HRESULT("incorrect encoder properties", res); + + if (encoderSpec->WriteCoderProperties(outStream) != S_OK) + throw kWriteError; + + bool fileSizeWasUsed = true; + if (eos || stdInMode) + { + fileSize = (UInt64)(Int64)-1; + fileSizeWasUsed = false; + } + + { + Byte temp[8]; + for (int i = 0; i < 8; i++) + temp[i]= (Byte)(fileSize >> (8 * i)); + if (WriteStream(outStream, temp, 8) != S_OK) + throw kWriteError; + } + + res = encoder->Code(inStream, outStream, NULL, NULL, progress); + if (progressSpec) + progressSpec->ClosePrint(); + + if (res != S_OK) + return Error_HRESULT("Encoding error", res); + + UInt64 processedSize = encoderSpec->GetInputProcessedSize(); + + if (fileSizeWasUsed && processedSize != fileSize) + throw "Incorrect size of processed data"; + } + else + { + NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; + CMyComPtr decoder = decoderSpec; + + decoderSpec->FinishStream = true; + + const unsigned kPropertiesSize = 5; + Byte header[kPropertiesSize + 8]; + + if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) + throw kReadError; + + if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) + throw "SetDecoderProperties error"; + + UInt64 unpackSize = 0; + for (int i = 0; i < 8; i++) + unpackSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); + + bool unpackSizeDefined = (unpackSize != (UInt64)(Int64)-1); + + HRESULT res = decoder->Code(inStream, outStream, NULL, unpackSizeDefined ? &unpackSize : NULL, progress); + if (progressSpec) + progressSpec->ClosePrint(); + + if (res != S_OK) + { + if (res == S_FALSE) + { + PrintError("Decoding error"); + return 1; + } + return Error_HRESULT("Decoding error", res); + } + + if (unpackSizeDefined && unpackSize != decoderSpec->GetOutputProcessedSize()) + throw "incorrect uncompressed size in header"; + } + } + + if (outStreamSpec) + { + if (!stdOutMode) + Print_Size("Output size: ", outStreamSpec->ProcessedSize); + if (outStreamSpec->Close() != S_OK) + throw "File closing error"; + } + + return 0; +} + +int MY_CDECL main(int numArgs, const char *args[]) +{ + NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; + + try { return main2(numArgs, args); } + catch (const char *s) + { + PrintError(s); + return 1; + } + catch(...) + { + PrintError("Unknown Error"); + return 1; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp new file mode 100644 index 0000000..d7326ef --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsp @@ -0,0 +1,510 @@ +# Microsoft Developer Studio Project File - Name="LzmaCon" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=LzmaCon - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LzmaCon.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LzmaCon.mak" CFG="LzmaCon - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaCon - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "LzmaCon - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaCon - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gr /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\lzma.exe" + +!ELSEIF "$(CFG)" == "LzmaCon - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\lzma.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaCon - Win32 Release" +# Name "LzmaCon - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaEncoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Registry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\SystemInfo.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Thread.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\ComTry.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CrcReg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\LzFindPrepare.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyCom.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyUnknown.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Types.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MethodProps.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Common\Bench.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Bench.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.h +# End Source File +# End Group +# Begin Group "Console" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Console\BenchCon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\BenchCon.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzFindOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma86.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma86Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma86Enc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\LzmaAlone.cpp +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw new file mode 100644 index 0000000..e62c9d2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/LzmaCon.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaCon"=.\LzmaCon.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile new file mode 100644 index 0000000..5e53327 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile @@ -0,0 +1,63 @@ +PROG = lzma.exe +MY_CONSOLE = 1 + +CURRENT_OBJS = \ + $O\LzmaAlone.obj \ + +COMPRESS_OBJS = \ + $O\LzmaDecoder.obj \ + $O\LzmaEncoder.obj \ + $O\LzmaRegister.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\CrcReg.obj \ + $O\IntToString.obj \ + $O\LzFindPrepare.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\NewHandler.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + +WIN_OBJS = \ + $O\FileIO.obj \ + $O\PropVariant.obj \ + $O\Registry.obj \ + $O\System.obj \ + $O\SystemInfo.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\MethodProps.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + +UI_COMMON_OBJS = \ + $O\Bench.obj \ + +CONSOLE_OBJS = \ + $O\ConsoleClose.obj \ + $O\BenchCon.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\Lzma86Dec.obj \ + $O\Lzma86Enc.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" +!include "../../LzFindOpt.mak" +!include "../../LzmaDec.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile.gcc new file mode 100644 index 0000000..58c204a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/makefile.gcc @@ -0,0 +1,116 @@ +PROG = lzma + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +else + +MT_OBJS = \ + $O/LzFindMt.o \ + $O/LzFindOpt.o \ + $O/Synchronization.o \ + $O/Threads.o \ + + + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +SYS_OBJS = \ + $O/Registry.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileName.o \ + $O/MyWindows.o \ + $O/TimeUtils.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/LzFindPrepare.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + +WIN_OBJS = \ + $O/FileIO.o \ + $O/PropVariant.o \ + $O/System.o \ + $O/SystemInfo.o \ + +COMPRESS_OBJS = \ + $O/LzmaDecoder.o \ + $O/LzmaEncoder.o \ + $O/LzmaRegister.o \ + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FileStreams.o \ + $O/FilterCoder.o \ + $O/MethodProps.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + +C_OBJS = \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Alloc.o \ + $O/Bra86.o \ + $O/CpuArch.o \ + $O/LzFind.o \ + $O/LzmaDec.o \ + $O/LzmaEnc.o \ + $O/Lzma86Dec.o \ + $O/Lzma86Enc.o \ + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + $O/LzmaAlone.o \ + $O/Bench.o \ + +include ../../7zip_gcc.mak diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/resource.rc new file mode 100644 index 0000000..43b5073 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaCon/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("LZMA", "lzma") diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp new file mode 100644 index 0000000..8e0f9b9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/LzmaSpec/LzmaSpec.cpp @@ -0,0 +1,715 @@ +/* LzmaSpec.cpp -- LZMA Reference Decoder +2015-06-14 : Igor Pavlov : Public domain */ + +// This code implements LZMA file decoding according to LZMA specification. +// This code is not optimized for speed. + +#include + +#ifdef _MSC_VER + #pragma warning(disable : 4710) // function not inlined + #pragma warning(disable : 4996) // This function or variable may be unsafe +#endif + +typedef unsigned char Byte; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG + typedef unsigned long UInt32; +#else + typedef unsigned int UInt32; +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 UInt64; +#else + typedef unsigned long long int UInt64; +#endif + + +struct CInputStream +{ + FILE *File; + UInt64 Processed; + + void Init() { Processed = 0; } + + Byte ReadByte() + { + int c = getc(File); + if (c < 0) + throw "Unexpected end of file"; + Processed++; + return (Byte)c; + } +}; + + +struct COutStream +{ + FILE *File; + UInt64 Processed; + + void Init() { Processed = 0; } + + void WriteByte(Byte b) + { + if (putc(b, File) == EOF) + throw "File writing error"; + Processed++; + } +}; + + +class COutWindow +{ + Byte *Buf; + UInt32 Pos; + UInt32 Size; + bool IsFull; + +public: + unsigned TotalPos; + COutStream OutStream; + + COutWindow(): Buf(NULL) {} + ~COutWindow() { delete []Buf; } + + void Create(UInt32 dictSize) + { + Buf = new Byte[dictSize]; + Pos = 0; + Size = dictSize; + IsFull = false; + TotalPos = 0; + } + + void PutByte(Byte b) + { + TotalPos++; + Buf[Pos++] = b; + if (Pos == Size) + { + Pos = 0; + IsFull = true; + } + OutStream.WriteByte(b); + } + + Byte GetByte(UInt32 dist) const + { + return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos]; + } + + void CopyMatch(UInt32 dist, unsigned len) + { + for (; len > 0; len--) + PutByte(GetByte(dist)); + } + + bool CheckDistance(UInt32 dist) const + { + return dist <= Pos || IsFull; + } + + bool IsEmpty() const + { + return Pos == 0 && !IsFull; + } +}; + + +#define kNumBitModelTotalBits 11 +#define kNumMoveBits 5 + +typedef UInt16 CProb; + +#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2) + +#define INIT_PROBS(p) \ + { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; } + +class CRangeDecoder +{ + UInt32 Range; + UInt32 Code; + + void Normalize(); + +public: + + CInputStream *InStream; + bool Corrupted; + + bool Init(); + bool IsFinishedOK() const { return Code == 0; } + + UInt32 DecodeDirectBits(unsigned numBits); + unsigned DecodeBit(CProb *prob); +}; + +bool CRangeDecoder::Init() +{ + Corrupted = false; + Range = 0xFFFFFFFF; + Code = 0; + + Byte b = InStream->ReadByte(); + + for (int i = 0; i < 4; i++) + Code = (Code << 8) | InStream->ReadByte(); + + if (b != 0 || Code == Range) + Corrupted = true; + return b == 0; +} + +#define kTopValue ((UInt32)1 << 24) + +void CRangeDecoder::Normalize() +{ + if (Range < kTopValue) + { + Range <<= 8; + Code = (Code << 8) | InStream->ReadByte(); + } +} + +UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits) +{ + UInt32 res = 0; + do + { + Range >>= 1; + Code -= Range; + UInt32 t = 0 - ((UInt32)Code >> 31); + Code += Range & t; + + if (Code == Range) + Corrupted = true; + + Normalize(); + res <<= 1; + res += t + 1; + } + while (--numBits); + return res; +} + +unsigned CRangeDecoder::DecodeBit(CProb *prob) +{ + unsigned v = *prob; + UInt32 bound = (Range >> kNumBitModelTotalBits) * v; + unsigned symbol; + if (Code < bound) + { + v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits; + Range = bound; + symbol = 0; + } + else + { + v -= v >> kNumMoveBits; + Code -= bound; + Range -= bound; + symbol = 1; + } + *prob = (CProb)v; + Normalize(); + return symbol; +} + + +unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc) +{ + unsigned m = 1; + unsigned symbol = 0; + for (unsigned i = 0; i < numBits; i++) + { + unsigned bit = rc->DecodeBit(&probs[m]); + m <<= 1; + m += bit; + symbol |= (bit << i); + } + return symbol; +} + +template +class CBitTreeDecoder +{ + CProb Probs[(unsigned)1 << NumBits]; + +public: + + void Init() + { + INIT_PROBS(Probs); + } + + unsigned Decode(CRangeDecoder *rc) + { + unsigned m = 1; + for (unsigned i = 0; i < NumBits; i++) + m = (m << 1) + rc->DecodeBit(&Probs[m]); + return m - ((unsigned)1 << NumBits); + } + + unsigned ReverseDecode(CRangeDecoder *rc) + { + return BitTreeReverseDecode(Probs, NumBits, rc); + } +}; + +#define kNumPosBitsMax 4 + +#define kNumStates 12 +#define kNumLenToPosStates 4 +#define kNumAlignBits 4 +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) +#define kMatchMinLen 2 + +class CLenDecoder +{ + CProb Choice; + CProb Choice2; + CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax]; + CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax]; + CBitTreeDecoder<8> HighCoder; + +public: + + void Init() + { + Choice = PROB_INIT_VAL; + Choice2 = PROB_INIT_VAL; + HighCoder.Init(); + for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++) + { + LowCoder[i].Init(); + MidCoder[i].Init(); + } + } + + unsigned Decode(CRangeDecoder *rc, unsigned posState) + { + if (rc->DecodeBit(&Choice) == 0) + return LowCoder[posState].Decode(rc); + if (rc->DecodeBit(&Choice2) == 0) + return 8 + MidCoder[posState].Decode(rc); + return 16 + HighCoder.Decode(rc); + } +}; + +unsigned UpdateState_Literal(unsigned state) +{ + if (state < 4) return 0; + else if (state < 10) return state - 3; + else return state - 6; +} +unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; } +unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; } +unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; } + +#define LZMA_DIC_MIN (1 << 12) + +class CLzmaDecoder +{ +public: + CRangeDecoder RangeDec; + COutWindow OutWindow; + + bool markerIsMandatory; + unsigned lc, pb, lp; + UInt32 dictSize; + UInt32 dictSizeInProperties; + + void DecodeProperties(const Byte *properties) + { + unsigned d = properties[0]; + if (d >= (9 * 5 * 5)) + throw "Incorrect LZMA properties"; + lc = d % 9; + d /= 9; + pb = d / 5; + lp = d % 5; + dictSizeInProperties = 0; + for (int i = 0; i < 4; i++) + dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i); + dictSize = dictSizeInProperties; + if (dictSize < LZMA_DIC_MIN) + dictSize = LZMA_DIC_MIN; + } + + CLzmaDecoder(): LitProbs(NULL) {} + ~CLzmaDecoder() { delete []LitProbs; } + + void Create() + { + OutWindow.Create(dictSize); + CreateLiterals(); + } + + int Decode(bool unpackSizeDefined, UInt64 unpackSize); + +private: + + CProb *LitProbs; + + void CreateLiterals() + { + LitProbs = new CProb[(UInt32)0x300 << (lc + lp)]; + } + + void InitLiterals() + { + UInt32 num = (UInt32)0x300 << (lc + lp); + for (UInt32 i = 0; i < num; i++) + LitProbs[i] = PROB_INIT_VAL; + } + + void DecodeLiteral(unsigned state, UInt32 rep0) + { + unsigned prevByte = 0; + if (!OutWindow.IsEmpty()) + prevByte = OutWindow.GetByte(1); + + unsigned symbol = 1; + unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc)); + CProb *probs = &LitProbs[(UInt32)0x300 * litState]; + + if (state >= 7) + { + unsigned matchByte = OutWindow.GetByte(rep0 + 1); + do + { + unsigned matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + break; + } + while (symbol < 0x100); + } + while (symbol < 0x100) + symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]); + OutWindow.PutByte((Byte)(symbol - 0x100)); + } + + CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates]; + CBitTreeDecoder AlignDecoder; + CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex]; + + void InitDist() + { + for (unsigned i = 0; i < kNumLenToPosStates; i++) + PosSlotDecoder[i].Init(); + AlignDecoder.Init(); + INIT_PROBS(PosDecoders); + } + + unsigned DecodeDistance(unsigned len) + { + unsigned lenState = len; + if (lenState > kNumLenToPosStates - 1) + lenState = kNumLenToPosStates - 1; + + unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); + if (posSlot < 4) + return posSlot; + + unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1); + UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec); + else + { + dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits; + dist += AlignDecoder.ReverseDecode(&RangeDec); + } + return dist; + } + + CProb IsMatch[kNumStates << kNumPosBitsMax]; + CProb IsRep[kNumStates]; + CProb IsRepG0[kNumStates]; + CProb IsRepG1[kNumStates]; + CProb IsRepG2[kNumStates]; + CProb IsRep0Long[kNumStates << kNumPosBitsMax]; + + CLenDecoder LenDecoder; + CLenDecoder RepLenDecoder; + + void Init() + { + InitLiterals(); + InitDist(); + + INIT_PROBS(IsMatch); + INIT_PROBS(IsRep); + INIT_PROBS(IsRepG0); + INIT_PROBS(IsRepG1); + INIT_PROBS(IsRepG2); + INIT_PROBS(IsRep0Long); + + LenDecoder.Init(); + RepLenDecoder.Init(); + } +}; + + +#define LZMA_RES_ERROR 0 +#define LZMA_RES_FINISHED_WITH_MARKER 1 +#define LZMA_RES_FINISHED_WITHOUT_MARKER 2 + +int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize) +{ + if (!RangeDec.Init()) + return LZMA_RES_ERROR; + + Init(); + + UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + unsigned state = 0; + + for (;;) + { + if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory) + if (RangeDec.IsFinishedOK()) + return LZMA_RES_FINISHED_WITHOUT_MARKER; + + unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); + + if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0) + { + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + DecodeLiteral(state, rep0); + state = UpdateState_Literal(state); + unpackSize--; + continue; + } + + unsigned len; + + if (RangeDec.DecodeBit(&IsRep[state]) != 0) + { + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + if (OutWindow.IsEmpty()) + return LZMA_RES_ERROR; + if (RangeDec.DecodeBit(&IsRepG0[state]) == 0) + { + if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0) + { + state = UpdateState_ShortRep(state); + OutWindow.PutByte(OutWindow.GetByte(rep0 + 1)); + unpackSize--; + continue; + } + } + else + { + UInt32 dist; + if (RangeDec.DecodeBit(&IsRepG1[state]) == 0) + dist = rep1; + else + { + if (RangeDec.DecodeBit(&IsRepG2[state]) == 0) + dist = rep2; + else + { + dist = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = dist; + } + len = RepLenDecoder.Decode(&RangeDec, posState); + state = UpdateState_Rep(state); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = LenDecoder.Decode(&RangeDec, posState); + state = UpdateState_Match(state); + rep0 = DecodeDistance(len); + if (rep0 == 0xFFFFFFFF) + return RangeDec.IsFinishedOK() ? + LZMA_RES_FINISHED_WITH_MARKER : + LZMA_RES_ERROR; + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0)) + return LZMA_RES_ERROR; + } + len += kMatchMinLen; + bool isError = false; + if (unpackSizeDefined && unpackSize < len) + { + len = (unsigned)unpackSize; + isError = true; + } + OutWindow.CopyMatch(rep0 + 1, len); + unpackSize -= len; + if (isError) + return LZMA_RES_ERROR; + } +} + +static void Print(const char *s) +{ + fputs(s, stdout); +} + +static void PrintError(const char *s) +{ + fputs(s, stderr); +} + + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + +void ConvertUInt64ToString(UInt64 val, char *s) +{ + char temp[32]; + unsigned i = 0; + while (val >= 10) + { + temp[i++] = (char)('0' + (unsigned)(val % 10)); + val /= 10; + } + *s++ = (char)('0' + (unsigned)val); + while (i != 0) + { + i--; + *s++ = temp[i]; + } + *s = 0; +} + +void PrintUInt64(const char *title, UInt64 v) +{ + Print(title); + Print(" : "); + char s[32]; + ConvertUInt64ToString(v, s); + Print(s); + Print(" bytes \n"); +} + +int main2(int numArgs, const char *args[]) +{ + Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n"); + if (numArgs == 1) + Print("\nUse: lzmaSpec a.lzma outFile"); + + if (numArgs != 3) + throw "you must specify two parameters"; + + CInputStream inStream; + inStream.File = fopen(args[1], "rb"); + inStream.Init(); + if (inStream.File == 0) + throw "Can't open input file"; + + CLzmaDecoder lzmaDecoder; + lzmaDecoder.OutWindow.OutStream.File = fopen(args[2], "wb+"); + lzmaDecoder.OutWindow.OutStream.Init(); + if (inStream.File == 0) + throw "Can't open output file"; + + Byte header[13]; + int i; + for (i = 0; i < 13; i++) + header[i] = inStream.ReadByte(); + + lzmaDecoder.DecodeProperties(header); + + printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb); + printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties); + printf("\nDictionary Size for decoding = %u", lzmaDecoder.dictSize); + + UInt64 unpackSize = 0; + bool unpackSizeDefined = false; + for (i = 0; i < 8; i++) + { + Byte b = header[5 + i]; + if (b != 0xFF) + unpackSizeDefined = true; + unpackSize |= (UInt64)b << (8 * i); + } + + lzmaDecoder.markerIsMandatory = !unpackSizeDefined; + + Print("\n"); + if (unpackSizeDefined) + PrintUInt64("Uncompressed Size", unpackSize); + else + Print("End marker is expected\n"); + lzmaDecoder.RangeDec.InStream = &inStream; + + Print("\n"); + + lzmaDecoder.Create(); + + int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize); + + PrintUInt64("Read ", inStream.Processed); + PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed); + + if (res == LZMA_RES_ERROR) + throw "LZMA decoding error"; + else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER) + Print("Finished without end marker"); + else if (res == LZMA_RES_FINISHED_WITH_MARKER) + { + if (unpackSizeDefined) + { + if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize) + throw "Finished with end marker before than specified size"; + Print("Warning: "); + } + Print("Finished with end marker"); + } + else + throw "Internal Error"; + + Print("\n"); + + if (lzmaDecoder.RangeDec.Corrupted) + { + Print("\nWarning: LZMA stream is corrupted\n"); + } + + return 0; +} + + +int + #ifdef _MSC_VER + __cdecl + #endif +main(int numArgs, const char *args[]) +{ + try { return main2(numArgs, args); } + catch (const char *s) + { + PrintError("\nError:\n"); + PrintError(s); + PrintError("\n"); + return 1; + } + catch(...) + { + PrintError("\nError\n"); + return 1; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/7z.ico b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/7z.ico new file mode 100644 index 0000000000000000000000000000000000000000..47ffb781e0b093aaa123dfb25d83bbd9c94faf41 GIT binary patch literal 1078 zcmZQzU}RuoP*4zH0D%`w3=C=v3=9GS5WWT@0|Os31A_(w1A_ts1A_wtNIeTkDMJGj zn8HFdFfcSQFfcSUKq!U=5R>7+fddQ;4IqjC3=IDn7#RNlhfoavK}?4K|3QLSjH5*8 zKMDZZi7bGH{{dnf$SM3FcVglH{{V77KiIusHa7kTh=1Vn{~7o}{zLFV3K$qbe6T(L zK?)#zkRXcv{E&bGtNQ@57ZhM1e}L4Z^P%nsNh7--7auGRBd~-AObSdx%%&j;wgpPi z&>FbWP^;h+D4l~+J}9j-GC(2KCc9I5PkL|G>|{z`)PI@PVJ +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=SFXCon - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SFXCon.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SFXCon.mak" CFG="SFXCon - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SFXCon - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "SFXCon - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SFXCon - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"C:\Util\7zCon.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "SFXCon - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /I "..\..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "EXTRACT_ONLY" /D "_SFX" /D "NO_READ_FROM_CODER" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"C:\Util\7zCon.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SFXCon - Win32 Release" +# Name "SFXCon - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\HandlerOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group +# Begin Group "Console" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ConsoleClose.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\ExtractCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\List.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\List.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\MainAr.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\OpenCallbackConsole.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\PercentPrinter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\PercentPrinter.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UserInputUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Console\UserInputUtils.h +# End Source File +# End Group +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Coder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdRegister.cpp +# End Source File +# End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAesRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdInStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdInStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdOutStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StdOutStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterArc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\RegisterCodec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.h +# End Source File +# End Group +# Begin Group "UI" + +# PROP Default_Filter "" +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExitCode.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\PropIDUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\PropIDUtils.h +# End Source File +# End Group +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\AesOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7z.ico +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\IArchive.h +# End Source File +# Begin Source File + +SOURCE=.\SfxCon.cpp +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SFXCon.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SFXCon.dsw new file mode 100644 index 0000000..27bf7e6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SFXCon.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SFXCon"=.\SFXCon.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SfxCon.cpp new file mode 100644 index 0000000..b149889 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/SfxCon.cpp @@ -0,0 +1,504 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/MyWindows.h" + +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/MyException.h" + +#ifdef _WIN32 +#include "../../../Windows/DLL.h" +#else +#include "../../../Common/StringConvert.h" +#endif +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" + +#include "../../UI/Common/ExitCode.h" +#include "../../UI/Common/Extract.h" + +#include "../../UI/Console/ExtractCallbackConsole.h" +#include "../../UI/Console/List.h" +#include "../../UI/Console/OpenCallbackConsole.h" + +#include "../../MyVersion.h" + +#include "../../../../C/DllSecur.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; +using namespace NCommandLineParser; + +#ifdef _WIN32 +HINSTANCE g_hInstance = 0; +#endif +int g_CodePage = -1; +extern CStdOutStream *g_StdStream; + +static const char * const kCopyrightString = +"\n7-Zip SFX " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n"; + +static const int kNumSwitches = 6; + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kDisablePercents, + kYes, + kPassword, + kOutputDir +}; + +} + +namespace NRecursedType { +enum EEnum +{ + kRecursed, + kWildcardOnlyRecursed, + kNonRecursed +}; +} +/* +static const char kRecursedIDChar = 'R'; + +namespace NRecursedPostCharIndex { + enum EEnum + { + kWildcardRecursionOnly = 0, + kNoRecursion = 1 + }; +} + +static const char kFileListID = '@'; +static const char kImmediateNameID = '!'; + +static const char kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be +static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be +*/ + +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) + +static const CSwitchForm kSwitchForms[kNumSwitches] = +{ + { "?", SWFRM_SIMPLE }, + { "H", SWFRM_SIMPLE }, + { "BD", SWFRM_SIMPLE }, + { "Y", SWFRM_SIMPLE }, + { "P", SWFRM_STRING_SINGL(1) }, + { "O", SWFRM_STRING_SINGL(1) }, +}; + +static const int kNumCommandForms = 3; + +static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] = +{ + NRecursedType::kRecursed +}; + +// static const bool kTestExtractRecursedDefault = true; +// static const bool kAddRecursedDefault = false; + +static const char * const kUniversalWildcard = "*"; + +static const char * const kHelpString = + "\nUsage: 7zSFX [] [...] [...]\n" + "\n" + "\n" + // " l: List contents of archive\n" + " t: Test integrity of archive\n" + " x: eXtract files with full pathname (default)\n" + "\n" + // " -bd Disable percentage indicator\n" + " -o{Directory}: set Output directory\n" + " -p{Password}: set Password\n" + " -y: assume Yes on all queries\n"; + + +// --------------------------- +// exception messages + +static const char * const kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError +// static const char * const kIncorrectListFile = "Incorrect wildcard in listfile"; +static const char * const kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line"; + +// static const CSysString kFileIsNotArchiveMessageBefore = "File \""; +// static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive"; + +// static const char * const kProcessArchiveMessage = " archive: "; + +static const char * const kCantFindSFX = " cannot find sfx"; + +namespace NCommandType +{ + enum EEnum + { + kTest = 0, + kFullExtract, + kList + }; +} + +static const char *g_Commands = "txl"; + +struct CArchiveCommand +{ + NCommandType::EEnum CommandType; + + NRecursedType::EEnum DefaultRecursedType() const; +}; + +static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) +{ + UString s = commandString; + s.MakeLower_Ascii(); + if (s.Len() != 1) + return false; + if (s[0] >= 0x80) + return false; + int index = FindCharPosInString(g_Commands, (char)s[0]); + if (index < 0) + return false; + command.CommandType = (NCommandType::EEnum)index; + return true; +} + +NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const +{ + return kCommandRecursedDefault[CommandType]; +} + +static void PrintHelp(void) +{ + g_StdOut << kHelpString; +} + +MY_ATTR_NORETURN +static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code) +{ + g_StdOut << message << endl; + throw code; +} + +MY_ATTR_NORETURN +static void PrintHelpAndExit() // yyy +{ + PrintHelp(); + ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); +} + +// ------------------------------------------------------------------ +// filenames functions + +static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, + const UString &name, bool include, NRecursedType::EEnum type) +{ + /* + if (!IsWildcardFilePathLegal(name)) + return false; + */ + bool isWildcard = DoesNameContainWildcard(name); + bool recursed = false; + + switch (type) + { + case NRecursedType::kWildcardOnlyRecursed: + recursed = isWildcard; + break; + case NRecursedType::kRecursed: + recursed = true; + break; + case NRecursedType::kNonRecursed: + recursed = false; + break; + } + wildcardCensor.AddPreItem(include, name, recursed, true); + return true; +} + +static void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor, + const UString &name, bool include, NRecursedType::EEnum type) +{ + if (!AddNameToCensor(wildcardCensor, name, include, type)) + ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError); +} + + +#ifndef _WIN32 +static void GetArguments(int numArgs, char *args[], UStringVector &parts) +{ + parts.Clear(); + for (int i = 0; i < numArgs; i++) + { + UString s = MultiByteToUnicodeString(args[i]); + parts.Add(s); + } +} +#endif + + +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +); +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +) +{ + #ifdef _WIN32 + // do we need load Security DLLs for console program? + LoadSecurityDlls(); + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + SetFileApisToOEM(); + #endif + + #ifdef ENV_HAVE_LOCALE + MY_SetLocale(); + #endif + + g_StdOut << kCopyrightString; + + UStringVector commandStrings; + #ifdef _WIN32 + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + #else + GetArguments(numArgs, args, commandStrings); + #endif + + #ifdef _WIN32 + + FString arcPath; + { + FString path; + NDLL::MyGetModuleFileName(path); + if (!MyGetFullPathName(path, arcPath)) + { + g_StdOut << "GetFullPathName Error"; + return NExitCode::kFatalError; + } + } + + #else + + if (commandStrings.IsEmpty()) + return NExitCode::kFatalError; + + const FString arcPath = us2fs(commandStrings.Front()); + + #endif + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + NCommandLineParser::CParser parser; + + try + { + if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings)) + { + g_StdOut << "Command line error:" << endl + << parser.ErrorMessage << endl + << parser.ErrorLine << endl; + return NExitCode::kUserError; + } + } + catch(...) + { + PrintHelpAndExit(); + } + + if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + { + PrintHelp(); + return 0; + } + + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + + unsigned curCommandIndex = 0; + + CArchiveCommand command; + if (nonSwitchStrings.IsEmpty()) + command.CommandType = NCommandType::kFullExtract; + else + { + const UString &cmd = nonSwitchStrings[curCommandIndex]; + if (!ParseArchiveCommand(cmd, command)) + { + g_StdOut << "ERROR: Unknown command:" << endl << cmd << endl; + return NExitCode::kUserError; + } + curCommandIndex = 1; + } + + + NRecursedType::EEnum recursedType; + recursedType = command.DefaultRecursedType(); + + NWildcard::CCensor wildcardCensor; + + { + if (nonSwitchStrings.Size() == curCommandIndex) + AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType); + for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++) + { + const UString &s = nonSwitchStrings[curCommandIndex]; + if (s.IsEmpty()) + throw "Empty file path"; + AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType); + } + } + + bool yesToAll = parser[NKey::kYes].ThereIs; + + // NExtractMode::EEnum extractMode; + // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); + + bool passwordEnabled = parser[NKey::kPassword].ThereIs; + + UString password; + if (passwordEnabled) + password = parser[NKey::kPassword].PostStrings[0]; + + if (!NFind::DoesFileExist_FollowLink(arcPath)) + throw kCantFindSFX; + + FString outputDir; + if (parser[NKey::kOutputDir].ThereIs) + { + outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + NName::NormalizeDirPathPrefix(outputDir); + } + + + wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); + + { + UStringVector v1, v2; + v1.Add(fs2us(arcPath)); + v2.Add(fs2us(arcPath)); + const NWildcard::CCensorNode &wildcardCensorHead = + wildcardCensor.Pairs.Front().Head; + + CCodecs *codecs = new CCodecs; + CMyComPtr< + #ifdef EXTERNAL_CODECS + ICompressCodecsInfo + #else + IUnknown + #endif + > compressCodecsInfo = codecs; + { + HRESULT result = codecs->Load(); + if (result != S_OK) + throw CSystemException(result); + } + + if (command.CommandType != NCommandType::kList) + { + CExtractCallbackConsole *ecs = new CExtractCallbackConsole; + CMyComPtr extractCallback = ecs; + ecs->Init(g_StdStream, &g_StdErr, g_StdStream); + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = passwordEnabled; + ecs->Password = password; + #endif + + /* + COpenCallbackConsole openCallback; + openCallback.Init(g_StdStream, g_StdStream); + + #ifndef _NO_CRYPTO + openCallback.PasswordIsDefined = passwordEnabled; + openCallback.Password = password; + #endif + */ + + CExtractOptions eo; + eo.StdOutMode = false; + eo.YesToAll = yesToAll; + eo.TestMode = command.CommandType == NCommandType::kTest; + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.OverwriteMode = yesToAll ? + NExtract::NOverwriteMode::kOverwrite : + NExtract::NOverwriteMode::kAsk; + eo.OutputDir = outputDir; + + UString errorMessage; + CDecompressStat stat; + HRESULT result = Extract( + codecs, CObjectVector(), CIntVector(), + v1, v2, + wildcardCensorHead, + eo, ecs, ecs, + // NULL, // hash + errorMessage, stat); + if (!errorMessage.IsEmpty()) + { + (*g_StdStream) << endl << "Error: " << errorMessage;; + if (result == S_OK) + result = E_FAIL; + } + + if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) + { + if (ecs->NumArcsWithError != 0) + (*g_StdStream) << endl << "Archive Errors" << endl; + if (ecs->NumFileErrors != 0) + (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + } + else + { + throw CSystemException(E_NOTIMPL); + + /* + UInt64 numErrors = 0; + UInt64 numWarnings = 0; + HRESULT result = ListArchives( + codecs, CObjectVector(), CIntVector(), + false, // stdInMode + v1, v2, + true, // processAltStreams + false, // showAltStreams + wildcardCensorHead, + true, // enableHeaders + false, // techMode + #ifndef _NO_CRYPTO + passwordEnabled, password, + #endif + numErrors, numWarnings); + if (numErrors > 0) + { + g_StdOut << endl << "Errors: " << numErrors; + return NExitCode::kFatalError; + } + if (result != S_OK) + throw CSystemException(result); + */ + } + } + return 0; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile new file mode 100644 index 0000000..633bd77 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile @@ -0,0 +1,133 @@ +PROG = 7zCon.sfx +MY_CONSOLE = 1 +MY_FIXED = 1 + +CFLAGS = $(CFLAGS) \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + +CURRENT_OBJS = \ + $O\SfxCon.obj \ + +CONSOLE_OBJS = \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\List.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UserInputUtils.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\NewHandler.obj \ + $O\StdInStream.obj \ + $O\StdOutStream.obj \ + $O\StringConvert.obj \ + $O\UTFConvert.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConv.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\InBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\DefaultName.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + $O\PropIDUtils.obj \ + +AR_OBJS = \ + $O\SplitHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zHandler.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdRegister.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\LzmaDec.obj \ + $O\MtDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" +!include "../../LzmaDec.mak" +!include "../../Sha256.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile.gcc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile.gcc new file mode 100644 index 0000000..889ec1f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/makefile.gcc @@ -0,0 +1,204 @@ +PROG = 7zCon + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + +include ../../LzmaDec_gcc.mak + + +LOCAL_FLAGS_ST = +MT_OBJS = + + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/StreamBinder.o \ + $O/Synchronization.o \ + $O/VirtThread.o \ + $O/Threads.o \ + +endif + + + +LOCAL_FLAGS_SYS = + +ifdef SystemDrive + +LOCAL_FLAGS_SYS = \ + +SYS_OBJS = \ + $O/DLL.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_ST) \ + $(LOCAL_FLAGS_SYS) \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + + +CURRENT_OBJS = \ + $O/SfxCon.o \ + +CONSOLE_OBJS = \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/List.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UserInputUtils.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/IntToString.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/Sha256Prepare.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/StringConvert.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + \ + $O/System.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + \ + +UI_COMMON_OBJS = \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/DefaultName.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + +AR_OBJS = \ + $O/SplitHandler.o \ + +AR_COMMON_OBJS = \ + $O/CoderMixer2.o \ + $O/ItemNameUtils.o \ + $O/MultiStream.o \ + $O/OutStreamWithCRC.o \ + +7Z_OBJS = \ + $O/7zDecode.o \ + $O/7zExtract.o \ + $O/7zHandler.o \ + $O/7zIn.o \ + $O/7zRegister.o \ + +COMPRESS_OBJS = \ + $O/Bcj2Coder.o \ + $O/Bcj2Register.o \ + $O/BcjCoder.o \ + $O/BcjRegister.o \ + $O/BranchMisc.o \ + $O/BranchRegister.o \ + $O/CopyCoder.o \ + $O/CopyRegister.o \ + $O/DeltaFilter.o \ + $O/Lzma2Decoder.o \ + $O/Lzma2Register.o \ + $O/LzmaDecoder.o \ + $O/LzmaRegister.o \ + $O/PpmdDecoder.o \ + $O/PpmdRegister.o \ + +CRYPTO_OBJS = \ + $O/7zAes.o \ + $O/7zAesRegister.o \ + $O/MyAes.o \ + +C_OBJS = \ + $O/Alloc.o \ + $O/Bcj2.o \ + $O/Bra.o \ + $O/Bra86.o \ + $O/BraIA64.o \ + $O/CpuArch.o \ + $O/Delta.o \ + \ + $O/Lzma2Dec.o \ + $O/Lzma2DecMt.o \ + $O/LzmaDec.o \ + $O/MtDec.o \ + $O/Ppmd7.o \ + $O/Ppmd7Dec.o \ + $O/Sha256.o \ + $O/Sha256Opt.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + $O/Aes.o \ + $O/AesOpt.o \ + +OBJS = \ + $(LZMA_DEC_OPT_OBJS) \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(SYS_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(COMPRESS_OBJS) \ + $(CRYPTO_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + $(CURRENT_OBJS) \ + +include ../../7zip_gcc.mak diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/resource.rc new file mode 100644 index 0000000..58331b8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXCon/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7z Console SFX", "7z.sfx") + +101 ICON "7z.ico" \ No newline at end of file diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp new file mode 100644 index 0000000..8eaeabe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp @@ -0,0 +1,246 @@ +// ExtractCallbackSfx.h + +#include "StdAfx.h" + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" + +#include "ExtractCallbackSfx.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static LPCSTR const kCantDeleteFile = "Cannot delete output file"; +static LPCSTR const kCantOpenFile = "Cannot open output file"; +static LPCSTR const kUnsupportedMethod = "Unsupported Method"; + +void CExtractCallbackImp::Init(IInArchive *archiveHandler, + const FString &directoryPath, + const UString &itemDefaultName, + const FILETIME &defaultMTime, + UInt32 defaultAttributes) +{ + _message.Empty(); + _isCorrupt = false; + _itemDefaultName = itemDefaultName; + _defaultMTime = defaultMTime; + _defaultAttributes = defaultAttributes; + _archiveHandler = archiveHandler; + _directoryPath = directoryPath; + NName::NormalizeDirPathPrefix(_directoryPath); +} + +HRESULT CExtractCallbackImp::Open_CheckBreak() +{ + #ifndef _NO_PROGRESS + return ProgressDialog.Sync.ProcessStopAndPause(); + #else + return S_OK; + #endif +} + +HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + return S_OK; +} + +HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */) +{ + #ifndef _NO_PROGRESS + return ProgressDialog.Sync.ProcessStopAndPause(); + #else + return S_OK; + #endif +} + +HRESULT CExtractCallbackImp::Open_Finished() +{ + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 size) +{ + #ifndef _NO_PROGRESS + ProgressDialog.Sync.SetProgress(size, 0); + #endif + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *completeValue) +{ + #ifndef _NO_PROGRESS + RINOK(ProgressDialog.Sync.ProcessStopAndPause()); + if (completeValue != NULL) + ProgressDialog.Sync.SetPos(*completeValue); + #endif + return S_OK; +} + +void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts) +{ + FString fullPath = _directoryPath; + FOR_VECTOR (i, dirPathParts) + { + fullPath += us2fs(dirPathParts[i]); + CreateDir(fullPath); + fullPath.Add_PathSepar(); + } +} + +STDMETHODIMP CExtractCallbackImp::GetStream(UInt32 index, + ISequentialOutStream **outStream, Int32 askExtractMode) +{ + #ifndef _NO_PROGRESS + if (ProgressDialog.Sync.GetStopped()) + return E_ABORT; + #endif + _outFileStream.Release(); + + UString fullPath; + { + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_EMPTY) + fullPath = _itemDefaultName; + else + { + if (prop.vt != VT_BSTR) + return E_FAIL; + fullPath.SetFromBstr(prop.bstrVal); + } + _filePath = fullPath; + } + + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract) + { + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + _processedFileInfo.Attributes = _defaultAttributes; + else + { + if (prop.vt != VT_UI4) + return E_FAIL; + _processedFileInfo.Attributes = prop.ulVal; + } + + RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop)); + _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal); + + bool isAnti = false; + { + NCOM::CPropVariant propTemp; + RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp)); + if (propTemp.vt == VT_BOOL) + isAnti = VARIANT_BOOLToBool(propTemp.boolVal); + } + + RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); + switch (prop.vt) + { + case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break; + case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break; + default: return E_FAIL; + } + + UStringVector pathParts; + SplitPathToParts(fullPath, pathParts); + if (pathParts.IsEmpty()) + return E_FAIL; + + UString processedPath = fullPath; + + if (!_processedFileInfo.IsDir) + pathParts.DeleteBack(); + if (!pathParts.IsEmpty()) + { + if (!isAnti) + CreateComplexDirectory(pathParts); + } + + FString fullProcessedPath = _directoryPath + us2fs(processedPath); + + if (_processedFileInfo.IsDir) + { + _diskFilePath = fullProcessedPath; + + if (isAnti) + RemoveDir(_diskFilePath); + else + SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime); + return S_OK; + } + + NFind::CFileInfo fileInfo; + if (fileInfo.Find(fullProcessedPath)) + { + if (!DeleteFileAlways(fullProcessedPath)) + { + _message = kCantDeleteFile; + return E_FAIL; + } + } + + if (!isAnti) + { + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Create(fullProcessedPath, true)) + { + _message = kCantOpenFile; + return E_FAIL; + } + _outFileStream = outStreamLoc; + *outStream = outStreamLoc.Detach(); + } + _diskFilePath = fullProcessedPath; + } + else + { + *outStream = NULL; + } + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::PrepareOperation(Int32 askExtractMode) +{ + _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult) +{ + switch (resultEOperationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + + default: + { + _outFileStream.Release(); + switch (resultEOperationResult) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + _message = kUnsupportedMethod; + break; + default: + _isCorrupt = true; + } + return E_FAIL; + } + } + if (_outFileStream != NULL) + { + _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); + RINOK(_outFileStreamSpec->Close()); + } + _outFileStream.Release(); + if (_extractMode) + SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes); + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h new file mode 100644 index 0000000..cfbc5c0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h @@ -0,0 +1,86 @@ +// ExtractCallbackSfx.h + +#ifndef __EXTRACT_CALLBACK_SFX_H +#define __EXTRACT_CALLBACK_SFX_H + +#include "resource.h" + +#include "../../../Windows/ResourceString.h" + +#include "../../Archive/IArchive.h" + +#include "../../Common/FileStreams.h" +#include "../../ICoder.h" + +#include "../../UI/FileManager/LangUtils.h" + +#ifndef _NO_PROGRESS +#include "../../UI/FileManager/ProgressDialog.h" +#endif +#include "../../UI/Common/ArchiveOpenCallback.h" + +class CExtractCallbackImp: + public IArchiveExtractCallback, + public IOpenCallbackUI, + public CMyUnknownImp +{ +public: + + MY_UNKNOWN_IMP + + INTERFACE_IArchiveExtractCallback(;) + INTERFACE_IOpenCallbackUI(;) + +private: + CMyComPtr _archiveHandler; + FString _directoryPath; + UString _filePath; + FString _diskFilePath; + + bool _extractMode; + struct CProcessedFileInfo + { + FILETIME MTime; + bool IsDir; + UInt32 Attributes; + } _processedFileInfo; + + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + + UString _itemDefaultName; + FILETIME _defaultMTime; + UInt32 _defaultAttributes; + + void CreateComplexDirectory(const UStringVector &dirPathParts); +public: + #ifndef _NO_PROGRESS + CProgressDialog ProgressDialog; + #endif + + bool _isCorrupt; + UString _message; + + void Init(IInArchive *archiveHandler, + const FString &directoryPath, + const UString &itemDefaultName, + const FILETIME &defaultMTime, + UInt32 defaultAttributes); + + #ifndef _NO_PROGRESS + HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread) + { + ProgressDialog.Create(title, thread, 0); + { + ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING)); + } + + ProgressDialog.Show(SW_SHOWNORMAL); + return S_OK; + } + virtual ~CExtractCallbackImp() { ProgressDialog.Destroy(); } + #endif + +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp new file mode 100644 index 0000000..71b65c6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp @@ -0,0 +1,137 @@ +// ExtractEngine.cpp + +#include "StdAfx.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" + +#include "../../UI/Common/OpenArchive.h" + +#include "../../UI/FileManager/FormatUtils.h" +#include "../../UI/FileManager/LangUtils.h" + +#include "ExtractCallbackSfx.h" +#include "ExtractEngine.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static LPCSTR const kCantFindArchive = "Cannot find archive file"; +static LPCSTR const kCantOpenArchive = "Cannot open the file as archive"; + +struct CThreadExtracting +{ + CCodecs *Codecs; + FString FileName; + FString DestFolder; + + CExtractCallbackImp *ExtractCallbackSpec; + CMyComPtr ExtractCallback; + + CArchiveLink ArchiveLink; + HRESULT Result; + UString ErrorMessage; + + void Process2() + { + NFind::CFileInfo fi; + if (!fi.Find(FileName)) + { + ErrorMessage = kCantFindArchive; + Result = E_FAIL; + return; + } + + CObjectVector incl; + CIntVector excl; + COpenOptions options; + options.codecs = Codecs; + options.types = &incl; + options.excludedFormats = ! + options.filePath = fs2us(FileName); + + Result = ArchiveLink.Open2(options, ExtractCallbackSpec); + if (Result != S_OK) + { + ErrorMessage = kCantOpenArchive; + return; + } + + FString dirPath = DestFolder; + NName::NormalizeDirPathPrefix(dirPath); + + if (!CreateComplexDir(dirPath)) + { + ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, + #ifdef LANG + 0x02000603, + #endif + fs2us(dirPath)); + Result = E_FAIL; + return; + } + + ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)"Default", fi.MTime, 0); + + Result = ArchiveLink.GetArchive()->Extract(0, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback); + } + + void Process() + { + try + { + #ifndef _NO_PROGRESS + CProgressCloser closer(ExtractCallbackSpec->ProgressDialog); + #endif + Process2(); + } + catch(...) { Result = E_FAIL; } + } + + static THREAD_FUNC_DECL MyThreadFunction(void *param) + { + ((CThreadExtracting *)param)->Process(); + return 0; + } +}; + +HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, + bool showProgress, bool &isCorrupt, UString &errorMessage) +{ + isCorrupt = false; + CThreadExtracting t; + + t.Codecs = codecs; + t.FileName = fileName; + t.DestFolder = destFolder; + + t.ExtractCallbackSpec = new CExtractCallbackImp; + t.ExtractCallback = t.ExtractCallbackSpec; + + #ifndef _NO_PROGRESS + + if (showProgress) + { + t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON; + NWindows::CThread thread; + RINOK(thread.Create(CThreadExtracting::MyThreadFunction, &t)); + + UString title; + LangString(IDS_PROGRESS_EXTRACTING, title); + t.ExtractCallbackSpec->StartProgressDialog(title, thread); + } + else + + #endif + { + t.Process2(); + } + + errorMessage = t.ErrorMessage; + if (errorMessage.IsEmpty()) + errorMessage = t.ExtractCallbackSpec->_message; + isCorrupt = t.ExtractCallbackSpec->_isCorrupt; + return t.Result; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h new file mode 100644 index 0000000..295d77b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h @@ -0,0 +1,11 @@ +// ExtractEngine.h + +#ifndef __EXTRACT_ENGINE_H +#define __EXTRACT_ENGINE_H + +#include "../../UI/Common/LoadCodecs.h" + +HRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder, + bool showProgress, bool &isCorrupt, UString &errorMessage); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp new file mode 100644 index 0000000..754cc0e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsp @@ -0,0 +1,803 @@ +# Microsoft Developer Studio Project File - Name="SFXSetup" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SFXSetup - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SFXSetup.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SFXSetup.mak" CFG="SFXSetup - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SFXSetup - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SFXSetup - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "SFXSetup - Win32 ReleaseD" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SFXSetup - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gz /MT /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zS.sfx" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "SFXSetup - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\UTIL\7zSfxS.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "SFXSetup - Win32 ReleaseD" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseD" +# PROP BASE Intermediate_Dir "ReleaseD" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseD" +# PROP Intermediate_Dir "ReleaseD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "_SFX" /D "_NO_CRYPTO" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\UTIL\7zWinSR.exe" +# SUBTRACT BASE LINK32 /debug /nodefaultlib +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zSD.sfx" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "SFXSetup - Win32 Release" +# Name "SFXSetup - Win32 Debug" +# Name "SFXSetup - Win32 ReleaseD" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Interface" + +# PROP Default_Filter "" +# End Group +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zItem.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Coder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\TextConfig.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\TextConfig.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\UTFConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Group "Control" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Dialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Dialog.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Window.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Window.h +# End Source File +# End Group +# Begin Group "7z Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.h +# End Source File +# End Group +# Begin Group "UI" + +# PROP Default_Filter "" +# Begin Group "Explorer" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.h +# End Source File +# End Group +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractMode.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.h +# End Source File +# End Group +# End Group +# Begin Group "File Manager" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\FormatUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FormatUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\LangUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgressDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgressDialog.h +# End Source File +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ExtractCallbackSfx.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractCallbackSfx.h +# End Source File +# Begin Source File + +SOURCE=.\ExtractEngine.cpp +# End Source File +# Begin Source File + +SOURCE=.\ExtractEngine.h +# End Source File +# Begin Source File + +SOURCE=.\setup.ico +# End Source File +# Begin Source File + +SOURCE=.\SfxSetup.cpp +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw new file mode 100644 index 0000000..f563b21 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SFXSetup.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SFXSetup"=.\SFXSetup.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp new file mode 100644 index 0000000..86b4f0f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp @@ -0,0 +1,366 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyWindows.h" + +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/TextConfig.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/ResourceString.h" + +#include "../../UI/Explorer/MyMessages.h" + +#include "ExtractEngine.h" + +#include "../../../../C/DllSecur.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +HINSTANCE g_hInstance; + +static CFSTR const kTempDirPrefix = FTEXT("7zS"); + +#define _SHELL_EXECUTE + +static bool ReadDataString(CFSTR fileName, LPCSTR startID, + LPCSTR endID, AString &stringResult) +{ + stringResult.Empty(); + NIO::CInFile inFile; + if (!inFile.Open(fileName)) + return false; + const size_t kBufferSize = (1 << 12); + + Byte buffer[kBufferSize]; + const unsigned signatureStartSize = MyStringLen(startID); + const unsigned signatureEndSize = MyStringLen(endID); + + size_t numBytesPrev = 0; + bool writeMode = false; + UInt64 posTotal = 0; + for (;;) + { + if (posTotal > (1 << 20)) + return (stringResult.IsEmpty()); + const size_t numReadBytes = kBufferSize - numBytesPrev; + size_t processedSize; + if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) + return false; + if (processedSize == 0) + return true; + const size_t numBytesInBuffer = numBytesPrev + processedSize; + UInt32 pos = 0; + for (;;) + { + if (writeMode) + { + if (pos + signatureEndSize > numBytesInBuffer) + break; + if (memcmp(buffer + pos, endID, signatureEndSize) == 0) + return true; + char b = buffer[pos]; + if (b == 0) + return false; + stringResult += b; + pos++; + } + else + { + if (pos + signatureStartSize > numBytesInBuffer) + break; + if (memcmp(buffer + pos, startID, signatureStartSize) == 0) + { + writeMode = true; + pos += signatureStartSize; + } + else + pos++; + } + } + numBytesPrev = numBytesInBuffer - pos; + posTotal += pos; + memmove(buffer, buffer + pos, numBytesPrev); + } +} + +static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; +static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; + +struct CInstallIDInit +{ + CInstallIDInit() + { + kStartID[0] = ';'; + kEndID[0] = ';'; + }; +} g_CInstallIDInit; + + +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; +#endif + +static void ShowErrorMessageSpec(const UString &name) +{ + UString message = NError::MyFormatMessage(::GetLastError()); + int pos = message.Find(L"%1"); + if (pos >= 0) + { + message.Delete(pos, 2); + message.Insert(pos, name); + } + ShowErrorMessage(NULL, message); +} + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */,int /* nCmdShow */) +{ + g_hInstance = (HINSTANCE)hInstance; + + NT_CHECK + + #ifdef _WIN32 + LoadSecurityDlls(); + #endif + + // InitCommonControls(); + + UString archiveName, switches; + #ifdef _SHELL_EXECUTE + UString executeFile, executeParameters; + #endif + NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches); + + FString fullPath; + NDLL::MyGetModuleFileName(fullPath); + + switches.Trim(); + bool assumeYes = false; + if (switches.IsPrefixedBy_Ascii_NoCase("-y")) + { + assumeYes = true; + switches = switches.Ptr(2); + switches.Trim(); + } + + AString config; + if (!ReadDataString(fullPath, kStartID, kEndID, config)) + { + if (!assumeYes) + ShowErrorMessage(L"Can't load config info"); + return 1; + } + + UString dirPrefix ("." STRING_PATH_SEPARATOR); + UString appLaunched; + bool showProgress = true; + if (!config.IsEmpty()) + { + CObjectVector pairs; + if (!GetTextConfig(config, pairs)) + { + if (!assumeYes) + ShowErrorMessage(L"Config failed"); + return 1; + } + UString friendlyName = GetTextConfigValue(pairs, "Title"); + UString installPrompt = GetTextConfigValue(pairs, "BeginPrompt"); + UString progress = GetTextConfigValue(pairs, "Progress"); + if (progress.IsEqualTo_Ascii_NoCase("no")) + showProgress = false; + int index = FindTextConfigItem(pairs, "Directory"); + if (index >= 0) + dirPrefix = pairs[index].String; + if (!installPrompt.IsEmpty() && !assumeYes) + { + if (MessageBoxW(0, installPrompt, friendlyName, MB_YESNO | + MB_ICONQUESTION) != IDYES) + return 0; + } + appLaunched = GetTextConfigValue(pairs, "RunProgram"); + + #ifdef _SHELL_EXECUTE + executeFile = GetTextConfigValue(pairs, "ExecuteFile"); + executeParameters = GetTextConfigValue(pairs, "ExecuteParameters"); + #endif + } + + CTempDir tempDir; + if (!tempDir.Create(kTempDirPrefix)) + { + if (!assumeYes) + ShowErrorMessage(L"Cannot create temp folder archive"); + return 1; + } + + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + { + HRESULT result = codecs->Load(); + if (result != S_OK) + { + ShowErrorMessage(L"Cannot load codecs"); + return 1; + } + } + + const FString tempDirPath = tempDir.GetPath(); + // tempDirPath = L"M:\\1\\"; // to test low disk space + { + bool isCorrupt = false; + UString errorMessage; + HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress, + isCorrupt, errorMessage); + + if (result != S_OK) + { + if (!assumeYes) + { + if (result == S_FALSE || isCorrupt) + { + NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage); + result = E_FAIL; + } + if (result != E_ABORT) + { + if (errorMessage.IsEmpty()) + errorMessage = NError::MyFormatMessage(result); + ::MessageBoxW(0, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR); + } + } + return 1; + } + } + + #ifndef UNDER_CE + CCurrentDirRestorer currentDirRestorer; + if (!SetCurrentDir(tempDirPath)) + return 1; + #endif + + HANDLE hProcess = 0; +#ifdef _SHELL_EXECUTE + if (!executeFile.IsEmpty()) + { + CSysString filePath (GetSystemString(executeFile)); + SHELLEXECUTEINFO execInfo; + execInfo.cbSize = sizeof(execInfo); + execInfo.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + ; + execInfo.hwnd = NULL; + execInfo.lpVerb = NULL; + execInfo.lpFile = filePath; + + if (!switches.IsEmpty()) + { + executeParameters.Add_Space_if_NotEmpty(); + executeParameters += switches; + } + + CSysString parametersSys (GetSystemString(executeParameters)); + if (parametersSys.IsEmpty()) + execInfo.lpParameters = NULL; + else + execInfo.lpParameters = parametersSys; + + execInfo.lpDirectory = NULL; + execInfo.nShow = SW_SHOWNORMAL; + execInfo.hProcess = 0; + /* BOOL success = */ ::ShellExecuteEx(&execInfo); + UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp; + if (result <= 32) + { + if (!assumeYes) + ShowErrorMessage(L"Cannot open file"); + return 1; + } + hProcess = execInfo.hProcess; + } + else +#endif + { + if (appLaunched.IsEmpty()) + { + appLaunched = L"setup.exe"; + if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched))) + { + if (!assumeYes) + ShowErrorMessage(L"Cannot find setup.exe"); + return 1; + } + } + + { + FString s2 = tempDirPath; + NName::NormalizeDirPathPrefix(s2); + appLaunched.Replace(L"%%T" WSTRING_PATH_SEPARATOR, fs2us(s2)); + } + + UString appNameForError = appLaunched; // actually we need to rtemove parameters also + + appLaunched.Replace(L"%%T", fs2us(tempDirPath)); + + if (!switches.IsEmpty()) + { + appLaunched.Add_Space(); + appLaunched += switches; + } + STARTUPINFO startupInfo; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpReserved = 0; + startupInfo.lpDesktop = 0; + startupInfo.lpTitle = 0; + startupInfo.dwFlags = 0; + startupInfo.cbReserved2 = 0; + startupInfo.lpReserved2 = 0; + + PROCESS_INFORMATION processInformation; + + CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched)); + + BOOL createResult = CreateProcess(NULL, (LPTSTR)(LPCTSTR)appLaunchedSys, + NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */, + &startupInfo, &processInformation); + if (createResult == 0) + { + if (!assumeYes) + { + // we print name of exe file, if error message is + // ERROR_BAD_EXE_FORMAT: "%1 is not a valid Win32 application". + ShowErrorMessageSpec(appNameForError); + } + return 1; + } + ::CloseHandle(processInformation.hThread); + hProcess = processInformation.hProcess; + } + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + ::CloseHandle(hProcess); + } + return 0; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.h new file mode 100644 index 0000000..37bbd0c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/StdAfx.h @@ -0,0 +1,13 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#include + +// #define printf(x) NO_PRINTF_(x) +// #define sprintf(x) NO_SPRINTF_(x) + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/makefile new file mode 100644 index 0000000..9fddbc0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/makefile @@ -0,0 +1,117 @@ +PROG = 7zS.sfx +MY_FIXED = 1 + +CFLAGS = $(CFLAGS) \ + -DNO_REGISTRY \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + -D_NO_CRYPTO \ + +CURRENT_OBJS = \ + $O\SfxSetup.obj \ + $O\ExtractCallbackSfx.obj \ + $O\ExtractEngine.obj \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\TextConfig.obj \ + $O\UTFConvert.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\ResourceString.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Window.obj \ + +WIN_CTRL_OBJS = \ + $O\Dialog.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FileStreams.obj \ + $O\InBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveOpenCallback.obj \ + $O\DefaultName.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + +EXPLORER_OBJS = \ + $O\MyMessages.obj \ + +FM_OBJS = \ + $O\FormatUtils.obj \ + $O\ProgressDialog.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zHandler.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\LzmaDec.obj \ + $O\MtDec.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" +!include "../../LzmaDec.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.h new file mode 100644 index 0000000..d5f440b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.h @@ -0,0 +1,6 @@ +#define IDI_ICON 1 + +#define IDS_EXTRACTION_ERROR_TITLE 7 +#define IDS_EXTRACTION_ERROR_MESSAGE 8 +#define IDS_CANNOT_CREATE_FOLDER 3003 +#define IDS_PROGRESS_EXTRACTING 3300 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.rc new file mode 100644 index 0000000..47e1b76 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/resource.rc @@ -0,0 +1,16 @@ +#include "../../MyVersionInfo.rc" +#include "resource.h" + +MY_VERSION_INFO_APP("7z Setup SFX", "7zS.sfx") + +IDI_ICON ICON "setup.ico" + +STRINGTABLE +BEGIN + IDS_EXTRACTION_ERROR_TITLE "Extraction Failed" + IDS_EXTRACTION_ERROR_MESSAGE "File is corrupt" + IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" + IDS_PROGRESS_EXTRACTING "Extracting" +END + +#include "../../UI/FileManager/ProgressDialog.rc" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/setup.ico b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXSetup/setup.ico new file mode 100644 index 0000000000000000000000000000000000000000..bb455be1e7ad179c85570c6493ac7d1461cba2f1 GIT binary patch literal 1078 zcmZQzU}RuoP*4zH0D%`w3=C=v3=9GS5WWT@0|Os31A_(w1A_ts1A_wtNIeTkDMJGj zn8HFdFfcSQFfcSUKq!U=5R>7+fddQ;4IqjC3=IDn7#RNlhfoavK}?4K|3QN2#x)y5 zfB{sZzZwFJVf^h7U<_3Nmxn6ohe&TXhAKeFLo`qz-_g;)zyNa}v#~*Wc>@E7v9bMs z5HK({`2W3up}8K)|I7^HbC`es43YnA0OB{-*VjY*XKc*y|9b=T_wS$kLE8WS{|u66 zu&+1o@96mdqoe=7F~|1?2IkN0Q2GC#`M)7+fddQ;4IqjC3=IDn7#RNlhfoavK}?4K|3QLSjH5*8 zKMDZZi7bGH{{dnf$SM3FcVglH{{V77KiIusHa7kTh=1Vn{~7o}{zLFV3K$qbe6T(L zK?)#zkRXcv{E&bGtNQ@57ZhM1e}L4Z^P%nsNh7--7auGRBd~-AObSdx%%&j;wgpPi z&>FbWP^;h+D4l~+J}9j-GC(2KCc9I5PkL|G>|{z`)PI@PVJ +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SFXWin - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SFXWin.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SFXWin.mak" CFG="SFXWin - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SFXWin - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SFXWin - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "SFXWin - Win32 ReleaseD" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SFXWin - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "SFXWin - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zsfx.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "SFXWin - Win32 ReleaseD" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "SFXWin___Win32_ReleaseD" +# PROP BASE Intermediate_Dir "SFXWin___Win32_ReleaseD" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "SFXWin___Win32_ReleaseD" +# PROP Intermediate_Dir "SFXWin___Win32_ReleaseD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "_SFX" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_SFXWIN32" /D "_WINDOWS" /D "_MBCS" /D "EXTRACT_ONLY" /D "NO_REGISTRY" /D "NO_READ_FROM_CODER" /D "_SFX" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7z.sfx" /opt:NOWIN98 +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zD.sfx" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "SFXWin - Win32 Release" +# Name "SFXWin - Win32 Debug" +# Name "SFXWin - Win32 ReleaseD" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zExtract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\7z\7zRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\SplitHandler.cpp +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\CoderMixer2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\MultiStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Archive\Common\OutStreamWithCRC.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Coder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Bcj2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BcjRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchMisc.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\BranchRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\CopyRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\DeltaFilter.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Decoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Lzma2Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LzmaRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\PpmdRegister.cpp +# End Source File +# End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zAesRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\MyAes.h +# End Source File +# End Group +# Begin Group "Dialogs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\BrowseDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\BrowseDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ComboDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ComboDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\OverwriteDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PasswordDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PasswordDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgressDialog2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ProgressDialog2.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CreateCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\CWrappers.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilePathAutoRename.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LockedStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\PropId.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamBinder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\VirtThread.h +# End Source File +# End Group +# Begin Group "File Manager" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\FileManager\ExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\ExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FormatUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\FormatUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PropertyName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\PropertyName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SysIconUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\FileManager\SysIconUtils.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Group "Control" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ComboBox.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ComboBox.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Dialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\Dialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ListView.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Control\ListView.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\..\Windows\CommonDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\CommonDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ErrorMsg.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\ResourceString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Shell.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Shell.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\System.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Window.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Window.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Sha256Prepare.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.h +# End Source File +# End Group +# Begin Group "UI" + +# PROP Default_Filter "" +# Begin Group "UI Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveExtractCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ArchiveOpenCallback.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\DefaultName.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\Extract.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\ExtractingFilePath.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\LoadCodecs.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Common\OpenArchive.h +# End Source File +# End Group +# Begin Group "GUI" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\GUI\ExtractDialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\ExtractDialog.h +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\ExtractGUI.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\GUI\ExtractGUI.h +# End Source File +# End Group +# Begin Group "Explorer" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\UI\Explorer\MyMessages.h +# End Source File +# End Group +# End Group +# Begin Group "C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\7zCrcOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Aes.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\AesOpt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Bra86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\BraIA64.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\CpuArch.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Delta.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\DllSecur.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Lzma2DecMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\MtDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Ppmd7Dec.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha256Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Threads.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7z.ico +# End Source File +# Begin Source File + +SOURCE=.\7z1.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\SfxWin.cpp +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SFXWin.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SFXWin.dsw new file mode 100644 index 0000000..a9926c7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SFXWin.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SFXWin"=.\SFXWin.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SfxWin.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SfxWin.cpp new file mode 100644 index 0000000..2f80932 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/SfxWin.cpp @@ -0,0 +1,243 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyWindows.h" + +#include + +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/ResourceString.h" + +#include "../../ICoder.h" +#include "../../IPassword.h" +#include "../../Archive/IArchive.h" +#include "../../UI/Common/Extract.h" +#include "../../UI/Common/ExitCode.h" +#include "../../UI/Explorer/MyMessages.h" +#include "../../UI/FileManager/MyWindowsNew.h" +#include "../../UI/GUI/ExtractGUI.h" +#include "../../UI/GUI/ExtractRes.h" + +#include "../../../../C/DllSecur.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +HINSTANCE g_hInstance; + +#ifndef UNDER_CE + +DWORD g_ComCtl32Version; + +static DWORD GetDllVersion(LPCTSTR dllName) +{ + DWORD dwVersion = 0; + HINSTANCE hinstDll = LoadLibrary(dllName); + if (hinstDll) + { + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hr = (*pDllGetVersion)(&dvi); + if (SUCCEEDED(hr)) + dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); + } + FreeLibrary(hinstDll); + } + return dwVersion; +} + +#endif + +bool g_LVN_ITEMACTIVATE_Support = true; + +static const wchar_t * const kUnknownExceptionMessage = L"ERROR: Unknown Error!"; + +static void ErrorMessageForHRESULT(HRESULT res) +{ + ShowErrorMessage(HResultToMessage(res)); +} + +static int APIENTRY WinMain2() +{ + // OleInitialize is required for ProgressBar in TaskBar. + #ifndef UNDER_CE + OleInitialize(NULL); + #endif + + #ifndef UNDER_CE + g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); + g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); + #endif + + UString password; + bool assumeYes = false; + bool outputFolderDefined = false; + FString outputFolder; + UStringVector commandStrings; + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + FOR_VECTOR (i, commandStrings) + { + const UString &s = commandStrings[i]; + if (s.Len() > 1 && s[0] == '-') + { + wchar_t c = MyCharLower_Ascii(s[1]); + if (c == 'y') + { + assumeYes = true; + if (s.Len() != 2) + { + ShowErrorMessage(L"Bad command"); + return 1; + } + } + else if (c == 'o') + { + outputFolder = us2fs(s.Ptr(2)); + NName::NormalizeDirPathPrefix(outputFolder); + outputFolderDefined = !outputFolder.IsEmpty(); + } + else if (c == 'p') + { + password = s.Ptr(2); + } + } + } + + FString path; + NDLL::MyGetModuleFileName(path); + + FString fullPath; + if (!MyGetFullPathName(path, fullPath)) + { + ShowErrorMessage(L"Error 1329484"); + return 1; + } + + CCodecs *codecs = new CCodecs; + CMyComPtr compressCodecsInfo = codecs; + HRESULT result = codecs->Load(); + if (result != S_OK) + { + ErrorMessageForHRESULT(result); + return 1; + } + + // COpenCallbackGUI openCallback; + + // openCallback.PasswordIsDefined = !password.IsEmpty(); + // openCallback.Password = password; + + CExtractCallbackImp *ecs = new CExtractCallbackImp; + CMyComPtr extractCallback = ecs; + ecs->Init(); + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = !password.IsEmpty(); + ecs->Password = password; + #endif + + CExtractOptions eo; + + FString dirPrefix; + if (!GetOnlyDirPrefix(path, dirPrefix)) + { + ShowErrorMessage(L"Error 1329485"); + return 1; + } + + eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; + eo.YesToAll = assumeYes; + eo.OverwriteMode = assumeYes ? + NExtract::NOverwriteMode::kOverwrite : + NExtract::NOverwriteMode::kAsk; + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.TestMode = false; + + UStringVector v1, v2; + v1.Add(fs2us(fullPath)); + v2.Add(fs2us(fullPath)); + NWildcard::CCensorNode wildcardCensor; + wildcardCensor.AddItem(true, L"*", true, true, true, true); + + bool messageWasDisplayed = false; + result = ExtractGUI(codecs, + CObjectVector(), CIntVector(), + v1, v2, + wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs); + + if (result == S_OK) + { + if (!ecs->IsOK()) + return NExitCode::kFatalError; + return 0; + } + if (result == E_ABORT) + return NExitCode::kUserBreak; + if (!messageWasDisplayed) + { + if (result == S_FALSE) + ShowErrorMessage(L"Error in archive"); + else + ErrorMessageForHRESULT(result); + } + if (result == E_OUTOFMEMORY) + return NExitCode::kMemoryError; + return NExitCode::kFatalError; +} + +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return NExitCode::kFatalError; +#endif + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + /* lpCmdLine */, int /* nCmdShow */) +{ + g_hInstance = (HINSTANCE)hInstance; + + NT_CHECK + + try + { + #ifdef _WIN32 + LoadSecurityDlls(); + #endif + + return WinMain2(); + } + catch(const CNewException &) + { + ErrorMessageForHRESULT(E_OUTOFMEMORY); + return NExitCode::kMemoryError; + } + catch(...) + { + ShowErrorMessage(kUnknownExceptionMessage); + return NExitCode::kFatalError; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.h new file mode 100644 index 0000000..975a17e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/StdAfx.h @@ -0,0 +1,14 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#include +#include + +// #define printf(x) NO_PRINTF_(x) +// #define sprintf(x) NO_SPRINTF_(x) + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/makefile new file mode 100644 index 0000000..57d922f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/makefile @@ -0,0 +1,153 @@ +PROG = 7z.sfx +MY_FIXED = 1 + +CFLAGS = $(CFLAGS) \ + -DNO_REGISTRY \ + -DEXTRACT_ONLY \ + -DNO_READ_FROM_CODER \ + -D_SFX \ + +!IFDEF UNDER_CE +LIBS = $(LIBS) ceshell.lib Commctrl.lib +!ELSE +LIBS = $(LIBS) comctl32.lib comdlg32.lib +!ENDIF + +CURRENT_OBJS = \ + $O\SfxWin.obj \ + +GUI_OBJS = \ + $O\ExtractDialog.obj \ + $O\ExtractGUI.obj \ + +COMMON_OBJS = \ + $O\CRC.obj \ + $O\CommandLineParser.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\CommonDialog.obj \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConv.obj \ + $O\ResourceString.obj \ + $O\Shell.obj \ + $O\Synchronization.obj \ + $O\System.obj \ + $O\Window.obj \ + +WIN_CTRL_OBJS = \ + $O\ComboBox.obj \ + $O\Dialog.obj \ + $O\ListView.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\CWrappers.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\InBuffer.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\OutBuffer.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamBinder.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\VirtThread.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\DefaultName.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + +EXPLORER_OBJS = \ + $O\MyMessages.obj \ + +FM_OBJS = \ + $O\BrowseDialog.obj \ + $O\ComboDialog.obj \ + $O\ExtractCallback.obj \ + $O\FormatUtils.obj \ + $O\OverwriteDialog.obj \ + $O\PasswordDialog.obj \ + $O\ProgressDialog2.obj \ + $O\PropertyName.obj \ + $O\SysIconUtils.obj \ + +AR_OBJS = \ + $O\SplitHandler.obj \ + +AR_COMMON_OBJS = \ + $O\CoderMixer2.obj \ + $O\ItemNameUtils.obj \ + $O\MultiStream.obj \ + $O\OutStreamWithCRC.obj \ + +7Z_OBJS = \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zHandler.obj \ + $O\7zIn.obj \ + $O\7zRegister.obj \ + +COMPRESS_OBJS = \ + $O\Bcj2Coder.obj \ + $O\Bcj2Register.obj \ + $O\BcjCoder.obj \ + $O\BcjRegister.obj \ + $O\BranchMisc.obj \ + $O\BranchRegister.obj \ + $O\CopyCoder.obj \ + $O\CopyRegister.obj \ + $O\DeltaFilter.obj \ + $O\Lzma2Decoder.obj \ + $O\Lzma2Register.obj \ + $O\LzmaDecoder.obj \ + $O\LzmaRegister.obj \ + $O\PpmdDecoder.obj \ + $O\PpmdRegister.obj \ + +CRYPTO_OBJS = \ + $O\7zAes.obj \ + $O\7zAesRegister.obj \ + $O\MyAes.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\BraIA64.obj \ + $O\CpuArch.obj \ + $O\Delta.obj \ + $O\DllSecur.obj \ + $O\Lzma2Dec.obj \ + $O\Lzma2DecMt.obj \ + $O\LzmaDec.obj \ + $O\MtDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + $O\Threads.obj \ + +!include "../../Aes.mak" +!include "../../Crc.mak" +!include "../../LzmaDec.mak" +!include "../../Sha256.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.h b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.h new file mode 100644 index 0000000..30fe203 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.h @@ -0,0 +1 @@ +#define IDI_ICON 1 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.rc new file mode 100644 index 0000000..91292b2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Bundles/SFXWin/resource.rc @@ -0,0 +1,50 @@ +#include "../../MyVersionInfo.rc" +#include "../../GuiCommon.rc" +#include "../../UI/GUI/ExtractDialogRes.h" +#include "../../UI/FileManager/PropertyNameRes.h" + +#include "resource.h" + +MY_VERSION_INFO_APP("7z SFX", "7z.sfx") + +#define xc 240 +#define yc 64 + +IDI_ICON ICON "7z.ico" + +IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "7-Zip self-extracting archive" +BEGIN + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 + EDITTEXT IDC_EXTRACT_PATH, m, 21, xc - bxsDots - 12, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, 20, bxsDots, bys, WS_GROUP + DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys +END + +#ifdef UNDER_CE + +#undef xc +#define xc 144 + +IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "7-Zip self-extracting archive" +BEGIN + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 12, 8 + EDITTEXT IDC_EXTRACT_PATH, m, m + bys + 4, xc, 14, ES_AUTOHSCROLL + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m, bxsDots, bys, WS_GROUP + DEFPUSHBUTTON "Extract", IDOK, bx2, by, bxs, bys, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys +END + +#endif + +#include "../../UI/FileManager/OverwriteDialog.rc" +#include "../../UI/FileManager/PasswordDialog.rc" +#include "../../UI/FileManager/ProgressDialog2.rc" +#include "../../UI/GUI/Extract.rc" + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PROP_MTIME "Modified" +END diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.cpp new file mode 100644 index 0000000..ee4c36a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.cpp @@ -0,0 +1,347 @@ +// CWrappers.c + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "CWrappers.h" + +#include "StreamUtils.h" + +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw() +{ + switch (res) + { + case S_OK: return SZ_OK; + case E_OUTOFMEMORY: return SZ_ERROR_MEM; + case E_INVALIDARG: return SZ_ERROR_PARAM; + case E_ABORT: return SZ_ERROR_PROGRESS; + case S_FALSE: return SZ_ERROR_DATA; + case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED; + } + return defaultRes; +} + + +HRESULT SResToHRESULT(SRes res) throw() +{ + switch (res) + { + case SZ_OK: return S_OK; + + case SZ_ERROR_DATA: + case SZ_ERROR_CRC: + case SZ_ERROR_INPUT_EOF: + return S_FALSE; + + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PARAM: return E_INVALIDARG; + case SZ_ERROR_PROGRESS: return E_ABORT; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; + // case SZ_ERROR_OUTPUT_EOF: + // case SZ_ERROR_READ: + // case SZ_ERROR_WRITE: + // case SZ_ERROR_THREAD: + // case SZ_ERROR_ARCHIVE: + // case SZ_ERROR_NO_ARCHIVE: + // return E_FAIL; + } + if (res < 0) + return res; + return E_FAIL; +} + + +#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) + +#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) + + +static SRes CompressProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 outSize) throw() +{ + CCompressProgressWrap *p = CONTAINER_FROM_VTBL(pp, CCompressProgressWrap, vt); + p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); + return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); +} + +void CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw() +{ + vt.Progress = CompressProgress; + Progress = progress; + Res = SZ_OK; +} + +static const UInt32 kStreamStepSize = (UInt32)1 << 31; + +static SRes MyRead(const ISeqInStream *pp, void *data, size_t *size) throw() +{ + CSeqInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqInStreamWrap, vt); + UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); + p->Res = (p->Stream->Read(data, curSize, &curSize)); + *size = curSize; + p->Processed += curSize; + if (p->Res == S_OK) + return SZ_OK; + return HRESULT_To_SRes(p->Res, SZ_ERROR_READ); +} + +static size_t MyWrite(const ISeqOutStream *pp, const void *data, size_t size) throw() +{ + CSeqOutStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeqOutStreamWrap, vt); + if (p->Stream) + { + p->Res = WriteStream(p->Stream, data, size); + if (p->Res != 0) + return 0; + } + else + p->Res = S_OK; + p->Processed += size; + return size; +} + + +void CSeqInStreamWrap::Init(ISequentialInStream *stream) throw() +{ + vt.Read = MyRead; + Stream = stream; + Processed = 0; + Res = S_OK; +} + +void CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw() +{ + vt.Write = MyWrite; + Stream = stream; + Res = SZ_OK; + Processed = 0; +} + + +static SRes InStreamWrap_Read(const ISeekInStream *pp, void *data, size_t *size) throw() +{ + CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt); + UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); + p->Res = p->Stream->Read(data, curSize, &curSize); + *size = curSize; + return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes InStreamWrap_Seek(const ISeekInStream *pp, Int64 *offset, ESzSeek origin) throw() +{ + CSeekInStreamWrap *p = CONTAINER_FROM_VTBL(pp, CSeekInStreamWrap, vt); + UInt32 moveMethod; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break; + default: return SZ_ERROR_PARAM; + } + UInt64 newPosition; + p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition); + *offset = (Int64)newPosition; + return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ; +} + +void CSeekInStreamWrap::Init(IInStream *stream) throw() +{ + Stream = stream; + vt.Read = InStreamWrap_Read; + vt.Seek = InStreamWrap_Seek; + Res = S_OK; +} + + +/* ---------- CByteInBufWrap ---------- */ + +void CByteInBufWrap::Free() throw() +{ + ::MidFree(Buf); + Buf = NULL; +} + +bool CByteInBufWrap::Alloc(UInt32 size) throw() +{ + if (!Buf || size != Size) + { + Free(); + Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); + Size = size; + } + return (Buf != NULL); +} + +Byte CByteInBufWrap::ReadByteFromNewBlock() throw() +{ + if (!Extra && Res == S_OK) + { + UInt32 avail; + Res = Stream->Read(Buf, Size, &avail); + Processed += (size_t)(Cur - Buf); + Cur = Buf; + Lim = Buf + avail; + if (avail != 0) + return *Cur++; + } + Extra = true; + return 0; +} + +static Byte Wrap_ReadByte(const IByteIn *pp) throw() +{ + CByteInBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt); + if (p->Cur != p->Lim) + return *p->Cur++; + return p->ReadByteFromNewBlock(); +} + +CByteInBufWrap::CByteInBufWrap(): Buf(NULL) +{ + vt.Read = Wrap_ReadByte; +} + + + +/* ---------- CByteOutBufWrap ---------- */ + +/* +void CLookToSequentialWrap::Free() throw() +{ + ::MidFree(BufBase); + BufBase = NULL; +} + +bool CLookToSequentialWrap::Alloc(UInt32 size) throw() +{ + if (!BufBase || size != Size) + { + Free(); + BufBase = (Byte *)::MidAlloc((size_t)size); + Size = size; + } + return (BufBase != NULL); +} +*/ + +/* +EXTERN_C_BEGIN + +void CLookToSequentialWrap_Look(ILookInSeqStream *pp) +{ + CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj; + + if (p->Extra || p->Res != S_OK) + return; + { + UInt32 avail; + p->Res = p->Stream->Read(p->BufBase, p->Size, &avail); + p->Processed += avail; + pp->Buf = p->BufBase; + pp->Limit = pp->Buf + avail; + if (avail == 0) + p->Extra = true; + } +} + +EXTERN_C_END +*/ + + +/* ---------- CByteOutBufWrap ---------- */ + +void CByteOutBufWrap::Free() throw() +{ + ::MidFree(Buf); + Buf = NULL; +} + +bool CByteOutBufWrap::Alloc(size_t size) throw() +{ + if (!Buf || size != Size) + { + Free(); + Buf = (Byte *)::MidAlloc(size); + Size = size; + } + return (Buf != NULL); +} + +HRESULT CByteOutBufWrap::Flush() throw() +{ + if (Res == S_OK) + { + const size_t size = (size_t)(Cur - Buf); + Res = WriteStream(Stream, Buf, size); + if (Res == S_OK) + Processed += size; + // else throw 11; + } + Cur = Buf; // reset pointer for later Wrap_WriteByte() + return Res; +} + +static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw() +{ + CByteOutBufWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt); + Byte *dest = p->Cur; + *dest = b; + p->Cur = ++dest; + if (dest == p->Lim) + p->Flush(); +} + +CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(NULL), Size(0) +{ + vt.Write = Wrap_WriteByte; +} + + +/* ---------- CLookOutWrap ---------- */ + +/* +void CLookOutWrap::Free() throw() +{ + ::MidFree(Buf); + Buf = NULL; +} + +bool CLookOutWrap::Alloc(size_t size) throw() +{ + if (!Buf || size != Size) + { + Free(); + Buf = (Byte *)::MidAlloc(size); + Size = size; + } + return (Buf != NULL); +} + +static size_t LookOutWrap_GetOutBuf(const ILookOutStream *pp, void **buf) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + *buf = p->Buf; + return p->Size; +} + +static size_t LookOutWrap_Write(const ILookOutStream *pp, size_t size) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + if (p->Res == S_OK && size != 0) + { + p->Res = WriteStream(p->Stream, p->Buf, size); + if (p->Res == S_OK) + { + p->Processed += size; + return size; + } + } + return 0; +} + +CLookOutWrap::CLookOutWrap() throw(): Buf(NULL), Size(0) +{ + vt.GetOutBuf = LookOutWrap_GetOutBuf; + vt.Write = LookOutWrap_Write; +} +*/ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.h new file mode 100644 index 0000000..e7196a5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CWrappers.h @@ -0,0 +1,182 @@ +// CWrappers.h + +#ifndef __C_WRAPPERS_H +#define __C_WRAPPERS_H + +#include "../ICoder.h" +#include "../../Common/MyCom.h" + +SRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw(); +HRESULT SResToHRESULT(SRes res) throw(); + +struct CCompressProgressWrap +{ + ICompressProgress vt; + ICompressProgressInfo *Progress; + HRESULT Res; + + void Init(ICompressProgressInfo *progress) throw(); +}; + + +struct CSeqInStreamWrap +{ + ISeqInStream vt; + ISequentialInStream *Stream; + HRESULT Res; + UInt64 Processed; + + void Init(ISequentialInStream *stream) throw(); +}; + + +struct CSeekInStreamWrap +{ + ISeekInStream vt; + IInStream *Stream; + HRESULT Res; + + void Init(IInStream *stream) throw(); +}; + + +struct CSeqOutStreamWrap +{ + ISeqOutStream vt; + ISequentialOutStream *Stream; + HRESULT Res; + UInt64 Processed; + + void Init(ISequentialOutStream *stream) throw(); +}; + + +struct CByteInBufWrap +{ + IByteIn vt; + const Byte *Cur; + const Byte *Lim; + Byte *Buf; + UInt32 Size; + ISequentialInStream *Stream; + UInt64 Processed; + bool Extra; + HRESULT Res; + + CByteInBufWrap(); + ~CByteInBufWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); + void Init() + { + Lim = Cur = Buf; + Processed = 0; + Extra = false; + Res = S_OK; + } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } + Byte ReadByteFromNewBlock() throw(); + Byte ReadByte() + { + if (Cur != Lim) + return *Cur++; + return ReadByteFromNewBlock(); + } +}; + + +/* +struct CLookToSequentialWrap +{ + Byte *BufBase; + UInt32 Size; + ISequentialInStream *Stream; + UInt64 Processed; + bool Extra; + HRESULT Res; + + CLookToSequentialWrap(): BufBase(NULL) {} + ~CLookToSequentialWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); + void Init() + { + // Lim = Cur = Buf; + Processed = 0; + Extra = false; + Res = S_OK; + } + // UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + + Byte ReadByteFromNewBlock() throw(); + Byte ReadByte() + { + if (Cur != Lim) + return *Cur++; + return ReadByteFromNewBlock(); + } +}; + +EXTERN_C_BEGIN +// void CLookToSequentialWrap_Look(ILookInSeqStream *pp); +EXTERN_C_END +*/ + + + +struct CByteOutBufWrap +{ + IByteOut vt; + Byte *Cur; + const Byte *Lim; + Byte *Buf; + size_t Size; + ISequentialOutStream *Stream; + UInt64 Processed; + HRESULT Res; + + CByteOutBufWrap() throw(); + ~CByteOutBufWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); + void Init() + { + Cur = Buf; + Lim = Buf + Size; + Processed = 0; + Res = S_OK; + } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } + HRESULT Flush() throw(); + void WriteByte(Byte b) + { + *Cur++ = b; + if (Cur == Lim) + Flush(); + } +}; + + +/* +struct CLookOutWrap +{ + ILookOutStream vt; + Byte *Buf; + size_t Size; + ISequentialOutStream *Stream; + UInt64 Processed; + HRESULT Res; + + CLookOutWrap() throw(); + ~CLookOutWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); + void Init() + { + Processed = 0; + Res = S_OK; + } +}; +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.cpp new file mode 100644 index 0000000..e62bb0b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.cpp @@ -0,0 +1,544 @@ +// CreateCoder.cpp + +#include "StdAfx.h" + +#include "../../Windows/Defs.h" +#include "../../Windows/PropVariant.h" + +#include "CreateCoder.h" + +#include "FilterCoder.h" +#include "RegisterCodec.h" + +static const unsigned kNumCodecsMax = 64; +extern +unsigned g_NumCodecs; +unsigned g_NumCodecs = 0; +extern +const CCodecInfo *g_Codecs[]; +const CCodecInfo *g_Codecs[kNumCodecsMax]; + +// We use g_ExternalCodecs in other stages. +#ifdef EXTERNAL_CODECS +/* +extern CExternalCodecs g_ExternalCodecs; +#define CHECK_GLOBAL_CODECS \ + if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs; +*/ +#define CHECK_GLOBAL_CODECS +#endif + + +void RegisterCodec(const CCodecInfo *codecInfo) throw() +{ + if (g_NumCodecs < kNumCodecsMax) + g_Codecs[g_NumCodecs++] = codecInfo; +} + +static const unsigned kNumHashersMax = 16; +extern +unsigned g_NumHashers; +unsigned g_NumHashers = 0; +extern +const CHasherInfo *g_Hashers[]; +const CHasherInfo *g_Hashers[kNumHashersMax]; + +void RegisterHasher(const CHasherInfo *hashInfo) throw() +{ + if (g_NumHashers < kNumHashersMax) + g_Hashers[g_NumHashers++] = hashInfo; +} + + +#ifdef EXTERNAL_CODECS + +static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) +{ + NWindows::NCOM::CPropVariant prop; + RINOK(codecsInfo->GetProperty(index, propID, &prop)); + if (prop.vt == VT_EMPTY) + res = 1; + else if (prop.vt == VT_UI4) + res = prop.ulVal; + else + return E_INVALIDARG; + return S_OK; +} + +static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) +{ + NWindows::NCOM::CPropVariant prop; + RINOK(codecsInfo->GetProperty(index, propID, &prop)); + if (prop.vt == VT_EMPTY) + res = true; + else if (prop.vt == VT_BOOL) + res = VARIANT_BOOLToBool(prop.boolVal); + else + return E_INVALIDARG; + return S_OK; +} + +HRESULT CExternalCodecs::Load() +{ + Codecs.Clear(); + Hashers.Clear(); + + if (GetCodecs) + { + CCodecInfoEx info; + + UString s; + UInt32 num; + RINOK(GetCodecs->GetNumMethods(&num)); + + for (UInt32 i = 0; i < num; i++) + { + NWindows::NCOM::CPropVariant prop; + + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + continue; // old Interface + info.Id = prop.uhVal.QuadPart; + + prop.Clear(); + + info.Name.Empty(); + RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + continue; + + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams)); + { + UInt32 numUnpackStreams = 1; + RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams)); + if (numUnpackStreams != 1) + continue; + } + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); + RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); + + Codecs.Add(info); + } + } + + if (GetHashers) + { + UInt32 num = GetHashers->GetNumHashers(); + CHasherInfoEx info; + + for (UInt32 i = 0; i < num; i++) + { + NWindows::NCOM::CPropVariant prop; + + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + continue; + info.Id = prop.uhVal.QuadPart; + + prop.Clear(); + + info.Name.Empty(); + RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); + if (prop.vt == VT_BSTR) + info.Name.SetFromWStr_if_Ascii(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + continue; + + Hashers.Add(info); + } + } + + return S_OK; +} + +#endif + + +int FindMethod_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + bool encode, + CMethodId &methodId, + UInt32 &numStreams) +{ + unsigned i; + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + if ((encode ? codec.CreateEncoder : codec.CreateDecoder) + && StringsAreEqualNoCase_Ascii(name, codec.Name)) + { + methodId = codec.Id; + numStreams = codec.NumStreams; + return (int)i; + } + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) + { + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned) + && StringsAreEqualNoCase_Ascii(name, codec.Name)) + { + methodId = codec.Id; + numStreams = codec.NumStreams; + return (int)(g_NumCodecs + i); + } + } + + #endif + + return -1; +} + + +static int FindMethod_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode) +{ + unsigned i; + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder)) + return (int)i; + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) + { + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)) + return (int)(g_NumCodecs + i); + } + + #endif + + return -1; +} + + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name) +{ + name.Empty(); + + unsigned i; + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + if (methodId == codec.Id) + { + name = codec.Name; + return true; + } + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + for (i = 0; i < __externalCodecs->Codecs.Size(); i++) + { + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + if (methodId == codec.Id) + { + name = codec.Name; + return true; + } + } + + #endif + + return false; +} + +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId) +{ + unsigned i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) + { + methodId = codec.Id; + return true; + } + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (StringsAreEqualNoCase_Ascii(name, codec.Name)) + { + methodId = codec.Id; + return true; + } + } + + #endif + + return false; +} + +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods) +{ + methods.ClearAndSetSize(g_NumHashers); + unsigned i; + for (i = 0; i < g_NumHashers; i++) + methods[i] = (*g_Hashers[i]).Id; + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) + methods.Add(__externalCodecs->Hashers[i].Id); + + #endif +} + + + +HRESULT CreateCoder_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + unsigned i, bool encode, + CMyComPtr &filter, + CCreatedCoder &cod) +{ + cod.IsExternal = false; + cod.IsFilter = false; + cod.NumStreams = 1; + + if (i < g_NumCodecs) + { + const CCodecInfo &codec = *g_Codecs[i]; + // if (codec.Id == methodId) + { + if (encode) + { + if (codec.CreateEncoder) + { + void *p = codec.CreateEncoder(); + if (codec.IsFilter) filter = (ICompressFilter *)p; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; + } + } + else + if (codec.CreateDecoder) + { + void *p = codec.CreateDecoder(); + if (codec.IsFilter) filter = (ICompressFilter *)p; + else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p; + else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; } + return S_OK; + } + } + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (__externalCodecs) + { + i -= g_NumCodecs; + cod.IsExternal = true; + if (i < __externalCodecs->Codecs.Size()) + { + const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; + // if (codec.Id == methodId) + { + if (encode) + { + if (codec.EncoderIsAssigned) + { + if (codec.NumStreams == 1) + { + HRESULT res = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder); + if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) + return res; + if (cod.Coder) + return res; + return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter); + } + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); + } + } + else + if (codec.DecoderIsAssigned) + { + if (codec.NumStreams == 1) + { + HRESULT res = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder); + if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE) + return res; + if (cod.Coder) + return res; + return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter); + } + cod.NumStreams = codec.NumStreams; + return __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2); + } + } + } + } + #endif + + return S_OK; +} + + +HRESULT CreateCoder_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + unsigned index, bool encode, + CCreatedCoder &cod) +{ + CMyComPtr filter; + HRESULT res = CreateCoder_Index( + EXTERNAL_CODECS_LOC_VARS + index, encode, + filter, cod); + + if (filter) + { + cod.IsFilter = true; + CFilterCoder *coderSpec = new CFilterCoder(encode); + cod.Coder = coderSpec; + coderSpec->Filter = filter; + } + + return res; +} + + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &filter, + CCreatedCoder &cod) +{ + int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode); + if (index < 0) + return S_OK; + return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod); +} + + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod) +{ + CMyComPtr filter; + HRESULT res = CreateCoder_Id( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); + + if (filter) + { + cod.IsFilter = true; + CFilterCoder *coderSpec = new CFilterCoder(encode); + cod.Coder = coderSpec; + coderSpec->Filter = filter; + } + + return res; +} + + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &coder) +{ + CCreatedCoder cod; + HRESULT res = CreateCoder_Id( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + cod); + coder = cod.Coder; + return res; +} + +HRESULT CreateFilter( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &filter) +{ + CCreatedCoder cod; + return CreateCoder_Id( + EXTERNAL_CODECS_LOC_VARS + methodId, encode, + filter, cod); +} + + +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr &hasher) +{ + name.Empty(); + + unsigned i; + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + if (codec.Id == methodId) + { + hasher = codec.CreateHasher(); + name = codec.Name; + break; + } + } + + #ifdef EXTERNAL_CODECS + + CHECK_GLOBAL_CODECS + + if (!hasher && __externalCodecs) + for (i = 0; i < __externalCodecs->Hashers.Size(); i++) + { + const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; + if (codec.Id == methodId) + { + name = codec.Name; + return __externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher); + } + } + + #endif + + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.h new file mode 100644 index 0000000..20d0ef3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/CreateCoder.h @@ -0,0 +1,192 @@ +// CreateCoder.h + +#ifndef __CREATE_CODER_H +#define __CREATE_CODER_H + +#include "../../Common/MyCom.h" +#include "../../Common/MyString.h" + +#include "../ICoder.h" + +#include "MethodId.h" + +/* + if EXTERNAL_CODECS is not defined, the code supports only codecs that + are statically linked at compile-time and link-time. + + if EXTERNAL_CODECS is defined, the code supports also codecs from another + executable modules, that can be linked dynamically at run-time: + - EXE module can use codecs from external DLL files. + - DLL module can use codecs from external EXE and DLL files. + + CExternalCodecs contains information about codecs and interfaces to create them. + + The order of codecs: + 1) Internal codecs + 2) External codecs +*/ + +#ifdef EXTERNAL_CODECS + +struct CCodecInfoEx +{ + CMethodId Id; + AString Name; + UInt32 NumStreams; + bool EncoderIsAssigned; + bool DecoderIsAssigned; + + CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} +}; + +struct CHasherInfoEx +{ + CMethodId Id; + AString Name; +}; + +#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, +#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) +#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); +#define IMPL_ISetCompressCodecsInfo2(x) \ +STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ + COM_TRY_BEGIN __externalCodecs.GetCodecs = compressCodecsInfo; return __externalCodecs.Load(); COM_TRY_END } +#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) + +struct CExternalCodecs +{ + CMyComPtr GetCodecs; + CMyComPtr GetHashers; + + CObjectVector Codecs; + CObjectVector Hashers; + + bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; } + + HRESULT Load(); + + void ClearAndRelease() + { + Hashers.Clear(); + Codecs.Clear(); + GetHashers.Release(); + GetCodecs.Release(); + } + + ~CExternalCodecs() + { + GetHashers.Release(); + GetCodecs.Release(); + } +}; + +extern CExternalCodecs g_ExternalCodecs; + +#define EXTERNAL_CODECS_VARS2 (__externalCodecs.IsSet() ? &__externalCodecs : &g_ExternalCodecs) +#define EXTERNAL_CODECS_VARS2_L (&__externalCodecs) +#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs) + +#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs __externalCodecs; + +#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, +#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L, +#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G, + +#define DECL_EXTERNAL_CODECS_LOC_VARS2 const CExternalCodecs *__externalCodecs +#define EXTERNAL_CODECS_LOC_VARS2 __externalCodecs + +#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, +#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, + +#else + +#define PUBLIC_ISetCompressCodecsInfo +#define QUERY_ENTRY_ISetCompressCodecsInfo +#define DECL_ISetCompressCodecsInfo +#define IMPL_ISetCompressCodecsInfo +#define EXTERNAL_CODECS_VARS2 +#define DECL_EXTERNAL_CODECS_VARS +#define EXTERNAL_CODECS_VARS +#define EXTERNAL_CODECS_VARS_L +#define EXTERNAL_CODECS_VARS_G +#define DECL_EXTERNAL_CODECS_LOC_VARS2 +#define EXTERNAL_CODECS_LOC_VARS2 +#define DECL_EXTERNAL_CODECS_LOC_VARS +#define EXTERNAL_CODECS_LOC_VARS + +#endif + +int FindMethod_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + bool encode, + CMethodId &methodId, + UInt32 &numStreams); + +bool FindMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name); + +bool FindHashMethod( + DECL_EXTERNAL_CODECS_LOC_VARS + const AString &name, + CMethodId &methodId); + +void GetHashMethods( + DECL_EXTERNAL_CODECS_LOC_VARS + CRecordVector &methods); + + +struct CCreatedCoder +{ + CMyComPtr Coder; + CMyComPtr Coder2; + + bool IsExternal; + bool IsFilter; // = true, if Coder was created from filter + UInt32 NumStreams; + + // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {} +}; + + +HRESULT CreateCoder_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + unsigned codecIndex, bool encode, + CMyComPtr &filter, + CCreatedCoder &cod); + +HRESULT CreateCoder_Index( + DECL_EXTERNAL_CODECS_LOC_VARS + unsigned index, bool encode, + CCreatedCoder &cod); + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &filter, + CCreatedCoder &cod); + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CCreatedCoder &cod); + +HRESULT CreateCoder_Id( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &coder); + +HRESULT CreateFilter( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, bool encode, + CMyComPtr &filter); + +HRESULT CreateHasher( + DECL_EXTERNAL_CODECS_LOC_VARS + CMethodId methodId, + AString &name, + CMyComPtr &hasher); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.cpp new file mode 100644 index 0000000..1ebfd72 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.cpp @@ -0,0 +1,46 @@ +// FilePathAutoRename.cpp + +#include "StdAfx.h" + +#include "../../Windows/FileFind.h" + +#include "FilePathAutoRename.h" + +using namespace NWindows; + +static bool MakeAutoName(const FString &name, + const FString &extension, UInt32 value, FString &path) +{ + path = name; + path.Add_UInt32(value); + path += extension; + return NFile::NFind::DoesFileOrDirExist(path); +} + +bool AutoRenamePath(FString &path) +{ + int dotPos = path.ReverseFind_Dot(); + int slashPos = path.ReverseFind_PathSepar(); + + FString name = path; + FString extension; + if (dotPos > slashPos + 1) + { + name.DeleteFrom((unsigned)dotPos); + extension = path.Ptr((unsigned)dotPos); + } + name += '_'; + + FString temp; + + UInt32 left = 1, right = ((UInt32)1 << 30); + while (left != right) + { + UInt32 mid = (left + right) / 2; + if (MakeAutoName(name, extension, mid, temp)) + left = mid + 1; + else + right = mid; + } + return !MakeAutoName(name, extension, right, path); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.h new file mode 100644 index 0000000..7b57659 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilePathAutoRename.h @@ -0,0 +1,10 @@ +// FilePathAutoRename.h + +#ifndef __FILE_PATH_AUTO_RENAME_H +#define __FILE_PATH_AUTO_RENAME_H + +#include "../../Common/MyString.h" + +bool AutoRenamePath(FString &fullProcessedPath); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.cpp new file mode 100644 index 0000000..466f46e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.cpp @@ -0,0 +1,542 @@ +// FileStreams.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#include +#include +#include "../../Windows/FileFind.h" +#endif + +#ifdef SUPPORT_DEVICE_FILE +#include "../../../C/Alloc.h" +#include "../../Common/Defs.h" +#endif + +#include "FileStreams.h" + +static inline HRESULT GetLastError_HRESULT() +{ + DWORD lastError = ::GetLastError(); + if (lastError == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(lastError); +} + +static inline HRESULT ConvertBoolToHRESULT(bool result) +{ + if (result) + return S_OK; + return GetLastError_HRESULT(); +} + + +#ifdef SUPPORT_DEVICE_FILE +static const UInt32 kClusterSize = 1 << 18; +#endif + +CInFileStream::CInFileStream(): + #ifdef SUPPORT_DEVICE_FILE + VirtPos(0), + PhyPos(0), + Buf(0), + BufSize(0), + #endif + SupportHardLinks(false), + Callback(NULL), + CallbackRef(0) +{ +} + +CInFileStream::~CInFileStream() +{ + #ifdef SUPPORT_DEVICE_FILE + MidFree(Buf); + #endif + + if (Callback) + Callback->InFileStream_On_Destroy(CallbackRef); +} + +STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef USE_WIN_FILE + + #ifdef SUPPORT_DEVICE_FILE + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (File.IsDeviceFile) + { + if (File.SizeDefined) + { + if (VirtPos >= File.Size) + return VirtPos == File.Size ? S_OK : E_FAIL; + UInt64 rem = File.Size - VirtPos; + if (size > rem) + size = (UInt32)rem; + } + for (;;) + { + const UInt32 mask = kClusterSize - 1; + const UInt64 mask2 = ~(UInt64)mask; + UInt64 alignedPos = VirtPos & mask2; + if (BufSize > 0 && BufStartPos == alignedPos) + { + UInt32 pos = (UInt32)VirtPos & mask; + if (pos >= BufSize) + return S_OK; + UInt32 rem = MyMin(BufSize - pos, size); + memcpy(data, Buf + pos, rem); + VirtPos += rem; + if (processedSize) + *processedSize += rem; + return S_OK; + } + + bool useBuf = false; + if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) + useBuf = true; + else + { + UInt64 end = VirtPos + size; + if ((end & mask) != 0) + { + end &= mask2; + if (end <= VirtPos) + useBuf = true; + else + size = (UInt32)(end - VirtPos); + } + } + if (!useBuf) + break; + if (alignedPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = realNewPosition; + } + + BufStartPos = alignedPos; + UInt32 readSize = kClusterSize; + if (File.SizeDefined) + readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); + + if (!Buf) + { + Buf = (Byte *)MidAlloc(kClusterSize); + if (!Buf) + return E_OUTOFMEMORY; + } + bool result = File.Read1(Buf, readSize, BufSize); + if (!result) + return ConvertBoolToHRESULT(result); + + if (BufSize == 0) + return S_OK; + PhyPos += BufSize; + } + + if (VirtPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = VirtPos = realNewPosition; + } + } + #endif + + UInt32 realProcessedSize; + const bool result = File.ReadPart(data, size, realProcessedSize); + if (processedSize) + *processedSize = realProcessedSize; + + #ifdef SUPPORT_DEVICE_FILE + VirtPos += realProcessedSize; + PhyPos += realProcessedSize; + #endif + + if (result) + return S_OK; + + #else // USE_WIN_FILE + + if (processedSize) + *processedSize = 0; + const ssize_t res = File.read_part(data, (size_t)size); + if (res != -1) + { + if (processedSize) + *processedSize = (UInt32)res; + return S_OK; + } + #endif // USE_WIN_FILE + + { + const DWORD error = ::GetLastError(); + if (Callback) + return Callback->InFileStream_On_Error(CallbackRef, error); + if (error == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(error); + } +} + +#ifdef UNDER_CE +STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fread(data, 1, size, stdin); + int error = ferror(stdin); + if (processedSize) + *processedSize = s2; + if (s2 <= size && error == 0) + return S_OK; + return E_FAIL; +} +#else +STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef _WIN32 + + DWORD realProcessedSize; + UInt32 sizeTemp = (1 << 20); + if (sizeTemp > size) + sizeTemp = size; + BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); + if (processedSize) + *processedSize = realProcessedSize; + if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) + return S_OK; + return ConvertBoolToHRESULT(res != FALSE); + + #else + + if (processedSize) + *processedSize = 0; + ssize_t res; + do + { + res = read(0, data, (size_t)size); + } + while (res < 0 && (errno == EINTR)); + if (res == -1) + return GetLastError_HRESULT(); + if (processedSize) + *processedSize = (UInt32)res; + return S_OK; + + #endif +} + +#endif + +STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + + #ifdef USE_WIN_FILE + + #ifdef SUPPORT_DEVICE_FILE + if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) + { + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += VirtPos; break; + case STREAM_SEEK_END: offset += File.Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + VirtPos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; + } + #endif + + UInt64 realNewPosition; + bool result = File.Seek(offset, seekOrigin, realNewPosition); + + #ifdef SUPPORT_DEVICE_FILE + PhyPos = VirtPos = realNewPosition; + #endif + + if (newPosition) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.seek((off_t)offset, (int)seekOrigin); + if (res == -1) + return GetLastError_HRESULT(); + if (newPosition) + *newPosition = (UInt64)res; + return S_OK; + + #endif +} + +STDMETHODIMP CInFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + +#ifdef USE_WIN_FILE + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + if (cTime) *cTime = info.ftCreationTime; + if (aTime) *aTime = info.ftLastAccessTime; + if (mTime) *mTime = info.ftLastWriteTime; + if (attrib) *attrib = info.dwFileAttributes; + return S_OK; + } + return GetLastError_HRESULT(); +} + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + props->VolID = info.dwVolumeSerialNumber; + props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + props->FileID_High = 0; + props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; + props->Attrib = info.dwFileAttributes; + props->CTime = info.ftCreationTime; + props->ATime = info.ftLastAccessTime; + props->MTime = info.ftLastWriteTime; + return S_OK; + } + return GetLastError_HRESULT(); +} + +#elif !defined(_WIN32) + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + if (size) *size = (UInt64)st.st_size; + #ifdef __APPLE__ + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, *mTime); + #else + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, *mTime); + #endif + if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + return S_OK; +} + +// #include + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + props->Size = (UInt64)st.st_size; + /* + dev_t stat::st_dev: + GCC:Linux long unsigned int : __dev_t + Mac: int + */ + props->VolID = (UInt64)(Int64)st.st_dev; + props->FileID_Low = st.st_ino; + props->FileID_High = 0; + props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) + props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + #ifdef __APPLE__ + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, props->MTime); + #else + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, props->MTime); + #endif + + /* + printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" + , (unsigned)(props->NumLinks) + , (unsigned)(st.st_dev) + , (unsigned)(st.st_ino) + ); + */ + + return S_OK; +} + +#endif + +////////////////////////// +// COutFileStream + +HRESULT COutFileStream::Close() +{ + return ConvertBoolToHRESULT(File.Close()); +} + +STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef USE_WIN_FILE + + UInt32 realProcessedSize; + const bool result = File.Write(data, size, realProcessedSize); + ProcessedSize += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return ConvertBoolToHRESULT(result); + + #else + + if (processedSize) + *processedSize = 0; + size_t realProcessedSize; + const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize); + ProcessedSize += realProcessedSize; + if (processedSize) + *processedSize = (UInt32)realProcessedSize; + if (res == -1) + return GetLastError_HRESULT(); + return S_OK; + + #endif +} + +STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + + #ifdef USE_WIN_FILE + + UInt64 realNewPosition; + bool result = File.Seek(offset, seekOrigin, realNewPosition); + if (newPosition) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.seek((off_t)offset, (int)seekOrigin); + if (res == -1) + return GetLastError_HRESULT(); + if (newPosition) + *newPosition = (UInt64)res; + return S_OK; + + #endif +} + +STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) +{ + #ifdef USE_WIN_FILE + + UInt64 currentPos; + if (!File.Seek(0, FILE_CURRENT, currentPos)) + return E_FAIL; + bool result = File.SetLength(newSize); + UInt64 currentPos2; + result = result && File.Seek(currentPos, currentPos2); + return result ? S_OK : E_FAIL; + + #else + + // SetLength() uses ftruncate() that doesn't change file offset + if (!File.SetLength(newSize)) + return GetLastError_HRESULT(); + return S_OK; + + #endif +} + +HRESULT COutFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + +#ifdef UNDER_CE + +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fwrite(data, 1, size, stdout); + if (processedSize) + *processedSize = s2; + return (s2 == size) ? S_OK : E_FAIL; +} + +#else + +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + #ifdef _WIN32 + + UInt32 realProcessedSize; + BOOL res = TRUE; + if (size > 0) + { + // Seems that Windows doesn't like big amounts writing to stdout. + // So we limit portions by 32KB. + UInt32 sizeTemp = (1 << 15); + if (sizeTemp > size) + sizeTemp = size; + res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + data, sizeTemp, (DWORD *)&realProcessedSize, NULL); + _size += realProcessedSize; + size -= realProcessedSize; + data = (const void *)((const Byte *)data + realProcessedSize); + if (processedSize) + *processedSize += realProcessedSize; + } + return ConvertBoolToHRESULT(res != FALSE); + + #else + + ssize_t res; + + do + { + res = write(1, data, (size_t)size); + } + while (res < 0 && (errno == EINTR)); + + if (res == -1) + return GetLastError_HRESULT(); + + _size += (size_t)res; + if (processedSize) + *processedSize = (UInt32)res; + return S_OK; + + #endif +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.h new file mode 100644 index 0000000..fe9f4c1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FileStreams.h @@ -0,0 +1,151 @@ +// FileStreams.h + +#ifndef __FILE_STREAMS_H +#define __FILE_STREAMS_H + +#ifdef _WIN32 +#define USE_WIN_FILE +#endif + +#include "../../Common/MyCom.h" +#include "../../Common/MyString.h" + +#include "../../Windows/FileIO.h" + +#include "../IStream.h" + +struct IInFileStream_Callback +{ + virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; + virtual void InFileStream_On_Destroy(UINT_PTR val) = 0; +}; + +class CInFileStream: + public IInStream, + public IStreamGetSize, + public IStreamGetProps, + public IStreamGetProps2, + public CMyUnknownImp +{ +public: + NWindows::NFile::NIO::CInFile File; + + #ifdef USE_WIN_FILE + + #ifdef SUPPORT_DEVICE_FILE + UInt64 VirtPos; + UInt64 PhyPos; + UInt64 BufStartPos; + Byte *Buf; + UInt32 BufSize; + #endif + + #endif + + bool SupportHardLinks; + + IInFileStream_Callback *Callback; + UINT_PTR CallbackRef; + + virtual ~CInFileStream(); + + CInFileStream(); + + bool Open(CFSTR fileName) + { + return File.Open(fileName); + } + + bool OpenShared(CFSTR fileName, bool shareForWrite) + { + return File.OpenShared(fileName, shareForWrite); + } + + MY_QUERYINTERFACE_BEGIN2(IInStream) + MY_QUERYINTERFACE_ENTRY(IStreamGetSize) + MY_QUERYINTERFACE_ENTRY(IStreamGetProps) + MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + STDMETHOD(GetSize)(UInt64 *size); + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); + STDMETHOD(GetProps2)(CStreamFileProps *props); +}; + +class CStdInFileStream: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + virtual ~CStdInFileStream() {} + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +class COutFileStream: + public IOutStream, + public CMyUnknownImp +{ +public: + NWindows::NFile::NIO::COutFile File; + + virtual ~COutFileStream() {} + bool Create(CFSTR fileName, bool createAlways) + { + ProcessedSize = 0; + return File.Create(fileName, createAlways); + } + bool Open(CFSTR fileName, DWORD creationDisposition) + { + ProcessedSize = 0; + return File.Open(fileName, creationDisposition); + } + + HRESULT Close(); + + UInt64 ProcessedSize; + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) + { + return File.SetTime(cTime, aTime, mTime); + } + bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); + + bool SeekToBegin_bool() + { + #ifdef USE_WIN_FILE + return File.SeekToBegin(); + #else + return File.seekToBegin() == 0; + #endif + } + + HRESULT GetSize(UInt64 *size); +}; + +class CStdOutFileStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + UInt64 _size; +public: + MY_UNKNOWN_IMP + + UInt64 GetSize() const { return _size; } + CStdOutFileStream(): _size(0) {} + virtual ~CStdOutFileStream() {} + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.cpp new file mode 100644 index 0000000..fb99f61 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.cpp @@ -0,0 +1,436 @@ +// FilterCoder.cpp + +#include "StdAfx.h" + +#include "../../Common/Defs.h" + +#include "FilterCoder.h" +#include "StreamUtils.h" + +#ifdef _WIN32 + #define alignedMidBuffer_Alloc g_MidAlloc +#else + #define alignedMidBuffer_Alloc g_AlignedAlloc +#endif + +CAlignedMidBuffer::~CAlignedMidBuffer() +{ + ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf); +} + +void CAlignedMidBuffer::AllocAligned(size_t size) +{ + ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf); + _buf = (Byte *)ISzAlloc_Alloc(&alignedMidBuffer_Alloc, size); +} + +/* + AES filters need 16-bytes alignment for HARDWARE-AES instructions. + So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block. + + AES-CBC filters need data size aligned for 16-bytes. + So the encoder can add zeros to the end of original stream. + + Some filters (BCJ and others) don't process data at the end of stream in some cases. + So the encoder and decoder write such last bytes without change. +*/ + + +static const UInt32 kBufSize = 1 << 20; + +STDMETHODIMP CFilterCoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } +STDMETHODIMP CFilterCoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } + +HRESULT CFilterCoder::Alloc() +{ + UInt32 size = MyMin(_inBufSize, _outBufSize); + /* minimal bufSize is 16 bytes for AES and IA64 filter. + bufSize for AES must be aligned for 16 bytes. + We use (1 << 12) min size to support future aligned filters. */ + const UInt32 kMinSize = 1 << 12; + size &= ~(UInt32)(kMinSize - 1); + if (size < kMinSize) + size = kMinSize; + if (!_buf || _bufSize != size) + { + AllocAligned(size); + if (!_buf) + return E_OUTOFMEMORY; + _bufSize = size; + } + return S_OK; +} + +HRESULT CFilterCoder::Init_and_Alloc() +{ + RINOK(Filter->Init()); + return Alloc(); +} + +CFilterCoder::CFilterCoder(bool encodeMode): + _bufSize(0), + _inBufSize(kBufSize), + _outBufSize(kBufSize), + _encodeMode(encodeMode), + _outSizeIsDefined(false), + _outSize(0), + _nowPos64(0) + {} + +CFilterCoder::~CFilterCoder() +{ +} + +STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + RINOK(Init_and_Alloc()); + + UInt64 prev = 0; + UInt64 nowPos64 = 0; + bool inputFinished = false; + UInt32 pos = 0; + + while (!outSize || nowPos64 < *outSize) + { + if (!inputFinished) + { + size_t processedSize = _bufSize - pos; + RINOK(ReadStream(inStream, _buf + pos, &processedSize)); + pos += (UInt32)processedSize; + inputFinished = (pos != _bufSize); + } + + if (pos == 0) + return S_OK; + + UInt32 filtered = Filter->Filter(_buf, pos); + + if (filtered > pos) + { + // AES + if (!inputFinished || filtered > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + Byte *buf = _buf; + do + buf[pos] = 0; + while (++pos != filtered); + + if (filtered != Filter->Filter(buf, filtered)) + return E_FAIL; + } + + UInt32 size = (filtered != 0 ? filtered : pos); + if (outSize) + { + const UInt64 remSize = *outSize - nowPos64; + if (size > remSize) + size = (UInt32)remSize; + } + + RINOK(WriteStream(outStream, _buf, size)); + nowPos64 += size; + + if (filtered == 0) + return S_OK; + pos -= filtered; + for (UInt32 i = 0; i < pos; i++) + _buf[i] = _buf[filtered++]; + + if (progress && (nowPos64 - prev) >= (1 << 22)) + { + prev = nowPos64; + RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); + } + } + + return S_OK; +} + + + +// ---------- Write to Filter ---------- + +STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) +{ + _outStream = outStream; + return S_OK; +} + +STDMETHODIMP CFilterCoder::ReleaseOutStream() +{ + _outStream.Release(); + return S_OK; +} + +HRESULT CFilterCoder::Flush2() +{ + while (_convSize != 0) + { + UInt32 num = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (num > rem) + num = (UInt32)rem; + if (num == 0) + return k_My_HRESULT_WritingWasCut; + } + + UInt32 processed = 0; + HRESULT res = _outStream->Write(_buf + _convPos, num, &processed); + if (processed == 0) + return res != S_OK ? res : E_FAIL; + + _convPos += processed; + _convSize -= processed; + _nowPos64 += processed; + RINOK(res); + } + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + return S_OK; +} + +STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + RINOK(Flush2()); + + // _convSize is 0 + // _convPos is 0 + // _bufPos is small + + if (_bufPos != _bufSize) + { + UInt32 num = MyMin(size, _bufSize - _bufPos); + memcpy(_buf + _bufPos, data, num); + size -= num; + data = (const Byte *)data + num; + if (processedSize) + *processedSize += num; + _bufPos += num; + if (_bufPos != _bufSize) + continue; + } + + // _bufPos == _bufSize + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) + break; + if (_convSize > _bufPos) + { + // that case is not possible. + _convSize = 0; + return E_FAIL; + } + } + + return S_OK; +} + +STDMETHODIMP CFilterCoder::OutStreamFinish() +{ + for (;;) + { + RINOK(Flush2()); + if (_bufPos == 0) + break; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize == 0) + _convSize = _bufPos; + else if (_convSize > _bufPos) + { + // AES + if (_convSize > _bufSize) + { + _convSize = 0; + return E_FAIL; + } + if (!_encodeMode) + { + _convSize = 0; + return S_FALSE; + } + for (; _bufPos < _convSize; _bufPos++) + _buf[_bufPos] = 0; + _convSize = Filter->Filter(_buf, _bufPos); + if (_convSize != _bufPos) + return E_FAIL; + } + } + + CMyComPtr finish; + _outStream.QueryInterface(IID_IOutStreamFinish, &finish); + if (finish) + return finish->OutStreamFinish(); + return S_OK; +} + +// ---------- Init functions ---------- + +STDMETHODIMP CFilterCoder::InitEncoder() +{ + InitSpecVars(); + return Init_and_Alloc(); +} + +HRESULT CFilterCoder::Init_NoSubFilterInit() +{ + InitSpecVars(); + return Alloc(); +} + +STDMETHODIMP CFilterCoder::SetOutStreamSize(const UInt64 *outSize) +{ + InitSpecVars(); + if (outSize) + { + _outSize = *outSize; + _outSizeIsDefined = true; + } + return Init_and_Alloc(); +} + +// ---------- Read from Filter ---------- + +STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) +{ + _inStream = inStream; + return S_OK; +} + +STDMETHODIMP CFilterCoder::ReleaseInStream() +{ + _inStream.Release(); + return S_OK; +} + + +STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + while (size != 0) + { + if (_convSize != 0) + { + if (size > _convSize) + size = _convSize; + if (_outSizeIsDefined) + { + UInt64 rem = _outSize - _nowPos64; + if (size > rem) + size = (UInt32)rem; + } + memcpy(data, _buf + _convPos, size); + _convPos += size; + _convSize -= size; + _nowPos64 += size; + if (processedSize) + *processedSize = size; + break; + } + + if (_convPos != 0) + { + UInt32 num = _bufPos - _convPos; + for (UInt32 i = 0; i < num; i++) + _buf[i] = _buf[_convPos + i]; + _bufPos = num; + _convPos = 0; + } + + { + size_t readSize = _bufSize - _bufPos; + HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize); + _bufPos += (UInt32)readSize; + RINOK(res); + } + + _convSize = Filter->Filter(_buf, _bufPos); + + if (_convSize == 0) + { + if (_bufPos == 0) + break; + // BCJ + _convSize = _bufPos; + continue; + } + + if (_convSize > _bufPos) + { + // AES + if (_convSize > _bufSize) + return E_FAIL; + if (!_encodeMode) + return S_FALSE; + + do + _buf[_bufPos] = 0; + while (++_bufPos != _convSize); + + _convSize = Filter->Filter(_buf, _convSize); + if (_convSize != _bufPos) + return E_FAIL; + } + } + + return S_OK; +} + + +#ifndef _NO_CRYPTO + +STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) + { return _SetPassword->CryptoSetPassword(data, size); } + +STDMETHODIMP CFilterCoder::SetKey(const Byte *data, UInt32 size) + { return _CryptoProperties->SetKey(data, size); } + +STDMETHODIMP CFilterCoder::SetInitVector(const Byte *data, UInt32 size) + { return _CryptoProperties->SetInitVector(data, size); } + +#endif + + +#ifndef EXTRACT_ONLY + +STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) + { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } + +STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) + { return _WriteCoderProperties->WriteCoderProperties(outStream); } + +/* +STDMETHODIMP CFilterCoder::ResetSalt() + { return _CryptoResetSalt->ResetSalt(); } +*/ + +STDMETHODIMP CFilterCoder::ResetInitVector() + { return _CryptoResetInitVector->ResetInitVector(); } + +#endif + + +STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) + { return _SetDecoderProperties2->SetDecoderProperties2(data, size); } diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.h new file mode 100644 index 0000000..6668fdb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/FilterCoder.h @@ -0,0 +1,205 @@ +// FilterCoder.h + +#ifndef __FILTER_CODER_H +#define __FILTER_CODER_H + +#include "../../../C/Alloc.h" + +#include "../../Common/MyCom.h" +#include "../ICoder.h" + +#ifndef _NO_CRYPTO +#include "../IPassword.h" +#endif + +#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \ + { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ + *outObject = (void *)(i *)this; } + + +struct CAlignedMidBuffer +{ + Byte *_buf; + + CAlignedMidBuffer(): _buf(NULL) {} + ~CAlignedMidBuffer(); + void AllocAligned(size_t size); +}; + +class CFilterCoder: + public ICompressCoder, + + public ICompressSetOutStreamSize, + public ICompressInitEncoder, + + public ICompressSetInStream, + public ISequentialInStream, + + public ICompressSetOutStream, + public ISequentialOutStream, + public IOutStreamFinish, + + public ICompressSetBufSize, + + #ifndef _NO_CRYPTO + public ICryptoSetPassword, + public ICryptoProperties, + #endif + + #ifndef EXTRACT_ONLY + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + // public ICryptoResetSalt, + public ICryptoResetInitVector, + #endif + + public ICompressSetDecoderProperties2, + public CMyUnknownImp, + public CAlignedMidBuffer +{ + UInt32 _bufSize; + UInt32 _inBufSize; + UInt32 _outBufSize; + + bool _encodeMode; + bool _outSizeIsDefined; + UInt64 _outSize; + UInt64 _nowPos64; + + CMyComPtr _inStream; + CMyComPtr _outStream; + UInt32 _bufPos; + UInt32 _convPos; // current pos in buffer for converted data + UInt32 _convSize; // size of converted data starting from _convPos + + void InitSpecVars() + { + _bufPos = 0; + _convPos = 0; + _convSize = 0; + + _outSizeIsDefined = false; + _outSize = 0; + _nowPos64 = 0; + } + + HRESULT Alloc(); + HRESULT Init_and_Alloc(); + HRESULT Flush2(); + + #ifndef _NO_CRYPTO + CMyComPtr _SetPassword; + CMyComPtr _CryptoProperties; + #endif + + #ifndef EXTRACT_ONLY + CMyComPtr _SetCoderProperties; + CMyComPtr _WriteCoderProperties; + // CMyComPtr _CryptoResetSalt; + CMyComPtr _CryptoResetInitVector; + #endif + + CMyComPtr _SetDecoderProperties2; + +public: + CMyComPtr Filter; + + CFilterCoder(bool encodeMode); + ~CFilterCoder(); + + class C_InStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_InStream_Releaser(): FilterCoder(NULL) {} + ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } + }; + + class C_OutStream_Releaser + { + public: + CFilterCoder *FilterCoder; + C_OutStream_Releaser(): FilterCoder(NULL) {} + ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } + }; + + class C_Filter_Releaser + { + public: + CFilterCoder *FilterCoder; + C_Filter_Releaser(): FilterCoder(NULL) {} + ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); } + }; + + + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ICompressInitEncoder) + + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) + MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) + MY_QUERYINTERFACE_ENTRY(IOutStreamFinish) + + MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) + + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _SetPassword) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoProperties, Filter, _CryptoProperties) + #endif + + #ifndef EXTRACT_ONLY + MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) + MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _WriteCoderProperties) + // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) + MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) + #endif + + MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _SetDecoderProperties2) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(InitEncoder)(); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(OutStreamFinish)(); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + #ifndef _NO_CRYPTO + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); + + STDMETHOD(SetKey)(const Byte *data, UInt32 size); + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); + #endif + + #ifndef EXTRACT_ONLY + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + // STDMETHOD(ResetSalt)(); + STDMETHOD(ResetInitVector)(); + #endif + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + + HRESULT Init_NoSubFilterInit(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.cpp new file mode 100644 index 0000000..6f6eeca --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.cpp @@ -0,0 +1,163 @@ +// InBuffer.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "InBuffer.h" + +CInBufferBase::CInBufferBase() throw(): + _buf(0), + _bufLim(0), + _bufBase(0), + _stream(0), + _processedSize(0), + _bufSize(0), + _wasFinished(false), + NumExtraBytes(0) +{} + +bool CInBuffer::Create(size_t bufSize) throw() +{ + const unsigned kMinBlockSize = 1; + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_bufBase != 0 && _bufSize == bufSize) + return true; + Free(); + _bufSize = bufSize; + _bufBase = (Byte *)::MidAlloc(bufSize); + return (_bufBase != 0); +} + +void CInBuffer::Free() throw() +{ + ::MidFree(_bufBase); + _bufBase = 0; +} + +void CInBufferBase::Init() throw() +{ + _processedSize = 0; + _buf = _bufBase; + _bufLim = _buf; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif + NumExtraBytes = 0; +} + +bool CInBufferBase::ReadBlock() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return false; + #endif + if (_wasFinished) + return false; + _processedSize += (size_t)(_buf - _bufBase); + _buf = _bufBase; + _bufLim = _bufBase; + UInt32 processed; + // FIX_ME: we can improve it to support (_bufSize >= (1 << 32)) + HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw CInBufferException(result); + #endif + _bufLim = _buf + processed; + _wasFinished = (processed == 0); + return !_wasFinished; +} + +bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) +{ + if (!ReadBlock()) + { + NumExtraBytes++; + b = 0xFF; + return false; + } + b = *_buf++; + return true; +} + +Byte CInBufferBase::ReadByte_FromNewBlock() +{ + if (!ReadBlock()) + { + NumExtraBytes++; + return 0xFF; + } + return *_buf++; +} + +size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) +{ + size_t num = 0; + for (;;) + { + const size_t rem = (size_t)(_bufLim - _buf); + if (size <= rem) + { + if (size != 0) + { + memcpy(buf, _buf, size); + _buf += size; + num += size; + } + return num; + } + if (rem != 0) + { + memcpy(buf, _buf, rem); + _buf += rem; + buf += rem; + num += rem; + size -= rem; + } + if (!ReadBlock()) + return num; + } + + /* + if ((size_t)(_bufLim - _buf) >= size) + { + const Byte *src = _buf; + for (size_t i = 0; i < size; i++) + buf[i] = src[i]; + _buf += size; + return size; + } + for (size_t i = 0; i < size; i++) + { + if (_buf >= _bufLim) + if (!ReadBlock()) + return i; + buf[i] = *_buf++; + } + return size; + */ +} + +size_t CInBufferBase::Skip(size_t size) +{ + size_t processed = 0; + for (;;) + { + const size_t rem = (size_t)(_bufLim - _buf); + if (rem >= size) + { + _buf += size; + return processed + size; + } + _buf += rem; + processed += rem; + size -= rem; + if (!ReadBlock()) + return processed; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.h new file mode 100644 index 0000000..fa06394 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InBuffer.h @@ -0,0 +1,109 @@ +// InBuffer.h + +#ifndef __IN_BUFFER_H +#define __IN_BUFFER_H + +#include "../../Common/MyException.h" +#include "../IStream.h" + +#ifndef _NO_EXCEPTIONS +struct CInBufferException: public CSystemException +{ + CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} +}; +#endif + +class CInBufferBase +{ +protected: + Byte *_buf; + Byte *_bufLim; + Byte *_bufBase; + + ISequentialInStream *_stream; + UInt64 _processedSize; + size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger + // only up to 32-bits values now are supported! + bool _wasFinished; + + bool ReadBlock(); + bool ReadByte_FromNewBlock(Byte &b); + Byte ReadByte_FromNewBlock(); + +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + UInt32 NumExtraBytes; + + CInBufferBase() throw(); + + // the size of portion of data in real stream that was already read from this object + // it doesn't include unused data in buffer + // it doesn't include virtual Extra bytes after the end of real stream data + UInt64 GetStreamSize() const { return _processedSize + (size_t)(_buf - _bufBase); } + + // the size of virtual data that was read from this object + // it doesn't include unused data in buffers + // it includes any virtual Extra bytes after the end of real data + UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (size_t)(_buf - _bufBase); } + + bool WasFinished() const { return _wasFinished; } + + void SetStream(ISequentialInStream *stream) { _stream = stream; } + + void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos) + { + _bufBase = buf; + _bufSize = bufSize; + _processedSize = 0; + _buf = buf + pos; + _bufLim = buf + end; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif + NumExtraBytes = 0; + } + + void Init() throw(); + + MY_FORCE_INLINE + bool ReadByte(Byte &b) + { + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(b); + b = *_buf++; + return true; + } + + MY_FORCE_INLINE + bool ReadByte_FromBuf(Byte &b) + { + if (_buf >= _bufLim) + return false; + b = *_buf++; + return true; + } + + MY_FORCE_INLINE + Byte ReadByte() + { + if (_buf >= _bufLim) + return ReadByte_FromNewBlock(); + return *_buf++; + } + + size_t ReadBytes(Byte *buf, size_t size); + size_t Skip(size_t size); +}; + +class CInBuffer: public CInBufferBase +{ +public: + ~CInBuffer() { Free(); } + bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported! + void Free() throw(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.cpp new file mode 100644 index 0000000..cae6b80 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.cpp @@ -0,0 +1,171 @@ +// InOutTempBuffer.cpp + +#include "StdAfx.h" + +#include "InOutTempBuffer.h" +#include "StreamUtils.h" + +#ifdef USE_InOutTempBuffer_FILE + +#include "../../../C/7zCrc.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static const size_t kTempBufSize = (1 << 20); + +#define kTempFilePrefixString FTEXT("7zt") +CInOutTempBuffer::~CInOutTempBuffer() +{ + delete []_buf; +} +#endif + +CInOutTempBuffer::CInOutTempBuffer() + #ifdef USE_InOutTempBuffer_FILE + : _buf(NULL) + #endif +{ } + +void CInOutTempBuffer::Create() +{ + #ifdef USE_InOutTempBuffer_FILE + if (!_buf) + _buf = new Byte[kTempBufSize]; + #endif +} + +void CInOutTempBuffer::InitWriting() +{ + #ifdef USE_InOutTempBuffer_FILE + _bufPos = 0; + _crc = CRC_INIT_VAL; + _tempFileCreated = false; + #endif + _size = 0; +} + + +#ifdef USE_InOutTempBuffer_FILE + +static inline HRESULT Get_HRESULT_LastError() +{ + #ifdef _WIN32 + DWORD lastError = ::GetLastError(); + if (lastError != 0) + return HRESULT_FROM_WIN32(lastError); + #endif + return E_FAIL; +} + +#endif + + +HRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size) +{ + #ifdef USE_InOutTempBuffer_FILE + + if (size == 0) + return S_OK; + size_t cur = kTempBufSize - _bufPos; + if (cur != 0) + { + if (cur > size) + cur = size; + memcpy(_buf + _bufPos, data, cur); + _crc = CrcUpdate(_crc, data, cur); + _bufPos += cur; + _size += cur; + size -= (UInt32)cur; + data = ((const Byte *)data) + cur; + } + + if (size == 0) + return S_OK; + + if (!_tempFileCreated) + { + if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) + return Get_HRESULT_LastError(); + _tempFileCreated = true; + } + UInt32 processed; + if (!_outFile.Write(data, size, processed)) + return Get_HRESULT_LastError(); + _crc = CrcUpdate(_crc, data, processed); + _size += processed; + return (processed == size) ? S_OK : E_FAIL; + + #else + + const size_t newSize = _size + size; + if (newSize < _size) + return E_OUTOFMEMORY; + if (!_dynBuffer.EnsureCapacity(newSize)) + return E_OUTOFMEMORY; + memcpy(((Byte *)_dynBuffer) + _size, data, size); + _size = newSize; + return S_OK; + + #endif +} + + +HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) +{ + #ifdef USE_InOutTempBuffer_FILE + + if (!_outFile.Close()) + return E_FAIL; + + UInt64 size = 0; + UInt32 crc = CRC_INIT_VAL; + + if (_bufPos != 0) + { + RINOK(WriteStream(stream, _buf, _bufPos)); + crc = CrcUpdate(crc, _buf, _bufPos); + size += _bufPos; + } + + if (_tempFileCreated) + { + NIO::CInFile inFile; + if (!inFile.Open(_tempFile.GetPath())) + return E_FAIL; + while (size < _size) + { + UInt32 processed; + if (!inFile.ReadPart(_buf, kTempBufSize, processed)) + return E_FAIL; + if (processed == 0) + break; + RINOK(WriteStream(stream, _buf, processed)); + crc = CrcUpdate(crc, _buf, processed); + size += processed; + } + } + return (_crc == crc && size == _size) ? S_OK : E_FAIL; + + #else + + return WriteStream(stream, (const Byte *)_dynBuffer, _size); + + #endif +} + +/* +STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processed) +{ + if (!_buf->Write(data, size)) + { + if (processed) + *processed = 0; + return E_FAIL; + } + if (processed) + *processed = size; + return S_OK; +} +*/ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.h new file mode 100644 index 0000000..755935e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/InOutTempBuffer.h @@ -0,0 +1,66 @@ +// InOutTempBuffer.h + +#ifndef __IN_OUT_TEMP_BUFFER_H +#define __IN_OUT_TEMP_BUFFER_H + +#ifdef _WIN32 +// #define USE_InOutTempBuffer_FILE +#endif + +#ifdef USE_InOutTempBuffer_FILE +#include "../../Windows/FileDir.h" +#else +#include "StreamObjects.h" +#endif + +#include "../IStream.h" + +class CInOutTempBuffer +{ + #ifdef USE_InOutTempBuffer_FILE + + NWindows::NFile::NDir::CTempFile _tempFile; + NWindows::NFile::NIO::COutFile _outFile; + bool _tempFileCreated; + Byte *_buf; + size_t _bufPos; + UInt64 _size; + UInt32 _crc; + + #else + + CByteDynBuffer _dynBuffer; + size_t _size; + + #endif + + CLASS_NO_COPY(CInOutTempBuffer); +public: + CInOutTempBuffer(); + void Create(); + + #ifdef USE_InOutTempBuffer_FILE + ~CInOutTempBuffer(); + #endif + + void InitWriting(); + HRESULT Write_HRESULT(const void *data, UInt32 size); + HRESULT WriteToStream(ISequentialOutStream *stream); + UInt64 GetDataSize() const { return _size; } +}; + +/* +class CSequentialOutTempBufferImp: + public ISequentialOutStream, + public CMyUnknownImp +{ + CInOutTempBuffer *_buf; +public: + void Init(CInOutTempBuffer *buffer) { _buf = buffer; } + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.cpp new file mode 100644 index 0000000..add6636 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.cpp @@ -0,0 +1,367 @@ +// LimitedStreams.cpp + +#include "StdAfx.h" + +#include + +#include "LimitedStreams.h" + +STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + { + const UInt64 rem = _size - _pos; + if (size > rem) + size = (UInt32)rem; + } + HRESULT result = S_OK; + if (size != 0) + { + result = _stream->Read(data, size, &realProcessedSize); + _pos += realProcessedSize; + if (realProcessedSize == 0) + _wasFinished = true; + } + if (processedSize) + *processedSize = realProcessedSize; + return result; +} + +STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= _size) + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } + { + const UInt64 rem = _size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } + UInt64 newPos = _startOffset + _virtPos; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + HRESULT res = _stream->Read(data, size, &size); + if (processedSize) + *processedSize = size; + _physPos += size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream) +{ + *resStream = 0; + CLimitedInStream *streamSpec = new CLimitedInStream; + CMyComPtr streamTemp = streamSpec; + streamSpec->SetStream(inStream); + RINOK(streamSpec->InitAndSeek(pos, size)); + streamSpec->SeekToStart(); + *resStream = streamTemp.Detach(); + return S_OK; +} + +STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= Size) + return S_OK; + { + UInt64 rem = Size - _virtPos; + if (size > rem) + size = (UInt32)rem; + } + if (size == 0) + return S_OK; + + if (_curRem == 0) + { + const UInt32 blockSize = (UInt32)1 << BlockSizeLog; + const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); + const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); + const UInt32 phyBlock = Vector[virtBlock]; + + UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + + _curRem = blockSize - offsetInBlock; + + for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) + _curRem += (UInt32)1 << BlockSizeLog; + } + + if (size > _curRem) + size = _curRem; + HRESULT res = Stream->Read(data, size, &size); + if (processedSize) + *processedSize = size; + _physPos += size; + _virtPos += size; + _curRem -= size; + return res; +} + +STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + if (_virtPos != (UInt64)offset) + _curRem = 0; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} + + +STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= Extents.Back().Virt) + return S_OK; + if (size == 0) + return S_OK; + + unsigned left = 0, right = Extents.Size() - 1; + for (;;) + { + unsigned mid = (left + right) / 2; + if (mid == left) + break; + if (_virtPos < Extents[mid].Virt) + right = mid; + else + left = mid; + } + + const CSeekExtent &extent = Extents[left]; + UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt); + if (_needStartSeek || _phyPos != phyPos) + { + _needStartSeek = false; + _phyPos = phyPos; + RINOK(SeekToPhys()); + } + + UInt64 rem = Extents[left + 1].Virt - _virtPos; + if (size > rem) + size = (UInt32)rem; + + HRESULT res = Stream->Read(data, size, &size); + _phyPos += size; + _virtPos += size; + if (processedSize) + *processedSize = size; + return res; +} + +STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += Extents.Back().Virt; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + + +STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (processedSize) + *processedSize = 0; + if (size > _size) + { + if (_size == 0) + { + _overflow = true; + if (!_overflowIsAllowed) + return E_FAIL; + if (processedSize) + *processedSize = size; + return S_OK; + } + size = (UInt32)_size; + } + if (_stream) + result = _stream->Write(data, size, &size); + _size -= size; + if (processedSize) + *processedSize = size; + return result; +} + + +STDMETHODIMP CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Read(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + return res; +} + +STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: + { + UInt64 pos = 0; + RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos)); + if (pos < Offset) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = pos - Offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; + } + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (_virtPos >= _size) + { + // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case. + return S_OK; + // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF + } + UInt64 rem = _size - _virtPos; + if (rem < size) + size = (UInt32)rem; + + UInt64 newPos = _startOffset + _virtPos; + UInt64 offsetInCache = newPos - _cachePhyPos; + HRESULT res = S_OK; + if (newPos >= _cachePhyPos && + offsetInCache <= _cacheSize && + size <= _cacheSize - (size_t)offsetInCache) + { + if (size != 0) + memcpy(data, _cache + (size_t)offsetInCache, size); + } + else + { + if (newPos != _physPos) + { + _physPos = newPos; + RINOK(SeekToPhys()); + } + res = _stream->Read(data, size, &size); + _physPos += size; + } + if (processedSize) + *processedSize = size; + _virtPos += size; + return res; +} + +STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = _virtPos; + return S_OK; +} + +STDMETHODIMP CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 cur; + HRESULT res = Stream->Write(data, size, &cur); + if (processedSize) + *processedSize = cur; + _virtPos += cur; + if (_virtSize < _virtPos) + _virtSize = _virtPos; + return res; +} + +STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _virtPos; break; + case STREAM_SEEK_END: offset += _virtSize; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _virtPos = (UInt64)offset; + if (newPosition) + *newPosition = _virtPos; + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize) +{ + _virtSize = newSize; + return Stream->SetSize(Offset + newSize); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.h new file mode 100644 index 0000000..ade2993 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LimitedStreams.h @@ -0,0 +1,252 @@ +// LimitedStreams.h + +#ifndef __LIMITED_STREAMS_H +#define __LIMITED_STREAMS_H + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" +#include "../IStream.h" + +class CLimitedSequentialInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + UInt64 _pos; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(UInt64 streamSize) + { + _size = streamSize; + _pos = 0; + _wasFinished = false; + } + + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + UInt64 GetSize() const { return _pos; } + UInt64 GetRem() const { return _size - _pos; } + bool WasFinished() const { return _wasFinished; } +}; + +class CLimitedInStream: + public IInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _size; + UInt64 _startOffset; + + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } +public: + void SetStream(IInStream *stream) { _stream = stream; } + HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) + { + _startOffset = startOffset; + _physPos = startOffset; + _virtPos = 0; + _size = size; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } +}; + +HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); + +class CClusterInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _physPos; + UInt32 _curRem; +public: + unsigned BlockSizeLog; + UInt64 Size; + CMyComPtr Stream; + CRecordVector Vector; + UInt64 StartOffset; + + HRESULT SeekToPhys() { return Stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } + + HRESULT InitAndSeek() + { + _curRem = 0; + _virtPos = 0; + _physPos = StartOffset; + if (Vector.Size() > 0) + { + _physPos = StartOffset + (Vector[0] << BlockSizeLog); + return SeekToPhys(); + } + return S_OK; + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +struct CSeekExtent +{ + UInt64 Phy; + UInt64 Virt; +}; + +class CExtentsStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _phyPos; + UInt64 _virtPos; + bool _needStartSeek; + + HRESULT SeekToPhys() { return Stream->Seek((Int64)_phyPos, STREAM_SEEK_SET, NULL); } + +public: + CMyComPtr Stream; + CRecordVector Extents; + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + void ReleaseStream() { Stream.Release(); } + + void Init() + { + _virtPos = 0; + _phyPos = 0; + _needStartSeek = true; + } +}; + +class CLimitedSequentialOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + bool _overflow; + bool _overflowIsAllowed; +public: + MY_UNKNOWN_IMP1(ISequentialOutStream) + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(UInt64 size, bool overflowIsAllowed = false) + { + _size = size; + _overflow = false; + _overflowIsAllowed = overflowIsAllowed; + } + bool IsFinishedOK() const { return (_size == 0 && !_overflow); } + UInt64 GetRem() const { return _size; } +}; + + +class CTailInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _virtPos; +public: + CMyComPtr Stream; + UInt64 Offset; + + void Init() + { + _virtPos = 0; + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Stream->Seek((Int64)Offset, STREAM_SEEK_SET, NULL); } +}; + +class CLimitedCachedInStream: + public IInStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _virtPos; + UInt64 _physPos; + UInt64 _size; + UInt64 _startOffset; + + const Byte *_cache; + size_t _cacheSize; + size_t _cachePhyPos; + + + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } +public: + CByteBuffer Buffer; + + void SetStream(IInStream *stream) { _stream = stream; } + void SetCache(size_t cacheSize, size_t cachePos) + { + _cache = Buffer; + _cacheSize = cacheSize; + _cachePhyPos = cachePos; + } + + HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) + { + _startOffset = startOffset; + _physPos = startOffset; + _virtPos = 0; + _size = size; + return SeekToPhys(); + } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } +}; + +class CTailOutStream: + public IOutStream, + public CMyUnknownImp +{ + UInt64 _virtPos; + UInt64 _virtSize; +public: + CMyComPtr Stream; + UInt64 Offset; + + virtual ~CTailOutStream() {} + + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream) + + void Init() + { + _virtPos = 0; + _virtSize = 0; + } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.cpp new file mode 100644 index 0000000..ca39fb4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.cpp @@ -0,0 +1,3 @@ +// LockedStream.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.h new file mode 100644 index 0000000..efebf19 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/LockedStream.h @@ -0,0 +1,6 @@ +// LockedStream.h + +#ifndef __LOCKED_STREAM_H +#define __LOCKED_STREAM_H + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.cpp new file mode 100644 index 0000000..1566c97 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.cpp @@ -0,0 +1,3 @@ +// MethodId.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.h new file mode 100644 index 0000000..28b615f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodId.h @@ -0,0 +1,10 @@ +// MethodId.h + +#ifndef __7Z_METHOD_ID_H +#define __7Z_METHOD_ID_H + +#include "../../Common/MyTypes.h" + +typedef UInt64 CMethodId; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.cpp new file mode 100644 index 0000000..3ab89dd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.cpp @@ -0,0 +1,542 @@ +// MethodProps.cpp + +#include "StdAfx.h" + +#include "../../Common/StringToInt.h" + +#include "MethodProps.h" + +using namespace NWindows; + +bool StringToBool(const wchar_t *s, bool &res) +{ + if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) + { + res = true; + return true; + } + if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF")) + { + res = false; + return true; + } + return false; +} + +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest) +{ + switch (prop.vt) + { + case VT_EMPTY: dest = true; return S_OK; + case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK; + case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG; + } + return E_INVALIDARG; +} + +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + number = ConvertStringToUInt32(start, &end); + return (unsigned)(end - start); +} + +static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number) +{ + const wchar_t *start = srcString; + const wchar_t *end; + number = ConvertStringToUInt64(start, &end); + return (unsigned)(end - start); +} + +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) +{ + // =VT_UI4 + // =VT_EMPTY + // {stringUInt32}=VT_EMPTY + + if (prop.vt == VT_UI4) + { + if (!name.IsEmpty()) + return E_INVALIDARG; + resValue = prop.ulVal; + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + if (name.IsEmpty()) + return S_OK; + UInt32 v; + if (ParseStringToUInt32(name, v) != name.Len()) + return E_INVALIDARG; + resValue = v; + return S_OK; +} + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) +{ + if (name.IsEmpty()) + { + switch (prop.vt) + { + case VT_UI4: + numThreads = prop.ulVal; + break; + default: + { + bool val; + RINOK(PROPVARIANT_to_bool(prop, val)); + numThreads = (val ? defaultNumThreads : 1); + break; + } + } + return S_OK; + } + if (prop.vt != VT_EMPTY) + return E_INVALIDARG; + return ParsePropToUInt32(name, prop, numThreads); +} + + +static HRESULT SetLogSizeProp(UInt64 number, NCOM::CPropVariant &destProp) +{ + if (number >= 64) + return E_INVALIDARG; + UInt32 val32; + if (number < 32) + val32 = (UInt32)1 << (unsigned)number; + /* + else if (number == 32 && reduce_4GB_to_32bits) + val32 = (UInt32)(Int32)-1; + */ + else + { + destProp = (UInt64)((UInt64)1 << (unsigned)number); + return S_OK; + } + destProp = (UInt32)val32; + return S_OK; +} + + +static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp) +{ + /* if (reduce_4GB_to_32bits) we can reduce (4 GiB) property to (4 GiB - 1). + to fit the value to UInt32 for clients that do not support 64-bit values */ + + const wchar_t *end; + const UInt64 number = ConvertStringToUInt64(s, &end); + const unsigned numDigits = (unsigned)(end - s.Ptr()); + if (numDigits == 0 || s.Len() > numDigits + 1) + return E_INVALIDARG; + + if (s.Len() == numDigits) + return SetLogSizeProp(number, destProp); + + unsigned numBits; + + switch (MyCharLower_Ascii(s[numDigits])) + { + case 'b': numBits = 0; break; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + default: return E_INVALIDARG; + } + + const UInt64 range4g = ((UInt64)1 << (32 - numBits)); + if (number < range4g) + destProp = (UInt32)((UInt32)number << numBits); + /* + else if (number == range4g && reduce_4GB_to_32bits) + destProp = (UInt32)(Int32)-1; + */ + else if (numBits == 0) + destProp = (UInt64)number; + else if (number >= ((UInt64)1 << (64 - numBits))) + return E_INVALIDARG; + else + destProp = (UInt64)((UInt64)number << numBits); + return S_OK; +} + + +static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp) +{ + if (prop.vt == VT_UI4) + return SetLogSizeProp(prop.ulVal, destProp); + + if (prop.vt == VT_BSTR) + { + UString s; + s = prop.bstrVal; + return StringToDictSize(s, destProp); + } + return E_INVALIDARG; +} + + +void CProps::AddProp32(PROPID propid, UInt32 val) +{ + CProp &prop = Props.AddNew(); + prop.IsOptional = true; + prop.Id = propid; + prop.Value = (UInt32)val; +} + +void CProps::AddPropBool(PROPID propid, bool val) +{ + CProp &prop = Props.AddNew(); + prop.IsOptional = true; + prop.Id = propid; + prop.Value = val; +} + +class CCoderProps +{ + PROPID *_propIDs; + NCOM::CPropVariant *_props; + unsigned _numProps; + unsigned _numPropsMax; +public: + CCoderProps(unsigned numPropsMax): + _propIDs(NULL), + _props(NULL), + _numProps(0), + _numPropsMax(numPropsMax) + { + _propIDs = new PROPID[numPropsMax]; + _props = new NCOM::CPropVariant[numPropsMax]; + } + ~CCoderProps() + { + delete []_propIDs; + delete []_props; + } + void AddProp(const CProp &prop); + HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties) + { + return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps); + } +}; + +void CCoderProps::AddProp(const CProp &prop) +{ + if (_numProps >= _numPropsMax) + throw 1; + _propIDs[_numProps] = prop.Id; + _props[_numProps] = prop.Value; + _numProps++; +} + +HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const +{ + return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL); +} + +HRESULT CProps::SetCoderProps_DSReduce_Aff( + ICompressSetCoderProperties *scp, + const UInt64 *dataSizeReduce, + const UInt64 *affinity) const +{ + CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) ); + FOR_VECTOR (i, Props) + coderProps.AddProp(Props[i]); + if (dataSizeReduce) + { + CProp prop; + prop.Id = NCoderPropID::kReduceSize; + prop.Value = *dataSizeReduce; + coderProps.AddProp(prop); + } + if (affinity) + { + CProp prop; + prop.Id = NCoderPropID::kAffinity; + prop.Value = *affinity; + coderProps.AddProp(prop); + } + return coderProps.SetProps(scp); +} + + +int CMethodProps::FindProp(PROPID id) const +{ + for (int i = (int)Props.Size() - 1; i >= 0; i--) + if (Props[(unsigned)i].Id == id) + return i; + return -1; +} + +unsigned CMethodProps::GetLevel() const +{ + int i = FindProp(NCoderPropID::kLevel); + if (i < 0) + return 5; + if (Props[(unsigned)i].Value.vt != VT_UI4) + return 9; + UInt32 level = Props[(unsigned)i].Value.ulVal; + return level > 9 ? 9 : (unsigned)level; +} + +struct CNameToPropID +{ + VARTYPE VarType; + const char *Name; +}; + + +// the following are related to NCoderPropID::EEnum values + +static const CNameToPropID g_NameToPropID[] = +{ + { VT_UI4, "" }, + { VT_UI4, "d" }, + { VT_UI4, "mem" }, + { VT_UI4, "o" }, + { VT_UI4, "c" }, + { VT_UI4, "pb" }, + { VT_UI4, "lc" }, + { VT_UI4, "lp" }, + { VT_UI4, "fb" }, + { VT_BSTR, "mf" }, + { VT_UI4, "mc" }, + { VT_UI4, "pass" }, + { VT_UI4, "a" }, + { VT_UI4, "mt" }, + { VT_BOOL, "eos" }, + { VT_UI4, "x" }, + { VT_UI8, "reduce" }, + { VT_UI8, "expect" }, + { VT_UI4, "b" }, + { VT_UI4, "check" }, + { VT_BSTR, "filter" }, + { VT_UI8, "memuse" } +}; + +static int FindPropIdExact(const UString &name) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++) + if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) + return (int)i; + return -1; +} + +static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) +{ + if (varType == srcProp.vt) + { + destProp = srcProp; + return true; + } + + if (varType == VT_UI8 && srcProp.vt == VT_UI4) + { + destProp = (UInt64)srcProp.ulVal; + return true; + } + + if (varType == VT_BOOL) + { + bool res; + if (PROPVARIANT_to_bool(srcProp, res) != S_OK) + return false; + destProp = res; + return true; + } + if (srcProp.vt == VT_EMPTY) + { + destProp = srcProp; + return true; + } + return false; +} + +static void SplitParams(const UString &srcString, UStringVector &subStrings) +{ + subStrings.Clear(); + UString s; + unsigned len = srcString.Len(); + if (len == 0) + return; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L':') + { + subStrings.Add(s); + s.Empty(); + } + else + s += c; + } + subStrings.Add(s); +} + +static void SplitParam(const UString ¶m, UString &name, UString &value) +{ + int eqPos = param.Find(L'='); + if (eqPos >= 0) + { + name.SetFrom(param, (unsigned)eqPos); + value = param.Ptr((unsigned)(eqPos + 1)); + return; + } + unsigned i; + for (i = 0; i < param.Len(); i++) + { + wchar_t c = param[i]; + if (c >= L'0' && c <= L'9') + break; + } + name.SetFrom(param, i); + value = param.Ptr(i); +} + +static bool IsLogSizeProp(PROPID propid) +{ + switch (propid) + { + case NCoderPropID::kDictionarySize: + case NCoderPropID::kUsedMemorySize: + case NCoderPropID::kBlockSize: + case NCoderPropID::kBlockSize2: + // case NCoderPropID::kReduceSize: + return true; + } + return false; +} + +HRESULT CMethodProps::SetParam(const UString &name, const UString &value) +{ + int index = FindPropIdExact(name); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; + CProp prop; + prop.Id = (unsigned)index; + + if (IsLogSizeProp(prop.Id)) + { + RINOK(StringToDictSize(value, prop.Value)); + } + else + { + NCOM::CPropVariant propValue; + if (nameToPropID.VarType == VT_BSTR) + propValue = value; + else if (nameToPropID.VarType == VT_BOOL) + { + bool res; + if (!StringToBool(value, res)) + return E_INVALIDARG; + propValue = res; + } + else if (!value.IsEmpty()) + { + if (nameToPropID.VarType == VT_UI4) + { + UInt32 number; + if (ParseStringToUInt32(value, number) == value.Len()) + propValue = number; + else + propValue = value; + } + else if (nameToPropID.VarType == VT_UI8) + { + UInt64 number; + if (ParseStringToUInt64(value, number) == value.Len()) + propValue = number; + else + propValue = value; + } + else + propValue = value; + } + if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); + return S_OK; +} + +HRESULT CMethodProps::ParseParamsFromString(const UString &srcString) +{ + UStringVector params; + SplitParams(srcString, params); + FOR_VECTOR (i, params) + { + const UString ¶m = params[i]; + UString name, value; + SplitParam(param, name, value); + RINOK(SetParam(name, value)); + } + return S_OK; +} + +HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (realName.Len() == 0) + { + // [empty]=method + return E_INVALIDARG; + } + if (value.vt == VT_EMPTY) + { + // {realName}=[empty] + UString name, valueStr; + SplitParam(realName, name, valueStr); + return SetParam(name, valueStr); + } + + // {realName}=value + int index = FindPropIdExact(realName); + if (index < 0) + return E_INVALIDARG; + const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; + CProp prop; + prop.Id = (unsigned)index; + + if (IsLogSizeProp(prop.Id)) + { + RINOK(PROPVARIANT_to_DictSize(value, prop.Value)); + } + else + { + if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) + return E_INVALIDARG; + } + Props.Add(prop); + return S_OK; +} + +HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) +{ + MethodName.Empty(); + int splitPos = s.Find(L':'); + { + UString temp = s; + if (splitPos >= 0) + temp.DeleteFrom((unsigned)splitPos); + if (!temp.IsAscii()) + return E_INVALIDARG; + MethodName.SetFromWStr_if_Ascii(temp); + } + if (splitPos < 0) + return S_OK; + PropsString = s.Ptr((unsigned)(splitPos + 1)); + return ParseParamsFromString(PropsString); +} + +HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value) +{ + if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m")) + return ParseParamsFromPROPVARIANT(realName, value); + // -m{N}=method + if (value.vt != VT_BSTR) + return E_INVALIDARG; + UString s; + s = value.bstrVal; + return ParseMethodFromString(s); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.h new file mode 100644 index 0000000..bd9283f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/MethodProps.h @@ -0,0 +1,292 @@ +// MethodProps.h + +#ifndef __7Z_METHOD_PROPS_H +#define __7Z_METHOD_PROPS_H + +#include "../../Common/MyString.h" +#include "../../Common/Defs.h" + +#include "../../Windows/Defs.h" + +#include "../../Windows/PropVariant.h" + +#include "../ICoder.h" + +bool StringToBool(const wchar_t *s, bool &res); +HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); +unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); +HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); + +HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); + +struct CProp +{ + PROPID Id; + bool IsOptional; + NWindows::NCOM::CPropVariant Value; + CProp(): IsOptional(false) {} +}; + +struct CProps +{ + CObjectVector Props; + + void Clear() { Props.Clear(); } + + bool AreThereNonOptionalProps() const + { + FOR_VECTOR (i, Props) + if (!Props[i].IsOptional) + return true; + return false; + } + + void AddProp32(PROPID propid, UInt32 val); + + void AddPropBool(PROPID propid, bool val); + + void AddProp_Ascii(PROPID propid, const char *s) + { + CProp &prop = Props.AddNew(); + prop.IsOptional = true; + prop.Id = propid; + prop.Value = s; + } + + HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; + HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; +}; + +class CMethodProps: public CProps +{ + HRESULT SetParam(const UString &name, const UString &value); +public: + unsigned GetLevel() const; + int Get_NumThreads() const + { + const int i = FindProp(NCoderPropID::kNumThreads); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) + return (int)val.ulVal; + } + return -1; + } + + bool Get_DicSize(UInt64 &res) const + { + res = 0; + const int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) + { + res = val.ulVal; + return true; + } + if (val.vt == VT_UI8) + { + res = val.uhVal.QuadPart; + return true; + } + } + return false; + } + + int FindProp(PROPID id) const; + + UInt32 Get_Lzma_Algo() const + { + int i = FindProp(NCoderPropID::kAlgorithm); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) + return val.ulVal; + } + return GetLevel() >= 5 ? 1 : 0; + } + + UInt64 Get_Lzma_DicSize() const + { + UInt64 v; + if (Get_DicSize(v)) + return v; + const unsigned level = GetLevel(); + const UInt32 dictSize = + ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : + ( level <= 6 ? ((UInt32)1 << (level + 19)) : + ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) + ))); + return dictSize; + } + + bool Get_Lzma_Eos() const + { + int i = FindProp(NCoderPropID::kEndMarker); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_BOOL) + return VARIANT_BOOLToBool(val.boolVal); + } + return false; + } + + bool Are_Lzma_Model_Props_Defined() const + { + if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; + if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; + return false; + } + + UInt32 Get_Lzma_NumThreads() const + { + if (Get_Lzma_Algo() == 0) + return 1; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + return numThreads < 2 ? 1 : 2; + return 2; + } + + int Get_Xz_NumThreads(UInt32 &lzmaThreads) const + { + lzmaThreads = 1; + int numThreads = Get_NumThreads(); + if (numThreads >= 0 && numThreads <= 1) + return 1; + if (Get_Lzma_Algo() != 0) + lzmaThreads = 2; + return numThreads; + } + + UInt64 GetProp_BlockSize(PROPID id) const + { + const int i = FindProp(id); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) { return val.ulVal; } + if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } + } + return 0; + } + + UInt64 Get_Xz_BlockSize() const + { + { + UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize); + UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2); + UInt64 minSize = MyMin(blockSize1, blockSize2); + if (minSize != 0) + return minSize; + UInt64 maxSize = MyMax(blockSize1, blockSize2); + if (maxSize != 0) + return maxSize; + } + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + const UInt64 dictSize = Get_Lzma_DicSize(); + UInt64 blockSize = (UInt64)dictSize << 2; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + blockSize += (kMinSize - 1); + blockSize &= ~(UInt64)(kMinSize - 1); + return blockSize; + } + + + UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const + { + fixedNumber = false; + int numThreads = Get_NumThreads(); + if (numThreads >= 0) + { + fixedNumber = true; + if (numThreads < 1) return 1; + const unsigned kNumBZip2ThreadsMax = 64; + if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; + return (unsigned)numThreads; + } + return 1; + } + + UInt32 Get_BZip2_BlockSize() const + { + const int i = FindProp(NCoderPropID::kDictionarySize); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) + { + UInt32 blockSize = val.ulVal; + const UInt32 kDicSizeMin = 100000; + const UInt32 kDicSizeMax = 900000; + if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; + if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; + return blockSize; + } + } + const unsigned level = GetLevel(); + return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); + } + + UInt64 Get_Ppmd_MemSize() const + { + const int i = FindProp(NCoderPropID::kUsedMemorySize); + if (i >= 0) + { + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; + if (val.vt == VT_UI4) + return val.ulVal; + if (val.vt == VT_UI8) + return val.uhVal.QuadPart; + } + const unsigned level = GetLevel(); + const UInt32 mem = (UInt32)1 << (level + 19); + return mem; + } + + void AddProp_Level(UInt32 level) + { + AddProp32(NCoderPropID::kLevel, level); + } + + void AddProp_NumThreads(UInt32 numThreads) + { + AddProp32(NCoderPropID::kNumThreads, numThreads); + } + + void AddProp_EndMarker_if_NotFound(bool eos) + { + if (FindProp(NCoderPropID::kEndMarker) < 0) + AddPropBool(NCoderPropID::kEndMarker, eos); + } + + HRESULT ParseParamsFromString(const UString &srcString); + HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); +}; + +class COneMethodInfo: public CMethodProps +{ +public: + AString MethodName; + UString PropsString; + + void Clear() + { + CMethodProps::Clear(); + MethodName.Empty(); + PropsString.Empty(); + } + bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } + HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); + HRESULT ParseMethodFromString(const UString &s); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.cpp new file mode 100644 index 0000000..b16124c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.cpp @@ -0,0 +1,39 @@ +// OffsetStream.cpp + +#include "StdAfx.h" + +#include "../../Common/Defs.h" + +#include "OffsetStream.h" + +HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) +{ + _offset = offset; + _stream = stream; + return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); +} + +STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + return _stream->Write(data, size, processedSize); +} + +STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin == STREAM_SEEK_SET) + { + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + offset += _offset; + } + UInt64 absoluteNewPosition = 0; // =0 for gcc-10 + HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); + if (newPosition) + *newPosition = absoluteNewPosition - _offset; + return result; +} + +STDMETHODIMP COffsetOutStream::SetSize(UInt64 newSize) +{ + return _stream->SetSize(_offset + newSize); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.h new file mode 100644 index 0000000..9074a24 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OffsetStream.h @@ -0,0 +1,26 @@ +// OffsetStream.h + +#ifndef __OFFSET_STREAM_H +#define __OFFSET_STREAM_H + +#include "../../Common/MyCom.h" + +#include "../IStream.h" + +class COffsetOutStream: + public IOutStream, + public CMyUnknownImp +{ + UInt64 _offset; + CMyComPtr _stream; +public: + HRESULT Init(IOutStream *stream, UInt64 offset); + + MY_UNKNOWN_IMP + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.cpp new file mode 100644 index 0000000..4ba34a0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.cpp @@ -0,0 +1,111 @@ +// OutBuffer.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "OutBuffer.h" + +bool COutBuffer::Create(UInt32 bufSize) throw() +{ + const UInt32 kMinBlockSize = 1; + if (bufSize < kMinBlockSize) + bufSize = kMinBlockSize; + if (_buf != 0 && _bufSize == bufSize) + return true; + Free(); + _bufSize = bufSize; + _buf = (Byte *)::MidAlloc(bufSize); + return (_buf != 0); +} + +void COutBuffer::Free() throw() +{ + ::MidFree(_buf); + _buf = 0; +} + +void COutBuffer::Init() throw() +{ + _streamPos = 0; + _limitPos = _bufSize; + _pos = 0; + _processedSize = 0; + _overDict = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +UInt64 COutBuffer::GetProcessedSize() const throw() +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufSize; + return res; +} + + +HRESULT COutBuffer::FlushPart() throw() +{ + // _streamPos < _bufSize + UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + result = ErrorCode; + #endif + if (_buf2 != 0) + { + memcpy(_buf2, _buf + _streamPos, size); + _buf2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode == S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buf + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + if (_streamPos == _bufSize) + _streamPos = 0; + if (_pos == _bufSize) + { + _overDict = true; + _pos = 0; + } + _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() throw() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return ErrorCode; + #endif + + while (_streamPos != _pos) + { + HRESULT result = FlushPart(); + if (result != S_OK) + return result; + } + return S_OK; +} + +void COutBuffer::FlushWithCheck() +{ + HRESULT result = Flush(); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw COutBufferException(result); + #endif +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.h new file mode 100644 index 0000000..d7ca9f6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/OutBuffer.h @@ -0,0 +1,66 @@ +// OutBuffer.h + +#ifndef __OUT_BUFFER_H +#define __OUT_BUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyException.h" + +#ifndef _NO_EXCEPTIONS +struct COutBufferException: public CSystemException +{ + COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} +}; +#endif + +class COutBuffer +{ +protected: + Byte *_buf; + UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; + UInt32 _bufSize; + ISequentialOutStream *_stream; + UInt64 _processedSize; + Byte *_buf2; + bool _overDict; + + HRESULT FlushPart() throw(); +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + COutBuffer(): _buf(0), _pos(0), _stream(0), _buf2(0) {} + ~COutBuffer() { Free(); } + + bool Create(UInt32 bufSize) throw(); + void Free() throw(); + + void SetMemStream(Byte *buf) { _buf2 = buf; } + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init() throw(); + HRESULT Flush() throw(); + void FlushWithCheck(); + + void WriteByte(Byte b) + { + UInt32 pos = _pos; + _buf[pos] = b; + pos++; + _pos = pos; + if (pos == _limitPos) + FlushWithCheck(); + } + void WriteBytes(const void *data, size_t size) + { + for (size_t i = 0; i < size; i++) + WriteByte(((const Byte *)data)[i]); + } + + UInt64 GetProcessedSize() const throw(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.cpp new file mode 100644 index 0000000..41385cc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.cpp @@ -0,0 +1,51 @@ +// ProgressUtils.cpp + +#include "StdAfx.h" + +#include "ProgressUtils.h" + +CLocalProgress::CLocalProgress(): + ProgressOffset(0), + InSize(0), + OutSize(0), + SendRatio(true), + SendProgress(true) + {} + +void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) +{ + _ratioProgress.Release(); + _progress = progress; + _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); + _inSizeIsMain = inSizeIsMain; +} + +STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + UInt64 inSize2 = InSize; + UInt64 outSize2 = OutSize; + + if (inSize) + inSize2 += (*inSize); + if (outSize) + outSize2 += (*outSize); + + if (SendRatio && _ratioProgress) + { + RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2)); + } + + if (SendProgress) + { + inSize2 += ProgressOffset; + outSize2 += ProgressOffset; + return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2); + } + + return S_OK; +} + +HRESULT CLocalProgress::SetCur() +{ + return SetRatioInfo(NULL, NULL); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.h new file mode 100644 index 0000000..e94265b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/ProgressUtils.h @@ -0,0 +1,35 @@ +// ProgressUtils.h + +#ifndef __PROGRESS_UTILS_H +#define __PROGRESS_UTILS_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" +#include "../IProgress.h" + +class CLocalProgress: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr _progress; + CMyComPtr _ratioProgress; + bool _inSizeIsMain; +public: + UInt64 ProgressOffset; + UInt64 InSize; + UInt64 OutSize; + bool SendRatio; + bool SendProgress; + + CLocalProgress(); + + void Init(IProgress *progress, bool inSizeIsMain); + HRESULT SetCur(); + + MY_UNKNOWN_IMP1(ICompressProgressInfo) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/PropId.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/PropId.cpp new file mode 100644 index 0000000..11d20d5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/PropId.cpp @@ -0,0 +1,108 @@ +// PropId.cpp + +#include "StdAfx.h" + +#include "../../Common/MyWindows.h" + +#include "../PropID.h" + +// VARTYPE +const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = +{ + VT_EMPTY, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI4, + VT_FILETIME, + VT_FILETIME, + VT_FILETIME, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BOOL, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidUnpackVer + VT_UI4, // or VT_UI8 kpidVolume + VT_BOOL, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BOOL, + VT_BOOL, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, // kpidChecksum + VT_BSTR, + VT_UI8, + VT_BSTR, // or VT_UI8 kpidId + VT_BSTR, + VT_BSTR, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI4, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BSTR, // kpidNtSecure + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_BSTR, // SHA-1 + VT_BSTR, // SHA-256 + VT_BSTR, + VT_UI8, + VT_UI4, + VT_UI4, + VT_BSTR, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_UI8, + VT_BSTR, + VT_BSTR, + VT_BSTR, + VT_BOOL, + VT_BOOL, + VT_BOOL, + VT_UI8, + VT_UI8, + VT_BSTR, // kpidNtReparse + VT_BSTR, + VT_UI8, + VT_UI8, + VT_BOOL, + VT_BSTR, + VT_BSTR +}; diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterArc.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterArc.h new file mode 100644 index 0000000..3421ba1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterArc.h @@ -0,0 +1,78 @@ +// RegisterArc.h + +#ifndef __REGISTER_ARC_H +#define __REGISTER_ARC_H + +#include "../Archive/IArchive.h" + +struct CArcInfo +{ + UInt16 Flags; + Byte Id; + Byte SignatureSize; + UInt16 SignatureOffset; + + const Byte *Signature; + const char *Name; + const char *Ext; + const char *AddExt; + + Func_CreateInArchive CreateInArchive; + Func_CreateOutArchive CreateOutArchive; + Func_IsArc IsArc; + + bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; } +}; + +void RegisterArc(const CArcInfo *arcInfo) throw(); + + +#define IMP_CreateArcIn_2(c) \ + static IInArchive *CreateArc() { return new c; } + +#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler()) + +#ifdef EXTRACT_ONLY + #define IMP_CreateArcOut + #define CreateArcOut NULL +#else + #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); } +#endif + +#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, crIn, crOut, isArc } ; \ + +#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, crIn, crOut, isArc) \ + struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArc g_RegisterArc; + + +#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn_2(cls) \ + REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \ + IMP_CreateArcIn_2(cls) \ + REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, CreateArc, NULL, isArc) + +#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \ + REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc) + +#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \ + REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc) + + +#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_R(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) + +#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, isArc) \ + IMP_CreateArcIn \ + IMP_CreateArcOut \ + REGISTER_ARC_V(n, e, ae, id, ARRAY_SIZE(sig), sig, offs, flags, CreateArc, CreateArcOut, isArc) \ + struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \ + static CRegisterArcDecSig g_RegisterArc; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterCodec.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterCodec.h new file mode 100644 index 0000000..a942da7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/RegisterCodec.h @@ -0,0 +1,106 @@ +// RegisterCodec.h + +#ifndef __REGISTER_CODEC_H +#define __REGISTER_CODEC_H + +#include "../Common/MethodId.h" + +#include "../ICoder.h" + +typedef void * (*CreateCodecP)(); + +struct CCodecInfo +{ + CreateCodecP CreateDecoder; + CreateCodecP CreateEncoder; + CMethodId Id; + const char *Name; + UInt32 NumStreams; + bool IsFilter; +}; + +void RegisterCodec(const CCodecInfo *codecInfo) throw(); + + +#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); } +#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) + +#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x +#define REGISTER_CODEC_VAR(x) static const CCodecInfo g_CodecInfo_ ## x = + +#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ + REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo_ ## x); }}; \ + static REGISTER_CODEC_NAME(x) g_RegisterCodec_ ## x; + + +#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x +#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] = + +#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ + REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < ARRAY_SIZE(g_CodecsInfo); i++) \ + RegisterCodec(&g_CodecsInfo[i]); }}; \ + static REGISTER_CODECS_NAME(x) g_RegisterCodecs; + + +#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR(x) \ + { crDec, crEnc, id, name, 1, false }; \ + REGISTER_CODEC(x) + + +#ifdef EXTRACT_ONLY + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_2(x, CreateDec, NULL, id, name) +#else + #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \ + REGISTER_CODEC_CREATE(CreateDec, clsDec) \ + REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \ + REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name) +#endif + + + +#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter) + +#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \ + { crDec, crEnc, id, name, 1, true } + +#define REGISTER_FILTER(x, crDec, crEnc, id, name) \ + REGISTER_CODEC_VAR(x) \ + REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ + REGISTER_CODEC(x) + +#ifdef EXTRACT_ONLY + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name) +#else + #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER_CREATE(x ## _CreateEnc, clsEnc) \ + REGISTER_FILTER(x, x ## _CreateDec, x ## _CreateEnc, id, name) +#endif + + + +struct CHasherInfo +{ + IHasher * (*CreateHasher)(); + CMethodId Id; + const char *Name; + UInt32 DigestSize; +}; + +void RegisterHasher(const CHasherInfo *hasher) throw(); + +#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x + +#define REGISTER_HASHER(cls, id, name, size) \ + STDMETHODIMP_(UInt32) cls::GetDigestSize() throw() { return size; } \ + static IHasher *CreateHasherSpec() { return new cls(); } \ + static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \ + struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \ + static REGISTER_HASHER_NAME(cls) g_RegisterHasher; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StdAfx.h new file mode 100644 index 0000000..1cbd7fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.cpp new file mode 100644 index 0000000..6b6e0e5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.cpp @@ -0,0 +1,158 @@ +// StreamBinder.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" + +#include "StreamBinder.h" + +class CBinderInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + CStreamBinder *_binder; +public: + MY_UNKNOWN_IMP1(ISequentialInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + ~CBinderInStream() { _binder->CloseRead_CallOnce(); } + CBinderInStream(CStreamBinder *binder): _binder(binder) {} +}; + +STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Read(data, size, processedSize); } + +class CBinderOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CStreamBinder *_binder; +public: + MY_UNKNOWN_IMP1(ISequentialOutStream) + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + ~CBinderOutStream() { _binder->CloseWrite(); } + CBinderOutStream(CStreamBinder *binder): _binder(binder) {} +}; + +STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) + { return _binder->Write(data, size, processedSize); } + + +static HRESULT Event__Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event) +{ + WRes wres; + if (event.IsCreated()) + wres = event.Reset(); + else + wres = event.Create(); + return HRESULT_FROM_WIN32(wres); +} + +HRESULT CStreamBinder::Create_ReInit() +{ + RINOK(Event__Create_or_Reset(_canRead_Event)); + // RINOK(Event__Create_or_Reset(_canWrite_Event)); + + // _canWrite_Semaphore.Close(); + // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce() + _canWrite_Semaphore.OptCreateInit(0, 3); + + // _readingWasClosed = false; + _readingWasClosed2 = false; + + _waitWrite = true; + _bufSize = 0; + _buf = NULL; + ProcessedSize = 0; + // WritingWasCut = false; + return S_OK; +} + + +void CStreamBinder::CreateStreams2(CMyComPtr &inStream, CMyComPtr &outStream) +{ + inStream = new CBinderInStream(this); + outStream = new CBinderOutStream(this); +} + +// (_canRead_Event && _bufSize == 0) means that stream is finished. + +HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size != 0) + { + if (_waitWrite) + { + WRes wres = _canRead_Event.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + _waitWrite = false; + } + if (size > _bufSize) + size = _bufSize; + if (size != 0) + { + memcpy(data, _buf, size); + _buf = ((const Byte *)_buf) + size; + ProcessedSize += size; + if (processedSize) + *processedSize = size; + _bufSize -= size; + + /* + if (_bufSize == 0), then we have read whole buffer + we have two ways here: + - if we check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs + - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading + */ + if (_bufSize == 0) + { + _waitWrite = true; + // _canWrite_Event.Set(); + _canWrite_Semaphore.Release(); + } + } + } + return S_OK; +} + + +HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + + if (!_readingWasClosed2) + { + _buf = data; + _bufSize = size; + _canRead_Event.Set(); + + /* + _canWrite_Event.Lock(); + if (_readingWasClosed) + _readingWasClosed2 = true; + */ + + _canWrite_Semaphore.Lock(); + + // _bufSize : is remain size that was not read + size -= _bufSize; + + // size : is size of data that was read + if (size != 0) + { + // if some data was read, then we report that size and return + if (processedSize) + *processedSize = size; + return S_OK; + } + _readingWasClosed2 = true; + } + + // WritingWasCut = true; + return k_My_HRESULT_WritingWasCut; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.h new file mode 100644 index 0000000..16c872f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamBinder.h @@ -0,0 +1,78 @@ +// StreamBinder.h + +#ifndef __STREAM_BINDER_H +#define __STREAM_BINDER_H + +#include "../../Windows/Synchronization.h" + +#include "../IStream.h" + +/* +We can use one from two code versions here: with Event or with Semaphore to unlock Writer thread +The difference for cases where Reading must be closed before Writing closing + +1) Event Version: _canWrite_Event + We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function. + The writer thread can get (_readingWasClosed) status in one from two iterations. + It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers. + reader thread: + _canWrite_Event.Set(); + _readingWasClosed = true; + _canWrite_Event.Set(); + writer thread: + _canWrite_Event.Wait() + if (_readingWasClosed) + +2) Semaphore Version: _canWrite_Semaphore + writer thread always will detect closing of reading in latest iteration after all data processing iterations +*/ + +class CStreamBinder +{ + NWindows::NSynchronization::CAutoResetEvent _canRead_Event; + // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; + NWindows::NSynchronization::CSemaphore _canWrite_Semaphore; + + // bool _readingWasClosed; // set it in reader thread and check it in write thread + bool _readingWasClosed2; // use it in writer thread + // bool WritingWasCut; + bool _waitWrite; // use it in reader thread + UInt32 _bufSize; + const void *_buf; +public: + UInt64 ProcessedSize; // the size that was read by reader thread + + void CreateStreams2(CMyComPtr &inStream, CMyComPtr &outStream); + + HRESULT Create_ReInit(); + + HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); + HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); + + void CloseRead_CallOnce() + { + // call it only once: for example, in destructor + + /* + _readingWasClosed = true; + _canWrite_Event.Set(); + */ + + /* + We must relase Semaphore only once !!! + we must release at least 2 items of Semaphore: + one item to unlock partial Write(), if Read() have read some items + then additional item to stop writing (_bufSize will be 0) + */ + _canWrite_Semaphore.Release(2); + } + + void CloseWrite() + { + _buf = NULL; + _bufSize = 0; + _canRead_Event.Set(); + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.cpp new file mode 100644 index 0000000..2d941df --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.cpp @@ -0,0 +1,293 @@ +// StreamObjects.cpp + +#include "StdAfx.h" + +#include + +#include "../../../C/Alloc.h" + +#include "StreamObjects.h" + +STDMETHODIMP CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= Buf.Size()) + return S_OK; + size_t rem = Buf.Size() - (size_t)_pos; + if (rem > size) + rem = (size_t)size; + memcpy(data, (const Byte *)Buf + (size_t)_pos, rem); + _pos += rem; + if (processedSize) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += Buf.Size(); break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} + +STDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= _size) + return S_OK; + size_t rem = _size - (size_t)_pos; + if (rem > size) + rem = (size_t)size; + memcpy(data, _data + (size_t)_pos, rem); + _pos += rem; + if (processedSize) + *processedSize = (UInt32)rem; + return S_OK; +} + +STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} + +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream) +{ + *stream = NULL; + CBufInStream *inStreamSpec = new CBufInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Init((const Byte *)data, size, ref); + *stream = streamTemp.Detach(); +} + +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream) +{ + *stream = NULL; + CBufferInStream *inStreamSpec = new CBufferInStream; + CMyComPtr streamTemp = inStreamSpec; + inStreamSpec->Buf.CopyFrom((const Byte *)data, size); + inStreamSpec->Init(); + *stream = streamTemp.Detach(); +} + +void CByteDynBuffer::Free() throw() +{ + free(_buf); + _buf = 0; + _capacity = 0; +} + +bool CByteDynBuffer::EnsureCapacity(size_t cap) throw() +{ + if (cap <= _capacity) + return true; + size_t delta = _capacity / 4; + size_t cap2 = _capacity + delta; + if (cap < cap2) + cap = cap2; + Byte *buf = (Byte *)realloc(_buf, cap); + if (!buf) + return false; + _buf = buf; + _capacity = cap; + return true; +} + +Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize) +{ + addSize += _size; + if (addSize < _size) + return NULL; + if (!_buffer.EnsureCapacity(addSize)) + return NULL; + return (Byte *)_buffer + _size; +} + +void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const +{ + dest.CopyFrom((const Byte *)_buffer, _size); +} + +STDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + Byte *buf = GetBufPtrForWriting(size); + if (!buf) + return E_OUTOFMEMORY; + memcpy(buf, data, size); + UpdateSize(size); + if (processedSize) + *processedSize = size; + return S_OK; +} + +STDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t rem = _size - _pos; + if (rem > size) + rem = (size_t)size; + if (rem != 0) + { + memcpy(_buffer + _pos, data, rem); + _pos += rem; + } + if (processedSize) + *processedSize = (UInt32)rem; + return (rem != 0 || size == 0) ? S_OK : E_FAIL; +} + +STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = _stream->Write(data, size, &realProcessedSize); + _size += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return result; +} + +static const UInt64 kEmptyTag = (UInt64)(Int64)-1; + +void CCachedInStream::Free() throw() +{ + MyFree(_tags); + _tags = NULL; + MidFree(_data); + _data = NULL; +} + +bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw() +{ + unsigned sizeLog = blockSizeLog + numBlocksLog; + if (sizeLog >= sizeof(size_t) * 8) + return false; + size_t dataSize = (size_t)1 << sizeLog; + if (!_data || dataSize != _dataSize) + { + MidFree(_data); + _data = (Byte *)MidAlloc(dataSize); + if (!_data) + return false; + _dataSize = dataSize; + } + if (!_tags || numBlocksLog != _numBlocksLog) + { + MyFree(_tags); + _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); + if (!_tags) + return false; + _numBlocksLog = numBlocksLog; + } + _blockSizeLog = blockSizeLog; + return true; +} + +void CCachedInStream::Init(UInt64 size) throw() +{ + _size = size; + _pos = 0; + size_t numBlocks = (size_t)1 << _numBlocksLog; + for (size_t i = 0; i < numBlocks; i++) + _tags[i] = kEmptyTag; +} + +STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_pos >= _size) + return S_OK; + + { + UInt64 rem = _size - _pos; + if (size > rem) + size = (UInt32)rem; + } + + while (size != 0) + { + const UInt64 cacheTag = _pos >> _blockSizeLog; + const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); + Byte *p = _data + (cacheIndex << _blockSizeLog); + + if (_tags[cacheIndex] != cacheTag) + { + _tags[cacheIndex] = kEmptyTag; + UInt64 remInBlock = _size - (cacheTag << _blockSizeLog); + size_t blockSize = (size_t)1 << _blockSizeLog; + if (blockSize > remInBlock) + blockSize = (size_t)remInBlock; + + RINOK(ReadBlock(cacheTag, p, blockSize)); + + _tags[cacheIndex] = cacheTag; + } + + const size_t kBlockSize = (size_t)1 << _blockSizeLog; + const size_t offset = (size_t)_pos & (kBlockSize - 1); + UInt32 cur = size; + const size_t rem = kBlockSize - offset; + if (cur > rem) + cur = (UInt32)rem; + + memcpy(data, p + offset, cur); + + if (processedSize) + *processedSize += cur; + data = (void *)((const Byte *)data + cur); + _pos += cur; + size -= cur; + } + + return S_OK; +} + + +STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += _pos; break; + case STREAM_SEEK_END: offset += _size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + _pos = (UInt64)offset; + if (newPosition) + *newPosition = (UInt64)offset; + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.h new file mode 100644 index 0000000..a8fb229 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamObjects.h @@ -0,0 +1,166 @@ +// StreamObjects.h + +#ifndef __STREAM_OBJECTS_H +#define __STREAM_OBJECTS_H + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" + +#include "../IStream.h" + +class CBufferInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 _pos; +public: + CByteBuffer Buf; + void Init() { _pos = 0; } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + + +struct CReferenceBuf: + public IUnknown, + public CMyUnknownImp +{ + CByteBuffer Buf; + MY_UNKNOWN_IMP +}; + + +class CBufInStream: + public IInStream, + public CMyUnknownImp +{ + const Byte *_data; + UInt64 _pos; + size_t _size; + CMyComPtr _ref; +public: + void Init(const Byte *data, size_t size, IUnknown *ref = NULL) + { + _data = data; + _size = size; + _pos = 0; + _ref = ref; + } + void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); } + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + + +void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); +void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); +inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) + { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } + + +class CByteDynBuffer +{ + size_t _capacity; + Byte *_buf; + CLASS_NO_COPY(CByteDynBuffer); +public: + CByteDynBuffer(): _capacity(0), _buf(NULL) {}; + // there is no copy constructor. So don't copy this object. + ~CByteDynBuffer() { Free(); } + void Free() throw(); + size_t GetCapacity() const { return _capacity; } + operator Byte*() const { return _buf; } + operator const Byte*() const { return _buf; } + bool EnsureCapacity(size_t capacity) throw(); +}; + + +class CDynBufSeqOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + CByteDynBuffer _buffer; + size_t _size; +public: + CDynBufSeqOutStream(): _size(0) {} + void Init() { _size = 0; } + size_t GetSize() const { return _size; } + const Byte *GetBuffer() const { return _buffer; } + void CopyToBuffer(CByteBuffer &dest) const; + Byte *GetBufPtrForWriting(size_t addSize); + void UpdateSize(size_t addSize) { _size += addSize; } + + MY_UNKNOWN_IMP1(ISequentialOutStream) + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + + +class CBufPtrSeqOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + Byte *_buffer; + size_t _size; + size_t _pos; +public: + void Init(Byte *buffer, size_t size) + { + _buffer = buffer; + _pos = 0; + _size = size; + } + size_t GetPos() const { return _pos; } + + MY_UNKNOWN_IMP1(ISequentialOutStream) + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + + +class CSequentialOutStreamSizeCount: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; +public: + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void Init() { _size = 0; } + UInt64 GetSize() const { return _size; } + + MY_UNKNOWN_IMP1(ISequentialOutStream) + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + + +class CCachedInStream: + public IInStream, + public CMyUnknownImp +{ + UInt64 *_tags; + Byte *_data; + size_t _dataSize; + unsigned _blockSizeLog; + unsigned _numBlocksLog; + UInt64 _size; + UInt64 _pos; +protected: + virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0; +public: + CCachedInStream(): _tags(NULL), _data(NULL) {} + virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!! + void Free() throw(); + bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); + void Init(UInt64 size) throw(); + + MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.cpp new file mode 100644 index 0000000..1402f42 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.cpp @@ -0,0 +1,56 @@ +// StreamUtils.cpp + +#include "StdAfx.h" + +#include "StreamUtils.h" + +static const UInt32 kBlockSize = ((UInt32)1 << 31); + +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw() +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; + UInt32 processedSizeLoc; + HRESULT res = stream->Read(data, curSize, &processedSizeLoc); + *processedSize += processedSizeLoc; + data = (void *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return S_OK; + } + return S_OK; +} + +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw() +{ + size_t processedSize = size; + RINOK(ReadStream(stream, data, &processedSize)); + return (size == processedSize) ? S_OK : S_FALSE; +} + +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw() +{ + size_t processedSize = size; + RINOK(ReadStream(stream, data, &processedSize)); + return (size == processedSize) ? S_OK : E_FAIL; +} + +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw() +{ + while (size != 0) + { + UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; + UInt32 processedSizeLoc; + HRESULT res = stream->Write(data, curSize, &processedSizeLoc); + data = (const void *)((const Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return E_FAIL; + } + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.h new file mode 100644 index 0000000..ae914c0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/StreamUtils.h @@ -0,0 +1,13 @@ +// StreamUtils.h + +#ifndef __STREAM_UTILS_H +#define __STREAM_UTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw(); +HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw(); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw(); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.cpp new file mode 100644 index 0000000..8f754e1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.cpp @@ -0,0 +1,57 @@ +// UniqBlocks.cpp + +#include "StdAfx.h" + +#include + +#include "UniqBlocks.h" + +unsigned CUniqBlocks::AddUniq(const Byte *data, size_t size) +{ + unsigned left = 0, right = Sorted.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + unsigned index = Sorted[mid]; + const CByteBuffer &buf = Bufs[index]; + size_t sizeMid = buf.Size(); + if (size < sizeMid) + right = mid; + else if (size > sizeMid) + left = mid + 1; + else + { + if (size == 0) + return index; + int cmp = memcmp(data, buf, size); + if (cmp == 0) + return index; + if (cmp < 0) + right = mid; + else + left = mid + 1; + } + } + unsigned index = Bufs.Size(); + Sorted.Insert(left, index); + Bufs.AddNew().CopyFrom(data, size); + return index; +} + +UInt64 CUniqBlocks::GetTotalSizeInBytes() const +{ + UInt64 size = 0; + FOR_VECTOR (i, Bufs) + size += Bufs[i].Size(); + return size; +} + +void CUniqBlocks::GetReverseMap() +{ + unsigned num = Sorted.Size(); + BufIndexToSortedIndex.ClearAndSetSize(num); + unsigned *p = &BufIndexToSortedIndex[0]; + const unsigned *sorted = &Sorted[0]; + for (unsigned i = 0; i < num; i++) + p[sorted[i]] = i; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.h new file mode 100644 index 0000000..d6cd372 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/UniqBlocks.h @@ -0,0 +1,26 @@ +// UniqBlocks.h + +#ifndef __UNIQ_BLOCKS_H +#define __UNIQ_BLOCKS_H + +#include "../../Common/MyTypes.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyVector.h" + +struct CUniqBlocks +{ + CObjectVector Bufs; + CUIntVector Sorted; + CUIntVector BufIndexToSortedIndex; + + unsigned AddUniq(const Byte *data, size_t size); + UInt64 GetTotalSizeInBytes() const; + void GetReverseMap(); + + bool IsOnlyEmpty() const + { + return (Bufs.Size() == 0 || (Bufs.Size() == 1 && Bufs[0].Size() == 0)); + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.cpp new file mode 100644 index 0000000..bf24bb1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.cpp @@ -0,0 +1,47 @@ +// VirtThread.cpp + +#include "StdAfx.h" + +#include "VirtThread.h" + +static THREAD_FUNC_DECL CoderThread(void *p) +{ + for (;;) + { + CVirtThread *t = (CVirtThread *)p; + t->StartEvent.Lock(); + if (t->Exit) + return 0; + t->Execute(); + t->FinishedEvent.Set(); + } +} + +WRes CVirtThread::Create() +{ + RINOK_WRes(StartEvent.CreateIfNotCreated_Reset()); + RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset()); + // StartEvent.Reset(); + // FinishedEvent.Reset(); + Exit = false; + if (Thread.IsCreated()) + return S_OK; + return Thread.Create(CoderThread, this); +} + +WRes CVirtThread::Start() +{ + Exit = false; + return StartEvent.Set(); +} + +void CVirtThread::WaitThreadFinish() +{ + Exit = true; + if (StartEvent.IsCreated()) + StartEvent.Set(); + if (Thread.IsCreated()) + { + Thread.Wait_Close(); + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.h b/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.h new file mode 100644 index 0000000..b4d8a5a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Common/VirtThread.h @@ -0,0 +1,24 @@ +// VirtThread.h + +#ifndef __VIRT_THREAD_H +#define __VIRT_THREAD_H + +#include "../../Windows/Synchronization.h" +#include "../../Windows/Thread.h" + +struct CVirtThread +{ + NWindows::NSynchronization::CAutoResetEvent StartEvent; + NWindows::NSynchronization::CAutoResetEvent FinishedEvent; + NWindows::CThread Thread; + bool Exit; + + ~CVirtThread() { WaitThreadFinish(); } + void WaitThreadFinish(); // call it in destructor of child class ! + WRes Create(); + WRes Start(); + virtual void Execute() = 0; + WRes WaitExecuteFinish() { return FinishedEvent.Lock(); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.cpp new file mode 100644 index 0000000..561fd08 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.cpp @@ -0,0 +1,666 @@ +// Bcj2Coder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "Bcj2Coder.h" + +namespace NCompress { +namespace NBcj2 { + +CBaseCoder::CBaseCoder() +{ + for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++) + { + _bufs[i] = NULL; + _bufsCurSizes[i] = 0; + _bufsNewSizes[i] = (1 << 18); + } +} + +CBaseCoder::~CBaseCoder() +{ + for (int i = 0; i < BCJ2_NUM_STREAMS + 1; i++) + ::MidFree(_bufs[i]); +} + +HRESULT CBaseCoder::Alloc(bool allocForOrig) +{ + unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS; + for (unsigned i = 0; i < num; i++) + { + UInt32 newSize = _bufsNewSizes[i]; + const UInt32 kMinBufSize = 1; + if (newSize < kMinBufSize) + newSize = kMinBufSize; + if (!_bufs[i] || newSize != _bufsCurSizes[i]) + { + if (_bufs[i]) + { + ::MidFree(_bufs[i]); + _bufs[i] = 0; + } + _bufsCurSizes[i] = 0; + Byte *buf = (Byte *)::MidAlloc(newSize); + _bufs[i] = buf; + if (!buf) + return E_OUTOFMEMORY; + _bufsCurSizes[i] = newSize; + } + } + return S_OK; +} + + + +#ifndef EXTRACT_ONLY + +CEncoder::CEncoder(): _relatLim(BCJ2_RELAT_LIMIT) {} +CEncoder::~CEncoder() {} + +STDMETHODIMP CEncoder::SetInBufSize(UInt32, UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; } +STDMETHODIMP CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; } + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + UInt32 relatLim = BCJ2_RELAT_LIMIT; + + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + switch (propID) + { + /* + case NCoderPropID::kDefaultProp: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = prop.ulVal; + if (v > 31) + return E_INVALIDARG; + relatLim = (UInt32)1 << v; + break; + } + */ + case NCoderPropID::kDictionarySize: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + relatLim = prop.ulVal; + if (relatLim > ((UInt32)1 << 31)) + return E_INVALIDARG; + break; + } + + case NCoderPropID::kNumThreads: + continue; + case NCoderPropID::kLevel: + continue; + + default: return E_INVALIDARG; + } + } + + _relatLim = relatLim; + + return S_OK; +} + + +HRESULT CEncoder::CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS) + return E_INVALIDARG; + + RINOK(Alloc()); + + UInt32 fileSize_for_Conv = 0; + if (inSizes && inSizes[0]) + { + UInt64 inSize = *inSizes[0]; + if (inSize <= BCJ2_FileSize_MAX) + fileSize_for_Conv = (UInt32)inSize; + } + + CMyComPtr getSubStreamSize; + inStreams[0]->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); + + CBcj2Enc enc; + + enc.src = _bufs[BCJ2_NUM_STREAMS]; + enc.srcLim = enc.src; + + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + enc.bufs[i] = _bufs[i]; + enc.lims[i] = _bufs[i] + _bufsCurSizes[i]; + } + } + + size_t numBytes_in_ReadBuf = 0; + UInt64 prevProgress = 0; + UInt64 totalStreamRead = 0; // size read from InputStream + UInt64 currentInPos = 0; // data that was processed, it doesn't include data in input buffer and data in enc.temp + UInt64 outSizeRc = 0; + + Bcj2Enc_Init(&enc); + + enc.fileIp = 0; + enc.fileSize = fileSize_for_Conv; + + enc.relatLimit = _relatLim; + + enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + bool needSubSize = false; + UInt64 subStreamIndex = 0; + UInt64 subStreamStartPos = 0; + bool readWasFinished = false; + + for (;;) + { + if (needSubSize && getSubStreamSize) + { + enc.fileIp = 0; + enc.fileSize = fileSize_for_Conv; + enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE; + + for (;;) + { + UInt64 subStreamSize = 0; + HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); + needSubSize = false; + + if (result == S_OK) + { + UInt64 newEndPos = subStreamStartPos + subStreamSize; + + bool isAccurateEnd = (newEndPos < totalStreamRead || + (newEndPos <= totalStreamRead && readWasFinished)); + + if (newEndPos <= currentInPos && isAccurateEnd) + { + subStreamStartPos = newEndPos; + subStreamIndex++; + continue; + } + + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; + + if (isAccurateEnd) + { + // data in enc.temp is possible here + size_t rem = (size_t)(totalStreamRead - newEndPos); + + /* Pos_of(enc.src) <= old newEndPos <= newEndPos + in another case, it's fail in some code */ + if ((size_t)(enc.srcLim - enc.src) < rem) + return E_FAIL; + + enc.srcLim -= rem; + enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK; + } + + if (subStreamSize <= BCJ2_FileSize_MAX) + { + enc.fileIp = enc.ip + (UInt32)(subStreamStartPos - currentInPos); + enc.fileSize = (UInt32)subStreamSize; + } + break; + } + + if (result == S_FALSE) + break; + if (result == E_NOTIMPL) + { + getSubStreamSize.Release(); + break; + } + return result; + } + } + + if (readWasFinished && totalStreamRead - currentInPos == Bcj2Enc_Get_InputData_Size(&enc)) + enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM; + + Bcj2Enc_Encode(&enc); + + currentInPos = totalStreamRead - numBytes_in_ReadBuf + (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS]) - enc.tempPos; + + if (Bcj2Enc_IsFinished(&enc)) + break; + + if (enc.state < BCJ2_NUM_STREAMS) + { + const size_t curSize = (size_t)(enc.bufs[enc.state] - _bufs[enc.state]); + // printf("Write stream = %2d %6d\n", enc.state, curSize); + RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize)); + if (enc.state == BCJ2_STREAM_RC) + outSizeRc += curSize; + + enc.bufs[enc.state] = _bufs[enc.state]; + enc.lims[enc.state] = _bufs[enc.state] + _bufsCurSizes[enc.state]; + } + else if (enc.state != BCJ2_ENC_STATE_ORIG) + return E_FAIL; + else + { + needSubSize = true; + + if (numBytes_in_ReadBuf != (size_t)(enc.src - _bufs[BCJ2_NUM_STREAMS])) + { + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; + continue; + } + + if (readWasFinished) + continue; + + numBytes_in_ReadBuf = 0; + enc.src = _bufs[BCJ2_NUM_STREAMS]; + enc.srcLim = _bufs[BCJ2_NUM_STREAMS]; + + UInt32 curSize = _bufsCurSizes[BCJ2_NUM_STREAMS]; + RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize)); + + // printf("Read %6d bytes\n", curSize); + if (curSize == 0) + { + readWasFinished = true; + continue; + } + + numBytes_in_ReadBuf = curSize; + totalStreamRead += numBytes_in_ReadBuf; + enc.srcLim = _bufs[BCJ2_NUM_STREAMS] + numBytes_in_ReadBuf; + } + + if (progress && currentInPos - prevProgress >= (1 << 20)) + { + const UInt64 outSize2 = currentInPos + outSizeRc + (size_t)(enc.bufs[BCJ2_STREAM_RC] - enc.bufs[BCJ2_STREAM_RC]); + prevProgress = currentInPos; + // printf("progress %8d, %8d\n", (int)inSize2, (int)outSize2); + RINOK(progress->SetRatioInfo(¤tInPos, &outSize2)); + } + } + + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + RINOK(WriteStream(outStreams[i], _bufs[i], (size_t)(enc.bufs[i] - _bufs[i]))); + } + + // if (currentInPos != subStreamStartPos + subStreamSize) return E_FAIL; + + return S_OK; +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + try + { + return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); + } + catch(...) { return E_FAIL; } +} + +#endif + + + + + + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size) { _bufsNewSizes[streamIndex] = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _bufsNewSizes[BCJ2_NUM_STREAMS] = size; return S_OK; } + +CDecoder::CDecoder(): _finishMode(false), _outSizeDefined(false), _outSize(0) +{} + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + _finishMode = (finishMode != 0); + return S_OK; +} + +void CDecoder::InitCommon() +{ + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + dec.lims[i] = dec.bufs[i] = _bufs[i]; + } + + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + _extraReadSizes[i] = 0; + _inStreamsProcessed[i] = 0; + _readRes[i] = S_OK; + } + } + + Bcj2Dec_Init(&dec); +} + +HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1) + return E_INVALIDARG; + + RINOK(Alloc()); + + InitCommon(); + + dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS]; + + UInt64 outSizeProcessed = 0; + UInt64 prevProgress = 0; + + HRESULT res = S_OK; + + for (;;) + { + if (Bcj2Dec_Decode(&dec) != SZ_OK) + return S_FALSE; + + if (dec.state < BCJ2_NUM_STREAMS) + { + size_t totalRead = _extraReadSizes[dec.state]; + { + Byte *buf = _bufs[dec.state]; + for (size_t i = 0; i < totalRead; i++) + buf[i] = dec.bufs[dec.state][i]; + dec.lims[dec.state] = + dec.bufs[dec.state] = buf; + } + + if (_readRes[dec.state] != S_OK) + { + res = _readRes[dec.state]; + break; + } + + do + { + UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead; + /* + we want to call Read even even if size is 0 + if (inSizes && inSizes[dec.state]) + { + UInt64 rem = *inSizes[dec.state] - _inStreamsProcessed[dec.state]; + if (curSize > rem) + curSize = (UInt32)rem; + } + */ + + HRESULT res2 = inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize); + _readRes[dec.state] = res2; + if (curSize == 0) + break; + _inStreamsProcessed[dec.state] += curSize; + totalRead += curSize; + if (res2 != S_OK) + break; + } + while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state)); + + if (_readRes[dec.state] != S_OK) + res = _readRes[dec.state]; + + if (totalRead == 0) + break; + + // res == S_OK; + + if (BCJ2_IS_32BIT_STREAM(dec.state)) + { + unsigned extraSize = ((unsigned)totalRead & 3); + _extraReadSizes[dec.state] = extraSize; + if (totalRead < 4) + { + res = (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE; + break; + } + totalRead -= extraSize; + } + + dec.lims[dec.state] = _bufs[dec.state] + totalRead; + } + else // if (dec.state <= BCJ2_STATE_ORIG) + { + const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); + if (curSize != 0) + { + outSizeProcessed += curSize; + RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)); + } + dec.dest = _bufs[BCJ2_NUM_STREAMS]; + { + size_t rem = _bufsCurSizes[BCJ2_NUM_STREAMS]; + if (outSizes && outSizes[0]) + { + UInt64 outSize = *outSizes[0] - outSizeProcessed; + if (rem > outSize) + rem = (size_t)outSize; + } + dec.destLim = dec.dest + rem; + if (rem == 0) + break; + } + } + + if (progress) + { + const UInt64 outSize2 = outSizeProcessed + (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); + if (outSize2 - prevProgress >= (1 << 22)) + { + const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (size_t)(dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]); + RINOK(progress->SetRatioInfo(&inSize2, &outSize2)); + prevProgress = outSize2; + } + } + } + + const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]); + if (curSize != 0) + { + outSizeProcessed += curSize; + RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize)); + } + + if (res != S_OK) + return res; + + if (_finishMode) + { + if (!Bcj2Dec_IsFinished(&dec)) + return S_FALSE; + + // we still allow the cases when input streams are larger than required for decoding. + // so the case (dec.state == BCJ2_STATE_ORIG) is also allowed, if MAIN stream is larger than required. + if (dec.state != BCJ2_STREAM_MAIN && + dec.state != BCJ2_DEC_STATE_ORIG) + return S_FALSE; + + if (inSizes) + { + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + { + const size_t rem = (size_t)(dec.lims[i] - dec.bufs[i]) + _extraReadSizes[i]; + /* + if (rem != 0) + return S_FALSE; + */ + if (inSizes[i] && *inSizes[i] != _inStreamsProcessed[i] - rem) + return S_FALSE; + } + } + } + + return S_OK; +} + +STDMETHODIMP CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream) +{ + _inStreams[streamIndex] = inStream; + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream2(UInt32 streamIndex) +{ + _inStreams[streamIndex].Release(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + _outSize = 0; + if (_outSizeDefined) + _outSize = *outSize; + + _outSize_Processed = 0; + + HRESULT res = Alloc(false); + + InitCommon(); + dec.destLim = dec.dest = NULL; + + return res; +} + + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + if (size == 0) + return S_OK; + + UInt32 totalProcessed = 0; + + if (_outSizeDefined) + { + UInt64 rem = _outSize - _outSize_Processed; + if (size > rem) + size = (UInt32)rem; + } + dec.dest = (Byte *)data; + dec.destLim = (const Byte *)data + size; + + HRESULT res = S_OK; + + for (;;) + { + SRes sres = Bcj2Dec_Decode(&dec); + if (sres != SZ_OK) + return S_FALSE; + + { + UInt32 curSize = (UInt32)(dec.dest - (Byte *)data); + if (curSize != 0) + { + totalProcessed += curSize; + if (processedSize) + *processedSize = totalProcessed; + data = (void *)((Byte *)data + curSize); + size -= curSize; + _outSize_Processed += curSize; + } + } + + if (dec.state >= BCJ2_NUM_STREAMS) + break; + + { + size_t totalRead = _extraReadSizes[dec.state]; + { + Byte *buf = _bufs[dec.state]; + for (size_t i = 0; i < totalRead; i++) + buf[i] = dec.bufs[dec.state][i]; + dec.lims[dec.state] = + dec.bufs[dec.state] = buf; + } + + if (_readRes[dec.state] != S_OK) + return _readRes[dec.state]; + + do + { + UInt32 curSize = _bufsCurSizes[dec.state] - (UInt32)totalRead; + HRESULT res2 = _inStreams[dec.state]->Read(_bufs[dec.state] + totalRead, curSize, &curSize); + _readRes[dec.state] = res2; + if (curSize == 0) + break; + _inStreamsProcessed[dec.state] += curSize; + totalRead += curSize; + if (res2 != S_OK) + break; + } + while (totalRead < 4 && BCJ2_IS_32BIT_STREAM(dec.state)); + + if (totalRead == 0) + { + if (totalProcessed == 0) + res = _readRes[dec.state]; + break; + } + + if (BCJ2_IS_32BIT_STREAM(dec.state)) + { + unsigned extraSize = ((unsigned)totalRead & 3); + _extraReadSizes[dec.state] = extraSize; + if (totalRead < 4) + { + if (totalProcessed != 0) + return S_OK; + return (_readRes[dec.state] != S_OK) ? _readRes[dec.state] : S_FALSE; + } + totalRead -= extraSize; + } + + dec.lims[dec.state] = _bufs[dec.state] + totalRead; + } + } + + if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed) + { + if (!Bcj2Dec_IsFinished(&dec)) + return S_FALSE; + + if (dec.state != BCJ2_STREAM_MAIN && + dec.state != BCJ2_DEC_STATE_ORIG) + return S_FALSE; + + /* + for (int i = 0; i < BCJ2_NUM_STREAMS; i++) + if (dec.bufs[i] != dec.lims[i] || _extraReadSizes[i] != 0) + return S_FALSE; + */ + } + + return res; +} + + +STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value) +{ + const size_t rem = (size_t)(dec.lims[streamIndex] - dec.bufs[streamIndex]) + _extraReadSizes[streamIndex]; + *value = _inStreamsProcessed[streamIndex] - rem; + return S_OK; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.h new file mode 100644 index 0000000..ca6a1e4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Coder.h @@ -0,0 +1,120 @@ +// Bcj2Coder.h + +#ifndef __COMPRESS_BCJ2_CODER_H +#define __COMPRESS_BCJ2_CODER_H + +#include "../../../C/Bcj2.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NBcj2 { + +class CBaseCoder +{ +protected: + Byte *_bufs[BCJ2_NUM_STREAMS + 1]; + UInt32 _bufsCurSizes[BCJ2_NUM_STREAMS + 1]; + UInt32 _bufsNewSizes[BCJ2_NUM_STREAMS + 1]; + + HRESULT Alloc(bool allocForOrig = true); +public: + CBaseCoder(); + ~CBaseCoder(); +}; + + +#ifndef EXTRACT_ONLY + +class CEncoder: + public ICompressCoder2, + public ICompressSetCoderProperties, + public ICompressSetBufSize, + public CMyUnknownImp, + public CBaseCoder +{ + UInt32 _relatLim; + + HRESULT CodeReal(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + +public: + MY_UNKNOWN_IMP3(ICompressCoder2, ICompressSetCoderProperties, ICompressSetBufSize) + + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + CEncoder(); + ~CEncoder(); +}; + +#endif + +class CDecoder: + public ICompressCoder2, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize2, + public ICompressSetInStream2, + public ISequentialInStream, + public ICompressSetOutStreamSize, + public ICompressSetBufSize, + public CMyUnknownImp, + public CBaseCoder +{ + unsigned _extraReadSizes[BCJ2_NUM_STREAMS]; + UInt64 _inStreamsProcessed[BCJ2_NUM_STREAMS]; + HRESULT _readRes[BCJ2_NUM_STREAMS]; + CMyComPtr _inStreams[BCJ2_NUM_STREAMS]; + + bool _finishMode; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _outSize_Processed; + CBcj2Dec dec; + + void InitCommon(); + // HRESULT ReadSpec(); + +public: + MY_UNKNOWN_IMP7( + ICompressCoder2, + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize2, + ICompressSetInStream2, + ISequentialInStream, + ICompressSetOutStreamSize, + ICompressSetBufSize + ); + + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress); + + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value); + + STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream2)(UInt32 streamIndex); + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + CDecoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Register.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Register.cpp new file mode 100644 index 0000000..2868f1c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Bcj2Register.cpp @@ -0,0 +1,24 @@ +// Bcj2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Bcj2Coder.h" + +namespace NCompress { +namespace NBcj2 { + +REGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2) +#ifndef EXTRACT_ONLY +REGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2) +#else +#define CreateCodecOut NULL +#endif + +REGISTER_CODEC_VAR(BCJ2) + { CreateCodec, CreateCodecOut, 0x303011B, "BCJ2", 4, false }; + +REGISTER_CODEC(BCJ2) + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.cpp new file mode 100644 index 0000000..32aa176 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.cpp @@ -0,0 +1,24 @@ +// BcjCoder.cpp + +#include "StdAfx.h" + +#include "BcjCoder.h" + +namespace NCompress { +namespace NBcj { + +STDMETHODIMP CCoder::Init() +{ + _bufferPos = 0; + x86_Convert_Init(_prevMask); + return S_OK; +} + +STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size) +{ + UInt32 processed = (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, _encode); + _bufferPos += processed; + return processed; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.h new file mode 100644 index 0000000..7883906 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjCoder.h @@ -0,0 +1,31 @@ +// BcjCoder.h + +#ifndef __COMPRESS_BCJ_CODER_H +#define __COMPRESS_BCJ_CODER_H + +#include "../../../C/Bra.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NBcj { + +class CCoder: + public ICompressFilter, + public CMyUnknownImp +{ + UInt32 _bufferPos; + UInt32 _prevMask; + int _encode; +public: + MY_UNKNOWN_IMP1(ICompressFilter); + INTERFACE_ICompressFilter(;) + + CCoder(int encode): _bufferPos(0), _encode(encode) { x86_Convert_Init(_prevMask); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjRegister.cpp new file mode 100644 index 0000000..f06dcfe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BcjRegister.cpp @@ -0,0 +1,17 @@ +// BcjRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "BcjCoder.h" + +namespace NCompress { +namespace NBcj { + +REGISTER_FILTER_E(BCJ, + CCoder(false), + CCoder(true), + 0x3030103, "BCJ") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.cpp new file mode 100644 index 0000000..d0e75e8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.cpp @@ -0,0 +1,23 @@ +// BranchMisc.cpp + +#include "StdAfx.h" + +#include "BranchMisc.h" + +namespace NCompress { +namespace NBranch { + +STDMETHODIMP CCoder::Init() +{ + _bufferPos = 0; + return S_OK; +} + +STDMETHODIMP_(UInt32) CCoder::Filter(Byte *data, UInt32 size) +{ + UInt32 processed = (UInt32)BraFunc(data, size, _bufferPos, _encode); + _bufferPos += processed; + return processed; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.h new file mode 100644 index 0000000..66fc23d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchMisc.h @@ -0,0 +1,35 @@ +// BranchMisc.h + +#ifndef __COMPRESS_BRANCH_MISC_H +#define __COMPRESS_BRANCH_MISC_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +EXTERN_C_BEGIN + +typedef SizeT (*Func_Bra)(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +namespace NCompress { +namespace NBranch { + +class CCoder: + public ICompressFilter, + public CMyUnknownImp +{ + UInt32 _bufferPos; + int _encode; + Func_Bra BraFunc; +public: + MY_UNKNOWN_IMP1(ICompressFilter); + INTERFACE_ICompressFilter(;) + + CCoder(Func_Bra bra, int encode): _bufferPos(0), _encode(encode), BraFunc(bra) {} +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchRegister.cpp new file mode 100644 index 0000000..6331c1b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/BranchRegister.cpp @@ -0,0 +1,41 @@ +// BranchRegister.cpp + +#include "StdAfx.h" + +#include "../../../C/Bra.h" + +#include "../Common/RegisterCodec.h" + +#include "BranchMisc.h" + +namespace NCompress { +namespace NBranch { + +#define CREATE_BRA(n) \ + REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(n ## _Convert, false)) \ + REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(n ## _Convert, true)) \ + +CREATE_BRA(PPC) +CREATE_BRA(IA64) +CREATE_BRA(ARM) +CREATE_BRA(ARMT) +CREATE_BRA(SPARC) + +#define METHOD_ITEM(n, id, name) \ + REGISTER_FILTER_ITEM( \ + CreateBra_Decoder_ ## n, \ + CreateBra_Encoder_ ## n, \ + 0x3030000 + id, name) + +REGISTER_CODECS_VAR +{ + METHOD_ITEM(PPC, 0x205, "PPC"), + METHOD_ITEM(IA64, 0x401, "IA64"), + METHOD_ITEM(ARM, 0x501, "ARM"), + METHOD_ITEM(ARMT, 0x701, "ARMT"), + METHOD_ITEM(SPARC, 0x805, "SPARC") +}; + +REGISTER_CODECS(Branch) + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/ByteSwap.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/ByteSwap.cpp new file mode 100644 index 0000000..4c11806 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/ByteSwap.cpp @@ -0,0 +1,92 @@ +// ByteSwap.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +namespace NCompress { +namespace NByteSwap { + +class CByteSwap2: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICompressFilter); + INTERFACE_ICompressFilter(;) +}; + +class CByteSwap4: + public ICompressFilter, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICompressFilter); + INTERFACE_ICompressFilter(;) +}; + +STDMETHODIMP CByteSwap2::Init() { return S_OK; } + +STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) +{ + const UInt32 kStep = 2; + if (size < kStep) + return 0; + size &= ~(kStep - 1); + + const Byte *end = data + (size_t)size; + + do + { + Byte b0 = data[0]; + data[0] = data[1]; + data[1] = b0; + data += kStep; + } + while (data != end); + + return size; +} + +STDMETHODIMP CByteSwap4::Init() { return S_OK; } + +STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) +{ + const UInt32 kStep = 4; + if (size < kStep) + return 0; + size &= ~(kStep - 1); + + const Byte *end = data + (size_t)size; + + do + { + Byte b0 = data[0]; + Byte b1 = data[1]; + data[0] = data[3]; + data[1] = data[2]; + data[2] = b1; + data[3] = b0; + data += kStep; + } + while (data != end); + + return size; +} + +REGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2()) +REGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4()) + +REGISTER_CODECS_VAR +{ + REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, "Swap2"), + REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, "Swap4") +}; + +REGISTER_CODECS(ByteSwap) + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CodecExports.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CodecExports.cpp new file mode 100644 index 0000000..2aea7b3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CodecExports.cpp @@ -0,0 +1,368 @@ +// CodecExports.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" +#include "../../Common/MyCom.h" + +#include "../../Windows/Defs.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +extern unsigned g_NumCodecs; +extern const CCodecInfo *g_Codecs[]; + +extern unsigned g_NumHashers; +extern const CHasherInfo *g_Hashers[]; + +static void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw() +{ + UINT len = (UINT)strlen(s); + BSTR dest = ::SysAllocStringLen(NULL, len); + if (dest) + { + for (UINT i = 0; i <= len; i++) + dest[i] = (Byte)s[i]; + prop->bstrVal = dest; + prop->vt = VT_BSTR; + } +} + +static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw() +{ + if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL) + value->vt = VT_BSTR; + return S_OK; +} + +static HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw() +{ + GUID clsId; + clsId.Data1 = k_7zip_GUID_Data1; + clsId.Data2 = k_7zip_GUID_Data2; + clsId.Data3 = typeId; + SetUi64(clsId.Data4, id); + return SetPropGUID(clsId, value); +} + +static HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw() +{ + index = -1; + if (clsid->Data1 != k_7zip_GUID_Data1 || + clsid->Data2 != k_7zip_GUID_Data2) + return S_OK; + + encode = true; + + if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false; + else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK; + + UInt64 id = GetUi64(clsid->Data4); + + for (unsigned i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &codec = *g_Codecs[i]; + + if (id != codec.Id + || (encode ? !codec.CreateEncoder : !codec.CreateDecoder) + || (isFilter ? !codec.IsFilter : codec.IsFilter)) + continue; + + if (codec.NumStreams == 1 ? isCoder2 : !isCoder2) + return E_NOINTERFACE; + + index = i; + return S_OK; + } + + return S_OK; +} + +/* +#ifdef __GNUC__ +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#endif +#endif +*/ + +static HRESULT CreateCoderMain(unsigned index, bool encode, void **coder) +{ + COM_TRY_BEGIN + + const CCodecInfo &codec = *g_Codecs[index]; + + void *c; + if (encode) + c = codec.CreateEncoder(); + else + c = codec.CreateDecoder(); + + if (c) + { + IUnknown *unk; + unk = (IUnknown *)c; + /* + if (codec.IsFilter) + unk = (IUnknown *)(ICompressFilter *)c; + else if (codec.NumStreams != 1) + unk = (IUnknown *)(ICompressCoder2 *)c; + else + unk = (IUnknown *)(ICompressCoder *)c; + */ + unk->AddRef(); + *coder = c; + } + return S_OK; + + COM_TRY_END +} + +static HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) +{ + *outObject = NULL; + + const CCodecInfo &codec = *g_Codecs[index]; + + if (encode ? !codec.CreateEncoder : !codec.CreateDecoder) + return CLASS_E_CLASSNOTAVAILABLE; + + if (codec.IsFilter) + { + if (*iid != IID_ICompressFilter) return E_NOINTERFACE; + } + else if (codec.NumStreams != 1) + { + if (*iid != IID_ICompressCoder2) return E_NOINTERFACE; + } + else + { + if (*iid != IID_ICompressCoder) return E_NOINTERFACE; + } + + return CreateCoderMain(index, encode, outObject); +} + + +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject) +{ + return CreateCoder2(false, index, iid, outObject); +} + + +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject) +{ + return CreateCoder2(true, index, iid, outObject); +} + + +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); +STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) +{ + *outObject = NULL; + + bool isFilter = false; + bool isCoder2 = false; + bool isCoder = (*iid == IID_ICompressCoder) != 0; + if (!isCoder) + { + isFilter = (*iid == IID_ICompressFilter) != 0; + if (!isFilter) + { + isCoder2 = (*iid == IID_ICompressCoder2) != 0; + if (!isCoder2) + return E_NOINTERFACE; + } + } + + bool encode; + int codecIndex; + HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); + if (res != S_OK) + return res; + if (codecIndex < 0) + return CLASS_E_CLASSNOTAVAILABLE; + + return CreateCoderMain(codecIndex, encode, outObject); +} + + +STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) +{ + ::VariantClear((VARIANTARG *)value); + const CCodecInfo &codec = *g_Codecs[codecIndex]; + switch (propID) + { + case NMethodPropID::kID: + value->uhVal.QuadPart = (UInt64)codec.Id; + value->vt = VT_UI8; + break; + case NMethodPropID::kName: + SetPropFromAscii(codec.Name, value); + break; + case NMethodPropID::kDecoder: + if (codec.CreateDecoder) + return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value); + break; + case NMethodPropID::kEncoder: + if (codec.CreateEncoder) + return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value); + break; + case NMethodPropID::kDecoderIsAssigned: + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL); + break; + case NMethodPropID::kEncoderIsAssigned: + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL); + break; + case NMethodPropID::kPackStreams: + if (codec.NumStreams != 1) + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.NumStreams; + } + break; + /* + case NMethodPropID::kIsFilter: + // if (codec.IsFilter) + { + value->vt = VT_BOOL; + value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter); + } + break; + */ + /* + case NMethodPropID::kDecoderFlags: + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.DecoderFlags; + } + break; + case NMethodPropID::kEncoderFlags: + { + value->vt = VT_UI4; + value->ulVal = (ULONG)codec.EncoderFlags; + } + break; + */ + } + return S_OK; +} + + +STDAPI GetNumberOfMethods(UINT32 *numCodecs); +STDAPI GetNumberOfMethods(UINT32 *numCodecs) +{ + *numCodecs = g_NumCodecs; + return S_OK; +} + + +// ---------- Hashers ---------- + +static int FindHasherClassId(const GUID *clsid) throw() +{ + if (clsid->Data1 != k_7zip_GUID_Data1 || + clsid->Data2 != k_7zip_GUID_Data2 || + clsid->Data3 != k_7zip_GUID_Data3_Hasher) + return -1; + UInt64 id = GetUi64(clsid->Data4); + for (unsigned i = 0; i < g_NumCodecs; i++) + if (id == g_Hashers[i]->Id) + return i; + return -1; +} + +static HRESULT CreateHasher2(UInt32 index, IHasher **hasher) +{ + COM_TRY_BEGIN + *hasher = g_Hashers[index]->CreateHasher(); + if (*hasher) + (*hasher)->AddRef(); + return S_OK; + COM_TRY_END +} + +STDAPI CreateHasher(const GUID *clsid, IHasher **outObject); +STDAPI CreateHasher(const GUID *clsid, IHasher **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + int index = FindHasherClassId(clsid); + if (index < 0) + return CLASS_E_CLASSNOTAVAILABLE; + return CreateHasher2(index, outObject); + COM_TRY_END +} + +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) +{ + ::VariantClear((VARIANTARG *)value); + const CHasherInfo &codec = *g_Hashers[codecIndex]; + switch (propID) + { + case NMethodPropID::kID: + value->uhVal.QuadPart = (UInt64)codec.Id; + value->vt = VT_UI8; + break; + case NMethodPropID::kName: + SetPropFromAscii(codec.Name, value); + break; + case NMethodPropID::kEncoder: + if (codec.CreateHasher) + return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value); + break; + case NMethodPropID::kDigestSize: + value->ulVal = (ULONG)codec.DigestSize; + value->vt = VT_UI4; + break; + } + return S_OK; +} + +class CHashers: + public IHashers, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(IHashers) + + STDMETHOD_(UInt32, GetNumHashers)(); + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); +}; + +STDAPI GetHashers(IHashers **hashers); +STDAPI GetHashers(IHashers **hashers) +{ + COM_TRY_BEGIN + *hashers = new CHashers; + if (*hashers) + (*hashers)->AddRef(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP_(UInt32) CHashers::GetNumHashers() +{ + return g_NumHashers; +} + +STDMETHODIMP CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + return ::GetHasherProp(index, propID, value); +} + +STDMETHODIMP CHashers::CreateHasher(UInt32 index, IHasher **hasher) +{ + return ::CreateHasher2(index, hasher); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.cpp new file mode 100644 index 0000000..d8487ad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.cpp @@ -0,0 +1,120 @@ +// Compress/CopyCoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "CopyCoder.h" + +namespace NCompress { + +static const UInt32 kBufSize = 1 << 17; + +CCopyCoder::~CCopyCoder() +{ + ::MidFree(_buf); +} + +STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */) +{ + return S_OK; +} + +STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (!_buf) + { + _buf = (Byte *)::MidAlloc(kBufSize); + if (!_buf) + return E_OUTOFMEMORY; + } + + TotalSize = 0; + + for (;;) + { + UInt32 size = kBufSize; + if (outSize && size > *outSize - TotalSize) + size = (UInt32)(*outSize - TotalSize); + if (size == 0) + return S_OK; + + HRESULT readRes = inStream->Read(_buf, size, &size); + + if (size == 0) + return readRes; + + if (outStream) + { + UInt32 pos = 0; + do + { + UInt32 curSize = size - pos; + HRESULT res = outStream->Write(_buf + pos, curSize, &curSize); + pos += curSize; + TotalSize += curSize; + RINOK(res); + if (curSize == 0) + return E_FAIL; + } + while (pos < size); + } + else + TotalSize += size; + + RINOK(readRes); + + if (progress) + { + RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); + } + } +} + +STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream) +{ + _inStream = inStream; + TotalSize = 0; + return S_OK; +} + +STDMETHODIMP CCopyCoder::ReleaseInStream() +{ + _inStream.Release(); + return S_OK; +} + +STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize = 0; + HRESULT res = _inStream->Read(data, size, &realProcessedSize); + TotalSize += realProcessedSize; + if (processedSize) + *processedSize = realProcessedSize; + return res; +} + +STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = TotalSize; + return S_OK; +} + +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + CMyComPtr copyCoder = new CCopyCoder; + return copyCoder->Code(inStream, outStream, NULL, NULL, progress); +} + +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) +{ + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)); + return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; +} + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.h new file mode 100644 index 0000000..a9d0b6d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyCoder.h @@ -0,0 +1,49 @@ +// Compress/CopyCoder.h + +#ifndef __COMPRESS_COPY_CODER_H +#define __COMPRESS_COPY_CODER_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { + +class CCopyCoder: + public ICompressCoder, + public ICompressSetInStream, + public ISequentialInStream, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + public CMyUnknownImp +{ + Byte *_buf; + CMyComPtr _inStream; +public: + UInt64 TotalSize; + + CCopyCoder(): _buf(0), TotalSize(0) {}; + ~CCopyCoder(); + + MY_UNKNOWN_IMP5( + ICompressCoder, + ICompressSetInStream, + ISequentialInStream, + ICompressSetFinishMode, + ICompressGetInStreamProcessedSize) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); +}; + +HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); +HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress); + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyRegister.cpp new file mode 100644 index 0000000..7141ab5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/CopyRegister.cpp @@ -0,0 +1,15 @@ +// CopyRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "CopyCoder.h" + +namespace NCompress { + +REGISTER_CODEC_CREATE(CreateCodec, CCopyCoder()) + +REGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, "Copy") + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/DeltaFilter.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/DeltaFilter.cpp new file mode 100644 index 0000000..3986ae4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/DeltaFilter.cpp @@ -0,0 +1,128 @@ +// DeltaFilter.cpp + +#include "StdAfx.h" + +#include "../../../C/Delta.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/RegisterCodec.h" + +namespace NCompress { +namespace NDelta { + +struct CDelta +{ + unsigned _delta; + Byte _state[DELTA_STATE_SIZE]; + + CDelta(): _delta(1) {} + void DeltaInit() { Delta_Init(_state); } +}; + + +#ifndef EXTRACT_ONLY + +class CEncoder: + public ICompressFilter, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP3(ICompressFilter, ICompressSetCoderProperties, ICompressWriteCoderProperties) + INTERFACE_ICompressFilter(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); +}; + +STDMETHODIMP CEncoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size) +{ + Delta_Encode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) +{ + UInt32 delta = _delta; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = props[i]; + PROPID propID = propIDs[i]; + if (propID >= NCoderPropID::kReduceSize) + continue; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + switch (propID) + { + case NCoderPropID::kDefaultProp: + delta = (UInt32)prop.ulVal; + if (delta < 1 || delta > 256) + return E_INVALIDARG; + break; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: break; + default: return E_INVALIDARG; + } + } + _delta = delta; + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = (Byte)(_delta - 1); + return outStream->Write(&prop, 1, NULL); +} + +#endif + + +class CDecoder: + public ICompressFilter, + public ICompressSetDecoderProperties2, + CDelta, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(ICompressFilter, ICompressSetDecoderProperties2) + INTERFACE_ICompressFilter(;) + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); +}; + +STDMETHODIMP CDecoder::Init() +{ + DeltaInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) +{ + Delta_Decode(_state, _delta, data, size); + return size; +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) +{ + if (size != 1) + return E_INVALIDARG; + _delta = (unsigned)props[0] + 1; + return S_OK; +} + + +REGISTER_FILTER_E(Delta, + CDecoder(), + CEncoder(), + 3, "Delta") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.cpp new file mode 100644 index 0000000..653fe2d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.cpp @@ -0,0 +1,265 @@ +// Lzma2Decoder.cpp + +#include "StdAfx.h" + +// #include + +#include "../../../C/Alloc.h" +// #include "../../../C/CpuTicks.h" + +#include "../Common/StreamUtils.h" + +#include "Lzma2Decoder.h" + +namespace NCompress { +namespace NLzma2 { + +CDecoder::CDecoder(): + _dec(NULL) + , _inProcessed(0) + , _prop(0xFF) + , _finishMode(false) + , _inBufSize(1 << 20) + , _outStep(1 << 20) + #ifndef _7ZIP_ST + , _tryMt(1) + , _numThreads(1) + , _memUsage((UInt64)(sizeof(size_t)) << 28) + #endif +{} + +CDecoder::~CDecoder() +{ + if (_dec) + Lzma2DecMt_Destroy(_dec); +} + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; } + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + if (size != 1) + return E_NOTIMPL; + if (prop[0] > 40) + return E_NOTIMPL; + _prop = prop[0]; + return S_OK; +} + + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + _finishMode = (finishMode != 0); + return S_OK; +} + + + +#ifndef _7ZIP_ST + +static UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize) +{ + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + UInt64 blockSize = (UInt64)dictSize << 2; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + blockSize += (kMinSize - 1); + blockSize &= ~(UInt64)(kMinSize - 1); + return blockSize; +} + +#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))) + +#endif + +#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; + +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + _inProcessed = 0; + + if (!_dec) + { + _dec = Lzma2DecMt_Create( + // &g_AlignedAlloc, + &g_Alloc, + &g_MidAlloc); + if (!_dec) + return E_OUTOFMEMORY; + } + + CLzma2DecMtProps props; + Lzma2DecMtProps_Init(&props); + + props.inBufSize_ST = _inBufSize; + props.outStep_ST = _outStep; + + #ifndef _7ZIP_ST + { + props.numThreads = 1; + UInt32 numThreads = _numThreads; + + if (_tryMt && numThreads >= 1) + { + UInt64 useLimit = _memUsage; + UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop); + UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize); + size_t expectedBlockSize = (size_t)expectedBlockSize64; + size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16; + if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize) + { + props.outBlockMax = expectedBlockSize; + props.inBlockMax = inBlockMax; + const size_t kOverheadSize = props.inBufSize_MT + (1 << 16); + UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize); + if (numThreads > okThreads) + numThreads = (UInt32)okThreads; + if (numThreads == 0) + numThreads = 1; + props.numThreads = numThreads; + } + } + } + #endif + + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + SRes res; + + UInt64 inProcessed = 0; + int isMT = False; + + #ifndef _7ZIP_ST + isMT = _tryMt; + #endif + + // UInt64 cpuTicks = GetCpuTicks(); + + res = Lzma2DecMt_Decode(_dec, _prop, &props, + &outWrap.vt, outSize, _finishMode, + &inWrap.vt, + &inProcessed, + &isMT, + progress ? &progressWrap.vt : NULL); + + /* + cpuTicks = GetCpuTicks() - cpuTicks; + printf("\n ticks = %10I64u\n", cpuTicks / 1000000); + */ + + + #ifndef _7ZIP_ST + /* we reset _tryMt, only if p->props.numThreads was changed */ + if (props.numThreads > 1) + _tryMt = isMT; + #endif + + _inProcessed = inProcessed; + + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) + + if (res == SZ_OK && _finishMode) + { + if (inSize && *inSize != inProcessed) + res = SZ_ERROR_DATA; + if (outSize && *outSize != outWrap.Processed) + res = SZ_ERROR_DATA; + } + + return SResToHRESULT(res); +} + + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inProcessed; + return S_OK; +} + + +#ifndef _7ZIP_ST + +STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads) +{ + _numThreads = numThreads; + return S_OK; +} + +STDMETHODIMP CDecoder::SetMemLimit(UInt64 memUsage) +{ + _memUsage = memUsage; + return S_OK; +} + +#endif + + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + CLzma2DecMtProps props; + Lzma2DecMtProps_Init(&props); + props.inBufSize_ST = _inBufSize; + props.outStep_ST = _outStep; + + _inProcessed = 0; + + if (!_dec) + { + _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc); + if (!_dec) + return E_OUTOFMEMORY; + } + + _inWrap.Init(_inStream); + + SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt); + + if (res != SZ_OK) + return SResToHRESULT(res); + return S_OK; +} + + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + size_t size2 = size; + UInt64 inProcessed = 0; + + SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed); + + _inProcessed += inProcessed; + if (processedSize) + *processedSize = (UInt32)size2; + if (res != SZ_OK) + return SResToHRESULT(res); + return S_OK; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.h new file mode 100644 index 0000000..e141488 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Decoder.h @@ -0,0 +1,96 @@ +// Lzma2Decoder.h + +#ifndef __LZMA2_DECODER_H +#define __LZMA2_DECODER_H + +#include "../../../C/Lzma2DecMt.h" + +#include "../Common/CWrappers.h" + +namespace NCompress { +namespace NLzma2 { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + public ICompressSetBufSize, + + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + + #ifndef _7ZIP_ST + public ICompressSetCoderMt, + public ICompressSetMemLimit, + #endif + + public CMyUnknownImp +{ + CLzma2DecMtHandle _dec; + UInt64 _inProcessed; + Byte _prop; + int _finishMode; + UInt32 _inBufSize; + UInt32 _outStep; + +public: + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) + + #ifndef NO_READ_FROM_CODER + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + #endif + + #ifndef _7ZIP_ST + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) + MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit) + #endif + + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + #ifndef _7ZIP_ST +private: + int _tryMt; + UInt32 _numThreads; + UInt64 _memUsage; +public: + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); + STDMETHOD(SetMemLimit)(UInt64 memUsage); + #endif + + #ifndef NO_READ_FROM_CODER +private: + CMyComPtr _inStream; + CSeqInStreamWrap _inWrap; +public: + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(); + virtual ~CDecoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.cpp new file mode 100644 index 0000000..6a5d679 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.cpp @@ -0,0 +1,126 @@ +// Lzma2Encoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "Lzma2Encoder.h" + +namespace NCompress { + +namespace NLzma { + +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); + +} + +namespace NLzma2 { + +CEncoder::CEncoder() +{ + _encoder = NULL; + _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc); + if (!_encoder) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder) + Lzma2Enc_Destroy(_encoder); +} + + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props) +{ + switch (propID) + { + case NCoderPropID::kBlockSize: + { + if (prop.vt == VT_UI4) + lzma2Props.blockSize = prop.ulVal; + else if (prop.vt == VT_UI8) + lzma2Props.blockSize = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + break; + } + case NCoderPropID::kNumThreads: + if (prop.vt != VT_UI4) + return E_INVALIDARG; + lzma2Props.numTotalThreads = (int)(prop.ulVal); + break; + default: + RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps)); + } + return S_OK; +} + + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + + for (UInt32 i = 0; i < numProps; i++) + { + RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props)); + } + return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props)); +} + + +STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID == NCoderPropID::kExpectedDataSize) + if (prop.vt == VT_UI8) + Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart); + } + return S_OK; +} + + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte prop = Lzma2Enc_WriteProperties(_encoder); + return WriteStream(outStream, &prop, 1); +} + + +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + SRes res = Lzma2Enc_Encode2(_encoder, + &outWrap.vt, NULL, NULL, + &inWrap.vt, NULL, 0, + progress ? &progressWrap.vt : NULL); + + RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + + return SResToHRESULT(res); +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.h new file mode 100644 index 0000000..f681ad1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Encoder.h @@ -0,0 +1,42 @@ +// Lzma2Encoder.h + +#ifndef __LZMA2_ENCODER_H +#define __LZMA2_ENCODER_H + +#include "../../../C/Lzma2Enc.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma2 { + +class CEncoder: + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public ICompressSetCoderPropertiesOpt, + public CMyUnknownImp +{ + CLzma2EncHandle _encoder; +public: + MY_UNKNOWN_IMP4( + ICompressCoder, + ICompressSetCoderProperties, + ICompressWriteCoderProperties, + ICompressSetCoderPropertiesOpt) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + CEncoder(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Register.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Register.cpp new file mode 100644 index 0000000..8f279eb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/Lzma2Register.cpp @@ -0,0 +1,22 @@ +// Lzma2Register.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Lzma2Decoder.h" + +#ifndef EXTRACT_ONLY +#include "Lzma2Encoder.h" +#endif + +namespace NCompress { +namespace NLzma2 { + +REGISTER_CODEC_E(LZMA2, + CDecoder(), + CEncoder(), + 0x21, + "LZMA2") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.cpp new file mode 100644 index 0000000..a25d36d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.cpp @@ -0,0 +1,346 @@ +// LzmaDecoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "LzmaDecoder.h" + +static HRESULT SResToHRESULT(SRes res) +{ + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_PARAM: return E_INVALIDARG; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; + case SZ_ERROR_DATA: return S_FALSE; + } + return E_FAIL; +} + +namespace NCompress { +namespace NLzma { + +CDecoder::CDecoder(): + _inBuf(NULL), + _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED), + FinishStream(false), + _propsWereSet(false), + _outSizeDefined(false), + _outStep(1 << 20), + _inBufSize(0), + _inBufSizeNew(1 << 20) +{ + _inProcessed = 0; + _inPos = _inLim = 0; + + /* + AlignOffsetAlloc_CreateVTable(&_alloc); + _alloc.numAlignBits = 7; + _alloc.offset = 0; + */ + LzmaDec_Construct(&_state); +} + +CDecoder::~CDecoder() +{ + LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt + MyFree(_inBuf); +} + +STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; } +STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; } + +HRESULT CDecoder::CreateInputBuffer() +{ + if (!_inBuf || _inBufSizeNew != _inBufSize) + { + MyFree(_inBuf); + _inBufSize = 0; + _inBuf = (Byte *)MyAlloc(_inBufSizeNew); + if (!_inBuf) + return E_OUTOFMEMORY; + _inBufSize = _inBufSizeNew; + } + return S_OK; +} + + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) +{ + RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt + _propsWereSet = true; + return CreateInputBuffer(); +} + + +void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + _outSize = 0; + if (_outSizeDefined) + _outSize = *outSize; + _outProcessed = 0; + _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED; + + LzmaDec_Init(&_state); +} + + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _inProcessed = 0; + _inPos = _inLim = 0; + SetOutStreamSizeResume(outSize); + return S_OK; +} + + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + FinishStream = (finishMode != 0); + return S_OK; +} + + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inProcessed; + return S_OK; +} + + +HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) +{ + if (!_inBuf || !_propsWereSet) + return S_FALSE; + + const UInt64 startInProgress = _inProcessed; + SizeT wrPos = _state.dicPos; + HRESULT readRes = S_OK; + + for (;;) + { + if (_inPos == _inLim && readRes == S_OK) + { + _inPos = _inLim = 0; + readRes = inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + const SizeT dicPos = _state.dicPos; + SizeT size; + { + SizeT next = _state.dicBufSize; + if (next - wrPos > _outStep) + next = wrPos + _outStep; + size = next - dicPos; + } + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) + { + size = (SizeT)rem; + if (FinishStream) + finishMode = LZMA_FINISH_END; + } + } + + SizeT inProcessed = _inLim - _inPos; + ELzmaStatus status; + + SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + const SizeT outProcessed = _state.dicPos - dicPos; + _outProcessed += outProcessed; + + // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0) + bool outFinished = (_outSizeDefined && _outProcessed >= _outSize); + + bool needStop = (res != 0 + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)); + + if (needStop || outProcessed >= size) + { + HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos); + + if (_state.dicPos == _state.dicBufSize) + _state.dicPos = 0; + wrPos = _state.dicPos; + + RINOK(res2); + + if (needStop) + { + if (res != 0) + { + // return SResToHRESULT(res); + return S_FALSE; + } + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (FinishStream) + if (_outSizeDefined && _outSize != _outProcessed) + return S_FALSE; + return readRes; + } + + if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT) + if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return readRes; + + return S_FALSE; + } + } + + if (progress) + { + const UInt64 inSize = _inProcessed - startInProgress; + RINOK(progress->SetRatioInfo(&inSize, &_outProcessed)); + } + } +} + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (!_inBuf) + return E_INVALIDARG; + SetOutStreamSize(outSize); + HRESULT res = CodeSpec(inStream, outStream, progress); + if (res == S_OK) + if (FinishStream && inSize && *inSize != _inProcessed) + res = S_FALSE; + return res; +} + + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } +STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } + + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) + { + size = (UInt32)rem; + if (FinishStream) + finishMode = LZMA_FINISH_END; + } + } + + HRESULT readRes = S_OK; + + for (;;) + { + if (_inPos == _inLim && readRes == S_OK) + { + _inPos = _inLim = 0; + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + SizeT inProcessed = _inLim - _inPos; + SizeT outProcessed = size; + ELzmaStatus status; + + SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + _outProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + + if (res != 0) + return S_FALSE; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; + + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (FinishStream + && _outSizeDefined && _outProcessed >= _outSize + && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return S_FALSE; + return readRes; + } + */ + + if (inProcessed == 0 && outProcessed == 0) + return readRes; + } +} + + +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + SetOutStreamSizeResume(outSize); + return CodeSpec(_inStream, outStream, progress); +} + + +HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize) +{ + RINOK(CreateInputBuffer()); + + if (processedSize) + *processedSize = 0; + + HRESULT readRes = S_OK; + + while (size != 0) + { + if (_inPos == _inLim) + { + _inPos = _inLim = 0; + if (readRes == S_OK) + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + if (_inLim == 0) + break; + } + + UInt32 cur = _inLim - _inPos; + if (cur > size) + cur = size; + memcpy(data, _inBuf + _inPos, cur); + _inPos += cur; + _inProcessed += cur; + size -= cur; + data = (Byte *)data + cur; + if (processedSize) + *processedSize += cur; + } + + return readRes; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.h new file mode 100644 index 0000000..37dec02 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaDecoder.h @@ -0,0 +1,113 @@ +// LzmaDecoder.h + +#ifndef __LZMA_DECODER_H +#define __LZMA_DECODER_H + +// #include "../../../C/Alloc.h" +#include "../../../C/LzmaDec.h" + +#include "../../Common/MyCom.h" +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma { + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + public ICompressSetBufSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + Byte *_inBuf; + UInt32 _inPos; + UInt32 _inLim; + + ELzmaStatus _lzmaStatus; + +public: + bool FinishStream; // set it before decoding, if you need to decode full LZMA stream + +private: + bool _propsWereSet; + bool _outSizeDefined; + UInt64 _outSize; + UInt64 _inProcessed; + UInt64 _outProcessed; + + UInt32 _outStep; + UInt32 _inBufSize; + UInt32 _inBufSizeNew; + + // CAlignOffsetAlloc _alloc; + + CLzmaDec _state; + + HRESULT CreateInputBuffer(); + HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress); + void SetOutStreamSizeResume(const UInt64 *outSize); + +public: + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize) + #ifndef NO_READ_FROM_CODER + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size); + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size); + + #ifndef NO_READ_FROM_CODER + +private: + CMyComPtr _inStream; +public: + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + + HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress); + HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize); + + #endif + + UInt64 GetInputProcessedSize() const { return _inProcessed; } + + CDecoder(); + virtual ~CDecoder(); + + UInt64 GetOutputProcessedSize() const { return _outProcessed; } + + bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; } + + bool CheckFinishStatus(bool withEndMark) const + { + return _lzmaStatus == (withEndMark ? + LZMA_STATUS_FINISHED_WITH_MARK : + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK); + } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.cpp new file mode 100644 index 0000000..4b3acd3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.cpp @@ -0,0 +1,346 @@ +// LzmaEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "LzmaEncoder.h" + +#include "../../Common/IntToString.h" +#include "../../Windows/TimeUtils.h" + +// #define LOG_LZMA_THREADS + +#ifdef LOG_LZMA_THREADS +#include + +EXTERN_C_BEGIN +void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); +EXTERN_C_END + +#endif + +namespace NCompress { +namespace NLzma { + +CEncoder::CEncoder() +{ + _encoder = NULL; + _encoder = LzmaEnc_Create(&g_AlignedAlloc); + if (!_encoder) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder) + LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc); +} + +static inline wchar_t GetLowCharFast(wchar_t c) +{ + return c |= 0x20; +} + +static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) +{ + wchar_t c = GetLowCharFast(*s++); + if (c == 'h') + { + if (GetLowCharFast(*s++) != 'c') + return 0; + int num = (int)(*s++ - L'0'); + if (num < 4 || num > 5) + return 0; + if (*s != 0) + return 0; + *btMode = 0; + *numHashBytes = num; + return 1; + } + + if (c != 'b') + return 0; + { + if (GetLowCharFast(*s++) != 't') + return 0; + int num = (int)(*s++ - L'0'); + if (num < 2 || num > 5) + return 0; + if (*s != 0) + return 0; + *btMode = 1; + *numHashBytes = num; + return 1; + } +} + +#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = (int)v; break; +#define SET_PROP_32U(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; + +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); +HRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) +{ + if (propID == NCoderPropID::kMatchFinder) + { + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; + } + + if (propID == NCoderPropID::kAffinity) + { + if (prop.vt == VT_UI8) + ep.affinity = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + return S_OK; + } + + if (propID > NCoderPropID::kReduceSize) + return S_OK; + + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8) + ep.reduceSize = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + return S_OK; + } + + if (propID == NCoderPropID::kDictionarySize) + { + if (prop.vt == VT_UI8) + { + // 21.03 : we support 64-bit VT_UI8 for dictionary and (dict == 4 GiB) + const UInt64 v = prop.uhVal.QuadPart; + if (v > ((UInt64)1 << 32)) + return E_INVALIDARG; + UInt32 dict; + if (v == ((UInt64)1 << 32)) + dict = (UInt32)(Int32)-1; + else + dict = (UInt32)v; + ep.dictSize = dict; + return S_OK; + } + } + + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = prop.ulVal; + switch (propID) + { + case NCoderPropID::kDefaultProp: + if (v > 32) + return E_INVALIDARG; + ep.dictSize = (v == 32) ? (UInt32)(Int32)-1 : (UInt32)1 << (unsigned)v; + break; + SET_PROP_32(kLevel, level) + SET_PROP_32(kNumFastBytes, fb) + SET_PROP_32U(kMatchFinderCycles, mc) + SET_PROP_32(kAlgorithm, algo) + SET_PROP_32U(kDictionarySize, dictSize) + SET_PROP_32(kPosStateBits, pb) + SET_PROP_32(kLitPosBits, lp) + SET_PROP_32(kLitContextBits, lc) + SET_PROP_32(kNumThreads, numThreads) + default: return E_INVALIDARG; + } + return S_OK; +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + switch (propID) + { + case NCoderPropID::kEndMarker: + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + props.writeEndMark = (prop.boolVal != VARIANT_FALSE); + break; + default: + RINOK(SetLzmaProp(propID, prop, props)); + } + } + return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); +} + + +STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID == NCoderPropID::kExpectedDataSize) + if (prop.vt == VT_UI8) + LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart); + } + return S_OK; +} + + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte props[LZMA_PROPS_SIZE]; + size_t size = LZMA_PROPS_SIZE; + RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); + return WriteStream(outStream, props, size); +} + + +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + + + +#ifdef LOG_LZMA_THREADS + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') +{ + char temp[64]; + char *p = temp + 32; + ConvertUInt64ToString(val, p); + unsigned len = (unsigned)strlen(p); + for (; len < numDigits; len++) + *--p = c; + printf("%s", p); +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total) +{ + printf(" %s :", s); + const UInt32 kFreq = 10000000; + UInt64 sec = val / kFreq; + PrintNum(sec, 6); + printf(" ."); + UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); + PrintNum(ms, 3, '0'); + + while (val > ((UInt64)1 << 56)) + { + val >>= 1; + total >>= 1; + } + + UInt64 percent = 0; + if (total != 0) + percent = val * 100 / total; + printf(" ="); + PrintNum(percent, 4); + printf("%%"); +} + + +struct CBaseStat +{ + UInt64 kernelTime, userTime; + + BOOL Get(HANDLE thread, const CBaseStat *prevStat) + { + FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; + BOOL res = GetThreadTimes(thread + , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT); + if (res) + { + kernelTime = GetTime64(kernelTimeFT); + userTime = GetTime64(userTimeFT); + if (prevStat) + { + kernelTime -= prevStat->kernelTime; + userTime -= prevStat->userTime; + } + } + return res; + } +}; + + +static void PrintStat(HANDLE thread, UInt64 totalTime, const CBaseStat *prevStat) +{ + CBaseStat newStat; + if (!newStat.Get(thread, prevStat)) + return; + + PrintTime("K", newStat.kernelTime, totalTime); + + const UInt64 processTime = newStat.kernelTime + newStat.userTime; + + PrintTime("U", newStat.userTime, totalTime); + PrintTime("S", processTime, totalTime); + printf("\n"); + // PrintTime("G ", totalTime, totalTime); +} + +#endif + + + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + #ifdef LOG_LZMA_THREADS + + FILETIME startTimeFT; + NWindows::NTime::GetCurUtcFileTime(startTimeFT); + UInt64 totalTime = GetTime64(startTimeFT); + CBaseStat oldStat; + if (!oldStat.Get(GetCurrentThread(), NULL)) + return E_FAIL; + + #endif + + + SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, + progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc); + + _inputProcessed = inWrap.Processed; + + RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + + + #ifdef LOG_LZMA_THREADS + + NWindows::NTime::GetCurUtcFileTime(startTimeFT); + totalTime = GetTime64(startTimeFT) - totalTime; + HANDLE lz_threads[2]; + LzmaEnc_GetLzThreads(_encoder, lz_threads); + printf("\n"); + printf("Main: "); PrintStat(GetCurrentThread(), totalTime, &oldStat); + printf("Hash: "); PrintStat(lz_threads[0], totalTime, NULL); + printf("BinT: "); PrintStat(lz_threads[1], totalTime, NULL); + // PrintTime("Total: ", totalTime, totalTime); + printf("\n"); + + #endif + + return SResToHRESULT(res); +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.h new file mode 100644 index 0000000..7d706ad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaEncoder.h @@ -0,0 +1,46 @@ +// LzmaEncoder.h + +#ifndef __LZMA_ENCODER_H +#define __LZMA_ENCODER_H + +#include "../../../C/LzmaEnc.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NLzma { + +class CEncoder: + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public ICompressSetCoderPropertiesOpt, + public CMyUnknownImp +{ + CLzmaEncHandle _encoder; + UInt64 _inputProcessed; +public: + MY_UNKNOWN_IMP4( + ICompressCoder, + ICompressSetCoderProperties, + ICompressWriteCoderProperties, + ICompressSetCoderPropertiesOpt) + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + CEncoder(); + virtual ~CEncoder(); + + UInt64 GetInputProcessedSize() const { return _inputProcessed; } + bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaRegister.cpp new file mode 100644 index 0000000..c802a99 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/LzmaRegister.cpp @@ -0,0 +1,22 @@ +// LzmaRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "LzmaDecoder.h" + +#ifndef EXTRACT_ONLY +#include "LzmaEncoder.h" +#endif + +namespace NCompress { +namespace NLzma { + +REGISTER_CODEC_E(LZMA, + CDecoder(), + CEncoder(), + 0x30101, + "LZMA") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.cpp new file mode 100644 index 0000000..7f54ec3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.cpp @@ -0,0 +1,220 @@ +// PpmdDecoder.cpp +// 2020-07-03 : Igor Pavlov : Public domain + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" +#include "../../../C/CpuArch.h" + +#include "../Common/StreamUtils.h" + +#include "PpmdDecoder.h" + +namespace NCompress { +namespace NPpmd { + +static const UInt32 kBufSize = (1 << 16); + +enum +{ + kStatus_NeedInit, + kStatus_Normal, + kStatus_Finished_With_Mark, + kStatus_Error +}; + +CDecoder::~CDecoder() +{ + ::MidFree(_outBuf); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) +{ + if (size < 5) + return E_INVALIDARG; + _order = props[0]; + UInt32 memSize = GetUi32(props + 1); + if ( + // _order < PPMD7_MIN_ORDER || + _order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return E_NOTIMPL; + if (!_inStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) + return E_OUTOFMEMORY; + return S_OK; +} + +#define _rangeDec _ppmd.rc.dec + +#define CHECK_EXTRA_ERROR \ + if (_inStream.Extra) { \ + _status = kStatus_Error; \ + return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); } + + +HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size) +{ + if (_res != S_OK) + return _res; + + switch (_status) + { + case kStatus_Finished_With_Mark: return S_OK; + case kStatus_Error: return S_FALSE; + case kStatus_NeedInit: + _inStream.Init(); + if (!Ppmd7z_RangeDec_Init(&_rangeDec)) + { + _status = kStatus_Error; + return (_res = S_FALSE); + } + CHECK_EXTRA_ERROR + _status = kStatus_Normal; + Ppmd7_Init(&_ppmd, _order); + break; + } + + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _processedSize; + if (size > rem) + size = (UInt32)rem; + } + + int sym = 0; + { + Byte *buf = memStream; + const Byte *lim = buf + size; + for (; buf != lim; buf++) + { + sym = Ppmd7z_DecodeSymbol(&_ppmd); + if (_inStream.Extra || sym < 0) + break; + *buf = (Byte)sym; + } + /* + buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim); + sym = _ppmd.LastSymbol; + */ + _processedSize += (size_t)(buf - memStream); + } + + CHECK_EXTRA_ERROR + + if (sym >= 0) + { + if (!FinishStream + || !_outSizeDefined + || _outSize != _processedSize + || _rangeDec.Code == 0) + return S_OK; + /* + // We can decode additional End Marker here: + sym = Ppmd7z_DecodeSymbol(&_ppmd); + CHECK_EXTRA_ERROR + */ + } + + if (sym != PPMD7_SYM_END || _rangeDec.Code != 0) + { + _status = kStatus_Error; + return (_res = S_FALSE); + } + + _status = kStatus_Finished_With_Mark; + return S_OK; +} + + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + if (!_outBuf) + { + _outBuf = (Byte *)::MidAlloc(kBufSize); + if (!_outBuf) + return E_OUTOFMEMORY; + } + + _inStream.Stream = inStream; + SetOutStreamSize(outSize); + + do + { + const UInt64 startPos = _processedSize; + HRESULT res = CodeSpec(_outBuf, kBufSize); + size_t processed = (size_t)(_processedSize - startPos); + RINOK(WriteStream(outStream, _outBuf, processed)); + RINOK(res); + if (_status == kStatus_Finished_With_Mark) + break; + if (progress) + { + const UInt64 inProcessed = _inStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize)); + } + } + while (!_outSizeDefined || _processedSize < _outSize); + + if (FinishStream && inSize && *inSize != _inStream.GetProcessed()) + return S_FALSE; + + return S_OK; +} + + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + _processedSize = 0; + _status = kStatus_NeedInit; + _res = SZ_OK; + return S_OK; +} + +STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) +{ + FinishStream = (finishMode != 0); + return S_OK; +} + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _inStream.GetProcessed(); + return S_OK; +} + +#ifndef NO_READ_FROM_CODER + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + InSeqStream = inStream; + _inStream.Stream = inStream; + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + InSeqStream.Release(); + return S_OK; +} + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + const UInt64 startPos = _processedSize; + HRESULT res = CodeSpec((Byte *)data, size); + if (processedSize) + *processedSize = (UInt32)(_processedSize - startPos); + return res; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.h new file mode 100644 index 0000000..f1a8ee2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdDecoder.h @@ -0,0 +1,91 @@ +// PpmdDecoder.h +// 2020-07-03 : Igor Pavlov : Public domain + +#ifndef __COMPRESS_PPMD_DECODER_H +#define __COMPRESS_PPMD_DECODER_H + +#include "../../../C/Ppmd7.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/CWrappers.h" + +namespace NCompress { +namespace NPpmd { + +class CDecoder : + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + #ifndef NO_READ_FROM_CODER + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + Byte *_outBuf; + CByteInBufWrap _inStream; + CPpmd7 _ppmd; + + Byte _order; + bool FinishStream; + bool _outSizeDefined; + HRESULT _res; + int _status; + UInt64 _outSize; + UInt64 _processedSize; + + HRESULT CodeSpec(Byte *memStream, UInt32 size); + +public: + + #ifndef NO_READ_FROM_CODER + CMyComPtr InSeqStream; + #endif + + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2) + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + #ifndef NO_READ_FROM_CODER + MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) + MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) + MY_QUERYINTERFACE_ENTRY(ISequentialInStream) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifndef NO_READ_FROM_CODER + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(): + _outBuf(NULL), + FinishStream(false), + _outSizeDefined(false) + { + Ppmd7_Construct(&_ppmd); + _ppmd.rc.dec.Stream = &_inStream.vt; + } + + ~CDecoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.cpp new file mode 100644 index 0000000..d41d2ac --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.cpp @@ -0,0 +1,193 @@ +// PpmdEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/StreamUtils.h" + +#include "PpmdEncoder.h" + +namespace NCompress { +namespace NPpmd { + +static const UInt32 kBufSize = (1 << 20); + +static const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 }; + +void CEncProps::Normalize(int level) +{ + if (level < 0) level = 5; + if (level > 9) level = 9; + if (MemSize == (UInt32)(Int32)-1) + MemSize = (UInt32)1 << (level + 19); + const unsigned kMult = 16; + if (MemSize / kMult > ReduceSize) + { + for (unsigned i = 16; i <= 31; i++) + { + UInt32 m = (UInt32)1 << i; + if (ReduceSize <= m / kMult) + { + if (MemSize > m) + MemSize = m; + break; + } + } + } + if (Order == -1) Order = kOrders[(unsigned)level]; +} + +CEncoder::CEncoder(): + _inBuf(NULL) +{ + _props.Normalize(-1); + Ppmd7_Construct(&_ppmd); + _ppmd.rc.enc.Stream = &_outStream.vt; +} + +CEncoder::~CEncoder() +{ + ::MidFree(_inBuf); + Ppmd7_Free(&_ppmd, &g_BigAlloc); +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + int level = -1; + CEncProps props; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + const PROPID propID = propIDs[i]; + if (propID > NCoderPropID::kReduceSize) + continue; + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1) + props.ReduceSize = (UInt32)prop.uhVal.QuadPart; + continue; + } + + if (propID == NCoderPropID::kUsedMemorySize) + { + // here we have selected (4 GiB - 1 KiB) as replacement for (4 GiB) MEM_SIZE. + const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10); + UInt32 v; + if (prop.vt == VT_UI8) + { + // 21.03 : we support 64-bit values (for 4 GiB value) + const UInt64 v64 = prop.uhVal.QuadPart; + if (v64 > ((UInt64)1 << 32)) + return E_INVALIDARG; + if (v64 == ((UInt64)1 << 32)) + v = kPpmd_Default_4g; + else + v = (UInt32)v64; + } + else if (prop.vt == VT_UI4) + v = (UInt32)prop.ulVal; + else + return E_INVALIDARG; + if (v > PPMD7_MAX_MEM_SIZE) + v = kPpmd_Default_4g; + + /* here we restrict MEM_SIZE for Encoder. + It's for better performance of encoding and decoding. + The Decoder still supports more MEM_SIZE values. */ + if (v < ((UInt32)1 << 16) || (v & 3) != 0) + return E_INVALIDARG; + // if (v < PPMD7_MIN_MEM_SIZE) return E_INVALIDARG; // (1 << 11) + /* + Supported MEM_SIZE range : + [ (1 << 11) , 0xFFFFFFFF - 12 * 3 ] - current 7-Zip's Ppmd7 constants + [ 1824 , 0xFFFFFFFF ] - real limits of Ppmd7 code + */ + props.MemSize = v; + continue; + } + + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 v = (UInt32)prop.ulVal; + switch (propID) + { + case NCoderPropID::kOrder: + if (v < 2 || v > 32) + return E_INVALIDARG; + props.Order = (Byte)v; + break; + case NCoderPropID::kNumThreads: break; + case NCoderPropID::kLevel: level = (int)v; break; + default: return E_INVALIDARG; + } + } + props.Normalize(level); + _props = props; + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + const UInt32 kPropSize = 5; + Byte props[kPropSize]; + props[0] = (Byte)_props.Order; + SetUi32(props + 1, _props.MemSize); + return WriteStream(outStream, props, kPropSize); +} + +HRESULT CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + if (!_inBuf) + { + _inBuf = (Byte *)::MidAlloc(kBufSize); + if (!_inBuf) + return E_OUTOFMEMORY; + } + if (!_outStream.Alloc(1 << 20)) + return E_OUTOFMEMORY; + if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc)) + return E_OUTOFMEMORY; + + _outStream.Stream = outStream; + _outStream.Init(); + + Ppmd7z_Init_RangeEnc(&_ppmd); + Ppmd7_Init(&_ppmd, (unsigned)_props.Order); + + UInt64 processed = 0; + for (;;) + { + UInt32 size; + RINOK(inStream->Read(_inBuf, kBufSize, &size)); + if (size == 0) + { + // We don't write EndMark in PPMD-7z. + // Ppmd7z_EncodeSymbol(&_ppmd, -1); + Ppmd7z_Flush_RangeEnc(&_ppmd); + return _outStream.Flush(); + } + const Byte *buf = _inBuf; + const Byte *lim = buf + size; + /* + for (; buf < lim; buf++) + { + Ppmd7z_EncodeSymbol(&_ppmd, *buf); + RINOK(_outStream.Res); + } + */ + + Ppmd7z_EncodeSymbols(&_ppmd, buf, lim); + RINOK(_outStream.Res); + + processed += size; + if (progress) + { + const UInt64 outSize = _outStream.GetProcessed(); + RINOK(progress->SetRatioInfo(&processed, &outSize)); + } + } +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.h new file mode 100644 index 0000000..0104663 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdEncoder.h @@ -0,0 +1,57 @@ +// PpmdEncoder.h + +#ifndef __COMPRESS_PPMD_ENCODER_H +#define __COMPRESS_PPMD_ENCODER_H + +#include "../../../C/Ppmd7.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +#include "../Common/CWrappers.h" + +namespace NCompress { +namespace NPpmd { + +struct CEncProps +{ + UInt32 MemSize; + UInt32 ReduceSize; + int Order; + + CEncProps() + { + MemSize = (UInt32)(Int32)-1; + ReduceSize = (UInt32)(Int32)-1; + Order = -1; + } + void Normalize(int level); +}; + +class CEncoder : + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CMyUnknownImp +{ + Byte *_inBuf; + CByteOutBufWrap _outStream; + CPpmd7 _ppmd; + CEncProps _props; +public: + MY_UNKNOWN_IMP3( + ICompressCoder, + ICompressSetCoderProperties, + ICompressWriteCoderProperties) + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + CEncoder(); + ~CEncoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdRegister.cpp new file mode 100644 index 0000000..a3ebb5f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/PpmdRegister.cpp @@ -0,0 +1,22 @@ +// PpmdRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "PpmdDecoder.h" + +#ifndef EXTRACT_ONLY +#include "PpmdEncoder.h" +#endif + +namespace NCompress { +namespace NPpmd { + +REGISTER_CODEC_E(PPMD, + CDecoder(), + CEncoder(), + 0x30401, + "PPMD") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/StdAfx.h new file mode 100644 index 0000000..1cbd7fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.cpp new file mode 100644 index 0000000..0371173 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.cpp @@ -0,0 +1,150 @@ +// XzDecoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../Common/CWrappers.h" + +#include "XzDecoder.h" + +namespace NCompress { +namespace NXz { + +#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; + +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + +static HRESULT SResToHRESULT_Code(SRes res) throw() +{ + if (res < 0) + return res; + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; + } + return S_FALSE; +} + + +HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, + const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) +{ + MainDecodeSRes = SZ_OK; + MainDecodeSRes_wasUsed = false; + XzStatInfo_Clear(&Stat); + + if (!xz) + { + xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc); + if (!xz) + return E_OUTOFMEMORY; + } + + CXzDecMtProps props; + XzDecMtProps_Init(&props); + + int isMT = False; + + #ifndef _7ZIP_ST + { + props.numThreads = 1; + UInt32 numThreads = _numThreads; + + if (_tryMt && numThreads > 1) + { + size_t memUsage = (size_t)_memUsage; + if (memUsage != _memUsage) + memUsage = (size_t)0 - 1; + props.memUseMax = memUsage; + isMT = (numThreads > 1); + } + + props.numThreads = numThreads; + } + #endif + + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(seqInStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + SRes res = XzDecMt_Decode(xz, + &props, + outSizeLimit, finishStream, + &outWrap.vt, + &inWrap.vt, + &Stat, + &isMT, + progress ? &progressWrap.vt : NULL); + + MainDecodeSRes = res; + + #ifndef _7ZIP_ST + // _tryMt = isMT; + #endif + + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) + + // return E_OUTOFMEMORY; // for debug check + + MainDecodeSRes_wasUsed = true; + + if (res == SZ_OK && finishStream) + { + /* + if (inSize && *inSize != Stat.PhySize) + res = SZ_ERROR_DATA; + */ + if (outSizeLimit && *outSizeLimit != outWrap.Processed) + res = SZ_ERROR_DATA; + } + + return SResToHRESULT_Code(res); +} + + +HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) +{ + return Decode(inStream, outStream, outSize, _finishStream, progress); +} + +STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode) +{ + _finishStream = (finishMode != 0); + return S_OK; +} + +STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = Stat.InSize; + return S_OK; +} + +#ifndef _7ZIP_ST + +STDMETHODIMP CComDecoder::SetNumberOfThreads(UInt32 numThreads) +{ + _numThreads = numThreads; + return S_OK; +} + +STDMETHODIMP CComDecoder::SetMemLimit(UInt64 memUsage) +{ + _memUsage = memUsage; + return S_OK; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.h new file mode 100644 index 0000000..7ad81f4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzDecoder.h @@ -0,0 +1,93 @@ +// XzDecoder.h + +#ifndef __XZ_DECODER_H +#define __XZ_DECODER_H + +#include "../../../C/Xz.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NXz { + +struct CDecoder +{ + CXzDecMtHandle xz; + int _tryMt; + UInt32 _numThreads; + UInt64 _memUsage; + + SRes MainDecodeSRes; // it's not HRESULT + bool MainDecodeSRes_wasUsed; + CXzStatInfo Stat; + + CDecoder(): + xz(NULL), + _tryMt(True), + _numThreads(1), + _memUsage((UInt64)(sizeof(size_t)) << 28), + MainDecodeSRes(SZ_OK), + MainDecodeSRes_wasUsed(false) + {} + + ~CDecoder() + { + if (xz) + XzDecMt_Destroy(xz); + } + + /* Decode() can return S_OK, if there is data after good xz streams, and that data is not new xz stream. + check also (Stat.DataAfterEnd) flag */ + + HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, + const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress); +}; + + +class CComDecoder: + public ICompressCoder, + public ICompressSetFinishMode, + public ICompressGetInStreamProcessedSize, + + #ifndef _7ZIP_ST + public ICompressSetCoderMt, + public ICompressSetMemLimit, + #endif + + public CMyUnknownImp, + public CDecoder +{ + bool _finishStream; + +public: + MY_QUERYINTERFACE_BEGIN2(ICompressCoder) + + MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) + MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) + + #ifndef _7ZIP_ST + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) + MY_QUERYINTERFACE_ENTRY(ICompressSetMemLimit) + #endif + + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetFinishMode)(UInt32 finishMode); + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + #ifndef _7ZIP_ST + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); + STDMETHOD(SetMemLimit)(UInt64 memUsage); + #endif + + CComDecoder(): _finishStream(false) {} +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.cpp new file mode 100644 index 0000000..d6f42ca --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.cpp @@ -0,0 +1,245 @@ +// XzEncoder.cpp + +#include "StdAfx.h" + +#include "../../../C/Alloc.h" + +#include "../../Common/MyString.h" +#include "../../Common/StringToInt.h" + +#include "../Common/CWrappers.h" +#include "../Common/StreamUtils.h" + +#include "XzEncoder.h" + +namespace NCompress { + +namespace NLzma2 { + +HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props); + +} + +namespace NXz { + +void CEncoder::InitCoderProps() +{ + XzProps_Init(&xzProps); +} + +CEncoder::CEncoder() +{ + XzProps_Init(&xzProps); + _encoder = NULL; + _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc); + if (!_encoder) + throw 1; +} + +CEncoder::~CEncoder() +{ + if (_encoder) + XzEnc_Destroy(_encoder); +} + + +struct CMethodNamePair +{ + UInt32 Id; + const char *Name; +}; + +static const CMethodNamePair g_NamePairs[] = +{ + { XZ_ID_Delta, "Delta" }, + { XZ_ID_X86, "BCJ" }, + { XZ_ID_PPC, "PPC" }, + { XZ_ID_IA64, "IA64" }, + { XZ_ID_ARM, "ARM" }, + { XZ_ID_ARMT, "ARMT" }, + { XZ_ID_SPARC, "SPARC" } + // { XZ_ID_LZMA2, "LZMA2" } +}; + +static int FilterIdFromName(const wchar_t *name) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_NamePairs); i++) + { + const CMethodNamePair &pair = g_NamePairs[i]; + if (StringsAreEqualNoCase_Ascii(name, pair.Name)) + return (int)pair.Id; + } + return -1; +} + + +HRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes) +{ + unsigned id; + switch (checkSizeInBytes) + { + case 0: id = XZ_CHECK_NO; break; + case 4: id = XZ_CHECK_CRC32; break; + case 8: id = XZ_CHECK_CRC64; break; + case 32: id = XZ_CHECK_SHA256; break; + default: return E_INVALIDARG; + } + xzProps.checkId = id; + return S_OK; +} + + +HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop) +{ + if (propID == NCoderPropID::kNumThreads) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + xzProps.numTotalThreads = (int)(prop.ulVal); + return S_OK; + } + + if (propID == NCoderPropID::kCheckSize) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + return SetCheckSize(prop.ulVal); + } + + if (propID == NCoderPropID::kBlockSize2) + { + if (prop.vt == VT_UI4) + xzProps.blockSize = prop.ulVal; + else if (prop.vt == VT_UI8) + xzProps.blockSize = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + return S_OK; + } + + if (propID == NCoderPropID::kReduceSize) + { + if (prop.vt == VT_UI8) + xzProps.reduceSize = prop.uhVal.QuadPart; + else + return E_INVALIDARG; + return S_OK; + } + + if (propID == NCoderPropID::kFilter) + { + if (prop.vt == VT_UI4) + { + UInt32 id32 = prop.ulVal; + if (id32 == XZ_ID_Delta) + return E_INVALIDARG; + xzProps.filterProps.id = prop.ulVal; + } + else + { + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + + const wchar_t *name = prop.bstrVal; + const wchar_t *end; + + UInt32 id32 = ConvertStringToUInt32(name, &end); + + if (end != name) + name = end; + else + { + if (IsString1PrefixedByString2_NoCase_Ascii(name, "Delta")) + { + name += 5; // strlen("Delta"); + id32 = XZ_ID_Delta; + } + else + { + int filterId = FilterIdFromName(prop.bstrVal); + if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */) + return E_INVALIDARG; + id32 = (unsigned)filterId; + } + } + + if (id32 == XZ_ID_Delta) + { + wchar_t c = *name; + if (c != '-' && c != ':') + return E_INVALIDARG; + name++; + UInt32 delta = ConvertStringToUInt32(name, &end); + if (end == name || *end != 0 || delta == 0 || delta > 256) + return E_INVALIDARG; + xzProps.filterProps.delta = delta; + } + + xzProps.filterProps.id = id32; + } + + return S_OK; + } + + return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props); +} + + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + XzProps_Init(&xzProps); + + for (UInt32 i = 0; i < numProps; i++) + { + RINOK(SetCoderProp(propIDs[i], coderProps[i])); + } + + return S_OK; + // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps)); +} + + +STDMETHODIMP CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, + const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + PROPID propID = propIDs[i]; + if (propID == NCoderPropID::kExpectedDataSize) + if (prop.vt == VT_UI8) + XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart); + } + return S_OK; +} + + +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) +{ + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; + + inWrap.Init(inStream); + outWrap.Init(outStream); + progressWrap.Init(progress); + + SRes res = XzEnc_SetProps(_encoder, &xzProps); + if (res == SZ_OK) + res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL); + + // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL); + + RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + + return SResToHRESULT(res); +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.h new file mode 100644 index 0000000..ea5190e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Compress/XzEncoder.h @@ -0,0 +1,46 @@ +// XzEncoder.h + +#ifndef __XZ_ENCODER_H +#define __XZ_ENCODER_H + +#include "../../../C/XzEnc.h" + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCompress { +namespace NXz { + + +class CEncoder: + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressSetCoderPropertiesOpt, + public CMyUnknownImp +{ + CXzEncHandle _encoder; +public: + CXzProps xzProps; + + MY_UNKNOWN_IMP3( + ICompressCoder, + ICompressSetCoderProperties, + ICompressSetCoderPropertiesOpt) + + void InitCoderProps(); + HRESULT SetCheckSize(UInt32 checkSizeInBytes); + HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop); + + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + + CEncoder(); + virtual ~CEncoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/Crc.mak new file mode 100644 index 0000000..815142d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crc.mak @@ -0,0 +1,8 @@ +C_OBJS = $(C_OBJS) \ + $O\7zCrc.obj +!IF "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ +!ELSE +ASM_OBJS = $(ASM_OBJS) \ +!ENDIF + $O\7zCrcOpt.obj diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crc64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/Crc64.mak new file mode 100644 index 0000000..d58a483 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crc64.mak @@ -0,0 +1,8 @@ +C_OBJS = $(C_OBJS) \ + $O\XzCrc64.obj +!IF "$(PLATFORM)" == "ia64" || "$(PLATFORM)" == "mips" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ +!ELSE +ASM_OBJS = $(ASM_OBJS) \ +!ENDIF + $O\XzCrc64Opt.obj diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.cpp new file mode 100644 index 0000000..7f34e91 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.cpp @@ -0,0 +1,317 @@ +// 7zAes.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" +#include "../../../C/Sha256.h" + +#include "../../Common/ComTry.h" +#include "../../Common/MyBuffer2.h" + +#ifndef _7ZIP_ST +#include "../../Windows/Synchronization.h" +#endif + +#include "../Common/StreamUtils.h" + +#include "7zAes.h" +#include "MyAes.h" + +#ifndef EXTRACT_ONLY +#include "RandGen.h" +#endif + +namespace NCrypto { +namespace N7z { + +static const unsigned k_NumCyclesPower_Supported_MAX = 24; + +bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const +{ + if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) + return false; + for (unsigned i = 0; i < SaltSize; i++) + if (Salt[i] != a.Salt[i]) + return false; + return (Password == a.Password); +} + +void CKeyInfo::CalcKey() +{ + if (NumCyclesPower == 0x3F) + { + unsigned pos; + for (pos = 0; pos < SaltSize; pos++) + Key[pos] = Salt[pos]; + for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++) + Key[pos++] = Password[i]; + for (; pos < kKeySize; pos++) + Key[pos] = 0; + } + else + { + const unsigned kUnrPow = 6; + const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow); + + const size_t bufSize = 8 + SaltSize + Password.Size(); + const size_t unrollSize = bufSize * numUnroll; + + // MY_ALIGN (16) + // CSha256 sha; + CAlignedBuffer sha(sizeof(CSha256) + unrollSize + bufSize * 2); + Byte *buf = sha + sizeof(CSha256); + + memcpy(buf, Salt, SaltSize); + memcpy(buf + SaltSize, Password, Password.Size()); + memset(buf + bufSize - 8, 0, 8); + + Sha256_Init((CSha256 *)(void *)(Byte *)sha); + + { + { + Byte *dest = buf; + for (UInt32 i = 1; i < numUnroll; i++) + { + dest += bufSize; + memcpy(dest, buf, bufSize); + } + } + + const UInt32 numRounds = (UInt32)1 << NumCyclesPower; + UInt32 r = 0; + do + { + Byte *dest = buf + bufSize - 8; + UInt32 i = r; + r += numUnroll; + do + { + SetUi32(dest, i); i++; dest += bufSize; + // SetUi32(dest, i); i++; dest += bufSize; + } + while (i < r); + Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize); + } + while (r < numRounds); + } + /* + UInt64 numRounds = (UInt64)1 << NumCyclesPower; + + do + { + Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize); + for (unsigned i = 0; i < 8; i++) + if (++(ctr[i]) != 0) + break; + } + while (--numRounds != 0); + */ + + Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); + memset(sha, 0, sha.Size()); + } +} + +bool CKeyInfoCache::GetKey(CKeyInfo &key) +{ + FOR_VECTOR (i, Keys) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + for (unsigned j = 0; j < kKeySize; j++) + key.Key[j] = cached.Key[j]; + if (i != 0) + Keys.MoveToFront(i); + return true; + } + } + return false; +} + +void CKeyInfoCache::FindAndAdd(const CKeyInfo &key) +{ + FOR_VECTOR (i, Keys) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + if (i != 0) + Keys.MoveToFront(i); + return; + } + } + Add(key); +} + +void CKeyInfoCache::Add(const CKeyInfo &key) +{ + if (Keys.Size() >= Size) + Keys.DeleteBack(); + Keys.Insert(0, key); +} + +static CKeyInfoCache g_GlobalKeyCache(32); + +#ifndef _7ZIP_ST + static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); +#else + #define MT_LOCK +#endif + +CBase::CBase(): + _cachedKeys(16), + _ivSize(0) +{ + for (unsigned i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; +} + +void CBase::PrepareKey() +{ + // BCJ2 threads use same password. So we use long lock. + MT_LOCK + + bool finded = false; + if (!_cachedKeys.GetKey(_key)) + { + finded = g_GlobalKeyCache.GetKey(_key); + if (!finded) + _key.CalcKey(); + _cachedKeys.Add(_key); + } + if (!finded) + g_GlobalKeyCache.FindAndAdd(_key); +} + +#ifndef EXTRACT_ONLY + +/* +STDMETHODIMP CEncoder::ResetSalt() +{ + _key.SaltSize = 4; + g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); + return S_OK; +} +*/ + +STDMETHODIMP CEncoder::ResetInitVector() +{ + for (unsigned i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; + _ivSize = 16; + MY_RAND_GEN(_iv, _ivSize); + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)]; + unsigned propsSize = 1; + + props[0] = (Byte)(_key.NumCyclesPower + | (_key.SaltSize == 0 ? 0 : (1 << 7)) + | (_ivSize == 0 ? 0 : (1 << 6))); + + if (_key.SaltSize != 0 || _ivSize != 0) + { + props[1] = (Byte)( + ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4) + | (_ivSize == 0 ? 0 : _ivSize - 1)); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _iv, _ivSize); + propsSize += _ivSize; + } + + return WriteStream(outStream, props, propsSize); +} + +CEncoder::CEncoder() +{ + // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); + // _key.NumCyclesPower = 0x3F; + _key.NumCyclesPower = 19; + _aesFilter = new CAesCbcEncoder(kKeySize); +} + +#endif + +CDecoder::CDecoder() +{ + _aesFilter = new CAesCbcDecoder(kKeySize); +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size) +{ + _key.ClearProps(); + + _ivSize = 0; + unsigned i; + for (i = 0; i < sizeof(_iv); i++) + _iv[i] = 0; + + if (size == 0) + return S_OK; + + Byte b0 = data[0]; + + _key.NumCyclesPower = b0 & 0x3F; + if ((b0 & 0xC0) == 0) + return size == 1 ? S_OK : E_INVALIDARG; + + if (size <= 1) + return E_INVALIDARG; + + Byte b1 = data[1]; + + unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); + unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F); + + if (size != 2 + saltSize + ivSize) + return E_INVALIDARG; + _key.SaltSize = saltSize; + data += 2; + for (i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; + for (i = 0; i < ivSize; i++) + _iv[i] = *data++; + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; +} + + +STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size) +{ + COM_TRY_BEGIN + + _key.Password.Wipe(); + _key.Password.CopyFrom(data, (size_t)size); + return S_OK; + + COM_TRY_END +} + +STDMETHODIMP CBaseCoder::Init() +{ + COM_TRY_BEGIN + + PrepareKey(); + CMyComPtr cp; + RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp)); + if (!cp) + return E_FAIL; + RINOK(cp->SetKey(_key.Key, kKeySize)); + RINOK(cp->SetInitVector(_iv, sizeof(_iv))); + return _aesFilter->Init(); + + COM_TRY_END +} + +STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size) +{ + return _aesFilter->Filter(data, size); +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.h b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.h new file mode 100644 index 0000000..a67ac0b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAes.h @@ -0,0 +1,129 @@ +// 7zAes.h + +#ifndef __CRYPTO_7Z_AES_H +#define __CRYPTO_7Z_AES_H + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyCom.h" +#include "../../Common/MyVector.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +namespace NCrypto { +namespace N7z { + +const unsigned kKeySize = 32; +const unsigned kSaltSizeMax = 16; +const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE; + +class CKeyInfo +{ +public: + unsigned NumCyclesPower; + unsigned SaltSize; + Byte Salt[kSaltSizeMax]; + CByteBuffer Password; + Byte Key[kKeySize]; + + bool IsEqualTo(const CKeyInfo &a) const; + void CalcKey(); + + CKeyInfo() { ClearProps(); } + void ClearProps() + { + NumCyclesPower = 0; + SaltSize = 0; + for (unsigned i = 0; i < sizeof(Salt); i++) + Salt[i] = 0; + } + + void Wipe() + { + Password.Wipe(); + NumCyclesPower = 0; + SaltSize = 0; + MY_memset_0_ARRAY(Salt); + MY_memset_0_ARRAY(Key); + } + + ~CKeyInfo() { Wipe(); } +}; + +class CKeyInfoCache +{ + unsigned Size; + CObjectVector Keys; +public: + CKeyInfoCache(unsigned size): Size(size) {} + bool GetKey(CKeyInfo &key); + void Add(const CKeyInfo &key); + void FindAndAdd(const CKeyInfo &key); +}; + +class CBase +{ + CKeyInfoCache _cachedKeys; +protected: + CKeyInfo _key; + Byte _iv[kIvSizeMax]; + unsigned _ivSize; + + void PrepareKey(); + CBase(); +}; + +class CBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp, + public CBase +{ +protected: + CMyComPtr _aesFilter; + +public: + INTERFACE_ICompressFilter(;) + + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); +}; + +#ifndef EXTRACT_ONLY + +class CEncoder: + public CBaseCoder, + public ICompressWriteCoderProperties, + // public ICryptoResetSalt, + public ICryptoResetInitVector +{ +public: + MY_UNKNOWN_IMP4( + ICompressFilter, + ICryptoSetPassword, + ICompressWriteCoderProperties, + // ICryptoResetSalt, + ICryptoResetInitVector) + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + // STDMETHOD(ResetSalt)(); + STDMETHOD(ResetInitVector)(); + CEncoder(); +}; + +#endif + +class CDecoder: + public CBaseCoder, + public ICompressSetDecoderProperties2 +{ +public: + MY_UNKNOWN_IMP3( + ICompressFilter, + ICryptoSetPassword, + ICompressSetDecoderProperties2) + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + CDecoder(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAesRegister.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAesRegister.cpp new file mode 100644 index 0000000..35605f4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/7zAesRegister.cpp @@ -0,0 +1,17 @@ +// 7zAesRegister.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "7zAes.h" + +namespace NCrypto { +namespace N7z { + +REGISTER_FILTER_E(_7zAES, + CDecoder, + CEncoder, + 0x6F10701, "7zAES") + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.cpp new file mode 100644 index 0000000..5cb7f46 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.cpp @@ -0,0 +1,205 @@ +// Crypto/MyAes.cpp + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "MyAes.h" + +namespace NCrypto { + +static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; + +CAesCoder::CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode): + _keySize(keySize), + _keyIsSet(false), + _encodeMode(encodeMode), + _ctrMode(ctrMode), + _aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2) +{ + // _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); + memset(_iv, 0, AES_BLOCK_SIZE); + /* + // we can use the following code to test 32-bit overflow case for AES-CTR + for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1); + _iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF; + */ + SetFunctions(0); +} + +STDMETHODIMP CAesCoder::Init() +{ + AesCbc_Init(Aes(), _iv); + return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL +} + +STDMETHODIMP_(UInt32) CAesCoder::Filter(Byte *data, UInt32 size) +{ + if (!_keyIsSet) + return 0; + if (size == 0) + return 0; + if (size < AES_BLOCK_SIZE) + { + #ifndef _SFX + if (_ctrMode) + { + // use that code only for last block !!! + Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS); + memset(ctr, 0, AES_BLOCK_SIZE); + memcpy(ctr, data, size); + _codeFunc(Aes(), ctr, 1); + memcpy(data, ctr, size); + return size; + } + #endif + return AES_BLOCK_SIZE; + } + size >>= 4; + _codeFunc(Aes(), data, size); + return size << 4; +} + +STDMETHODIMP CAesCoder::SetKey(const Byte *data, UInt32 size) +{ + if ((size & 0x7) != 0 || size < 16 || size > 32) + return E_INVALIDARG; + if (_keySize != 0 && size != _keySize) + return E_INVALIDARG; + AES_SET_KEY_FUNC setKeyFunc = (_ctrMode | _encodeMode) ? Aes_SetKey_Enc : Aes_SetKey_Dec; + setKeyFunc(Aes() + 4, data, size); + _keyIsSet = true; + return S_OK; +} + +STDMETHODIMP CAesCoder::SetInitVector(const Byte *data, UInt32 size) +{ + if (size != AES_BLOCK_SIZE) + return E_INVALIDARG; + memcpy(_iv, data, size); + CAesCoder::Init(); // don't call virtual function here !!! + return S_OK; +} + +#ifndef _SFX + +#ifdef MY_CPU_X86_OR_AMD64 + #define USE_HW_AES +#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) + #if defined(__clang__) + #if (__clang_major__ >= 8) // fix that check + #define USE_HW_AES + #endif + #elif defined(__GNUC__) + #if (__GNUC__ >= 6) // fix that check + #define USE_HW_AES + #endif + #elif defined(_MSC_VER) + #if _MSC_VER >= 1910 + #define USE_HW_AES + #endif + #endif +#endif + +#endif + + +bool CAesCoder::SetFunctions(UInt32 + #ifndef _SFX + algo + #endif + ) +{ + _codeFunc = g_AesCbc_Decode; + + #ifdef _SFX + + return true; + + #else + + if (_ctrMode) + _codeFunc = g_AesCtr_Code; + else if (_encodeMode) + _codeFunc = g_AesCbc_Encode; + + if (algo < 1) + return true; + + if (algo == 1) + { + _codeFunc = AesCbc_Decode; + + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code; + else if (_encodeMode) + _codeFunc = AesCbc_Encode; + #endif + return true; + } + + #ifdef USE_HW_AES + // if (CPU_IsSupported_AES()) + { + if (algo == 2) + if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) + { + _codeFunc = AesCbc_Decode_HW; + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code_HW; + else if (_encodeMode) + _codeFunc = AesCbc_Encode_HW; + #endif + return true; + } + + #if defined(MY_CPU_X86_OR_AMD64) + if (algo == 3) + if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) + { + _codeFunc = AesCbc_Decode_HW_256; + #ifndef _SFX + if (_ctrMode) + _codeFunc = AesCtr_Code_HW_256; + else if (_encodeMode) + _codeFunc = AesCbc_Encode_HW; + #endif + return true; + } + #endif + } + #endif + + return false; + + #endif +} + + +#ifndef _SFX + +STDMETHODIMP CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + UInt32 algo = 0; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal > 3) + return E_NOTIMPL; + algo = prop.ulVal; + } + } + if (!SetFunctions(algo)) + return E_NOTIMPL; + return S_OK; +} + +#endif + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.h b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.h new file mode 100644 index 0000000..a60042b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAes.h @@ -0,0 +1,79 @@ +// Crypto/MyAes.h + +#ifndef __CRYPTO_MY_AES_H +#define __CRYPTO_MY_AES_H + +#include "../../../C/Aes.h" + +#include "../../Common/MyBuffer2.h" +#include "../../Common/MyCom.h" + +#include "../ICoder.h" + +namespace NCrypto { + +class CAesCoder: + public ICompressFilter, + public ICryptoProperties, + #ifndef _SFX + public ICompressSetCoderProperties, + #endif + public CMyUnknownImp +{ + AES_CODE_FUNC _codeFunc; + // unsigned _offset; + unsigned _keySize; + bool _keyIsSet; + bool _encodeMode; + bool _ctrMode; + + // UInt32 _aes[AES_NUM_IVMRK_WORDS + 3]; + CAlignedBuffer _aes; + + Byte _iv[AES_BLOCK_SIZE]; + + // UInt32 *Aes() { return _aes + _offset; } + UInt32 *Aes() { return (UInt32 *)(void *)(Byte *)_aes; } + + bool SetFunctions(UInt32 algo); + +public: + CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode); + + virtual ~CAesCoder() {}; // we need virtual destructor for derived classes + + MY_QUERYINTERFACE_BEGIN2(ICompressFilter) + MY_QUERYINTERFACE_ENTRY(ICryptoProperties) + #ifndef _SFX + MY_QUERYINTERFACE_ENTRY(ICompressSetCoderProperties) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_ICompressFilter(;) + + void SetKeySize(unsigned size) { _keySize = size; } + + STDMETHOD(SetKey)(const Byte *data, UInt32 size); + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size); + + #ifndef _SFX + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); + #endif +}; + +#ifndef _SFX +struct CAesCbcEncoder: public CAesCoder +{ + CAesCbcEncoder(unsigned keySize = 0): CAesCoder(true, keySize, false) {} +}; +#endif + +struct CAesCbcDecoder: public CAesCoder +{ + CAesCbcDecoder(unsigned keySize = 0): CAesCoder(false, keySize, false) {} +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAesReg.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAesReg.cpp new file mode 100644 index 0000000..86bd254 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/MyAesReg.cpp @@ -0,0 +1,30 @@ +// MyAesReg.cpp + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "MyAes.h" + +namespace NCrypto { + +#ifndef _SFX + +#define REGISTER_AES_2(name, nameString, keySize, isCtr) \ + REGISTER_FILTER_E(name, \ + CAesCoder(false, keySize, isCtr), \ + CAesCoder(true , keySize, isCtr), \ + 0x6F00100 | ((keySize - 16) * 8) | (isCtr ? 4 : 1), \ + nameString) \ + +#define REGISTER_AES(name, nameString, isCtr) \ + /* REGISTER_AES_2(AES128 ## name, "AES128" nameString, 16, isCtr) */ \ + /* REGISTER_AES_2(AES192 ## name, "AES192" nameString, 24, isCtr) */ \ + REGISTER_AES_2(AES256 ## name, "AES256" nameString, 32, isCtr) \ + +REGISTER_AES(CBC, "CBC", false) +// REGISTER_AES(CTR, "CTR", true) + +#endif + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.cpp new file mode 100644 index 0000000..65633fd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.cpp @@ -0,0 +1,237 @@ +// RandGen.cpp + +#include "StdAfx.h" + +#include "RandGen.h" + +#ifndef USE_STATIC_SYSTEM_RAND + +#ifndef _7ZIP_ST +#include "../../Windows/Synchronization.h" +#endif + + +#ifdef _WIN32 + +#ifdef _WIN64 +#define USE_STATIC_RtlGenRandom +#endif + +#ifdef USE_STATIC_RtlGenRandom + +// #include + +EXTERN_C_BEGIN +#ifndef RtlGenRandom + #define RtlGenRandom SystemFunction036 + BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); +#endif +EXTERN_C_END + +#else +EXTERN_C_BEGIN +typedef BOOLEAN (WINAPI * Func_RtlGenRandom)(PVOID RandomBuffer, ULONG RandomBufferLength); +EXTERN_C_END +#endif + + +#else +#include +#include +#include +#include +#define USE_POSIX_TIME +#define USE_POSIX_TIME2 +#endif + +#ifdef USE_POSIX_TIME +#include +#ifdef USE_POSIX_TIME2 +#include +#endif +#endif + +// The seed and first generated data block depend from processID, +// theadID, timer and system random generator, if available. +// Other generated data blocks depend from previous state + +#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x)); + +void CRandomGenerator::Init() +{ + MY_ALIGN (16) + CSha256 hash; + Sha256_Init(&hash); + + unsigned numIterations = 1000; + + { + #ifndef UNDER_CE + const unsigned kNumIterations_Small = 100; + const unsigned kBufSize = 32; + MY_ALIGN (16) + Byte buf[kBufSize]; + #endif + + #ifdef _WIN32 + + DWORD w = ::GetCurrentProcessId(); + HASH_UPD(w); + w = ::GetCurrentThreadId(); + HASH_UPD(w); + + #ifdef UNDER_CE + /* + if (CeGenRandom(kBufSize, buf)) + { + numIterations = kNumIterations_Small; + Sha256_Update(&hash, buf, kBufSize); + } + */ + #elif defined(USE_STATIC_RtlGenRandom) + if (RtlGenRandom(buf, kBufSize)) + { + numIterations = kNumIterations_Small; + Sha256_Update(&hash, buf, kBufSize); + } + #else + { + HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll")); + if (hModule) + { + // SystemFunction036() is real name of RtlGenRandom() function + Func_RtlGenRandom my_RtlGenRandom = (Func_RtlGenRandom)(void *)GetProcAddress(hModule, "SystemFunction036"); + if (my_RtlGenRandom) + { + if (my_RtlGenRandom(buf, kBufSize)) + { + numIterations = kNumIterations_Small; + Sha256_Update(&hash, buf, kBufSize); + } + } + ::FreeLibrary(hModule); + } + } + #endif + + #else + + pid_t pid = getpid(); + HASH_UPD(pid); + pid = getppid(); + HASH_UPD(pid); + + { + int f = open("/dev/urandom", O_RDONLY); + unsigned numBytes = kBufSize; + if (f >= 0) + { + do + { + ssize_t n = read(f, buf, numBytes); + if (n <= 0) + break; + Sha256_Update(&hash, buf, (size_t)n); + numBytes -= (unsigned)n; + } + while (numBytes); + close(f); + if (numBytes == 0) + numIterations = kNumIterations_Small; + } + } + /* + { + int n = getrandom(buf, kBufSize, 0); + if (n > 0) + { + Sha256_Update(&hash, buf, n); + if (n == kBufSize) + numIterations = kNumIterations_Small; + } + } + */ + + #endif + } + + #ifdef _DEBUG + numIterations = 2; + #endif + + do + { + #ifdef _WIN32 + LARGE_INTEGER v; + if (::QueryPerformanceCounter(&v)) + HASH_UPD(v.QuadPart); + #endif + + #ifdef USE_POSIX_TIME + #ifdef USE_POSIX_TIME2 + timeval v; + if (gettimeofday(&v, 0) == 0) + { + HASH_UPD(v.tv_sec); + HASH_UPD(v.tv_usec); + } + #endif + time_t v2 = time(NULL); + HASH_UPD(v2); + #endif + + #ifdef _WIN32 + DWORD tickCount = ::GetTickCount(); + HASH_UPD(tickCount); + #endif + + for (unsigned j = 0; j < 100; j++) + { + Sha256_Final(&hash, _buff); + Sha256_Init(&hash); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + } + } + while (--numIterations); + + Sha256_Final(&hash, _buff); + _needInit = false; +} + +#ifndef _7ZIP_ST + static NWindows::NSynchronization::CCriticalSection g_CriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else + #define MT_LOCK +#endif + +void CRandomGenerator::Generate(Byte *data, unsigned size) +{ + MT_LOCK + + if (_needInit) + Init(); + while (size != 0) + { + MY_ALIGN (16) + CSha256 hash; + + Sha256_Init(&hash); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + Sha256_Final(&hash, _buff); + + Sha256_Init(&hash); + UInt32 salt = 0xF672ABD1; + HASH_UPD(salt); + Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); + MY_ALIGN (16) + Byte buff[SHA256_DIGEST_SIZE]; + Sha256_Final(&hash, buff); + for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--) + *data++ = buff[i]; + } +} + +CRandomGenerator g_RandomGenerator; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.h b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.h new file mode 100644 index 0000000..5122ec4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/RandGen.h @@ -0,0 +1,40 @@ +// RandGen.h + +#ifndef __CRYPTO_RAND_GEN_H +#define __CRYPTO_RAND_GEN_H + +#include "../../../C/Sha256.h" + +#ifdef _WIN64 +// #define USE_STATIC_SYSTEM_RAND +#endif + +#ifdef USE_STATIC_SYSTEM_RAND + +#ifdef _WIN32 +#include +#define MY_RAND_GEN(data, size) RtlGenRandom(data, size) +#else +#define MY_RAND_GEN(data, size) getrandom(data, size, 0) +#endif + +#else + +class CRandomGenerator +{ + Byte _buff[SHA256_DIGEST_SIZE]; + bool _needInit; + + void Init(); +public: + CRandomGenerator(): _needInit(true) {}; + void Generate(Byte *data, unsigned size); +}; + +extern CRandomGenerator g_RandomGenerator; + +#define MY_RAND_GEN(data, size) g_RandomGenerator.Generate(data, size) + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/StdAfx.h new file mode 100644 index 0000000..1cbd7fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Crypto/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/GuiCommon.rc b/3rdparty/lzma-21.03beta/CPP/7zip/GuiCommon.rc new file mode 100644 index 0000000..b67409b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/GuiCommon.rc @@ -0,0 +1,84 @@ +#include + +// #include +// #include + +// for Windows CE: +#include + + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#undef m +#undef bxs +#undef bys +#undef bxsDots +#undef y +#undef xc +#undef yc +#undef xs +#undef ys +#undef bx +#undef bx1 +#undef bx2 +#undef bx3 +#undef by +#undef by1 +#undef by2 +#undef by3 +#undef gSpace +#undef gSize +#undef marg2 +#undef marg3 + +#undef MY_DIALOG +#undef MY_RESIZE_DIALOG +#undef MY_PAGE + +#define m 8 +#define bxs 64 +#define bys 16 +#define bxsDots 20 + +#define xs (xc + m + m) +#define ys (yc + m + m) + +#define bx1 (xs - m - bxs) +#define bx2 (bx1 - m - bxs) +#define bx3 (bx2 - m - bxs) +#define bx bx1 + +#define by1 (ys - m - bys) +#define by2 (by1 - m - bys) +#define by by1 + + +#define MY_MODAL_DIALOG_STYLE STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU + +#define MY_MODAL_RESIZE_DIALOG_STYLE MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME + +#define MY_PAGE_STYLE STYLE WS_CHILD | WS_DISABLED | WS_CAPTION + +#define MY_FONT FONT 8, "MS Shell Dlg" + +#define SMALL_PAGE_SIZE_X 120 + +// #define MY_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +// #define MY_RESIZE_DIALOG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT +#define MY_PAGE DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT + +#define OK_CANCEL \ + DEFPUSHBUTTON "OK", IDOK, bx2, by, bxs, bys \ + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + +#define MY_BUTTON__CLOSE \ + DEFPUSHBUTTON "&Close", IDCLOSE, bx1, by, bxs, bys + + +#define MY_COMBO CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +#define MY_COMBO_SORTED MY_COMBO | CBS_SORT +#define MY_COMBO_WITH_EDIT CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + +#define MY_CHECKBOX "Button", BS_AUTOCHECKBOX | WS_TABSTOP + +#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Guid.txt b/3rdparty/lzma-21.03beta/CPP/7zip/Guid.txt new file mode 100644 index 0000000..f28afcd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Guid.txt @@ -0,0 +1,222 @@ +{23170F69-40C1-278A-0000-00yy00xx0000} + +00 IProgress.h + + 05 IProgress + // 050002 IProgress2 + +01 IFolderArchive.h + + // 05 IArchiveFolder // old + // 06 IInFolderArchive // old + 07 IFileExtractCallback.h::IFolderArchiveExtractCallback + 08 IFileExtractCallback.h::IFolderArchiveExtractCallback2 + // 0A IOutFolderArchive + 0B IFolderArchiveUpdateCallback + 0C Agent.h::IArchiveFolderInternal + 0D IArchiveFolder + 0E IInFolderArchive + 0F IOutFolderArchive + 10 IFolderArchiveUpdateCallback2 + 11 IFolderScanProgress + + 20 IFileExtractCallback.h::IGetProp + 30 IFileExtractCallback.h::IFolderExtractToStreamCallback + +03 IStream.h + + 01 ISequentialInStream + 02 ISequentialOutStream + 03 IInStream + 04 IOutStream + 06 IStreamGetSize + 07 IOutStreamFinish + 08 IStreamGetProps + 09 IStreamGetProps2 + + +04 ICoder.h + + 04 ICompressProgressInfo + 05 ICompressCoder + 18 ICompressCoder2 + 1F ICompressSetCoderPropertiesOpt + 20 ICompressSetCoderProperties + 21 ICompressSetDecoderProperties // + 22 ICompressSetDecoderProperties2 + 23 ICompressWriteCoderProperties + 24 ICompressGetInStreamProcessedSize + 25 ICompressSetCoderMt + 26 ICompressSetFinishMode + 27 ICompressGetInStreamProcessedSize2 + 28 ICompressSetMemLimit + 29 ICompressReadUnusedFromInBuf + + 30 ICompressGetSubStreamSize + 31 ICompressSetInStream + 32 ICompressSetOutStream +// 33 ICompressSetInStreamSize + 34 ICompressSetOutStreamSize + 35 ICompressSetBufSize + 36 ICompressInitEncoder + 37 ICompressSetInStream2 +// 38 ICompressSetOutStream2 +// 39 SetInStreamSize2 +// 3A SetOutStreamSize2 + + 40 ICompressFilter + 60 ICompressCodecsInfo + 61 ISetCompressCodecsInfo + 80 ICryptoProperties + 88 ICryptoResetSalt + 8C ICryptoResetInitVector + 90 ICryptoSetPassword + A0 ICryptoSetCRC + C0 IHasher + C1 IHashers + + +05 IPassword.h + + 10 ICryptoGetTextPassword + 11 ICryptoGetTextPassword2 + + +06 IArchive.h + + 03 ISetProperties + 04 IArchiveKeepModeForNextOpen + 05 IArchiveAllowTail + + 10 IArchiveOpenCallback + + 20 IArchiveExtractCallback + 21 IArchiveExtractCallbackMessage + + 30 IArchiveOpenVolumeCallback + 40 IInArchiveGetStream + 50 IArchiveOpenSetSubArchiveName + 60 IInArchive + 61 IArchiveOpenSeq + 70 IArchiveGetRawProps + 71 IArchiveGetRootProps + + 80 IArchiveUpdateCallback + 82 IArchiveUpdateCallback2 + 83 IArchiveUpdateCallbackFile + + A0 IOutArchive + + + +08 IFolder.h + + 00 IFolderFolder + 01 IEnumProperties + 02 IFolderGetTypeID + 03 IFolderGetPath + 04 IFolderWasChanged + 05 // IFolderReload + 06 // IFolderOperations old + 07 IFolderGetSystemIconIndex + 08 IFolderGetItemFullSize + 09 IFolderClone + 0A IFolderSetFlatMode + 0B IFolderOperationsExtractCallback + 0C // + 0D // + 0E IFolderProperties + 0F + 10 IFolderArcProps + 11 IGetFolderArcProps + 12 // IFolderOperations + 13 IFolderOperations + 14 IFolderCalcItemFullSize + 15 IFolderCompare + 16 IFolderGetItemName + 17 IFolderAltStreams + + +09 IFolder.h :: FOLDER_MANAGER_INTERFACE + + 00 - 04 // old IFolderManager + 05 IFolderManager + + +// 0A PluginInterface.h + 00 IInitContextMenu + 01 IPluginOptionsCallback + 02 IPluginOptions + + +Handler GUIDs: + +{23170F69-40C1-278A-1000-000110xx0000} + + 01 Zip + 02 BZip2 + 03 Rar + 04 Arj + 05 Z + 06 Lzh + 07 7z + 08 Cab + 09 Nsis + 0A lzma + 0B lzma86 + 0C xz + 0D ppmd + + C5 Base64 + C6 COFF + C7 Ext + C8 VMDK + C9 VDI + CA Qcow + CB GPT + CC Rar5 + CD IHex + CE Hxs + CF TE + D0 UEFIc + D1 UEFIs + D2 SquashFS + D3 CramFS + D4 APM + D5 Mslz + D6 Flv + D7 Swf + D8 Swfc + D9 Ntfs + DA Fat + DB Mbr + DC Vhd + DD Pe + DE Elf + DF Mach-O + E0 Udf + E1 Xar + E2 Mub + E3 Hfs + E4 Dmg + E5 Compound + E6 Wim + E7 Iso + E8 + E9 Chm + EA Split + EB Rpm + EC Deb + ED Cpio + EE Tar + EF GZip + +{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu + +// {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler +// {23170F69-40C1-278B- old codecs clsids +// {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions + +{23170F69-40C1-2790-id} Codec Decoders +{23170F69-40C1-2791-id} Codec Encoders +{23170F69-40C1-2792-id} Hashers diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/ICoder.h b/3rdparty/lzma-21.03beta/CPP/7zip/ICoder.h new file mode 100644 index 0000000..314d33d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/ICoder.h @@ -0,0 +1,432 @@ +// ICoder.h + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) + +CODER_INTERFACE(ICompressProgressInfo, 0x04) +{ + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; + + /* (inSize) can be NULL, if unknown + (outSize) can be NULL, if unknown + + returns: + S_OK + E_ABORT : Break by user + another error codes + */ +}; + +CODER_INTERFACE(ICompressCoder, 0x05) +{ + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) PURE; +}; + +CODER_INTERFACE(ICompressCoder2, 0x18) +{ + STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams, + ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +/* + ICompressCoder::Code + ICompressCoder2::Code + + returns: + S_OK : OK + S_FALSE : data error (for decoders) + E_OUTOFMEMORY : memory allocation error + E_NOTIMPL : unsupported encoding method (for decoders) + another error code : some error. For example, it can be error code received from inStream or outStream function. + + Parameters: + (inStream != NULL) + (outStream != NULL) + + if (inSize != NULL) + { + Encoders in 7-Zip ignore (inSize). + Decoder can use (*inSize) to check that stream was decoded correctly. + Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode) + } + + If it's required to limit the reading from input stream (inStream), it can + be done with ISequentialInStream implementation. + + if (outSize != NULL) + { + Encoders in 7-Zip ignore (outSize). + Decoder unpacks no more than (*outSize) bytes. + } + + (progress == NULL) is allowed. + + + Decoding with Code() function + ----------------------------- + + You can request some interfaces before decoding + - ICompressSetDecoderProperties2 + - ICompressSetFinishMode + + If you need to decode full stream: + { + 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1); + 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known. + } + + If you need to decode only part of stream: + { + 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0); + 2) Call the Code() function with specified (inSize = NULL) and specified (outSize). + } + + Encoding with Code() function + ----------------------------- + + You can request some interfaces : + - ICompressSetCoderProperties - use it before encoding to set properties + - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties. + + ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1) + The rules are similar to ICompressCoder rules +*/ + + +namespace NCoderPropID +{ + enum EEnum + { + kDefaultProp = 0, + kDictionarySize, // VT_UI4 + kUsedMemorySize, // VT_UI4 + kOrder, // VT_UI4 + kBlockSize, // VT_UI4 or VT_UI8 + kPosStateBits, // VT_UI4 + kLitContextBits, // VT_UI4 + kLitPosBits, // VT_UI4 + kNumFastBytes, // VT_UI4 + kMatchFinder, // VT_BSTR + kMatchFinderCycles, // VT_UI4 + kNumPasses, // VT_UI4 + kAlgorithm, // VT_UI4 + kNumThreads, // VT_UI4 + kEndMarker, // VT_BOOL + kLevel, // VT_UI4 + kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed + // encoder can use this value to reduce dictionary size and allocate data buffers + + kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt : + // it's estimated size of current data stream + // real data size can differ from that size + // encoder can use this value to optimize encoder initialization + + kBlockSize2, // VT_UI4 or VT_UI8 + kCheckSize, // VT_UI4 : size of digest in bytes + kFilter, // VT_BSTR + kMemUse, // VT_UI8 + kAffinity // VT_UI8 + }; +} + +CODER_INTERFACE(ICompressSetCoderPropertiesOpt, 0x1F) +{ + STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + /* returns: + S_OK + E_NOTIMP : unsupported properties + E_INVALIDARG : incorrect (or unsupported) properties + E_OUTOFMEMORY : memory allocation error + */ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE; +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) +{ + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressSetFinishMode, 0x26) +{ + STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE; + + /* finishMode: + 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined. + 1 : full decoding. The stream must be finished at the end of decoding. */ +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize2, 0x27) +{ + STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetMemLimit, 0x28) +{ + STDMETHOD(SetMemLimit)(UInt64 memUsage) PURE; +}; + + +/* + ICompressReadUnusedFromInBuf is supported by ICoder object + call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...). + ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed + to read from inStream to internal buffers more data than minimal data required for decoding. + So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input + data from the internal buffer. + in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code(). +*/ + +CODER_INTERFACE(ICompressReadUnusedFromInBuf, 0x29) +{ + STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize) PURE; +}; + + + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; + + /* returns: + S_OK : (*value) contains the size or estimated size (can be incorrect size) + S_FALSE : size is undefined + E_NOTIMP : the feature is not implemented + + Let's (read_size) is size of data that was already read by ISequentialInStream::Read(). + The caller should call GetSubStreamSize() after each Read() and check sizes: + if (start_of_subStream + *value < read_size) + { + // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream: + start_of_subStream += *value; + subStream++; + } + */ +}; + +CODER_INTERFACE(ICompressSetInStream, 0x31) +{ + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetOutStream, 0x32) +{ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +/* +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; + + /* That function initializes decoder structures. + Call this function only for stream version of decoder. + if (outSize == NULL), then output size is unknown + if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */ +}; + +CODER_INTERFACE(ICompressSetBufSize, 0x35) +{ + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE; + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressInitEncoder, 0x36) +{ + STDMETHOD(InitEncoder)() PURE; + + /* That function initializes encoder structures. + Call this function only for stream version of encoder. */ +}; + +CODER_INTERFACE(ICompressSetInStream2, 0x37) +{ + STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetOutStream2, 0x38) +{ + STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize2, 0x39) +{ + STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE; +}; +*/ + + +/* + ICompressFilter + Filter() converts as most as possible bytes required for fast processing. + Some filters have (smallest_fast_block). + For example, (smallest_fast_block == 16) for AES CBC/CTR filters. + If data stream is not finished, caller must call Filter() for larger block: + where (size >= smallest_fast_block). + if (size >= smallest_fast_block) + { + The filter can leave some bytes at the end of data without conversion: + if there are data alignment reasons or speed reasons. + The caller must read additional data from stream and call Filter() again. + } + If data stream was finished, caller can call Filter() for (size < smallest_fast_block) + + data : must be aligned for at least 16 bytes for some filters (AES) + + returns: (outSize): + if (outSize == 0) : Filter have not converted anything. + So the caller can stop processing, if data stream was finished. + if (outSize <= size) : Filter have converted outSize bytes + if (outSize > size) : Filter have not converted anything. + and it needs at least outSize bytes to convert one block + (it's for crypto block algorithms). +*/ + +#define INTERFACE_ICompressFilter(x) \ + STDMETHOD(Init)() x; \ + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \ + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + INTERFACE_ICompressFilter(PURE); +}; + + +CODER_INTERFACE(ICompressCodecsInfo, 0x60) +{ + STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE; + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; +}; + +CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) +{ + STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +/* +CODER_INTERFACE(ICryptoResetSalt, 0x88) +{ + STDMETHOD(ResetSalt)() PURE; +}; +*/ + +CODER_INTERFACE(ICryptoResetInitVector, 0x8C) +{ + STDMETHOD(ResetInitVector)() PURE; + + /* Call ResetInitVector() only for encoding. + Call ResetInitVector() before encoding and before WriteCoderProperties(). + Crypto encoder can create random IV in that function. */ +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + + +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kPackStreams, + kUnpackStreams, + kDescription, + kDecoderIsAssigned, + kEncoderIsAssigned, + kDigestSize + }; +} + + +#define INTERFACE_IHasher(x) \ + STDMETHOD_(void, Init)() throw() x; \ + STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \ + STDMETHOD_(void, Final)(Byte *digest) throw() x; \ + STDMETHOD_(UInt32, GetDigestSize)() throw() x; \ + +CODER_INTERFACE(IHasher, 0xC0) +{ + INTERFACE_IHasher(PURE) +}; + +CODER_INTERFACE(IHashers, 0xC1) +{ + STDMETHOD_(UInt32, GetNumHashers)() PURE; + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE; +}; + +extern "C" +{ + typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); + typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject); + typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject); + + typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); + + typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo); +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/IDecl.h b/3rdparty/lzma-21.03beta/CPP/7zip/IDecl.h new file mode 100644 index 0000000..077ef0e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/IDecl.h @@ -0,0 +1,28 @@ +// IDecl.h + +#ifndef __IDECL_H +#define __IDECL_H + +#include "../Common/MyUnknown.h" + +#define k_7zip_GUID_Data1 0x23170F69 +#define k_7zip_GUID_Data2 0x40C1 + +#define k_7zip_GUID_Data3_Common 0x278A + +#define k_7zip_GUID_Data3_Decoder 0x2790 +#define k_7zip_GUID_Data3_Encoder 0x2791 +#define k_7zip_GUID_Data3_Hasher 0x2792 + + +#define DECL_INTERFACE_SUB(i, base, groupId, subId) \ + DEFINE_GUID(IID_ ## i, \ + k_7zip_GUID_Data1, \ + k_7zip_GUID_Data2, \ + k_7zip_GUID_Data3_Common, \ + 0, 0, 0, (groupId), 0, (subId), 0, 0); \ + struct i: public base + +#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/IPassword.h b/3rdparty/lzma-21.03beta/CPP/7zip/IPassword.h new file mode 100644 index 0000000..4ccc9ac --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/IPassword.h @@ -0,0 +1,53 @@ +// IPassword.h + +#ifndef __IPASSWORD_H +#define __IPASSWORD_H + +#include "../Common/MyTypes.h" +#include "../Common/MyUnknown.h" + +#include "IDecl.h" + +#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) + +/* +How to use output parameter (BSTR *password): + +in: The caller is required to set BSTR value as NULL (no string). + The callee (in 7-Zip code) ignores the input value stored in BSTR variable, + +out: The callee rewrites BSTR variable (*password) with new allocated string pointer. + The caller must free BSTR string with function SysFreeString(); +*/ + +PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) +{ + STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; +}; + + +/* +CryptoGetTextPassword2() +in: + The caller is required to set BSTR value as NULL (no string). + The caller is not required to set (*passwordIsDefined) value. + +out: + Return code: != S_OK : error code + Return code: S_OK : success + + if (*passwordIsDefined == 1), the variable (*password) contains password string + + if (*passwordIsDefined == 0), the password is not defined, + but the callee still could set (*password) to some allocated string, for example, as empty string. + + The caller must free BSTR string with function SysFreeString() +*/ + + +PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) +{ + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/IProgress.h b/3rdparty/lzma-21.03beta/CPP/7zip/IProgress.h new file mode 100644 index 0000000..fac951e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/IProgress.h @@ -0,0 +1,19 @@ +// IProgress.h + +#ifndef __IPROGRESS_H +#define __IPROGRESS_H + +#include "../Common/MyTypes.h" + +#include "IDecl.h" + +#define INTERFACE_IProgress(x) \ + STDMETHOD(SetTotal)(UInt64 total) x; \ + STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ + +DECL_INTERFACE(IProgress, 0, 5) +{ + INTERFACE_IProgress(PURE) +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/IStream.h b/3rdparty/lzma-21.03beta/CPP/7zip/IStream.h new file mode 100644 index 0000000..48c67c1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/IStream.h @@ -0,0 +1,136 @@ +// IStream.h + +#ifndef __ISTREAM_H +#define __ISTREAM_H + +#include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" + +#include "IDecl.h" + +#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) +#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) + +STREAM_INTERFACE(ISequentialInStream, 0x01) +{ + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + + /* + The requirement for caller: (processedSize != NULL). + The callee can allow (processedSize == NULL) for compatibility reasons. + + if (size == 0), this function returns S_OK and (*processedSize) is set to 0. + + if (size != 0) + { + Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size), + where (avail_size) is the size of remaining bytes in stream. + If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0). + You must call Read() in loop, if you need to read exact amount of data. + } + + If seek pointer before Read() call was changed to position past the end of stream: + if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0. + + ERROR CASES: + If the function returns error code, then (*processedSize) is size of + data written to (data) buffer (it can be data before error or data with errors). + The recommended way for callee to work with reading errors: + 1) write part of data before error to (data) buffer and return S_OK. + 2) return error code for further calls of Read(). + */ +}; + +STREAM_INTERFACE(ISequentialOutStream, 0x02) +{ + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + + /* + The requirement for caller: (processedSize != NULL). + The callee can allow (processedSize == NULL) for compatibility reasons. + + if (size != 0) + { + Partial write is allowed: (*processedSize <= size), + but this function must write at least 1 byte: (*processedSize > 0). + You must call Write() in loop, if you need to write exact amount of data. + } + + ERROR CASES: + If the function returns error code, then (*processedSize) is size of + data written from (data) buffer. + */ +}; + +#ifdef _WIN32 + +#ifdef __HRESULT_FROM_WIN32 +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) +#else +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) +#endif + +#else + +#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY__E_ERROR_NEGATIVE_SEEK + +#endif + + +/* Seek() Function + If you seek before the beginning of the stream, Seek() function returns error code: + Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). + or STG_E_INVALIDFUNCTION + + It is allowed to seek past the end of the stream. + + + if Seek() returns error, then the value of *newPosition is undefined. +*/ + +STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; +}; + +STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; + STDMETHOD(SetSize)(UInt64 newSize) PURE; +}; + +STREAM_INTERFACE(IStreamGetSize, 0x06) +{ + STDMETHOD(GetSize)(UInt64 *size) PURE; +}; + +STREAM_INTERFACE(IOutStreamFinish, 0x07) +{ + STDMETHOD(OutStreamFinish)() PURE; +}; + + +STREAM_INTERFACE(IStreamGetProps, 0x08) +{ + STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) PURE; +}; + +struct CStreamFileProps +{ + UInt64 Size; + UInt64 VolID; + UInt64 FileID_Low; + UInt64 FileID_High; + UInt32 NumLinks; + UInt32 Attrib; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; +}; + +STREAM_INTERFACE(IStreamGetProps2, 0x09) +{ + STDMETHOD(GetProps2)(CStreamFileProps *props) PURE; +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/LzFindOpt.mak b/3rdparty/lzma-21.03beta/CPP/7zip/LzFindOpt.mak new file mode 100644 index 0000000..169e10f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/LzFindOpt.mak @@ -0,0 +1,7 @@ +!IF defined(USE_C_LZFINDOPT) || "$(PLATFORM)" != "x64" +C_OBJS = $(C_OBJS) \ + $O\LzFindOpt.obj +!ELSE +ASM_OBJS = $(ASM_OBJS) \ + $O\LzFindOpt.obj +!ENDIF diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec.mak b/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec.mak new file mode 100644 index 0000000..bed4700 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec.mak @@ -0,0 +1,7 @@ +!IF "$(PLATFORM)" == "x64" +!IFNDEF NO_ASM +CFLAGS_C_SPEC = -D_LZMA_DEC_OPT +ASM_OBJS = $(ASM_OBJS) \ + $O\LzmaDecOpt.obj +!ENDIF +!ENDIF diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec_gcc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec_gcc.mak new file mode 100644 index 0000000..51924f5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/LzmaDec_gcc.mak @@ -0,0 +1,14 @@ +ifdef USE_ASM +ifdef IS_X64 +USE_LZMA_DEC_ASM=1 +endif +ifdef IS_ARM64 +USE_LZMA_DEC_ASM=1 +endif +endif + +ifdef USE_LZMA_DEC_ASM + +LZMA_DEC_OPT_OBJS= $O/LzmaDecOpt.o + +endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/MyVersion.h b/3rdparty/lzma-21.03beta/CPP/7zip/MyVersion.h new file mode 100644 index 0000000..8f52a12 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/MyVersion.h @@ -0,0 +1,2 @@ +#define USE_COPYRIGHT_CR +#include "../../C/7zVersion.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/MyVersionInfo.rc b/3rdparty/lzma-21.03beta/CPP/7zip/MyVersionInfo.rc new file mode 100644 index 0000000..fab6686 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/MyVersionInfo.rc @@ -0,0 +1,2 @@ +#include "MyVersion.h" +#include "..\..\C\7zVersion.rc" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/PropID.h b/3rdparty/lzma-21.03beta/CPP/7zip/PropID.h new file mode 100644 index 0000000..1822f40 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/PropID.h @@ -0,0 +1,127 @@ +// PropID.h + +#ifndef __7ZIP_PROP_ID_H +#define __7ZIP_PROP_ID_H + +#include "../Common/MyTypes.h" + +enum +{ + kpidNoProperty = 0, + kpidMainSubfile, + kpidHandlerItemIndex, + kpidPath, + kpidName, + kpidExtension, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidAttrib, + kpidCTime, + kpidATime, + kpidMTime, + kpidSolid, + kpidCommented, + kpidEncrypted, + kpidSplitBefore, + kpidSplitAfter, + kpidDictionarySize, + kpidCRC, + kpidType, + kpidIsAnti, + kpidMethod, + kpidHostOS, + kpidFileSystem, + kpidUser, + kpidGroup, + kpidBlock, + kpidComment, + kpidPosition, + kpidPrefix, + kpidNumSubDirs, + kpidNumSubFiles, + kpidUnpackVer, + kpidVolume, + kpidIsVolume, + kpidOffset, + kpidLinks, + kpidNumBlocks, + kpidNumVolumes, + kpidTimeType, + kpidBit64, + kpidBigEndian, + kpidCpu, + kpidPhySize, + kpidHeadersSize, + kpidChecksum, + kpidCharacts, + kpidVa, + kpidId, + kpidShortName, + kpidCreatorApp, + kpidSectorSize, + kpidPosixAttrib, + kpidSymLink, + kpidError, + kpidTotalSize, + kpidFreeSpace, + kpidClusterSize, + kpidVolumeName, + kpidLocalName, + kpidProvider, + kpidNtSecure, + kpidIsAltStream, + kpidIsAux, + kpidIsDeleted, + kpidIsTree, + kpidSha1, + kpidSha256, + kpidErrorType, + kpidNumErrors, + kpidErrorFlags, + kpidWarningFlags, + kpidWarning, + kpidNumStreams, + kpidNumAltStreams, + kpidAltStreamsSize, + kpidVirtualSize, + kpidUnpackSize, + kpidTotalPhySize, + kpidVolumeIndex, + kpidSubType, + kpidShortComment, + kpidCodePage, + kpidIsNotArcType, + kpidPhySizeCantBeDetected, + kpidZerosTailIsAllowed, + kpidTailSize, + kpidEmbeddedStubSize, + kpidNtReparse, + kpidHardLink, + kpidINode, + kpidStreamId, + kpidReadOnly, + kpidOutName, + kpidCopyLink, + + kpid_NUM_DEFINED, + + kpidUserDefined = 0x10000 +}; + +extern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE + +const UInt32 kpv_ErrorFlags_IsNotArc = 1 << 0; +const UInt32 kpv_ErrorFlags_HeadersError = 1 << 1; +const UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2; +const UInt32 kpv_ErrorFlags_UnavailableStart = 1 << 3; +const UInt32 kpv_ErrorFlags_UnconfirmedStart = 1 << 4; +const UInt32 kpv_ErrorFlags_UnexpectedEnd = 1 << 5; +const UInt32 kpv_ErrorFlags_DataAfterEnd = 1 << 6; +const UInt32 kpv_ErrorFlags_UnsupportedMethod = 1 << 7; +const UInt32 kpv_ErrorFlags_UnsupportedFeature = 1 << 8; +const UInt32 kpv_ErrorFlags_DataError = 1 << 9; +const UInt32 kpv_ErrorFlags_CrcError = 1 << 10; +// const UInt32 kpv_ErrorFlags_Unsupported = 1 << 11; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/Sha256.mak b/3rdparty/lzma-21.03beta/CPP/7zip/Sha256.mak new file mode 100644 index 0000000..0bdbcb6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/Sha256.mak @@ -0,0 +1,13 @@ +COMMON_OBJS = $(COMMON_OBJS) \ + $O\Sha256Prepare.obj + +C_OBJS = $(C_OBJS) \ + $O\Sha256.obj + +!IF defined(USE_C_SHA) || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "arm64" +C_OBJS = $(C_OBJS) \ + $O\Sha256Opt.obj +!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips" && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +ASM_OBJS = $(ASM_OBJS) \ + $O\Sha256Opt.obj +!ENDIF diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/SubBuild.mak b/3rdparty/lzma-21.03beta/CPP/7zip/SubBuild.mak new file mode 100644 index 0000000..f86ce43 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/SubBuild.mak @@ -0,0 +1,3 @@ + cd $(@D) + $(MAKE) -nologo $(TARGETS) + cd .. diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.cpp new file mode 100644 index 0000000..0c69bdc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.cpp @@ -0,0 +1,1048 @@ +// Client7z.cpp + +#include "StdAfx.h" + +#include + +#include "../../../Common/MyWindows.h" + +#include "../../../Common/Defs.h" +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/NtCheck.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../../Common/FileStreams.h" + +#include "../../Archive/IArchive.h" + +#include "../../IPassword.h" +#include "../../../../C/7zVersion.h" + +#ifdef _WIN32 +extern +HINSTANCE g_hInstance; +HINSTANCE g_hInstance = 0; +#endif + +// You can find the list of all GUIDs in Guid.txt file. +// use another CLSIDs, if you want to support other formats (zip, rar, ...). +// {23170F69-40C1-278A-1000-000110070000} + +DEFINE_GUID(CLSID_CFormat7z, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); +DEFINE_GUID(CLSID_CFormatXz, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00); + +#define CLSID_Format CLSID_CFormat7z +// #define CLSID_Format CLSID_CFormatXz + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +#ifdef _WIN32 +#define kDllName "7z.dll" +#else +#define kDllName "7z.so" +#endif + +static const char * const kCopyrightString = + "\n" + "7-Zip" + " (" kDllName " client)" + " " MY_VERSION + " : " MY_COPYRIGHT_DATE + "\n"; + +static const char * const kHelpString = +"Usage: 7zcl.exe [a | l | x] archive.7z [fileName ...]\n" +"Examples:\n" +" 7zcl.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" +" 7zcl.exe l archive.7z : List contents of archive.7z\n" +" 7zcl.exe x archive.7z : eXtract files from archive.7z\n"; + + +static void Convert_UString_to_AString(const UString &s, AString &temp) +{ + int codePage = CP_OEMCP; + /* + int g_CodePage = -1; + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + */ + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); +} + +static FString CmdStringToFString(const char *s) +{ + return us2fs(GetUnicodeString(s)); +} + +static void Print(const char *s) +{ + fputs(s, stdout); +} + +static void Print(const AString &s) +{ + Print(s.Ptr()); +} + +static void Print(const UString &s) +{ + AString as; + Convert_UString_to_AString(s, as); + Print(as); +} + +static void Print(const wchar_t *s) +{ + Print(UString(s)); +} + +static void PrintNewLine() +{ + Print("\n"); +} + +static void PrintStringLn(const char *s) +{ + Print(s); + PrintNewLine(); +} + +static void PrintError(const char *message) +{ + Print("Error: "); + PrintNewLine(); + Print(message); + PrintNewLine(); +} + +static void PrintError(const char *message, const FString &name) +{ + PrintError(message); + Print(name); +} + + +static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) +{ + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt == VT_EMPTY) + result = false; + else + return E_FAIL; + return S_OK; +} + +static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) +{ + return IsArchiveItemProp(archive, index, kpidIsDir, result); +} + + +static const wchar_t * const kEmptyFileAlias = L"[Content]"; + + +////////////////////////////////////////////////////////////// +// Archive Open callback class + + +class CArchiveOpenCallback: + public IArchiveOpenCallback, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + bool PasswordIsDefined; + UString Password; + + CArchiveOpenCallback() : PasswordIsDefined(false) {} +}; + +STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) +{ + if (!PasswordIsDefined) + { + // You can ask real password here from user + // Password = GetPassword(OutStream); + // PasswordIsDefined = true; + PrintError("Password is not defined"); + return E_ABORT; + } + return StringToBstr(Password, password); +} + + + +static const char * const kIncorrectCommand = "incorrect command"; + +////////////////////////////////////////////////////////////// +// Archive Extracting callback class + +static const char * const kTestingString = "Testing "; +static const char * const kExtractingString = "Extracting "; +static const char * const kSkippingString = "Skipping "; + +static const char * const kUnsupportedMethod = "Unsupported Method"; +static const char * const kCRCFailed = "CRC Failed"; +static const char * const kDataError = "Data Error"; +static const char * const kUnavailableData = "Unavailable data"; +static const char * const kUnexpectedEnd = "Unexpected end of data"; +static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; +static const char * const kIsNotArc = "Is not archive"; +static const char * const kHeadersError = "Headers Error"; + + +class CArchiveExtractCallback: + public IArchiveExtractCallback, + public ICryptoGetTextPassword, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ICryptoGetTextPassword) + + // IProgress + STDMETHOD(SetTotal)(UInt64 size); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IArchiveExtractCallback + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); + STDMETHOD(PrepareOperation)(Int32 askExtractMode); + STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); + + // ICryptoGetTextPassword + STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); + +private: + CMyComPtr _archiveHandler; + FString _directoryPath; // Output directory + UString _filePath; // name inside arcvhive + FString _diskFilePath; // full path to file on disk + bool _extractMode; + struct CProcessedFileInfo + { + FILETIME MTime; + UInt32 Attrib; + bool isDir; + bool AttribDefined; + bool MTimeDefined; + } _processedFileInfo; + + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + +public: + void Init(IInArchive *archiveHandler, const FString &directoryPath); + + UInt64 NumErrors; + bool PasswordIsDefined; + UString Password; + + CArchiveExtractCallback() : PasswordIsDefined(false) {} +}; + +void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const FString &directoryPath) +{ + NumErrors = 0; + _archiveHandler = archiveHandler; + _directoryPath = directoryPath; + NName::NormalizeDirPathPrefix(_directoryPath); +} + +STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, + ISequentialOutStream **outStream, Int32 askExtractMode) +{ + *outStream = 0; + _outFileStream.Release(); + + { + // Get Name + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); + + UString fullPath; + if (prop.vt == VT_EMPTY) + fullPath = kEmptyFileAlias; + else + { + if (prop.vt != VT_BSTR) + return E_FAIL; + fullPath = prop.bstrVal; + } + _filePath = fullPath; + } + + if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) + return S_OK; + + { + // Get Attrib + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_EMPTY) + { + _processedFileInfo.Attrib = 0; + _processedFileInfo.AttribDefined = false; + } + else + { + if (prop.vt != VT_UI4) + return E_FAIL; + _processedFileInfo.Attrib = prop.ulVal; + _processedFileInfo.AttribDefined = true; + } + } + + RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); + + { + // Get Modified Time + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); + _processedFileInfo.MTimeDefined = false; + switch (prop.vt) + { + case VT_EMPTY: + // _processedFileInfo.MTime = _utcMTimeDefault; + break; + case VT_FILETIME: + _processedFileInfo.MTime = prop.filetime; + _processedFileInfo.MTimeDefined = true; + break; + default: + return E_FAIL; + } + + } + { + // Get Size + NCOM::CPropVariant prop; + RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); + UInt64 newFileSize; + /* bool newFileSizeDefined = */ ConvertPropVariantToUInt64(prop, newFileSize); + } + + + { + // Create folders for file + int slashPos = _filePath.ReverseFind_PathSepar(); + if (slashPos >= 0) + CreateComplexDir(_directoryPath + us2fs(_filePath.Left(slashPos))); + } + + FString fullProcessedPath = _directoryPath + us2fs(_filePath); + _diskFilePath = fullProcessedPath; + + if (_processedFileInfo.isDir) + { + CreateComplexDir(fullProcessedPath); + } + else + { + NFind::CFileInfo fi; + if (fi.Find(fullProcessedPath)) + { + if (!DeleteFileAlways(fullProcessedPath)) + { + PrintError("Cannot delete output file", fullProcessedPath); + return E_ABORT; + } + } + + _outFileStreamSpec = new COutFileStream; + CMyComPtr outStreamLoc(_outFileStreamSpec); + if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) + { + PrintError("Cannot open output file", fullProcessedPath); + return E_ABORT; + } + _outFileStream = outStreamLoc; + *outStream = outStreamLoc.Detach(); + } + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) +{ + _extractMode = false; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; + }; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: Print(kExtractingString); break; + case NArchive::NExtract::NAskMode::kTest: Print(kTestingString); break; + case NArchive::NExtract::NAskMode::kSkip: Print(kSkippingString); break; + }; + Print(_filePath); + return S_OK; +} + +STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) +{ + switch (operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + NumErrors++; + Print(" : "); + const char *s = NULL; + switch (operationResult) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + s = kUnsupportedMethod; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + s = kCRCFailed; + break; + case NArchive::NExtract::NOperationResult::kDataError: + s = kDataError; + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + s = kUnavailableData; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + s = kUnexpectedEnd; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + s = kDataAfterEnd; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + s = kIsNotArc; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + s = kHeadersError; + break; + } + if (s) + { + Print("Error : "); + Print(s); + } + else + { + char temp[16]; + ConvertUInt32ToString(operationResult, temp); + Print("Error #"); + Print(temp); + } + } + } + + if (_outFileStream) + { + if (_processedFileInfo.MTimeDefined) + _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); + RINOK(_outFileStreamSpec->Close()); + } + _outFileStream.Release(); + if (_extractMode && _processedFileInfo.AttribDefined) + SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); + PrintNewLine(); + return S_OK; +} + + +STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) +{ + if (!PasswordIsDefined) + { + // You can ask real password here from user + // Password = GetPassword(OutStream); + // PasswordIsDefined = true; + PrintError("Password is not defined"); + return E_ABORT; + } + return StringToBstr(Password, password); +} + + + +////////////////////////////////////////////////////////////// +// Archive Creating callback class + +struct CDirItem +{ + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + UString Name; + FString FullPath; + UInt32 Attrib; + + bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } +}; + +class CArchiveUpdateCallback: + public IArchiveUpdateCallback2, + public ICryptoGetTextPassword2, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) + + // IProgress + STDMETHOD(SetTotal)(UInt64 size); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IUpdateCallback2 + STDMETHOD(GetUpdateItemInfo)(UInt32 index, + Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); + STDMETHOD(SetOperationResult)(Int32 operationResult); + STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); + STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); + + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + +public: + CRecordVector VolumesSizes; + UString VolName; + UString VolExt; + + FString DirPrefix; + const CObjectVector *DirItems; + + bool PasswordIsDefined; + UString Password; + bool AskPassword; + + bool m_NeedBeClosed; + + FStringVector FailedFiles; + CRecordVector FailedCodes; + + CArchiveUpdateCallback(): + DirItems(NULL), + PasswordIsDefined(false), + AskPassword(false) + {} + + ~CArchiveUpdateCallback() { Finilize(); } + HRESULT Finilize(); + + void Init(const CObjectVector *dirItems) + { + DirItems = dirItems; + m_NeedBeClosed = false; + FailedFiles.Clear(); + FailedCodes.Clear(); + } +}; + +STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) +{ + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, + Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) +{ + if (newData) + *newData = BoolToInt(true); + if (newProperties) + *newProperties = BoolToInt(true); + if (indexInArchive) + *indexInArchive = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + + if (propID == kpidIsAnti) + { + prop = false; + prop.Detach(value); + return S_OK; + } + + { + const CDirItem &dirItem = (*DirItems)[index]; + switch (propID) + { + case kpidPath: prop = dirItem.Name; break; + case kpidIsDir: prop = dirItem.isDir(); break; + case kpidSize: prop = dirItem.Size; break; + case kpidAttrib: prop = dirItem.Attrib; break; + case kpidCTime: prop = dirItem.CTime; break; + case kpidATime: prop = dirItem.ATime; break; + case kpidMTime: prop = dirItem.MTime; break; + } + } + prop.Detach(value); + return S_OK; +} + +HRESULT CArchiveUpdateCallback::Finilize() +{ + if (m_NeedBeClosed) + { + PrintNewLine(); + m_NeedBeClosed = false; + } + return S_OK; +} + +static void GetStream2(const wchar_t *name) +{ + Print("Compressing "); + if (name[0] == 0) + name = kEmptyFileAlias; + Print(name); +} + +STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) +{ + RINOK(Finilize()); + + const CDirItem &dirItem = (*DirItems)[index]; + GetStream2(dirItem.Name); + + if (dirItem.isDir()) + return S_OK; + + { + CInFileStream *inStreamSpec = new CInFileStream; + CMyComPtr inStreamLoc(inStreamSpec); + FString path = DirPrefix + dirItem.FullPath; + if (!inStreamSpec->Open(path)) + { + DWORD sysError = ::GetLastError(); + FailedCodes.Add(sysError); + FailedFiles.Add(path); + // if (systemError == ERROR_SHARING_VIOLATION) + { + PrintNewLine(); + PrintError("WARNING: can't open file"); + // Print(NError::MyFormatMessageW(systemError)); + return S_FALSE; + } + // return sysError; + } + *inStream = inStreamLoc.Detach(); + } + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) +{ + m_NeedBeClosed = true; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) +{ + if (VolumesSizes.Size() == 0) + return S_FALSE; + if (index >= (UInt32)VolumesSizes.Size()) + index = VolumesSizes.Size() - 1; + *size = VolumesSizes[index]; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) +{ + wchar_t temp[16]; + ConvertUInt32ToString(index + 1, temp); + UString res = temp; + while (res.Len() < 2) + res.InsertAtFront(L'0'); + UString fileName = VolName; + fileName += '.'; + fileName += res; + fileName += VolExt; + COutFileStream *streamSpec = new COutFileStream; + CMyComPtr streamLoc(streamSpec); + if (!streamSpec->Create(us2fs(fileName), false)) + return ::GetLastError(); + *volumeStream = streamLoc.Detach(); + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + if (!PasswordIsDefined) + { + if (AskPassword) + { + // You can ask real password here from user + // Password = GetPassword(OutStream); + // PasswordIsDefined = true; + PrintError("Password is not defined"); + return E_ABORT; + } + } + *passwordIsDefined = BoolToInt(PasswordIsDefined); + return StringToBstr(Password, password); +} + + +// Main function + +#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION PrintError("Unsupported Windows version"); return 1; +#endif + +int MY_CDECL main(int numArgs, const char *args[]) +{ + NT_CHECK + + #ifdef ENV_HAVE_LOCALE + MY_SetLocale(); + #endif + + PrintStringLn(kCopyrightString); + + if (numArgs < 2) + { + PrintStringLn(kHelpString); + return 0; + } + + FString dllPrefix; + + #ifdef _WIN32 + dllPrefix = NDLL::GetModuleDirPrefix(); + #else + { + AString s (args[0]); + int sep = s.ReverseFind_PathSepar(); + s.DeleteFrom(sep + 1); + dllPrefix = s; + } + #endif + + NDLL::CLibrary lib; + if (!lib.Load(dllPrefix + FTEXT(kDllName))) + { + PrintError("Cannot load 7-zip library"); + return 1; + } + + Func_CreateObject createObjectFunc = (Func_CreateObject)lib.GetProc("CreateObject"); + if (!createObjectFunc) + { + PrintError("Cannot get CreateObject"); + return 1; + } + + char c = 0; + UString password; + bool passwordIsDefined = false; + CObjectVector params; + + for (int curCmd = 1; curCmd < numArgs; curCmd++) + { + AString a(args[curCmd]); + + if (!a.IsEmpty()) + { + if (a[0] == '-') + { + if (!passwordIsDefined && a[1] == 'p') + { + password = GetUnicodeString(a.Ptr(2)); + passwordIsDefined = true; + continue; + } + } + else + { + if (c) + { + params.Add(CmdStringToFString(a)); + continue; + } + if (a.Len() == 1) + { + c = (char)MyCharLower_Ascii(a[0]); + continue; + } + } + } + { + PrintError(kIncorrectCommand); + return 1; + } + } + + if (!c || params.Size() < 1) + { + PrintError(kIncorrectCommand); + return 1; + } + + const FString &archiveName = params[0]; + + if (c == 'a') + { + // create archive command + if (params.Size() < 2) + { + PrintError(kIncorrectCommand); + return 1; + } + CObjectVector dirItems; + { + unsigned i; + for (i = 1; i < params.Size(); i++) + { + CDirItem di; + const FString &name = params[i]; + + NFind::CFileInfo fi; + if (!fi.Find(name)) + { + PrintError("Can't find file", name); + return 1; + } + + di.Attrib = fi.Attrib; + di.Size = fi.Size; + di.CTime = fi.CTime; + di.ATime = fi.ATime; + di.MTime = fi.MTime; + di.Name = fs2us(name); + di.FullPath = name; + dirItems.Add(di); + } + } + + COutFileStream *outFileStreamSpec = new COutFileStream; + CMyComPtr outFileStream = outFileStreamSpec; + if (!outFileStreamSpec->Create(archiveName, false)) + { + PrintError("can't create archive file"); + return 1; + } + + CMyComPtr outArchive; + if (createObjectFunc(&CLSID_Format, &IID_IOutArchive, (void **)&outArchive) != S_OK) + { + PrintError("Cannot get class object"); + return 1; + } + + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + updateCallbackSpec->Init(&dirItems); + updateCallbackSpec->PasswordIsDefined = passwordIsDefined; + updateCallbackSpec->Password = password; + + /* + { + const wchar_t *names[] = + { + L"s", + L"x" + }; + const unsigned kNumProps = ARRAY_SIZE(names); + NCOM::CPropVariant values[kNumProps] = + { + false, // solid mode OFF + (UInt32)9 // compression level = 9 - ultra + }; + CMyComPtr setProperties; + outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties); + if (!setProperties) + { + PrintError("ISetProperties unsupported"); + return 1; + } + RINOK(setProperties->SetProperties(names, values, kNumProps)); + } + */ + + HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); + + updateCallbackSpec->Finilize(); + + if (result != S_OK) + { + PrintError("Update Error"); + return 1; + } + + FOR_VECTOR (i, updateCallbackSpec->FailedFiles) + { + PrintNewLine(); + PrintError("Error for file", updateCallbackSpec->FailedFiles[i]); + } + + if (updateCallbackSpec->FailedFiles.Size() != 0) + return 1; + } + else + { + if (params.Size() != 1) + { + PrintError(kIncorrectCommand); + return 1; + } + + bool listCommand; + + if (c == 'l') + listCommand = true; + else if (c == 'x') + listCommand = false; + else + { + PrintError(kIncorrectCommand); + return 1; + } + + CMyComPtr archive; + if (createObjectFunc(&CLSID_Format, &IID_IInArchive, (void **)&archive) != S_OK) + { + PrintError("Cannot get class object"); + return 1; + } + + CInFileStream *fileSpec = new CInFileStream; + CMyComPtr file = fileSpec; + + if (!fileSpec->Open(archiveName)) + { + PrintError("Cannot open archive file", archiveName); + return 1; + } + + { + CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; + CMyComPtr openCallback(openCallbackSpec); + openCallbackSpec->PasswordIsDefined = passwordIsDefined; + openCallbackSpec->Password = password; + + const UInt64 scanSize = 1 << 23; + if (archive->Open(file, &scanSize, openCallback) != S_OK) + { + PrintError("Cannot open file as archive", archiveName); + return 1; + } + } + + if (listCommand) + { + // List command + UInt32 numItems = 0; + archive->GetNumberOfItems(&numItems); + for (UInt32 i = 0; i < numItems; i++) + { + { + // Get uncompressed size of file + NCOM::CPropVariant prop; + archive->GetProperty(i, kpidSize, &prop); + char s[32]; + ConvertPropVariantToShortString(prop, s); + Print(s); + Print(" "); + } + { + // Get name of file + NCOM::CPropVariant prop; + archive->GetProperty(i, kpidPath, &prop); + if (prop.vt == VT_BSTR) + Print(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + Print("ERROR!"); + } + PrintNewLine(); + } + } + else + { + // Extract command + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr extractCallback(extractCallbackSpec); + extractCallbackSpec->Init(archive, FString()); // second parameter is output folder path + extractCallbackSpec->PasswordIsDefined = passwordIsDefined; + extractCallbackSpec->Password = password; + + /* + const wchar_t *names[] = + { + L"mt", + L"mtf" + }; + const unsigned kNumProps = sizeof(names) / sizeof(names[0]); + NCOM::CPropVariant values[kNumProps] = + { + (UInt32)1, + false + }; + CMyComPtr setProperties; + archive->QueryInterface(IID_ISetProperties, (void **)&setProperties); + if (setProperties) + setProperties->SetProperties(names, values, kNumProps); + */ + + HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); + + if (result != S_OK) + { + PrintError("Extract Error"); + return 1; + } + } + } + + return 0; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsp new file mode 100644 index 0000000..b412c8e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsp @@ -0,0 +1,235 @@ +# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Client7z - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Client7z.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Client7z - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe" + +!ELSEIF "$(CFG)" == "Client7z - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Client7z - Win32 Release" +# Name "Client7z - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileDir.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileName.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariantConv.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyVector.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Wildcard.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\Client7z.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sort.h +# End Source File +# End Target +# End Project diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsw b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsw new file mode 100644 index 0000000..598a6d3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/Client7z.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile new file mode 100644 index 0000000..988701e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile @@ -0,0 +1,28 @@ +PROG = 7zcl.exe +MY_CONSOLE = 1 + +CURRENT_OBJS = \ + $O\Client7z.obj \ + +COMMON_OBJS = \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\MyString.obj \ + $O\MyVector.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileName.obj \ + $O\PropVariant.obj \ + $O\PropVariantConv.obj \ + +7ZIP_COMMON_OBJS = \ + $O\FileStreams.obj \ + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile.gcc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile.gcc new file mode 100644 index 0000000..b65095b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/makefile.gcc @@ -0,0 +1,59 @@ +PROG = 7zcl +IS_NOT_STANDALONE = 1 + +# IS_X64 = 1 + + + +ifdef SystemDrive + +SYS_OBJS = \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + $O/TimeUtils.o \ + +endif + + +LOCAL_FLAGS = \ + + +CURRENT_OBJS = \ + $O/Client7z.o \ + +COMMON_OBJS = \ + $O/IntToString.o \ + $O/MyString.o \ + $O/MyVector.o \ + $O/NewHandler.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + $O/DLL.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + +7ZIP_COMMON_OBJS = \ + $O/FileStreams.o \ + + +OBJS = \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(SYS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(CURRENT_OBJS) \ + + +include ../../7zip_gcc.mak diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/resource.rc new file mode 100644 index 0000000..462df6f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Client7z/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip client" , "7zcl") diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.cpp new file mode 100644 index 0000000..00df80e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -0,0 +1,1480 @@ +// ArchiveCommandLine.cpp + +#include "StdAfx.h" +#undef printf +#undef sprintf + +#ifdef _WIN32 +#ifndef UNDER_CE +#include +#endif +#else +// for isatty() +#include +#endif + +#include + +#ifdef _7ZIP_LARGE_PAGES +#include "../../../../C/Alloc.h" +#endif + +#include "../../../Common/IntToString.h" +#include "../../../Common/ListFileUtils.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/System.h" +#ifdef _WIN32 +#include "../../../Windows/FileMapping.h" +#include "../../../Windows/MemoryLock.h" +#include "../../../Windows/Synchronization.h" +#endif + +#include "ArchiveCommandLine.h" +#include "EnumDirItems.h" +#include "Update.h" +#include "UpdateAction.h" + +extern bool g_CaseSensitive; +extern bool g_PathTrailReplaceMode; + +#ifdef _7ZIP_LARGE_PAGES +extern +bool g_LargePagesMode; +bool g_LargePagesMode = false; +#endif + +/* +#ifdef ENV_HAVE_LSTAT +EXTERN_C_BEGIN +extern int global_use_lstat; +EXTERN_C_END +#endif +*/ + +#ifdef UNDER_CE + +#define MY_IS_TERMINAL(x) false; + +#else + +// #define MY_isatty_fileno(x) (isatty(fileno(x))) +// #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); +static inline bool MY_IS_TERMINAL(FILE *x) +{ + return ( + #if defined(_MSC_VER) && (_MSC_VER >= 1400) + _isatty(_fileno(x)) + #else + isatty(fileno(x)) + #endif + != 0); +} + +#endif + +using namespace NCommandLineParser; +using namespace NWindows; +using namespace NFile; + +static bool StringToUInt32(const wchar_t *s, UInt32 &v) +{ + if (*s == 0) + return false; + const wchar_t *end; + v = ConvertStringToUInt32(s, &end); + return *end == 0; +} + + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kHelp3, + + kDisableHeaders, + kDisablePercents, + kShowTime, + kLogLevel, + + kOutStream, + kErrStream, + kPercentStream, + + kYes, + + kShowDialog, + kOverwrite, + + kArchiveType, + kExcludedArcType, + + kProperty, + kOutputDir, + kWorkingDir, + + kInclude, + kExclude, + kArInclude, + kArExclude, + kNoArName, + + kUpdate, + kVolume, + kRecursed, + + kAffinity, + kSfx, + kEmail, + kHash, + + kStdIn, + kStdOut, + + kLargePages, + kListfileCharSet, + kConsoleCharSet, + kTechMode, + + kPreserveATime, + kShareForWrite, + kStopAfterOpenError, + kCaseSensitive, + kArcNameMode, + + kDisableWildcardParsing, + kElimDup, + kFullPathMode, + + kHardLinks, + kSymLinks_AllowDangerous, + kSymLinks, + kNtSecurity, + + kAltStreams, + kReplaceColonForAltStream, + kWriteToAltStreamIfColon, + + kNameTrailReplace, + + kDeleteAfterCompressing, + kSetArcMTime + + #ifndef _NO_CRYPTO + , kPassword + #endif +}; + +} + + +static const wchar_t kRecursedIDChar = 'r'; +static const char * const kRecursedPostCharSet = "0-"; + +static const char * const k_ArcNameMode_PostCharSet = "sea"; + +static const char * const k_Stream_PostCharSet = "012"; + +static inline EArcNameMode ParseArcNameMode(int postCharIndex) +{ + switch (postCharIndex) + { + case 1: return k_ArcNameMode_Exact; + case 2: return k_ArcNameMode_Add; + default: return k_ArcNameMode_Smart; + } +} + +namespace NRecursedPostCharIndex { + enum EEnum + { + kWildcardRecursionOnly = 0, + kNoRecursion = 1 + }; +} + +// static const char +#define kImmediateNameID '!' +#ifdef _WIN32 +#define kMapNameID '#' +#endif +#define kFileListID '@' + +static const Byte kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be +static const Byte kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be + +static const char * const kOverwritePostCharSet = "asut"; + +static const NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = +{ + NExtract::NOverwriteMode::kOverwrite, + NExtract::NOverwriteMode::kSkip, + NExtract::NOverwriteMode::kRename, + NExtract::NOverwriteMode::kRenameExisting +}; + + + +#define SWFRM_3(t, mu, mi) t, mu, mi, NULL + +#define SWFRM_1(t) SWFRM_3(t, false, 0) +#define SWFRM_SIMPLE SWFRM_1(NSwitchType::kSimple) +#define SWFRM_MINUS SWFRM_1(NSwitchType::kMinus) +#define SWFRM_STRING SWFRM_1(NSwitchType::kString) + +#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi) +#define SWFRM_STRING_MULT(mi) SWFRM_3(NSwitchType::kString, true, mi) + + +static const CSwitchForm kSwitchForms[] = +{ + { "?", SWFRM_SIMPLE }, + { "h", SWFRM_SIMPLE }, + { "-help", SWFRM_SIMPLE }, + + { "ba", SWFRM_SIMPLE }, + { "bd", SWFRM_SIMPLE }, + { "bt", SWFRM_SIMPLE }, + { "bb", SWFRM_STRING_SINGL(0) }, + + { "bso", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + { "bse", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + { "bsp", NSwitchType::kChar, false, 1, k_Stream_PostCharSet }, + + { "y", SWFRM_SIMPLE }, + + { "ad", SWFRM_SIMPLE }, + { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet}, + + { "t", SWFRM_STRING_SINGL(1) }, + { "stx", SWFRM_STRING_MULT(1) }, + + { "m", SWFRM_STRING_MULT(1) }, + { "o", SWFRM_STRING_SINGL(1) }, + { "w", SWFRM_STRING }, + + { "i", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "x", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "ai", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "ax", SWFRM_STRING_MULT(kSomeCludePostStringMinSize) }, + { "an", SWFRM_SIMPLE }, + + { "u", SWFRM_STRING_MULT(1) }, + { "v", SWFRM_STRING_MULT(1) }, + { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet }, + + { "stm", SWFRM_STRING }, + { "sfx", SWFRM_STRING }, + { "seml", SWFRM_STRING_SINGL(0) }, + { "scrc", SWFRM_STRING_MULT(0) }, + + { "si", SWFRM_STRING }, + { "so", SWFRM_SIMPLE }, + + { "slp", SWFRM_STRING }, + { "scs", SWFRM_STRING }, + { "scc", SWFRM_STRING }, + { "slt", SWFRM_SIMPLE }, + + { "ssp", SWFRM_SIMPLE }, + { "ssw", SWFRM_SIMPLE }, + { "sse", SWFRM_SIMPLE }, + { "ssc", SWFRM_MINUS }, + { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet }, + + { "spd", SWFRM_SIMPLE }, + { "spe", SWFRM_MINUS }, + { "spf", SWFRM_STRING_SINGL(0) }, + + { "snh", SWFRM_MINUS }, + { "snld", SWFRM_MINUS }, + { "snl", SWFRM_MINUS }, + { "sni", SWFRM_SIMPLE }, + + { "sns", SWFRM_MINUS }, + { "snr", SWFRM_SIMPLE }, + { "snc", SWFRM_SIMPLE }, + + { "snt", SWFRM_MINUS }, + + { "sdel", SWFRM_SIMPLE }, + { "stl", SWFRM_SIMPLE } + + #ifndef _NO_CRYPTO + , { "p", SWFRM_STRING } + #endif +}; + +static const char * const kUniversalWildcard = "*"; +static const unsigned kMinNonSwitchWords = 1; +static const unsigned kCommandIndex = 0; + +// static const char * const kUserErrorMessage = "Incorrect command line"; +// static const char * const kCannotFindListFile = "Cannot find listfile"; +static const char * const kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; +static const char * const kTerminalOutError = "I won't write compressed data to a terminal"; +static const char * const kSameTerminalError = "I won't write data and program's messages to same stream"; +static const char * const kEmptyFilePath = "Empty file path"; + +bool CArcCommand::IsFromExtractGroup() const +{ + switch (CommandType) + { + case NCommandType::kTest: + case NCommandType::kExtract: + case NCommandType::kExtractFull: + return true; + default: + return false; + } +} + +NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const +{ + switch (CommandType) + { + case NCommandType::kTest: + case NCommandType::kExtractFull: + return NExtract::NPathMode::kFullPaths; + default: + return NExtract::NPathMode::kNoPaths; + } +} + +bool CArcCommand::IsFromUpdateGroup() const +{ + switch (CommandType) + { + case NCommandType::kAdd: + case NCommandType::kUpdate: + case NCommandType::kDelete: + case NCommandType::kRename: + return true; + default: + return false; + } +} + +static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) +{ + switch (index) + { + case NRecursedPostCharIndex::kWildcardRecursionOnly: + return NRecursedType::kWildcardOnlyRecursed; + case NRecursedPostCharIndex::kNoRecursion: + return NRecursedType::kNonRecursed; + default: + return NRecursedType::kRecursed; + } +} + +static const char *g_Commands = "audtexlbih"; + +static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) +{ + UString s (commandString); + s.MakeLower_Ascii(); + if (s.Len() == 1) + { + if (s[0] > 0x7F) + return false; + int index = FindCharPosInString(g_Commands, (char)s[0]); + if (index < 0) + return false; + command.CommandType = (NCommandType::EEnum)index; + return true; + } + if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n') + { + command.CommandType = (NCommandType::kRename); + return true; + } + return false; +} + +// ------------------------------------------------------------------ +// filenames functions + +static void AddNameToCensor(NWildcard::CCensor &censor, + const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching) +{ + bool recursed = false; + + switch (type) + { + case NRecursedType::kWildcardOnlyRecursed: + recursed = DoesNameContainWildcard(name); + break; + case NRecursedType::kRecursed: + recursed = true; + break; + default: + break; + } + censor.AddPreItem(include, name, recursed, wildcardMatching); +} + +static void AddRenamePair(CObjectVector *renamePairs, + const UString &oldName, const UString &newName, NRecursedType::EEnum type, + bool wildcardMatching) +{ + CRenamePair &pair = renamePairs->AddNew(); + pair.OldName = oldName; + pair.NewName = newName; + pair.RecursedType = type; + pair.WildcardParsing = wildcardMatching; + + if (!pair.Prepare()) + { + UString val; + val += pair.OldName; + val.Add_LF(); + val += pair.NewName; + val.Add_LF(); + if (type == NRecursedType::kRecursed) + val += "-r"; + else if (type == NRecursedType::kWildcardOnlyRecursed) + val += "-r0"; + throw CArcCmdLineException("Unsupported rename command:", val); + } +} + +static void AddToCensorFromListFile( + CObjectVector *renamePairs, + NWildcard::CCensor &censor, + LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, UInt32 codePage) +{ + UStringVector names; + /* + if (!NFind::DoesFileExist_FollowLink(us2fs(fileName))) + throw CArcCmdLineException(kCannotFindListFile, fileName); + */ + DWORD lastError = 0; + if (!ReadNamesFromListFile2(us2fs(fileName), names, codePage, lastError)) + { + if (lastError != 0) + { + UString m; + m = "The file operation error for listfile"; + m.Add_LF(); + m += NError::MyFormatMessage(lastError); + throw CArcCmdLineException(m, fileName); + } + throw CArcCmdLineException(kIncorrectListFile, fileName); + } + if (renamePairs) + { + if ((names.Size() & 1) != 0) + throw CArcCmdLineException(kIncorrectListFile, fileName); + for (unsigned i = 0; i < names.Size(); i += 2) + { + // change type !!!! + AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching); + } + } + else + FOR_VECTOR (i, names) + AddNameToCensor(censor, names[i], include, type, wildcardMatching); +} + +static void AddToCensorFromNonSwitchesStrings( + CObjectVector *renamePairs, + unsigned startIndex, + NWildcard::CCensor &censor, + const UStringVector &nonSwitchStrings, + int stopSwitchIndex, + NRecursedType::EEnum type, + bool wildcardMatching, + bool thereAreSwitchIncludes, UInt32 codePage) +{ + if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes) + AddNameToCensor(censor, UString(kUniversalWildcard), true, type, + true // wildcardMatching + ); + + int oldIndex = -1; + + if (stopSwitchIndex < 0) + stopSwitchIndex = (int)nonSwitchStrings.Size(); + + for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++) + { + const UString &s = nonSwitchStrings[i]; + if (s.IsEmpty()) + throw CArcCmdLineException(kEmptyFilePath); + if (i < (unsigned)stopSwitchIndex && s[0] == kFileListID) + AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage); + else if (renamePairs) + { + if (oldIndex == -1) + oldIndex = (int)i; + else + { + // NRecursedType::EEnum type is used for global wildcard (-i! switches) + AddRenamePair(renamePairs, nonSwitchStrings[(unsigned)oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching); + // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type); + oldIndex = -1; + } + } + else + AddNameToCensor(censor, s, true, type, wildcardMatching); + } + + if (oldIndex != -1) + { + throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[(unsigned)oldIndex]); + } +} + +#ifdef _WIN32 + +struct CEventSetEnd +{ + UString Name; + + CEventSetEnd(const wchar_t *name): Name(name) {} + ~CEventSetEnd() + { + NSynchronization::CManualResetEvent event; + if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0) + event.Set(); + } +}; + +static const char * const k_IncorrectMapCommand = "Incorrect Map command"; + +static const char *ParseMapWithPaths( + NWildcard::CCensor &censor, + const UString &s2, bool include, + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching) +{ + UString s (s2); + int pos = s.Find(L':'); + if (pos < 0) + return k_IncorrectMapCommand; + int pos2 = s.Find(L':', (unsigned)(pos + 1)); + if (pos2 < 0) + return k_IncorrectMapCommand; + + CEventSetEnd eventSetEnd((const wchar_t *)s + (unsigned)(pos2 + 1)); + s.DeleteFrom((unsigned)pos2); + UInt32 size; + if (!StringToUInt32(s.Ptr((unsigned)(pos + 1)), size) + || size < sizeof(wchar_t) + || size > ((UInt32)1 << 31) + || size % sizeof(wchar_t) != 0) + return "Unsupported Map data size"; + + s.DeleteFrom((unsigned)pos); + CFileMapping map; + if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0) + return "Cannot open mapping"; + LPVOID data = map.Map(FILE_MAP_READ, 0, size); + if (!data) + return "MapViewOfFile error"; + CFileUnmapper unmapper(data); + + UString name; + const wchar_t *p = (const wchar_t *)data; + if (*p != 0) // data format marker + return "Unsupported Map data"; + UInt32 numChars = size / sizeof(wchar_t); + for (UInt32 i = 1; i < numChars; i++) + { + wchar_t c = p[i]; + if (c == 0) + { + // MessageBoxW(0, name, L"7-Zip", 0); + AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching); + name.Empty(); + } + else + name += c; + } + if (!name.IsEmpty()) + return "Map data error"; + + return NULL; +} + +#endif + +static void AddSwitchWildcardsToCensor( + NWildcard::CCensor &censor, + const UStringVector &strings, bool include, + NRecursedType::EEnum commonRecursedType, + bool wildcardMatching, + UInt32 codePage) +{ + const char *errorMessage = NULL; + unsigned i; + for (i = 0; i < strings.Size(); i++) + { + const UString &name = strings[i]; + NRecursedType::EEnum recursedType; + unsigned pos = 0; + + if (name.Len() < kSomeCludePostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar) + { + pos++; + wchar_t c = name[pos]; + int index = -1; + if (c <= 0x7F) + index = FindCharPosInString(kRecursedPostCharSet, (char)c); + recursedType = GetRecursedTypeFromIndex(index); + if (index >= 0) + pos++; + } + else + recursedType = commonRecursedType; + + if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize) + { + errorMessage = "Too short switch"; + break; + } + + const UString tail = name.Ptr(pos + 1); + + if (name[pos] == kImmediateNameID) + AddNameToCensor(censor, tail, include, recursedType, wildcardMatching); + else if (name[pos] == kFileListID) + AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage); + #ifdef _WIN32 + else if (name[pos] == kMapNameID) + { + errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching); + if (errorMessage) + break; + } + #endif + else + { + errorMessage = "Incorrect wildcard type marker"; + break; + } + } + if (i != strings.Size()) + throw CArcCmdLineException(errorMessage, strings[i]); +} + +/* +static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) +{ + switch (i) + { + case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; + case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; + case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; + case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; + } + throw 98111603; +} +*/ + +static const char * const kUpdatePairStateIDSet = "pqrxyzw"; +static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; + +static const unsigned kNumUpdatePairActions = 4; +static const char * const kUpdateIgnoreItselfPostStringID = "-"; +static const wchar_t kUpdateNewArchivePostCharID = '!'; + + +static bool ParseUpdateCommandString2(const UString &command, + NUpdateArchive::CActionSet &actionSet, UString &postString) +{ + for (unsigned i = 0; i < command.Len();) + { + wchar_t c = MyCharLower_Ascii(command[i]); + int statePos = FindCharPosInString(kUpdatePairStateIDSet, (char)c); + if (c > 0x7F || statePos < 0) + { + postString = command.Ptr(i); + return true; + } + i++; + if (i >= command.Len()) + return false; + c = command[i]; + if (c < '0' || c >= (wchar_t)('0' + kNumUpdatePairActions)) + return false; + unsigned actionPos = (unsigned)(c - '0'); + actionSet.StateActions[(unsigned)statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos); + if (kUpdatePairStateNotSupportedActions[(unsigned)statePos] == (int)actionPos) + return false; + i++; + } + postString.Empty(); + return true; +} + +static void ParseUpdateCommandString(CUpdateOptions &options, + const UStringVector &updatePostStrings, + const NUpdateArchive::CActionSet &defaultActionSet) +{ + const char *errorMessage = "incorrect update switch command"; + unsigned i; + for (i = 0; i < updatePostStrings.Size(); i++) + { + const UString &updateString = updatePostStrings[i]; + if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID)) + { + if (options.UpdateArchiveItself) + { + options.UpdateArchiveItself = false; + options.Commands.Delete(0); + } + } + else + { + NUpdateArchive::CActionSet actionSet = defaultActionSet; + + UString postString; + if (!ParseUpdateCommandString2(updateString, actionSet, postString)) + break; + if (postString.IsEmpty()) + { + if (options.UpdateArchiveItself) + options.Commands[0].ActionSet = actionSet; + } + else + { + if (postString[0] != kUpdateNewArchivePostCharID) + break; + CUpdateArchiveCommand uc; + UString archivePath = postString.Ptr(1); + if (archivePath.IsEmpty()) + break; + uc.UserArchivePath = archivePath; + uc.ActionSet = actionSet; + options.Commands.Add(uc); + } + } + } + if (i != updatePostStrings.Size()) + throw CArcCmdLineException(errorMessage, updatePostStrings[i]); +} + +bool ParseComplexSize(const wchar_t *s, UInt64 &result); + +static void SetAddCommandOptions( + NCommandType::EEnum commandType, + const CParser &parser, + CUpdateOptions &options) +{ + NUpdateArchive::CActionSet defaultActionSet; + switch (commandType) + { + case NCommandType::kAdd: + defaultActionSet = NUpdateArchive::k_ActionSet_Add; + break; + case NCommandType::kDelete: + defaultActionSet = NUpdateArchive::k_ActionSet_Delete; + break; + default: + defaultActionSet = NUpdateArchive::k_ActionSet_Update; + } + + options.UpdateArchiveItself = true; + + options.Commands.Clear(); + CUpdateArchiveCommand updateMainCommand; + updateMainCommand.ActionSet = defaultActionSet; + options.Commands.Add(updateMainCommand); + if (parser[NKey::kUpdate].ThereIs) + ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, + defaultActionSet); + if (parser[NKey::kWorkingDir].ThereIs) + { + const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; + if (postString.IsEmpty()) + NDir::MyGetTempPath(options.WorkingDir); + else + options.WorkingDir = us2fs(postString); + } + options.SfxMode = parser[NKey::kSfx].ThereIs; + if (options.SfxMode) + options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]); + + if (parser[NKey::kVolume].ThereIs) + { + const UStringVector &sv = parser[NKey::kVolume].PostStrings; + FOR_VECTOR (i, sv) + { + UInt64 size; + if (!ParseComplexSize(sv[i], size) || size == 0) + throw CArcCmdLineException("Incorrect volume size:", sv[i]); + options.VolumesSizes.Add(size); + } + } +} + +static void SetMethodOptions(const CParser &parser, CObjectVector &properties) +{ + if (parser[NKey::kProperty].ThereIs) + { + FOR_VECTOR (i, parser[NKey::kProperty].PostStrings) + { + CProperty prop; + prop.Name = parser[NKey::kProperty].PostStrings[i]; + int index = prop.Name.Find(L'='); + if (index >= 0) + { + prop.Value = prop.Name.Ptr((unsigned)(index + 1)); + prop.Name.DeleteFrom((unsigned)index); + } + properties.Add(prop); + } + } +} + + +static inline void SetStreamMode(const CSwitchResult &sw, unsigned &res) +{ + if (sw.ThereIs) + res = (unsigned)sw.PostCharIndex; +} + + +#if defined(_WIN32) && !defined(UNDER_CE) +static void PrintHex(UString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} +#endif + + +void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, + CArcCmdLineOptions &options) +{ + Parse1Log.Empty(); + if (!parser.ParseStrings(kSwitchForms, ARRAY_SIZE(kSwitchForms), commandStrings)) + throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine); + + options.IsInTerminal = MY_IS_TERMINAL(stdin); + options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); + options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); + + options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; + + options.StdInMode = parser[NKey::kStdIn].ThereIs; + options.StdOutMode = parser[NKey::kStdOut].ThereIs; + options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; + options.TechMode = parser[NKey::kTechMode].ThereIs; + options.ShowTime = parser[NKey::kShowTime].ThereIs; + + if (parser[NKey::kDisablePercents].ThereIs + || options.StdOutMode + || !options.IsStdOutTerminal) + options.Number_for_Percents = k_OutStream_disabled; + + if (options.StdOutMode) + options.Number_for_Out = k_OutStream_disabled; + + SetStreamMode(parser[NKey::kOutStream], options.Number_for_Out); + SetStreamMode(parser[NKey::kErrStream], options.Number_for_Errors); + SetStreamMode(parser[NKey::kPercentStream], options.Number_for_Percents); + + if (parser[NKey::kLogLevel].ThereIs) + { + const UString &s = parser[NKey::kLogLevel].PostStrings[0]; + if (s.IsEmpty()) + options.LogLevel = 1; + else + { + UInt32 v; + if (!StringToUInt32(s, v)) + throw CArcCmdLineException("Unsupported switch postfix -bb", s); + options.LogLevel = (unsigned)v; + } + } + + if (parser[NKey::kCaseSensitive].ThereIs) + { + g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus; + options.CaseSensitiveChange = true; + options.CaseSensitive = g_CaseSensitive; + } + + + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_SymLink(); + #endif + + // options.LargePages = false; + + if (parser[NKey::kLargePages].ThereIs) + { + unsigned slp = 0; + const UString &s = parser[NKey::kLargePages].PostStrings[0]; + if (s.IsEmpty()) + slp = 1; + else if (s != L"-") + { + if (!StringToUInt32(s, slp)) + throw CArcCmdLineException("Unsupported switch postfix for -slp", s); + } + + #ifdef _7ZIP_LARGE_PAGES + if (slp > + #if defined(_WIN32) && !defined(UNDER_CE) + (unsigned)NSecurity::Get_LargePages_RiskLevel() + #else + 0 + #endif + ) + { + #ifdef _WIN32 // change it ! + SetLargePageSize(); + #endif + // note: this process also can inherit that Privilege from parent process + g_LargePagesMode = + #if defined(_WIN32) && !defined(UNDER_CE) + NSecurity::EnablePrivilege_LockMemory(); + #else + true; + #endif + } + #endif + } + + + #ifndef UNDER_CE + + if (parser[NKey::kAffinity].ThereIs) + { + const UString &s = parser[NKey::kAffinity].PostStrings[0]; + if (!s.IsEmpty()) + { + AString a; + a.SetFromWStr_if_Ascii(s); + Parse1Log += "Set process affinity mask: "; + + #ifdef _WIN32 + + UInt64 v = 0; + { + const char *end; + v = ConvertHexStringToUInt64(a, &end); + if (*end != 0) + a.Empty(); + } + if (a.IsEmpty()) + throw CArcCmdLineException("Unsupported switch postfix -stm", s); + + { + #ifndef _WIN64 + if (v >= ((UInt64)1 << 32)) + throw CArcCmdLineException("unsupported value -stm", s); + #endif + { + PrintHex(Parse1Log, v); + if (!SetProcessAffinityMask(GetCurrentProcess(), (DWORD_PTR)v)) + { + DWORD lastError = GetLastError(); + Parse1Log += " : ERROR : "; + Parse1Log += NError::MyFormatMessage(lastError); + } + } + } + + #else // _WIN32 + + { + Parse1Log += a; + NSystem::CProcessAffinity aff; + aff.CpuZero(); + for (unsigned i = 0; i < a.Len(); i++) + { + char c = a[i]; + unsigned v; + if (c >= '0' && c <= '9') v = (unsigned)(c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (unsigned)(c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (unsigned)(c - 'a'); + else + throw CArcCmdLineException("Unsupported switch postfix -stm", s); + for (unsigned k = 0; k < 4; k++) + { + const unsigned cpu = (a.Len() - 1 - i) * 4 + k; + if (v & ((unsigned)1 << k)) + aff.CpuSet(cpu); + } + } + + if (!aff.SetProcAffinity()) + { + DWORD lastError = GetLastError(); + Parse1Log += " : ERROR : "; + Parse1Log += NError::MyFormatMessage(lastError); + } + } + #endif // _WIN32 + + Parse1Log.Add_LF(); + } + } + + #endif +} + + + +struct CCodePagePair +{ + const char *Name; + UInt32 CodePage; +}; + +static const unsigned kNumByteOnlyCodePages = 3; + +static const CCodePagePair g_CodePagePairs[] = +{ + { "utf-8", CP_UTF8 }, + { "win", CP_ACP }, + { "dos", CP_OEMCP }, + { "utf-16le", MY__CP_UTF16 }, + { "utf-16be", MY__CP_UTF16BE } +}; + +static Int32 FindCharset(const NCommandLineParser::CParser &parser, unsigned keyIndex, + bool byteOnlyCodePages, Int32 defaultVal) +{ + if (!parser[keyIndex].ThereIs) + return defaultVal; + + UString name (parser[keyIndex].PostStrings.Back()); + UInt32 v; + if (StringToUInt32(name, v)) + if (v < ((UInt32)1 << 16)) + return (Int32)v; + name.MakeLower_Ascii(); + unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs); + for (unsigned i = 0;; i++) + { + if (i == num) // to disable warnings from different compilers + throw CArcCmdLineException("Unsupported charset:", name); + const CCodePagePair &pair = g_CodePagePairs[i]; + if (name.IsEqualTo(pair.Name)) + return (Int32)pair.CodePage; + } +} + + +static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp) +{ + bp.Def = parser[switchID].ThereIs; + if (bp.Def) + bp.Val = !parser[switchID].WithMinus; +} + +void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) +{ + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + const unsigned numNonSwitchStrings = nonSwitchStrings.Size(); + if (numNonSwitchStrings < kMinNonSwitchWords) + throw CArcCmdLineException("The command must be specified"); + + if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) + throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]); + + if (parser[NKey::kHash].ThereIs) + options.HashMethods = parser[NKey::kHash].PostStrings; + + if (parser[NKey::kElimDup].ThereIs) + { + options.ExtractOptions.ElimDup.Def = true; + options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus; + } + + NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath; + bool fullPathMode = parser[NKey::kFullPathMode].ThereIs; + if (fullPathMode) + { + censorPathMode = NWildcard::k_AbsPath; + const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; + if (!s.IsEmpty()) + { + if (s == L"2") + censorPathMode = NWildcard::k_FullPath; + else + throw CArcCmdLineException("Unsupported -spf:", s); + } + } + + if (parser[NKey::kNameTrailReplace].ThereIs) + g_PathTrailReplaceMode = !parser[NKey::kNameTrailReplace].WithMinus; + + NRecursedType::EEnum recursedType; + if (parser[NKey::kRecursed].ThereIs) + recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); + else + recursedType = NRecursedType::kNonRecursed; + + bool wildcardMatching = true; + if (parser[NKey::kDisableWildcardParsing].ThereIs) + wildcardMatching = false; + + options.ConsoleCodePage = FindCharset(parser, NKey::kConsoleCharSet, true, -1); + + UInt32 codePage = (UInt32)FindCharset(parser, NKey::kListfileCharSet, false, CP_UTF8); + + bool thereAreSwitchIncludes = false; + + if (parser[NKey::kInclude].ThereIs) + { + thereAreSwitchIncludes = true; + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage); + } + + if (parser[NKey::kExclude].ThereIs) + AddSwitchWildcardsToCensor(options.Censor, + parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage); + + unsigned curCommandIndex = kCommandIndex + 1; + bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && + options.Command.CommandType != NCommandType::kBenchmark && + options.Command.CommandType != NCommandType::kInfo && + options.Command.CommandType != NCommandType::kHash; + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + bool isRename = options.Command.CommandType == NCommandType::kRename; + + if ((isExtractOrList || isRename) && options.StdInMode) + thereIsArchiveName = false; + + if (parser[NKey::kArcNameMode].ThereIs) + options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex); + + if (thereIsArchiveName) + { + if (curCommandIndex >= numNonSwitchStrings) + throw CArcCmdLineException("Cannot find archive name"); + options.ArchiveName = nonSwitchStrings[curCommandIndex++]; + if (options.ArchiveName.IsEmpty()) + throw CArcCmdLineException("Archive name cannot by empty"); + #ifdef _WIN32 + // options.ArchiveName.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + } + + AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL, + curCommandIndex, options.Censor, + nonSwitchStrings, parser.StopSwitchIndex, + recursedType, wildcardMatching, + thereAreSwitchIncludes, codePage); + + options.YesToAll = parser[NKey::kYes].ThereIs; + + + #ifndef _NO_CRYPTO + options.PasswordEnabled = parser[NKey::kPassword].ThereIs; + if (options.PasswordEnabled) + options.Password = parser[NKey::kPassword].PostStrings[0]; + #endif + + options.ShowDialog = parser[NKey::kShowDialog].ThereIs; + + if (parser[NKey::kArchiveType].ThereIs) + options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; + + options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings; + + SetMethodOptions(parser, options.Properties); + + if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue(); + + SetBoolPair(parser, NKey::kAltStreams, options.AltStreams); + SetBoolPair(parser, NKey::kHardLinks, options.HardLinks); + SetBoolPair(parser, NKey::kSymLinks, options.SymLinks); + + CBoolPair symLinks_AllowDangerous; + SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); + + + /* + bool supportSymLink = options.SymLinks.Val; + + if (!options.SymLinks.Def) + { + if (isExtractOrList) + supportSymLink = true; + else + supportSymLink = false; + } + + #ifdef ENV_HAVE_LSTAT + if (supportSymLink) + global_use_lstat = 1; + else + global_use_lstat = 0; + #endif + */ + + + if (isExtractOrList) + { + CExtractOptionsBase &eo = options.ExtractOptions; + + { + CExtractNtOptions &nt = eo.NtOptions; + nt.NtSecurity = options.NtSecurity; + + nt.AltStreams = options.AltStreams; + if (!options.AltStreams.Def) + nt.AltStreams.Val = true; + + nt.HardLinks = options.HardLinks; + if (!options.HardLinks.Def) + nt.HardLinks.Val = true; + + nt.SymLinks = options.SymLinks; + if (!options.SymLinks.Def) + nt.SymLinks.Val = true; + + nt.SymLinks_AllowDangerous = symLinks_AllowDangerous; + + nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; + nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; + } + + options.Censor.AddPathsToCensor(NWildcard::k_AbsPath); + options.Censor.ExtendExclude(); + + // are there paths that look as non-relative (!Prefix.IsEmpty()) + if (!options.Censor.AllAreRelative()) + throw CArcCmdLineException("Cannot use absolute pathnames for this command"); + + NWildcard::CCensor &arcCensor = options.arcCensor; + + if (parser[NKey::kArInclude].ThereIs) + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage); + if (parser[NKey::kArExclude].ThereIs) + AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage); + + if (thereIsArchiveName) + AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching); + + arcCensor.AddPathsToCensor(NWildcard::k_RelatPath); + + #ifdef _WIN32 + ConvertToLongNames(arcCensor); + #endif + + arcCensor.ExtendExclude(); + + if (options.StdInMode) + options.ArcName_for_StdInMode = parser[NKey::kStdIn].PostStrings.Front(); + + if (isExtractGroupCommand) + { + if (options.StdOutMode) + { + if ( + options.Number_for_Percents == k_OutStream_stdout + // || options.Number_for_Out == k_OutStream_stdout + // || options.Number_for_Errors == k_OutStream_stdout + || + ( + (options.IsStdOutTerminal && options.IsStdErrTerminal) + && + ( + options.Number_for_Percents != k_OutStream_disabled + // || options.Number_for_Out != k_OutStream_disabled + // || options.Number_for_Errors != k_OutStream_disabled + ) + ) + ) + throw CArcCmdLineException(kSameTerminalError); + } + + if (parser[NKey::kOutputDir].ThereIs) + { + eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); + #ifdef _WIN32 + NFile::NName::NormalizeDirSeparators(eo.OutputDir); + #endif + NFile::NName::NormalizeDirPathPrefix(eo.OutputDir); + } + + eo.OverwriteMode = NExtract::NOverwriteMode::kAsk; + if (parser[NKey::kOverwrite].ThereIs) + { + eo.OverwriteMode = k_OverwriteModes[(unsigned)parser[NKey::kOverwrite].PostCharIndex]; + eo.OverwriteMode_Force = true; + } + else if (options.YesToAll) + { + eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite; + eo.OverwriteMode_Force = true; + } + } + + eo.PathMode = options.Command.GetPathMode(); + if (censorPathMode == NWildcard::k_AbsPath) + { + eo.PathMode = NExtract::NPathMode::kAbsPaths; + eo.PathMode_Force = true; + } + else if (censorPathMode == NWildcard::k_FullPath) + { + eo.PathMode = NExtract::NPathMode::kFullPaths; + eo.PathMode_Force = true; + } + } + else if (options.Command.IsFromUpdateGroup()) + { + if (parser[NKey::kArInclude].ThereIs) + throw CArcCmdLineException("-ai switch is not supported for this command"); + + CUpdateOptions &updateOptions = options.UpdateOptions; + + SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); + + updateOptions.MethodMode.Properties = options.Properties; + + if (parser[NKey::kPreserveATime].ThereIs) + updateOptions.PreserveATime = true; + if (parser[NKey::kShareForWrite].ThereIs) + updateOptions.OpenShareForWrite = true; + if (parser[NKey::kStopAfterOpenError].ThereIs) + updateOptions.StopAfterOpenError = true; + + updateOptions.PathMode = censorPathMode; + + updateOptions.AltStreams = options.AltStreams; + updateOptions.NtSecurity = options.NtSecurity; + updateOptions.HardLinks = options.HardLinks; + updateOptions.SymLinks = options.SymLinks; + + updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; + if (updateOptions.EMailMode) + { + updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); + if (updateOptions.EMailAddress.Len() > 0) + if (updateOptions.EMailAddress[0] == L'.') + { + updateOptions.EMailRemoveAfter = true; + updateOptions.EMailAddress.Delete(0); + } + } + + updateOptions.StdOutMode = options.StdOutMode; + updateOptions.StdInMode = options.StdInMode; + + updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs; + updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs; + + if (updateOptions.StdOutMode && updateOptions.EMailMode) + throw CArcCmdLineException("stdout mode and email mode cannot be combined"); + + if (updateOptions.StdOutMode) + { + if (options.IsStdOutTerminal) + throw CArcCmdLineException(kTerminalOutError); + + if (options.Number_for_Percents == k_OutStream_stdout + || options.Number_for_Out == k_OutStream_stdout + || options.Number_for_Errors == k_OutStream_stdout) + throw CArcCmdLineException(kSameTerminalError); + } + + if (updateOptions.StdInMode) + updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); + + if (options.Command.CommandType == NCommandType::kRename) + if (updateOptions.Commands.Size() != 1) + throw CArcCmdLineException("Only one archive can be created with rename command"); + } + else if (options.Command.CommandType == NCommandType::kBenchmark) + { + options.NumIterations = 1; + options.NumIterations_Defined = false; + if (curCommandIndex < numNonSwitchStrings) + { + if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations)) + throw CArcCmdLineException("Incorrect number of benchmark iterations", nonSwitchStrings[curCommandIndex]); + curCommandIndex++; + options.NumIterations_Defined = true; + } + } + else if (options.Command.CommandType == NCommandType::kHash) + { + options.Censor.AddPathsToCensor(censorPathMode); + options.Censor.ExtendExclude(); + + CHashOptions &hashOptions = options.HashOptions; + hashOptions.PathMode = censorPathMode; + hashOptions.Methods = options.HashMethods; + if (parser[NKey::kPreserveATime].ThereIs) + hashOptions.PreserveATime = true; + if (parser[NKey::kShareForWrite].ThereIs) + hashOptions.OpenShareForWrite = true; + hashOptions.StdInMode = options.StdInMode; + hashOptions.AltStreamsMode = options.AltStreams.Val; + hashOptions.SymLinks = options.SymLinks; + } + else if (options.Command.CommandType == NCommandType::kInfo) + { + } + else + throw 20150919; +} + + + +#ifndef _WIN32 + +static AString g_ModuleDirPrefix; + +void Set_ModuleDirPrefix_From_ProgArg0(const char *s); +void Set_ModuleDirPrefix_From_ProgArg0(const char *s) +{ + AString a (s); + int sep = a.ReverseFind_PathSepar(); + a.DeleteFrom((unsigned)(sep + 1)); + g_ModuleDirPrefix = a; +} + +namespace NWindows { +namespace NDLL { + +FString GetModuleDirPrefix(); +FString GetModuleDirPrefix() +{ + FString s; + + s = g_ModuleDirPrefix; + if (s.IsEmpty()) + s = FTEXT(".") FSTRING_PATH_SEPARATOR; + return s; + /* + setenv("_7ZIP_HOME_DIR", "/test/", 0); + const char *home = getenv("_7ZIP_HOME_DIR"); + if (home) + s = home; + else + s = FTEXT(".") FSTRING_PATH_SEPARATOR; + return s; + */ +} + +}} + +#endif // ! _WIN32 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.h new file mode 100644 index 0000000..1e488d8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -0,0 +1,154 @@ +// ArchiveCommandLine.h + +#ifndef __ARCHIVE_COMMAND_LINE_H +#define __ARCHIVE_COMMAND_LINE_H + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/Wildcard.h" + +#include "EnumDirItems.h" + +#include "Extract.h" +#include "HashCalc.h" +#include "Update.h" + +typedef CMessagePathException CArcCmdLineException; + +namespace NCommandType { enum EEnum +{ + kAdd = 0, + kUpdate, + kDelete, + kTest, + kExtract, + kExtractFull, + kList, + kBenchmark, + kInfo, + kHash, + kRename +};} + +struct CArcCommand +{ + NCommandType::EEnum CommandType; + + bool IsFromExtractGroup() const; + bool IsFromUpdateGroup() const; + bool IsTestCommand() const { return CommandType == NCommandType::kTest; } + NExtract::NPathMode::EEnum GetPathMode() const; +}; + +enum +{ + k_OutStream_disabled = 0, + k_OutStream_stdout = 1, + k_OutStream_stderr = 2 +}; + +struct CArcCmdLineOptions +{ + bool HelpMode; + + // bool LargePages; + bool CaseSensitiveChange; + bool CaseSensitive; + + bool IsInTerminal; + bool IsStdOutTerminal; + bool IsStdErrTerminal; + bool StdInMode; + bool StdOutMode; + bool EnableHeaders; + + bool YesToAll; + bool ShowDialog; + bool TechMode; + bool ShowTime; + + int ConsoleCodePage; + + NWildcard::CCensor Censor; + + CArcCommand Command; + UString ArchiveName; + + #ifndef _NO_CRYPTO + bool PasswordEnabled; + UString Password; + #endif + + UStringVector HashMethods; + + bool AppendName; + // UStringVector ArchivePathsSorted; + // UStringVector ArchivePathsFullSorted; + NWildcard::CCensor arcCensor; + UString ArcName_for_StdInMode; + + CObjectVector Properties; + + CExtractOptionsBase ExtractOptions; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + CUpdateOptions UpdateOptions; + CHashOptions HashOptions; + UString ArcType; + UStringVector ExcludedArcTypes; + + unsigned Number_for_Out; + unsigned Number_for_Errors; + unsigned Number_for_Percents; + unsigned LogLevel; + + // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; } + + // Benchmark + UInt32 NumIterations; + bool NumIterations_Defined; + + CArcCmdLineOptions(): + HelpMode(false), + // LargePages(false), + CaseSensitiveChange(false), + CaseSensitive(false), + + IsInTerminal(false), + IsStdOutTerminal(false), + IsStdErrTerminal(false), + + StdInMode(false), + StdOutMode(false), + + EnableHeaders(false), + + YesToAll(false), + ShowDialog(false), + TechMode(false), + ShowTime(false), + + ConsoleCodePage(-1), + + Number_for_Out(k_OutStream_stdout), + Number_for_Errors(k_OutStream_stderr), + Number_for_Percents(k_OutStream_stdout), + + LogLevel(0) + { + }; +}; + +class CArcCmdLineParser +{ + NCommandLineParser::CParser parser; +public: + UString Parse1Log; + void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options); + void Parse2(CArcCmdLineOptions &options); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp new file mode 100644 index 0000000..40e43d2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -0,0 +1,2192 @@ +// ArchiveExtractCallback.cpp + +#include "StdAfx.h" + +#undef sprintf +#undef printf + +// #include +// #include "../../../../C/CpuTicks.h" + +#include "../../../../C/Alloc.h" +#include "../../../../C/CpuArch.h" + + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + +#include "../../Common/FilePathAutoRename.h" +#include "../../Common/StreamUtils.h" + +#include "../Common/ExtractingFilePath.h" +#include "../Common/PropIDUtils.h" + +#include "ArchiveExtractCallback.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static const char * const kCantAutoRename = "Cannot create file with auto name"; +static const char * const kCantRenameFile = "Cannot rename existing file"; +static const char * const kCantDeleteOutputFile = "Cannot delete output file"; +static const char * const kCantDeleteOutputDir = "Cannot delete output folder"; +static const char * const kCantOpenOutFile = "Cannot open output file"; +static const char * const kCantSetFileLen = "Cannot set length for output file"; +#ifdef SUPPORT_LINKS +static const char * const kCantCreateHardLink = "Cannot create hard link"; +static const char * const kCantCreateSymLink = "Cannot create symbolic link"; +#endif + +#ifndef _SFX + +STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + if (_calculate) + _hash->Update(data, size); + _size += size; + if (processedSize) + *processedSize = size; + return result; +} + +#endif // _SFX + + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges(); +bool InitLocalPrivileges() +{ + NSecurity::CAccessToken token; + if (!token.OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES)) + return false; + + TOKEN_PRIVILEGES tp; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) + return false; + if (!token.AdjustPrivileges(&tp)) + return false; + return (GetLastError() == ERROR_SUCCESS); +} +#endif // _USE_SECURITY_CODE + + +#ifdef SUPPORT_LINKS + +int CHardLinkNode::Compare(const CHardLinkNode &a) const +{ + if (StreamId < a.StreamId) return -1; + if (StreamId > a.StreamId) return 1; + return MyCompare(INode, a.INode); +} + +static HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined) +{ + h.INode = 0; + h.StreamId = (UInt64)(Int64)-1; + defined = false; + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidINode, &prop)); + if (!ConvertPropVariantToUInt64(prop, h.INode)) + return S_OK; + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidStreamId, &prop)); + ConvertPropVariantToUInt64(prop, h.StreamId); + } + defined = true; + return S_OK; +} + + +HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector *realIndices) +{ + _hardLinks.Clear(); + + if (!_arc->Ask_INode) + return S_OK; + + IInArchive *archive = _arc->Archive; + CRecordVector &hardIDs = _hardLinks.IDs; + + { + UInt32 numItems; + if (realIndices) + numItems = realIndices->Size(); + else + { + RINOK(archive->GetNumberOfItems(&numItems)); + } + + for (UInt32 i = 0; i < numItems; i++) + { + CHardLinkNode h; + bool defined; + UInt32 realIndex = realIndices ? (*realIndices)[i] : i; + + RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined)); + if (defined) + { + bool isAltStream = false; + RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream)); + if (!isAltStream) + hardIDs.Add(h); + } + } + } + + hardIDs.Sort2(); + + { + // we keep only items that have 2 or more items + unsigned k = 0; + unsigned numSame = 1; + for (unsigned i = 1; i < hardIDs.Size(); i++) + { + if (hardIDs[i].Compare(hardIDs[i - 1]) != 0) + numSame = 1; + else if (++numSame == 2) + { + if (i - 1 != k) + hardIDs[k] = hardIDs[i - 1]; + k++; + } + } + hardIDs.DeleteFrom(k); + } + + _hardLinks.PrepareLinks(); + return S_OK; +} + +#endif // SUPPORT_LINKS + + +CArchiveExtractCallback::CArchiveExtractCallback(): + _arc(NULL), + WriteCTime(true), + WriteATime(true), + WriteMTime(true), + _multiArchives(false) +{ + LocalProgressSpec = new CLocalProgress(); + _localProgress = LocalProgressSpec; + + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} + + +void CArchiveExtractCallback::Init( + const CExtractNtOptions &ntOptions, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, + IFolderArchiveExtractCallback *extractCallback2, + bool stdOutMode, bool testMode, + const FString &directoryPath, + const UStringVector &removePathParts, bool removePartsForAltStreams, + UInt64 packSize) +{ + ClearExtractedDirsInfo(); + _outFileStream.Release(); + _bufPtrSeqOutStream.Release(); + + #ifdef SUPPORT_LINKS + _hardLinks.Clear(); + #endif + + #ifdef SUPPORT_ALT_STREAMS + _renamedFiles.Clear(); + #endif + + _ntOptions = ntOptions; + _wildcardCensor = wildcardCensor; + + _stdOutMode = stdOutMode; + _testMode = testMode; + + // _progressTotal = 0; + // _progressTotal_Defined = false; + + _packTotal = packSize; + _progressTotal = packSize; + _progressTotal_Defined = true; + + _extractCallback2 = extractCallback2; + _compressProgress.Release(); + _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); + _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage); + _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); + + #ifndef _SFX + + _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); + if (ExtractToStreamCallback) + { + Int32 useStreams = 0; + if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) + useStreams = 0; + if (useStreams == 0) + ExtractToStreamCallback.Release(); + } + + #endif + + LocalProgressSpec->Init(extractCallback2, true); + LocalProgressSpec->SendProgress = false; + + _removePathParts = removePathParts; + _removePartsForAltStreams = removePartsForAltStreams; + + #ifndef _SFX + _baseParentFolder = (UInt32)(Int32)-1; + _use_baseParentFolder_mode = false; + #endif + + _arc = arc; + _dirPathPrefix = directoryPath; + _dirPathPrefix_Full = directoryPath; + #if defined(_WIN32) && !defined(UNDER_CE) + if (!NName::IsAltPathPrefix(_dirPathPrefix)) + #endif + { + NName::NormalizeDirPathPrefix(_dirPathPrefix); + NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full); + NName::NormalizeDirPathPrefix(_dirPathPrefix_Full); + } +} + + +STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) +{ + COM_TRY_BEGIN + _progressTotal = size; + _progressTotal_Defined = true; + if (!_multiArchives && _extractCallback2) + return _extractCallback2->SetTotal(size); + return S_OK; + COM_TRY_END +} + + +static void NormalizeVals(UInt64 &v1, UInt64 &v2) +{ + const UInt64 kMax = (UInt64)1 << 31; + while (v1 > kMax) + { + v1 >>= 1; + v2 >>= 1; + } +} + + +static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) +{ + NormalizeVals(packTotal, unpTotal); + NormalizeVals(unpCur, unpTotal); + if (unpTotal == 0) + unpTotal = 1; + return unpCur * packTotal / unpTotal; +} + + +STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) +{ + COM_TRY_BEGIN + + if (!_extractCallback2) + return S_OK; + + UInt64 packCur; + if (_multiArchives) + { + packCur = LocalProgressSpec->InSize; + if (completeValue && _progressTotal_Defined) + packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); + completeValue = &packCur; + } + return _extractCallback2->SetCompleted(completeValue); + + COM_TRY_END +} + + +STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + COM_TRY_BEGIN + return _localProgress->SetRatioInfo(inSize, outSize); + COM_TRY_END +} + + +void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) +{ + bool isAbsPath = false; + + if (!dirPathParts.IsEmpty()) + { + const UString &s = dirPathParts[0]; + if (s.IsEmpty()) + isAbsPath = true; + #if defined(_WIN32) && !defined(UNDER_CE) + else + { + if (NName::IsDrivePath2(s)) + isAbsPath = true; + } + #endif + } + + if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) + fullPath.Empty(); + else + fullPath = _dirPathPrefix; + + FOR_VECTOR (i, dirPathParts) + { + if (i != 0) + fullPath.Add_PathSepar(); + const UString &s = dirPathParts[i]; + fullPath += us2fs(s); + #if defined(_WIN32) && !defined(UNDER_CE) + if (_pathMode == NExtract::NPathMode::kAbsPaths) + if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) + continue; + #endif + CreateDir(fullPath); + } +} + + +HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) +{ + filetimeIsDefined = false; + filetime.dwLowDateTime = 0; + filetime.dwHighDateTime = 0; + NCOM::CPropVariant prop; + RINOK(_arc->Archive->GetProperty(index, propID, &prop)); + if (prop.vt == VT_FILETIME) + { + filetime = prop.filetime; + filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT CArchiveExtractCallback::GetUnpackSize() +{ + return _arc->GetItemSize(_index, _curSize, _curSizeDefined); +} + +static void AddPathToMessage(UString &s, const FString &path) +{ + s += " : "; + s += fs2us(path); +} + +HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) +{ + UString s (message); + AddPathToMessage(s, path); + return _extractCallback2->MessageError(s); +} + +HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) +{ + DWORD errorCode = GetLastError(); + UString s (message); + if (errorCode != 0) + { + s += " : "; + s += NError::MyFormatMessage(errorCode); + } + AddPathToMessage(s, path); + return _extractCallback2->MessageError(s); +} + +HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) +{ + UString s (message); + if (errorCode != 0) + { + s += " : "; + s += NError::MyFormatMessage(errorCode); + } + AddPathToMessage(s, path1); + AddPathToMessage(s, path2); + return _extractCallback2->MessageError(s); +} + +#ifndef _SFX + +STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value) +{ + /* + if (propID == kpidName) + { + COM_TRY_BEGIN + NCOM::CPropVariant prop = Name; + prop.Detach(value); + return S_OK; + COM_TRY_END + } + */ + return Arc->Archive->GetProperty(IndexInArc, propID, value); +} + +#endif // _SFX + + +#ifdef SUPPORT_LINKS + +static UString GetDirPrefixOf(const UString &src) +{ + UString s (src); + if (!s.IsEmpty()) + { + if (IsPathSepar(s.Back())) + s.DeleteBack(); + int pos = s.ReverseFind_PathSepar(); + s.DeleteFrom((unsigned)(pos + 1)); + } + return s; +} + +#endif // SUPPORT_LINKS + +struct CLinkLevelsInfo +{ + bool IsAbsolute; + int LowLevel; + int FinalLevel; + + void Parse(const UString &path); +}; + +void CLinkLevelsInfo::Parse(const UString &path) +{ + IsAbsolute = NName::IsAbsolutePath(path); + + LowLevel = 0; + FinalLevel = 0; + + UStringVector parts; + SplitPathToParts(path, parts); + int level = 0; + + FOR_VECTOR (i, parts) + { + const UString &s = parts[i]; + if (s.IsEmpty()) + { + if (i == 0) + IsAbsolute = true; + continue; + } + if (s == L".") + continue; + if (s == L"..") + { + level--; + if (LowLevel > level) + LowLevel = level; + } + else + level++; + } + + FinalLevel = level; +} + + +bool IsSafePath(const UString &path); +bool IsSafePath(const UString &path) +{ + CLinkLevelsInfo levelsInfo; + levelsInfo.Parse(path); + return !levelsInfo.IsAbsolute + && levelsInfo.LowLevel >= 0 + && levelsInfo.FinalLevel > 0; +} + + +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) +{ + bool found = false; + + // CheckPathVect() doesn't check path to Parent nodes + if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include)) + { + if (!include) + return true; + + #ifdef SUPPORT_ALT_STREAMS + if (!item.IsAltStream) + return true; + #endif + + found = true; + } + + #ifdef SUPPORT_ALT_STREAMS + + if (!item.IsAltStream) + return false; + + UStringVector pathParts2 = item.PathParts; + if (pathParts2.IsEmpty()) + pathParts2.AddNew(); + UString &back = pathParts2.Back(); + back += ':'; + back += item.AltStreamName; + bool include2; + + if (node.CheckPathVect(pathParts2, + true, // isFile, + include2)) + { + include = include2; + return true; + } + + #endif // SUPPORT_ALT_STREAMS + + return found; +} + + +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item) +{ + bool include; + if (CensorNode_CheckPath2(node, item, include)) + return include; + return false; +} + + +static FString MakePath_from_2_Parts(const FString &prefix, const FString &path) +{ + FString s (prefix); + #if defined(_WIN32) && !defined(UNDER_CE) + if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back())) + { + if (!NName::IsDriveRootPath_SuperAllowed(prefix)) + s.DeleteBack(); + } + #endif + s += path; + return s; +} + + + +#ifdef SUPPORT_LINKS + +/* +struct CTempMidBuffer +{ + void *Buf; + + CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); } + ~CTempMidBuffer() { ::MidFree(Buf); } +}; + +HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) +{ + const size_t kBufSize = 1 << 16; + CTempMidBuffer buf(kBufSize); + if (!buf.Buf) + return E_OUTOFMEMORY; + + NIO::CInFile inFile; + NIO::COutFile outFile; + + if (!inFile.Open(_CopyFile_Path)) + return SendMessageError_with_LastError("Open error", _CopyFile_Path); + + for (;;) + { + UInt32 num; + + if (!inFile.Read(buf.Buf, kBufSize, num)) + return SendMessageError_with_LastError("Read error", _CopyFile_Path); + + if (num == 0) + return S_OK; + + + RINOK(WriteStream(outStream, buf.Buf, num)); + } +} +*/ + + +HRESULT CArchiveExtractCallback::ReadLink() +{ + IInArchive *archive = _arc->Archive; + const UInt32 index = _index; + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidHardLink, &prop)); + if (prop.vt == VT_BSTR) + { + _link.isHardLink = true; + // _link.isCopyLink = false; + _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive + _link.linkPath.SetFromBstr(prop.bstrVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + /* + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); + if (prop.vt == VT_BSTR) + { + _link.isHardLink = false; + _link.isCopyLink = true; + _link.isRelative = false; // RAR5: copy links are from root folder of archive + _link.linkPath.SetFromBstr(prop.bstrVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + */ + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidSymLink, &prop)); + if (prop.vt == VT_BSTR) + { + _link.isHardLink = false; + // _link.isCopyLink = false; + _link.isRelative = true; // RAR5, TAR: symbolic links can be relative + _link.linkPath.SetFromBstr(prop.bstrVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + NtReparse_Data = NULL; + NtReparse_Size = 0; + + if (_link.linkPath.IsEmpty() && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + + _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); + + // if (dataSize == 1234567) // for debug: unpacking without reparse + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + + #ifdef _WIN32 + + NtReparse_Data = data; + NtReparse_Size = dataSize; + + CReparseAttr reparse; + bool isOkReparse = reparse.Parse((const Byte *)data, dataSize); + if (isOkReparse) + { + _link.isHardLink = false; + // _link.isCopyLink = false; + _link.linkPath = reparse.GetPath(); + _link.isJunction = reparse.IsMountPoint(); + + if (reparse.IsSymLink_WSL()) + { + _link.isWSL = true; + _link.isRelative = reparse.IsRelative_WSL(); + } + else + _link.isRelative = reparse.IsRelative_Win(); + + #ifndef _WIN32 + _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + #endif + } + #endif + } + } + + if (_link.linkPath.IsEmpty()) + return S_OK; + + { + #ifdef _WIN32 + _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + + // rar5 uses "\??\" prefix for absolute links + if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) + { + _link.isRelative = false; + _link.linkPath.DeleteFrontal(4); + } + + for (;;) + // while (NName::IsAbsolutePath(linkPath)) + { + unsigned n = NName::GetRootPrefixSize(_link.linkPath); + if (n == 0) + break; + _link.isRelative = false; + _link.linkPath.DeleteFrontal(n); + } + } + + if (_link.linkPath.IsEmpty()) + return S_OK; + + if (!_link.isRelative && _removePathParts.Size() != 0) + { + UStringVector pathParts; + SplitPathToParts(_link.linkPath, pathParts); + bool badPrefix = false; + FOR_VECTOR (i, _removePathParts) + { + if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) + { + badPrefix = true; + break; + } + } + if (!badPrefix) + pathParts.DeleteFrontal(_removePathParts.Size()); + _link.linkPath = MakePathFromParts(pathParts); + } + + /* + if (!_link.linkPath.IsEmpty()) + { + printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr()); + } + */ + + return S_OK; +} + +#endif // SUPPORT_LINKS + + + +HRESULT CArchiveExtractCallback::Read_fi_Props() +{ + IInArchive *archive = _arc->Archive; + const UInt32 index = _index; + + _fi.AttribDefined = false; + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidPosixAttrib, &prop)); + if (prop.vt == VT_UI4) + { + _fi.SetFromPosixAttrib(prop.ulVal); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + { + _fi.Attrib = prop.ulVal; + _fi.AttribDefined = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + + RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); + RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); + RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); + return S_OK; +} + + + +void CArchiveExtractCallback::CorrectPathParts() +{ + UStringVector &pathParts = _item.PathParts; + + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream + || !pathParts.IsEmpty() + || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)) + #endif + Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir); + + #ifdef SUPPORT_ALT_STREAMS + + if (_item.IsAltStream) + { + UString s (_item.AltStreamName); + Correct_AltStream_Name(s); + bool needColon = true; + + if (pathParts.IsEmpty()) + { + pathParts.AddNew(); + if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) + needColon = false; + } + #ifdef _WIN32 + else if (_pathMode == NExtract::NPathMode::kAbsPaths && + NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size()) + pathParts.AddNew(); + #endif + + UString &name = pathParts.Back(); + if (needColon) + name += (char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'); + name += s; + } + + #endif // SUPPORT_ALT_STREAMS +} + + + +void CArchiveExtractCallback::CreateFolders() +{ + UStringVector &pathParts = _item.PathParts; + + if (!_item.IsDir) + { + if (!pathParts.IsEmpty()) + pathParts.DeleteBack(); + } + + if (pathParts.IsEmpty()) + return; + + FString fullPathNew; + CreateComplexDirectory(pathParts, fullPathNew); + + if (!_item.IsDir) + return; + + CDirPathTime &pt = _extractedFolders.AddNew(); + + pt.CTime = _fi.CTime; + pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); + + pt.ATime = _fi.ATime; + pt.ATimeDefined = (WriteATime && _fi.ATimeDefined); + + pt.MTimeDefined = false; + + if (WriteMTime) + { + if (_fi.MTimeDefined) + { + pt.MTime = _fi.MTime; + pt.MTimeDefined = true; + } + else if (_arc->MTimeDefined) + { + pt.MTime = _arc->MTime; + pt.MTimeDefined = true; + } + } + + pt.Path = fullPathNew; + pt.SetDirTime(); +} + + + +/* + CheckExistFile(fullProcessedPath) + it can change: fullProcessedPath, _isRenamed, _overwriteMode + (needExit = true) means that we must exit GetStream() even for S_OK result. +*/ + +HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool &needExit) +{ + needExit = true; // it was set already before + + NFind::CFileInfo fileInfo; + + if (fileInfo.Find(fullProcessedPath)) + { + if (_overwriteMode == NExtract::NOverwriteMode::kSkip) + return S_OK; + + if (_overwriteMode == NExtract::NOverwriteMode::kAsk) + { + int slashPos = fullProcessedPath.ReverseFind_PathSepar(); + FString realFullProcessedPath (fullProcessedPath.Left((unsigned)(slashPos + 1)) + fileInfo.Name); + + /* (fileInfo) can be symbolic link. + we can show final file properties here. */ + + Int32 overwriteResult; + RINOK(_extractCallback2->AskOverwrite( + fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path, + _fi.MTimeDefined ? &_fi.MTime : NULL, + _curSizeDefined ? &_curSize : NULL, + &overwriteResult)) + + switch (overwriteResult) + { + case NOverwriteAnswer::kCancel: + return E_ABORT; + case NOverwriteAnswer::kNo: + return S_OK; + case NOverwriteAnswer::kNoToAll: + _overwriteMode = NExtract::NOverwriteMode::kSkip; + return S_OK; + + case NOverwriteAnswer::kYes: + break; + case NOverwriteAnswer::kYesToAll: + _overwriteMode = NExtract::NOverwriteMode::kOverwrite; + break; + case NOverwriteAnswer::kAutoRename: + _overwriteMode = NExtract::NOverwriteMode::kRename; + break; + default: + return E_FAIL; + } + } // NExtract::NOverwriteMode::kAsk + + if (_overwriteMode == NExtract::NOverwriteMode::kRename) + { + if (!AutoRenamePath(fullProcessedPath)) + { + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); + return E_FAIL; + } + _isRenamed = true; + } + else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting) + { + FString existPath (fullProcessedPath); + if (!AutoRenamePath(existPath)) + { + RINOK(SendMessageError(kCantAutoRename, fullProcessedPath)); + return E_FAIL; + } + // MyMoveFile can rename folders. So it's OK to use it for folders too + if (!MyMoveFile(fullProcessedPath, existPath)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath)); + return E_FAIL; + } + } + else // not Rename* + { + if (fileInfo.IsDir()) + { + // do we need to delete all files in folder? + if (!RemoveDir(fullProcessedPath)) + { + RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath)); + return S_OK; + } + } + else // fileInfo is not Dir + { + if (NFind::DoesFileExist_Raw(fullProcessedPath)) + if (!DeleteFileAlways(fullProcessedPath)) + if (GetLastError() != ERROR_FILE_NOT_FOUND) // check it in linux + { + RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath)); + return S_OK; + // return E_FAIL; + } + } // fileInfo is not Dir + } // not Rename* + } + else // not Find(fullProcessedPath) + { + #if defined(_WIN32) && !defined(UNDER_CE) + // we need to clear READ-ONLY of parent before creating alt stream + int colonPos = NName::FindAltStreamColon(fullProcessedPath); + if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) + { + FString parentFsPath (fullProcessedPath); + parentFsPath.DeleteFrom((unsigned)colonPos); + NFind::CFileInfo parentFi; + if (parentFi.Find(parentFsPath)) + { + if (parentFi.IsReadOnly()) + SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); + } + } + #endif // defined(_WIN32) && !defined(UNDER_CE) + } + + needExit = false; + return S_OK; +} + + + + + + +HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr &outStreamLoc, bool &needExit) +{ + needExit = true; + + RINOK(Read_fi_Props()); + + #ifdef SUPPORT_LINKS + IInArchive *archive = _arc->Archive; + #endif + + const UStringVector &pathParts = _item.PathParts; + const UInt32 index = _index; + + bool isAnti = false; + RINOK(_arc->IsItemAnti(index, isAnti)); + + CorrectPathParts(); + + UString processedPath (MakePathFromParts(pathParts)); + + if (!isAnti) + CreateFolders(); + + FString fullProcessedPath (us2fs(processedPath)); + if (_pathMode != NExtract::NPathMode::kAbsPaths + || !NName::IsAbsolutePath(processedPath)) + { + fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath); + } + + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1) + { + int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex)); + if (renIndex >= 0) + { + const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex]; + fullProcessedPath = pair.Path; + fullProcessedPath += ':'; + UString s (_item.AltStreamName); + Correct_AltStream_Name(s); + fullProcessedPath += us2fs(s); + } + } + #endif // SUPPORT_ALT_STREAMS + + if (_item.IsDir) + { + _diskFilePath = fullProcessedPath; + if (isAnti) + RemoveDir(_diskFilePath); + #ifdef SUPPORT_LINKS + if (_link.linkPath.IsEmpty()) + #endif + return S_OK; + } + else if (!_isSplit) + { + RINOK(CheckExistFile(fullProcessedPath, needExit)); + if (needExit) + return S_OK; + needExit = true; + } + + _diskFilePath = fullProcessedPath; + + + if (isAnti) + { + needExit = false; + return S_OK; + } + + // not anti + + #ifdef SUPPORT_LINKS + + if (!_link.linkPath.IsEmpty()) + { + #ifndef UNDER_CE + { + bool linkWasSet = false; + RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)); + } + #endif // UNDER_CE + + // if (_CopyFile_Path.IsEmpty()) + { + needExit = false; + return S_OK; + } + } + + if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream) + { + CHardLinkNode h; + bool defined; + RINOK(Archive_Get_HardLinkNode(archive, index, h, defined)); + if (defined) + { + int linkIndex = _hardLinks.IDs.FindInSorted2(h); + if (linkIndex >= 0) + { + FString &hl = _hardLinks.Links[(unsigned)linkIndex]; + if (hl.IsEmpty()) + hl = fullProcessedPath; + else + { + if (!MyCreateHardLink(fullProcessedPath, hl)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)); + return S_OK; + } + + needExit = false; + return S_OK; + } + } + } + } + + #endif // SUPPORT_LINKS + + + // ---------- CREATE WRITE FILE ----- + + _outFileStreamSpec = new COutFileStream; + CMyComPtr outFileStream_Loc(_outFileStreamSpec); + + if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) + { + // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) + { + RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath)); + return S_OK; + } + } + + _fileWasExtracted = true; + + if (_curSizeDefined && _curSize > 0 && _curSize < (1 << 12)) + { + if (_fi.IsLinuxSymLink()) + { + _is_SymLink_in_Data = true; + _is_SymLink_in_Data_Linux = true; + } + else if (_fi.IsReparse()) + { + _is_SymLink_in_Data = true; + _is_SymLink_in_Data_Linux = false; + } + } + if (_is_SymLink_in_Data) + { + _outMemBuf.Alloc((size_t)_curSize); + _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream; + _bufPtrSeqOutStream = _bufPtrSeqOutStream_Spec; + _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); + outStreamLoc = _bufPtrSeqOutStream; + } + else // not reprase + { + if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSizeDefined && _curSize > (1 << 12)) + { + // UInt64 ticks = GetCpuTicks(); + _fileLength_that_WasSet = _curSize; + bool res = _outFileStreamSpec->File.SetLength(_curSize); + _fileLengthWasSet = res; + + // ticks = GetCpuTicks() - ticks; + // printf("\nticks = %10d\n", (unsigned)ticks); + if (!res) + { + RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath)); + } + + /* + _outFileStreamSpec->File.Close(); + ticks = GetCpuTicks() - ticks; + printf("\nticks = %10d\n", (unsigned)ticks); + return S_FALSE; + */ + + /* + File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow, + if we don't write any data. + File.SetLength() for remote share file (exFAT) can be slow in some cases, + and the Windows can return "network error" after 1 minute, + while remote file still can grow. + We need some way to detect such bad cases and disable PreAllocateOutFile mode. + */ + + res = _outFileStreamSpec->SeekToBegin_bool(); + if (!res) + { + RINOK(SendMessageError_with_LastError("Cannot seek to begin of file", fullProcessedPath)); + } + } // PreAllocateOutFile + + #ifdef SUPPORT_ALT_STREAMS + if (_isRenamed && !_item.IsAltStream) + { + CIndexToPathPair pair(index, fullProcessedPath); + unsigned oldSize = _renamedFiles.Size(); + unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair); + if (oldSize == _renamedFiles.Size()) + _renamedFiles[insertIndex].Path = fullProcessedPath; + } + #endif // SUPPORT_ALT_STREAMS + + if (_isSplit) + { + RINOK(_outFileStreamSpec->Seek((Int64)_position, STREAM_SEEK_SET, NULL)); + } + outStreamLoc = outFileStream_Loc; + } // if not reprase + + _outFileStream = outFileStream_Loc; + + needExit = false; + return S_OK; +} + + + + + + +STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) +{ + COM_TRY_BEGIN + + *outStream = NULL; + + #ifndef _SFX + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + #endif + + _outFileStream.Release(); + _bufPtrSeqOutStream.Release(); + + _encrypted = false; + _position = 0; + _isSplit = false; + + _curSize = 0; + _curSizeDefined = false; + _fileLengthWasSet = false; + _fileLength_that_WasSet = 0; + _index = index; + + _diskFilePath.Empty(); + + _isRenamed = false; + // _fi.Clear(); + _is_SymLink_in_Data = false; + _is_SymLink_in_Data_Linux = false; + + _fileWasExtracted = false; + + #ifdef SUPPORT_LINKS + // _CopyFile_Path.Empty(); + _link.Clear(); + #endif + + IInArchive *archive = _arc->Archive; + + #ifndef _SFX + _item._use_baseParentFolder_mode = _use_baseParentFolder_mode; + if (_use_baseParentFolder_mode) + { + _item._baseParentFolder = (int)_baseParentFolder; + if (_pathMode == NExtract::NPathMode::kFullPaths || + _pathMode == NExtract::NPathMode::kAbsPaths) + _item._baseParentFolder = -1; + } + #endif // _SFX + + #ifdef SUPPORT_ALT_STREAMS + _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon; + #endif + + RINOK(_arc->GetItem(index, _item)); + + { + NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, kpidPosition, &prop)); + if (prop.vt != VT_EMPTY) + { + if (prop.vt != VT_UI8) + return E_FAIL; + _position = prop.uhVal.QuadPart; + _isSplit = true; + } + } + + #ifdef SUPPORT_LINKS + RINOK(ReadLink()); + #endif // SUPPORT_LINKS + + + RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + RINOK(GetUnpackSize()); + + #ifdef SUPPORT_ALT_STREAMS + if (!_ntOptions.AltStreams.Val && _item.IsAltStream) + return S_OK; + #endif // SUPPORT_ALT_STREAMS + + UStringVector &pathParts = _item.PathParts; + + if (_wildcardCensor) + { + if (!CensorNode_CheckPath(*_wildcardCensor, _item)) + return S_OK; + } + + #ifndef _SFX + if (_use_baseParentFolder_mode) + { + if (!pathParts.IsEmpty()) + { + unsigned numRemovePathParts = 0; + + #ifdef SUPPORT_ALT_STREAMS + if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream) + numRemovePathParts = pathParts.Size(); + else + #endif + if (_pathMode == NExtract::NPathMode::kNoPaths || + _pathMode == NExtract::NPathMode::kNoPathsAlt) + numRemovePathParts = pathParts.Size() - 1; + pathParts.DeleteFrontal(numRemovePathParts); + } + } + else + #endif // _SFX + { + if (pathParts.IsEmpty()) + { + if (_item.IsDir) + return S_OK; + /* + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream) + #endif + return E_FAIL; + */ + } + + unsigned numRemovePathParts = 0; + + switch (_pathMode) + { + case NExtract::NPathMode::kFullPaths: + case NExtract::NPathMode::kCurPaths: + { + if (_removePathParts.IsEmpty()) + break; + bool badPrefix = false; + + if (pathParts.Size() < _removePathParts.Size()) + badPrefix = true; + else + { + if (pathParts.Size() == _removePathParts.Size()) + { + if (_removePartsForAltStreams) + { + #ifdef SUPPORT_ALT_STREAMS + if (!_item.IsAltStream) + #endif + badPrefix = true; + } + else + { + if (!_item.MainIsDir) + badPrefix = true; + } + } + + if (!badPrefix) + FOR_VECTOR (i, _removePathParts) + { + if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) + { + badPrefix = true; + break; + } + } + } + + if (badPrefix) + { + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + return E_FAIL; + } + else + numRemovePathParts = _removePathParts.Size(); + break; + } + + case NExtract::NPathMode::kNoPaths: + { + if (!pathParts.IsEmpty()) + numRemovePathParts = pathParts.Size() - 1; + break; + } + case NExtract::NPathMode::kNoPathsAlt: + { + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) + numRemovePathParts = pathParts.Size(); + else + #endif + if (!pathParts.IsEmpty()) + numRemovePathParts = pathParts.Size() - 1; + break; + } + /* + case NExtract::NPathMode::kFullPaths: + case NExtract::NPathMode::kAbsPaths: + break; + */ + default: + break; + } + + pathParts.DeleteFrontal(numRemovePathParts); + } + + + #ifndef _SFX + + if (ExtractToStreamCallback) + { + if (!GetProp) + { + GetProp_Spec = new CGetProp; + GetProp = GetProp_Spec; + } + GetProp_Spec->Arc = _arc; + GetProp_Spec->IndexInArc = index; + UString name (MakePathFromParts(pathParts)); + + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) + { + if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt)) + name += ':'; + name += _item.AltStreamName; + } + #endif + + return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp); + } + + #endif // _SFX + + + CMyComPtr outStreamLoc; + + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) + { + if (_stdOutMode) + outStreamLoc = new CStdOutFileStream; + else + { + bool needExit = true; + RINOK(GetExtractStream(outStreamLoc, needExit)); + if (needExit) + return S_OK; + } + } + + #ifndef _SFX + if (_hashStream) + { + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract || + askExtractMode == NArchive::NExtract::NAskMode::kTest) + { + _hashStreamSpec->SetStream(outStreamLoc); + outStreamLoc = _hashStream; + _hashStreamSpec->Init(true); + _hashStreamWasUsed = true; + } + } + #endif // _SFX + + if (outStreamLoc) + { + /* + #ifdef SUPPORT_LINKS + if (!_CopyFile_Path.IsEmpty()) + { + RINOK(PrepareOperation(askExtractMode)); + RINOK(MyCopyFile(outStreamLoc)); + return SetOperationResult(NArchive::NExtract::NOperationResult::kOK); + } + if (_link.isCopyLink && _testMode) + return S_OK; + #endif + */ + *outStream = outStreamLoc.Detach(); + } + + return S_OK; + + COM_TRY_END +} + + + + + + + + + + + +STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) +{ + COM_TRY_BEGIN + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->PrepareOperation7(askExtractMode); + #endif + + _extractMode = false; + + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; + }; + + return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir), + askExtractMode, _isSplit ? &_position: 0); + + COM_TRY_END +} + + + + + +HRESULT CArchiveExtractCallback::CloseFile() +{ + if (!_outFileStream) + return S_OK; + + HRESULT hres = S_OK; + + const UInt64 processedSize = _outFileStreamSpec->ProcessedSize; + if (_fileLengthWasSet && _fileLength_that_WasSet > processedSize) + { + bool res = _outFileStreamSpec->File.SetLength(processedSize); + _fileLengthWasSet = res; + if (!res) + { + HRESULT hres2 = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path)); + if (hres == S_OK) + hres = hres2; + } + } + + _curSize = processedSize; + _curSizeDefined = true; + + // #ifdef _WIN32 + _outFileStreamSpec->SetTime( + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); + // #endif + + RINOK(_outFileStreamSpec->Close()); + _outFileStream.Release(); + return hres; +} + + +#ifdef SUPPORT_LINKS + + +HRESULT CArchiveExtractCallback::SetFromLinkPath( + const FString &fullProcessedPath, + const CLinkInfo &linkInfo, + bool &linkWasSet) +{ + linkWasSet = false; + if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink) + return S_OK; + + UString relatPath; + + /* if (linkInfo.isRelative) + linkInfo.linkPath is final link path that must be stored to file link field + else + linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath. + */ + + if (linkInfo.isRelative) + relatPath = GetDirPrefixOf(_item.Path); + relatPath += linkInfo.linkPath; + + if (!IsSafePath(relatPath)) + { + return SendMessageError2( + 0, // errorCode + "Dangerous link path was ignored", + us2fs(_item.Path), + us2fs(linkInfo.linkPath)); // us2fs(relatPath) + } + + FString existPath; + if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative) + { + if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) + { + RINOK(SendMessageError("Incorrect path", us2fs(relatPath))); + } + } + else + { + existPath = us2fs(linkInfo.linkPath); + // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr()); + } + + if (existPath.IsEmpty()) + return SendMessageError("Empty link", fullProcessedPath); + + if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */) + { + // if (linkInfo.isHardLink) + { + if (!MyCreateHardLink(fullProcessedPath, existPath)) + { + HRESULT errorCode = GetLastError_noZero_HRESULT(); + RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)); + } + linkWasSet = true; + return S_OK; + } + /* + // IsCopyLink + { + NFind::CFileInfo fi; + if (!fi.Find(existPath)) + { + RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath)); + } + else + { + if (_curSizeDefined && _curSize == fi.Size) + _CopyFile_Path = existPath; + else + { + RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); + } + // RINOK(MyCopyFile(existPath, fullProcessedPath)); + } + } + */ + } + + // is Symbolic link + + /* + if (_item.IsDir && !isRelative) + { + // Windows before Vista doesn't support symbolic links. + // we could convert such symbolic links to Junction Points + // isJunction = true; + // convertToAbs = true; + } + */ + + if (!_ntOptions.SymLinks_AllowDangerous.Val) + { + #ifdef _WIN32 + if (_item.IsDir) + #endif + if (linkInfo.isRelative) + { + CLinkLevelsInfo levelsInfo; + levelsInfo.Parse(linkInfo.linkPath); + if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute) + { + return SendMessageError2( + 0, // errorCode + "Dangerous symbolic link path was ignored", + us2fs(_item.Path), + us2fs(linkInfo.linkPath)); + } + } + } + + + #ifdef _WIN32 + + CByteBuffer data; + // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr()); + if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL)) + return SendMessageError("Cannot fill link data", us2fs(_item.Path)); + + /* + if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) + { + SendMessageError("reconstructed Reparse is different", fs2us(existPath)); + } + */ + + CReparseAttr attr; + if (!attr.Parse(data, data.Size())) + { + RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))); + return S_OK; + } + if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) + { + RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); + return S_OK; + } + linkWasSet = true; + + return S_OK; + + + #else // ! _WIN32 + + if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath)) + { + RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)); + return S_OK; + } + linkWasSet = true; + + return S_OK; + + #endif // ! _WIN32 +} + + +bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) +{ + // this->isLinux = isLinuxData; + + if (isLinuxData) + { + isJunction = false; + isHardLink = false; + AString utf; + if (dataSize >= (1 << 12)) + return false; + utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); + UString u; + if (!ConvertUTF8ToUnicode(utf, u)) + return false; + linkPath = u; + + // in linux symbolic data: we expect that linux separator '/' is used + // if windows link was created, then we also must use linux separator + if (u.IsEmpty()) + return false; + wchar_t c = u[0]; + isRelative = !IS_PATH_SEPAR(c); + return true; + } + + CReparseAttr reparse; + if (!reparse.Parse(data, dataSize)) + return false; + isHardLink = false; + // isCopyLink = false; + linkPath = reparse.GetPath(); + isJunction = reparse.IsMountPoint(); + + if (reparse.IsSymLink_WSL()) + { + isWSL = true; + isRelative = reparse.IsRelative_WSL(); + } + else + isRelative = reparse.IsRelative_Win(); + + // FIXME !!! + #ifndef _WIN32 + linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + #endif + + return true; +} + +#endif // SUPPORT_LINKS + + +HRESULT CArchiveExtractCallback::CloseReparseAndFile() +{ + HRESULT res = S_OK; + + #ifdef SUPPORT_LINKS + + size_t reparseSize = 0; + bool repraseMode = false; + bool needSetReparse = false; + CLinkInfo linkInfo; + + if (_bufPtrSeqOutStream) + { + repraseMode = true; + reparseSize = _bufPtrSeqOutStream_Spec->GetPos(); + if (_curSizeDefined && reparseSize == _outMemBuf.Size()) + { + /* + CReparseAttr reparse; + DWORD errorCode = 0; + needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); + if (needSetReparse) + { + UString linkPath = reparse.GetPath(); + #ifndef _WIN32 + linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); + #endif + } + */ + needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux); + if (!needSetReparse) + res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); + } + else + { + res = SendMessageError_with_LastError("Unknown reparse stream", us2fs(_item.Path)); + } + if (!needSetReparse && _outFileStream) + { + HRESULT res2 = WriteStream(_outFileStream, _outMemBuf, reparseSize); + if (res == S_OK) + res = res2; + } + _bufPtrSeqOutStream.Release(); + } + + #endif // SUPPORT_LINKS + + + HRESULT res2 = CloseFile(); + + if (res == S_OK) + res = res2; + + RINOK(res); + + #ifdef SUPPORT_LINKS + if (repraseMode) + { + _curSize = reparseSize; + _curSizeDefined = true; + + #ifdef SUPPORT_LINKS + if (needSetReparse) + { + // in Linux : we must delete empty file before symbolic link creation + // in Windows : we can create symbolic link even without file deleting + if (!DeleteFileAlways(_diskFilePath)) + { + RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)); + } + { + bool linkWasSet = false; + RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)); + if (!linkWasSet) + _fileWasExtracted = false; + } + /* + if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) + { + res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath); + } + */ + } + #endif + } + #endif + return res; +} + + + +STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) +{ + COM_TRY_BEGIN + + #ifndef _SFX + if (ExtractToStreamCallback) + return ExtractToStreamCallback->SetOperationResult7(opRes, BoolToInt(_encrypted)); + #endif + + #ifndef _SFX + + if (_hashStreamWasUsed) + { + _hashStreamSpec->_hash->Final(_item.IsDir, + #ifdef SUPPORT_ALT_STREAMS + _item.IsAltStream + #else + false + #endif + , _item.Path); + _curSize = _hashStreamSpec->GetSize(); + _curSizeDefined = true; + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + } + + #endif // _SFX + + RINOK(CloseReparseAndFile()); + + #ifdef _USE_SECURITY_CODE + if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) + { + const void *data; + UInt32 dataSize; + UInt32 propType; + _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); + if (dataSize != 0) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + if (CheckNtSecure((const Byte *)data, dataSize)) + { + SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); + } + } + } + #endif // _USE_SECURITY_CODE + + if (!_curSizeDefined) + GetUnpackSize(); + + if (_curSizeDefined) + { + #ifdef SUPPORT_ALT_STREAMS + if (_item.IsAltStream) + AltStreams_UnpackSize += _curSize; + else + #endif + UnpackSize += _curSize; + } + + if (_item.IsDir) + NumFolders++; + #ifdef SUPPORT_ALT_STREAMS + else if (_item.IsAltStream) + NumAltStreams++; + #endif + else + NumFiles++; + + if (_fileWasExtracted) + if (!_stdOutMode && _extractMode && _fi.AttribDefined) + { + bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); + if (!res) + { + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); + } + } + + RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); + + return S_OK; + + COM_TRY_END +} + + + +STDMETHODIMP CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes) +{ + if (_folderArchiveExtractCallback2) + { + bool isEncrypted = false; + UString s; + + if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1) + { + CReadArcItem item; + RINOK(_arc->GetItem(index, item)); + s = item.Path; + RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted)); + } + else + { + s = '#'; + s.Add_UInt32(index); + // if (indexType == NArchive::NEventIndexType::kBlockIndex) {} + } + + return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s); + } + + return S_OK; +} + + +STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (!_cryptoGetTextPassword) + { + RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, + &_cryptoGetTextPassword)); + } + return _cryptoGetTextPassword->CryptoGetTextPassword(password); + COM_TRY_END +} + + +void CDirPathSortPair::SetNumSlashes(const FChar *s) +{ + for (unsigned numSlashes = 0;;) + { + FChar c = *s++; + if (c == 0) + { + Len = numSlashes; + return; + } + if (IS_PATH_SEPAR(c)) + numSlashes++; + } +} + + +bool CDirPathTime::SetDirTime() const +{ + return NDir::SetDirTime(Path, + CTimeDefined ? &CTime : NULL, + ATimeDefined ? &ATime : NULL, + MTimeDefined ? &MTime : NULL); +} + + +HRESULT CArchiveExtractCallback::SetDirsTimes() +{ + if (!_arc) + return S_OK; + + CRecordVector pairs; + pairs.ClearAndSetSize(_extractedFolders.Size()); + unsigned i; + + for (i = 0; i < _extractedFolders.Size(); i++) + { + CDirPathSortPair &pair = pairs[i]; + pair.Index = i; + pair.SetNumSlashes(_extractedFolders[i].Path); + } + + pairs.Sort2(); + + HRESULT res = S_OK; + + for (i = 0; i < pairs.Size(); i++) + { + const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; + if (!dpt.SetDirTime()) + { + // result = E_FAIL; + // do we need error message here in Windows and in posix? + // SendMessageError_with_LastError("Cannot set directory time", dpt.Path); + } + } + + /* + #ifndef _WIN32 + for (i = 0; i < _delayedSymLinks.Size(); i++) + { + const CDelayedSymLink &link = _delayedSymLinks[i]; + if (!link.Create()) + { + if (res == S_OK) + res = GetLastError_noZero_HRESULT(); + // res = E_FAIL; + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot create Symbolic Link", link._source); + } + } + #endif // _WIN32 + */ + + ClearExtractedDirsInfo(); + return res; +} + + +HRESULT CArchiveExtractCallback::CloseArc() +{ + HRESULT res = CloseReparseAndFile(); + HRESULT res2 = SetDirsTimes(); + if (res == S_OK) + res = res2; + _arc = NULL; + return res; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.h new file mode 100644 index 0000000..25eb644 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -0,0 +1,500 @@ +// ArchiveExtractCallback.h + +#ifndef __ARCHIVE_EXTRACT_CALLBACK_H +#define __ARCHIVE_EXTRACT_CALLBACK_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyLinux.h" +#include "../../../Common/Wildcard.h" + +#include "../../IPassword.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "../../Archive/IArchive.h" + +#include "ExtractMode.h" +#include "IFileExtractCallback.h" +#include "OpenArchive.h" + +#include "HashCalc.h" + +#ifndef _SFX + +class COutStreamWithHash: + public ISequentialOutStream, + public CMyUnknownImp +{ + CMyComPtr _stream; + UInt64 _size; + bool _calculate; +public: + IHashCalc *_hash; + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init(bool calculate = true) + { + InitCRC(); + _size = 0; + _calculate = calculate; + } + void EnableCalc(bool calculate) { _calculate = calculate; } + void InitCRC() { _hash->InitForNewFile(); } + UInt64 GetSize() const { return _size; } +}; + +#endif + +struct CExtractNtOptions +{ + CBoolPair NtSecurity; + CBoolPair SymLinks; + CBoolPair SymLinks_AllowDangerous; + CBoolPair HardLinks; + CBoolPair AltStreams; + bool ReplaceColonForAltStream; + bool WriteToAltStreamIfColon; + + bool PreAllocateOutFile; + + CExtractNtOptions(): + ReplaceColonForAltStream(false), + WriteToAltStreamIfColon(false) + { + SymLinks.Val = true; + SymLinks_AllowDangerous.Val = false; + HardLinks.Val = true; + AltStreams.Val = true; + + PreAllocateOutFile = + #ifdef _WIN32 + true; + #else + false; + #endif + } +}; + +#ifndef _SFX + +class CGetProp: + public IGetProp, + public CMyUnknownImp +{ +public: + const CArc *Arc; + UInt32 IndexInArc; + // UString Name; // relative path + + MY_UNKNOWN_IMP1(IGetProp) + INTERFACE_IGetProp(;) +}; + +#endif + +#ifndef _SFX +#ifndef UNDER_CE + +#define SUPPORT_LINKS + +#endif +#endif + + +#ifdef SUPPORT_LINKS + +struct CHardLinkNode +{ + UInt64 StreamId; + UInt64 INode; + + int Compare(const CHardLinkNode &a) const; +}; + +class CHardLinks +{ +public: + CRecordVector IDs; + CObjectVector Links; + + void Clear() + { + IDs.Clear(); + Links.Clear(); + } + + void PrepareLinks() + { + while (Links.Size() < IDs.Size()) + Links.AddNew(); + } +}; + +#endif + +#ifdef SUPPORT_ALT_STREAMS + +struct CIndexToPathPair +{ + UInt32 Index; + FString Path; + + CIndexToPathPair(UInt32 index): Index(index) {} + CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {} + + int Compare(const CIndexToPathPair &pair) const + { + return MyCompare(Index, pair.Index); + } +}; + +#endif + + + +struct CDirPathTime +{ + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + + FString Path; + + bool SetDirTime() const; +}; + + +#ifdef SUPPORT_LINKS + +struct CLinkInfo +{ + // bool isCopyLink; + bool isHardLink; + bool isJunction; + bool isRelative; + bool isWSL; + UString linkPath; + + void Clear() + { + // IsCopyLink = false; + isHardLink = false; + isJunction = false; + isRelative = false; + isWSL = false; + linkPath.Empty(); + } + + bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); +}; + +#endif // SUPPORT_LINKS + + +class CArchiveExtractCallback: + public IArchiveExtractCallback, + public IArchiveExtractCallbackMessage, + public ICryptoGetTextPassword, + public ICompressProgressInfo, + public CMyUnknownImp +{ + const CArc *_arc; + CExtractNtOptions _ntOptions; + + const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) + CMyComPtr _extractCallback2; + CMyComPtr _compressProgress; + CMyComPtr _cryptoGetTextPassword; + CMyComPtr _callbackMessage; + CMyComPtr _folderArchiveExtractCallback2; + + FString _dirPathPrefix; + FString _dirPathPrefix_Full; + NExtract::NPathMode::EEnum _pathMode; + NExtract::NOverwriteMode::EEnum _overwriteMode; + bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; + + #ifndef _SFX + + CMyComPtr ExtractToStreamCallback; + CGetProp *GetProp_Spec; + CMyComPtr GetProp; + + #endif + + CReadArcItem _item; + FString _diskFilePath; + UInt64 _position; + bool _isSplit; + + bool _extractMode; + + bool WriteCTime; + bool WriteATime; + bool WriteMTime; + + bool _encrypted; + + struct CProcessedFileInfo + { + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + UInt32 Attrib; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool AttribDefined; + + bool IsReparse() const + { + return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); + } + + bool IsLinuxSymLink() const + { + return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16)); + } + + void SetFromPosixAttrib(UInt32 a) + { + // here we set only part of combined attribute required by SetFileAttrib() call + #ifdef _WIN32 + // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. + Attrib = MY_LIN_S_ISDIR(a) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((a & 0222) == 0) // (& S_IWUSR) in p7zip + Attrib |= FILE_ATTRIBUTE_READONLY; + #else + Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; + #endif + AttribDefined = true; + } + } _fi; + + bool _is_SymLink_in_Data; + bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX + + bool _fileWasExtracted; + + UInt32 _index; + UInt64 _curSize; + bool _curSizeDefined; + bool _fileLengthWasSet; + UInt64 _fileLength_that_WasSet; + + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; + + CByteBuffer _outMemBuf; + CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; + CMyComPtr _bufPtrSeqOutStream; + + + #ifndef _SFX + + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + bool _hashStreamWasUsed; + + #endif + + bool _removePartsForAltStreams; + UStringVector _removePathParts; + + #ifndef _SFX + bool _use_baseParentFolder_mode; + UInt32 _baseParentFolder; + #endif + + bool _stdOutMode; + bool _testMode; + bool _multiArchives; + + CMyComPtr _localProgress; + UInt64 _packTotal; + + UInt64 _progressTotal; + bool _progressTotal_Defined; + + CObjectVector _extractedFolders; + + #ifndef _WIN32 + // CObjectVector _delayedSymLinks; + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX) + bool _saclEnabled; + #endif + + void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); + HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); + HRESULT GetUnpackSize(); + + HRESULT SendMessageError(const char *message, const FString &path); + HRESULT SendMessageError_with_LastError(const char *message, const FString &path); + HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); + +public: + + CLocalProgress *LocalProgressSpec; + + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 NumAltStreams; + UInt64 UnpackSize; + UInt64 AltStreams_UnpackSize; + + MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo) + + INTERFACE_IArchiveExtractCallback(;) + INTERFACE_IArchiveExtractCallbackMessage(;) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + CArchiveExtractCallback(); + + void InitForMulti(bool multiArchives, + NExtract::NPathMode::EEnum pathMode, + NExtract::NOverwriteMode::EEnum overwriteMode, + bool keepAndReplaceEmptyDirPrefixes) + { + _multiArchives = multiArchives; + _pathMode = pathMode; + _overwriteMode = overwriteMode; + _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; + NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; + } + + #ifndef _SFX + + void SetHashMethods(IHashCalc *hash) + { + if (!hash) + return; + _hashStreamSpec = new COutStreamWithHash; + _hashStream = _hashStreamSpec; + _hashStreamSpec->_hash = hash; + } + + #endif + + void Init( + const CExtractNtOptions &ntOptions, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, + IFolderArchiveExtractCallback *extractCallback2, + bool stdOutMode, bool testMode, + const FString &directoryPath, + const UStringVector &removePathParts, bool removePartsForAltStreams, + UInt64 packSize); + + + #ifdef SUPPORT_LINKS + +private: + CHardLinks _hardLinks; + CLinkInfo _link; + + // FString _CopyFile_Path; + // HRESULT MyCopyFile(ISequentialOutStream *outStream); + HRESULT Link(const FString &fullProcessedPath); + HRESULT ReadLink(); + +public: + // call PrepareHardLinks() after Init() + HRESULT PrepareHardLinks(const CRecordVector *realIndices); // NULL means all items + + #endif + + + #ifdef SUPPORT_ALT_STREAMS + CObjectVector _renamedFiles; + #endif + + // call it after Init() + + #ifndef _SFX + void SetBaseParentFolderIndex(UInt32 indexInArc) + { + _baseParentFolder = indexInArc; + _use_baseParentFolder_mode = true; + } + #endif + + HRESULT CloseArc(); + +private: + void ClearExtractedDirsInfo() + { + _extractedFolders.Clear(); + #ifndef _WIN32 + // _delayedSymLinks.Clear(); + #endif + } + + HRESULT Read_fi_Props(); + void CorrectPathParts(); + void CreateFolders(); + + bool _isRenamed; + HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); + HRESULT GetExtractStream(CMyComPtr &outStreamLoc, bool &needExit); + + HRESULT CloseFile(); + HRESULT CloseReparseAndFile(); + HRESULT CloseReparseAndFile2(); + HRESULT SetDirsTimes(); + + const void *NtReparse_Data; + UInt32 NtReparse_Size; + + #ifdef SUPPORT_LINKS + HRESULT SetFromLinkPath( + const FString &fullProcessedPath, + const CLinkInfo &linkInfo, + bool &linkWasSet); + #endif +}; + + +struct CArchiveExtractCallback_Closer +{ + CArchiveExtractCallback *_ref; + + CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {} + + HRESULT Close() + { + HRESULT res = S_OK; + if (_ref) + { + res = _ref->CloseArc(); + _ref = NULL; + } + return res; + } + + ~CArchiveExtractCallback_Closer() + { + Close(); + } +}; + + +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.cpp new file mode 100644 index 0000000..1baf3e1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.cpp @@ -0,0 +1,155 @@ +// ArchiveName.cpp + +#include "StdAfx.h" + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" + +#include "ExtractingFilePath.h" +#include "ArchiveName.h" + +using namespace NWindows; +using namespace NFile; + +static UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName) +{ + FString resultName = fi.Name; + if (!fi.IsDir() && !keepName) + { + int dotPos = resultName.ReverseFind_Dot(); + if (dotPos > 0) + { + FString archiveName2 = resultName.Left((unsigned)dotPos); + if (archiveName2.ReverseFind_Dot() < 0) + resultName = archiveName2; + } + } + return Get_Correct_FsFile_Name(fs2us(resultName)); +} + +static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName) +{ + FString resultName ("Archive"); + if (fromPrev) + { + FString dirPrefix; + if (NDir::GetOnlyDirPrefix(path, dirPrefix)) + { + if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back())) + { + #if defined(_WIN32) && !defined(UNDER_CE) + if (NName::IsDriveRootPath_SuperAllowed(dirPrefix)) + resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter + else + #endif + { + dirPrefix.DeleteBack(); + NFind::CFileInfo fi; + if (fi.Find(dirPrefix)) + resultName = fi.Name; + } + } + } + } + else + { + NFind::CFileInfo fi; + if (fi.Find(path)) + { + resultName = fi.Name; + if (!fi.IsDir() && !keepName) + { + int dotPos = resultName.ReverseFind_Dot(); + if (dotPos > 0) + { + FString name2 = resultName.Left((unsigned)dotPos); + if (name2.ReverseFind_Dot() < 0) + resultName = name2; + } + } + } + } + return resultName; +} + + +UString CreateArchiveName(const UStringVector &paths, const NFind::CFileInfo *fi) +{ + bool keepName = false; + /* + if (paths.Size() == 1) + { + const UString &name = paths[0]; + if (name.Len() > 4) + if (CompareFileNames(name.RightPtr(4), L".tar") == 0) + keepName = true; + } + */ + + UString name; + if (fi) + name = CreateArchiveName(*fi, keepName); + else + { + if (paths.IsEmpty()) + return L"archive"; + bool fromPrev = (paths.Size() > 1); + name = Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(paths.Front()), fromPrev, keepName))); + } + + UStringVector names; + + { + FOR_VECTOR (i, paths) + { + NFind::CFileInfo fi2; + const NFind::CFileInfo *fp; + if (fi && paths.Size() == 1) + fp = fi; + else + { + if (!fi2.Find(us2fs(paths[i]))) + continue; + fp = &fi2; + } + names.Add(fs2us(fp->Name)); + } + } + + UString postfix; + UInt32 index = 1; + + for (;;) + { + // we don't want cases when we include archive to itself. + // so we find first available name for archive + const UString name2 = name + postfix; + const UString name2_zip = name2 + L".zip"; + const UString name2_7z = name2 + L".7z"; + const UString name2_tar = name2 + L".tar"; + const UString name2_wim = name2 + L".wim"; + + unsigned i = 0; + + for (i = 0; i < names.Size(); i++) + { + const UString &fname = names[i]; + if ( 0 == CompareFileNames(fname, name2_zip) + || 0 == CompareFileNames(fname, name2_7z) + || 0 == CompareFileNames(fname, name2_tar) + || 0 == CompareFileNames(fname, name2_wim)) + break; + } + + if (i == names.Size()) + break; + index++; + postfix = "_"; + postfix.Add_UInt32(index); + } + + name += postfix; + return name; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.h new file mode 100644 index 0000000..0d32645 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveName.h @@ -0,0 +1,10 @@ +// ArchiveName.h + +#ifndef __ARCHIVE_NAME_H +#define __ARCHIVE_NAME_H + +#include "../../../Windows/FileFind.h" + +UString CreateArchiveName(const UStringVector &paths, const NWindows::NFile::NFind::CFileInfo *fi = NULL); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp new file mode 100644 index 0000000..d3e0d3c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -0,0 +1,158 @@ +// ArchiveOpenCallback.cpp + +#include "StdAfx.h" + +#include "../../../Common/ComTry.h" + +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" + +#include "../../Common/FileStreams.h" + +#include "ArchiveOpenCallback.h" + +using namespace NWindows; + +STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) +{ + COM_TRY_BEGIN + if (ReOpenCallback) + return ReOpenCallback->SetTotal(files, bytes); + if (!Callback) + return S_OK; + return Callback->Open_SetTotal(files, bytes); + COM_TRY_END +} + +STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) +{ + COM_TRY_BEGIN + if (ReOpenCallback) + return ReOpenCallback->SetCompleted(files, bytes); + if (!Callback) + return S_OK; + return Callback->Open_SetCompleted(files, bytes); + COM_TRY_END +} + +STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + if (_subArchiveMode) + switch (propID) + { + case kpidName: prop = _subArchiveName; break; + // case kpidSize: prop = _subArchiveSize; break; // we don't use it now + } + else + switch (propID) + { + case kpidName: prop = _fileInfo.Name; break; + case kpidIsDir: prop = _fileInfo.IsDir(); break; + case kpidSize: prop = _fileInfo.Size; break; + case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; + case kpidCTime: prop = _fileInfo.CTime; break; + case kpidATime: prop = _fileInfo.ATime; break; + case kpidMTime: prop = _fileInfo.MTime; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +struct CInFileStreamVol: public CInFileStream +{ + unsigned FileNameIndex; + COpenCallbackImp *OpenCallbackImp; + CMyComPtr OpenCallbackRef; + + ~CInFileStreamVol() + { + if (OpenCallbackRef) + OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false; + } +}; + + +// from ArchiveExtractCallback.cpp +bool IsSafePath(const UString &path); + +STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) +{ + COM_TRY_BEGIN + *inStream = NULL; + + if (_subArchiveMode) + return S_FALSE; + if (Callback) + { + RINOK(Callback->Open_CheckBreak()); + } + + UString name2 = name; + + + #ifndef _SFX + + #ifdef _WIN32 + name2.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + + // if (!allowAbsVolPaths) + if (!IsSafePath(name2)) + return S_FALSE; + + // #ifdef _WIN32 + // we don't want to support wildcards in names here here + if (name2.Find(L'?') >= 0 || + name2.Find(L'*') >= 0) + return S_FALSE; + // #endif + + #endif + + + FString fullPath; + if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath)) + return S_FALSE; + if (!_fileInfo.Find_FollowLink(fullPath)) + return S_FALSE; + if (_fileInfo.IsDir()) + return S_FALSE; + CInFileStreamVol *inFile = new CInFileStreamVol; + CMyComPtr inStreamTemp = inFile; + if (!inFile->Open(fullPath)) + { + return GetLastError_noZero_HRESULT(); + } + + FileSizes.Add(_fileInfo.Size); + FileNames.Add(name2); + inFile->FileNameIndex = FileNames_WasUsed.Add(true); + inFile->OpenCallbackImp = this; + inFile->OpenCallbackRef = this; + // TotalSize += _fileInfo.Size; + *inStream = inStreamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +#ifndef _NO_CRYPTO +STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (ReOpenCallback) + { + CMyComPtr getTextPassword; + ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); + if (getTextPassword) + return getTextPassword->CryptoGetTextPassword(password); + } + if (!Callback) + return E_NOTIMPL; + PasswordWasAsked = true; + return Callback->Open_CryptoGetTextPassword(password); + COM_TRY_END +} +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.h new file mode 100644 index 0000000..46b2676 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -0,0 +1,117 @@ +// ArchiveOpenCallback.h + +#ifndef __ARCHIVE_OPEN_CALLBACK_H +#define __ARCHIVE_OPEN_CALLBACK_H + +#include "../../../Common/MyCom.h" + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileIO.h" + +#ifndef _NO_CRYPTO +#include "../../IPassword.h" +#endif +#include "../../Archive/IArchive.h" + +#ifdef _NO_CRYPTO + +#define INTERFACE_IOpenCallbackUI_Crypto(x) + +#else + +#define INTERFACE_IOpenCallbackUI_Crypto(x) \ + virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ + /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \ + /* virtual bool Open_WasPasswordAsked() x; */ \ + /* virtual void Open_Clear_PasswordWasAsked_Flag() x; */ \ + +#endif + +#define INTERFACE_IOpenCallbackUI(x) \ + virtual HRESULT Open_CheckBreak() x; \ + virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ + virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ + virtual HRESULT Open_Finished() x; \ + INTERFACE_IOpenCallbackUI_Crypto(x) + +struct IOpenCallbackUI +{ + INTERFACE_IOpenCallbackUI(=0) +}; + +class COpenCallbackImp: + public IArchiveOpenCallback, + public IArchiveOpenVolumeCallback, + public IArchiveOpenSetSubArchiveName, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName) + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IArchiveOpenCallback(;) + INTERFACE_IArchiveOpenVolumeCallback(;) + + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif + + STDMETHOD(SetSubArchiveName(const wchar_t *name)) + { + _subArchiveMode = true; + _subArchiveName = name; + // TotalSize = 0; + return S_OK; + } + +private: + FString _folderPrefix; + NWindows::NFile::NFind::CFileInfo _fileInfo; + bool _subArchiveMode; + UString _subArchiveName; + +public: + UStringVector FileNames; + CBoolVector FileNames_WasUsed; + CRecordVector FileSizes; + + bool PasswordWasAsked; + + IOpenCallbackUI *Callback; + CMyComPtr ReOpenCallback; + // UInt64 TotalSize; + + COpenCallbackImp(): _subArchiveMode(false), Callback(NULL) {} + + HRESULT Init2(const FString &folderPrefix, const FString &fileName) + { + FileNames.Clear(); + FileNames_WasUsed.Clear(); + FileSizes.Clear(); + _subArchiveMode = false; + // TotalSize = 0; + PasswordWasAsked = false; + _folderPrefix = folderPrefix; + if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName)) + { + // throw 20121118; + return GetLastError_noZero_HRESULT(); + } + return S_OK; + } + + bool SetSecondFileInfo(CFSTR newName) + { + return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir(); + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.cpp new file mode 100644 index 0000000..fb4c172 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.cpp @@ -0,0 +1,4535 @@ +// Bench.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +// #include + +#ifndef _WIN32 + +#define USE_POSIX_TIME +#define USE_POSIX_TIME2 +#endif // _WIN32 + +#ifdef USE_POSIX_TIME +#include +#include +#ifdef USE_POSIX_TIME2 +#include +#include +#endif +#endif // USE_POSIX_TIME + +#ifdef _WIN32 +#define USE_ALLOCA +#endif + +#ifdef USE_ALLOCA +#ifdef _WIN32 +#include +#else +#include +#endif +#endif + +#include "../../../../C/7zCrc.h" +#include "../../../../C/RotateDefs.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" +#endif + +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/SystemInfo.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/MyBuffer2.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../Common/MethodProps.h" +#include "../../Common/StreamObjects.h" +#include "../../Common/StreamUtils.h" + +#include "Bench.h" + +using namespace NWindows; + +#ifndef _7ZIP_ST +static const UInt32 k_LZMA = 0x030101; +#endif + +static const UInt64 kComplexInCommands = (UInt64)1 << + #ifdef UNDER_CE + 31; + #else + 34; + #endif + +static const UInt32 kComplexInMs = 4000; + +static void SetComplexCommandsMs(UInt32 complexInMs, + bool isSpecifiedFreq, UInt64 cpuFreq, UInt64 &complexInCommands) +{ + complexInCommands = kComplexInCommands; + const UInt64 kMinFreq = (UInt64)1000000 * 4; + const UInt64 kMaxFreq = (UInt64)1000000 * 20000; + if (cpuFreq < kMinFreq && !isSpecifiedFreq) + cpuFreq = kMinFreq; + if (cpuFreq < kMaxFreq || isSpecifiedFreq) + { + if (complexInMs != 0) + complexInCommands = complexInMs * cpuFreq / 1000; + else + complexInCommands = cpuFreq >> 2; + } +} + +// const UInt64 kBenchmarkUsageMult = 1000000; // for debug +static const unsigned kBenchmarkUsageMultBits = 16; +static const UInt64 kBenchmarkUsageMult = 1 << kBenchmarkUsageMultBits; + +UInt64 Benchmark_GetUsage_Percents(UInt64 usage) +{ + return (100 * usage + kBenchmarkUsageMult / 2) / kBenchmarkUsageMult; +} + +static const unsigned kNumHashDictBits = 17; +static const UInt32 kFilterUnpackSize = (47 << 10); // + 5; // for test + +static const unsigned kOldLzmaDictBits = 32; + +// static const size_t kAdditionalSize = (size_t)1 << 32; // for debug +static const size_t kAdditionalSize = (size_t)1 << 16; +static const UInt32 kCompressedAdditionalSize = (1 << 10); + +static const UInt32 kMaxMethodPropSize = (1 << 6); + + +#define ALLOC_WITH_HRESULT(_buffer_, _size_) \ + { (_buffer_)->Alloc(_size_); \ + if (_size_ && !(_buffer_)->IsAllocated()) return E_OUTOFMEMORY; } + + +class CBaseRandomGenerator +{ + UInt32 A1; + UInt32 A2; + UInt32 Salt; +public: + CBaseRandomGenerator(UInt32 salt = 0): Salt(salt) { Init(); } + void Init() { A1 = 362436069; A2 = 521288629;} + MY_FORCE_INLINE + UInt32 GetRnd() + { + return Salt ^ + ( + ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ) + ); + } +}; + + +MY_NO_INLINE +static void RandGen(Byte *buf, size_t size) +{ + CBaseRandomGenerator RG; + const size_t size4 = size & ~((size_t)3); + size_t i; + for (i = 0; i < size4; i += 4) + { + const UInt32 v = RG.GetRnd(); + SetUi32(buf + i, v); + } + UInt32 v = RG.GetRnd(); + for (; i < size; i++) + { + buf[i] = (Byte)v; + v >>= 8; + } +} + + +class CBenchRandomGenerator: public CMidAlignedBuffer +{ + static UInt32 GetVal(UInt32 &res, unsigned numBits) + { + UInt32 val = res & (((UInt32)1 << numBits) - 1); + res >>= numBits; + return val; + } + + static UInt32 GetLen(UInt32 &r) + { + UInt32 len = GetVal(r, 2); + return GetVal(r, 1 + len); + } + +public: + + void GenerateSimpleRandom(UInt32 salt) + { + CBaseRandomGenerator rg(salt); + const size_t bufSize = Size(); + Byte *buf = (Byte *)*this; + for (size_t i = 0; i < bufSize; i++) + buf[i] = (Byte)rg.GetRnd(); + } + + void GenerateLz(unsigned dictBits, UInt32 salt) + { + CBaseRandomGenerator rg(salt); + size_t pos = 0; + size_t rep0 = 1; + const size_t bufSize = Size(); + Byte *buf = (Byte *)*this; + unsigned posBits = 1; + + // printf("\n dictBits = %d\n", (UInt32)dictBits); + // printf("\n bufSize = 0x%p\n", (const void *)bufSize); + + while (pos < bufSize) + { + /* + if (pos >= ((UInt32)1 << 31)) + printf(" %x\n", pos); + */ + UInt32 r = rg.GetRnd(); + if (GetVal(r, 1) == 0 || pos < 1024) + buf[pos++] = (Byte)(r & 0xFF); + else + { + UInt32 len; + len = 1 + GetLen(r); + + if (GetVal(r, 3) != 0) + { + len += GetLen(r); + + while (((size_t)1 << posBits) < pos) + posBits++; + + unsigned numBitsMax = dictBits; + if (numBitsMax > posBits) + numBitsMax = posBits; + + const unsigned kAddBits = 6; + unsigned numLogBits = 5; + if (numBitsMax <= (1 << 4) - 1 + kAddBits) + numLogBits = 4; + + for (;;) + { + const UInt32 ppp = GetVal(r, numLogBits) + kAddBits; + r = rg.GetRnd(); + if (ppp > numBitsMax) + continue; + // rep0 = GetVal(r, ppp); + rep0 = r & (((size_t)1 << ppp) - 1); + if (rep0 < pos) + break; + r = rg.GetRnd(); + } + rep0++; + } + + // len *= 300; // for debug + { + const size_t rem = bufSize - pos; + if (len > rem) + len = (UInt32)rem; + } + Byte *dest = buf + pos; + const Byte *src = dest - rep0; + pos += len; + for (UInt32 i = 0; i < len; i++) + *dest++ = *src++; + } + } + // printf("\n CRC = %x\n", CrcCalc(buf, bufSize)); + } +}; + + +class CBenchmarkInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + const Byte *Data; + size_t Pos; + size_t Size; + +public: + MY_UNKNOWN_IMP + void Init(const Byte *data, size_t size) + { + Data = data; + Size = size; + Pos = 0; + } + bool WasFinished() const { return Pos == Size; } + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + const UInt32 kMaxBlockSize = (1 << 20); + if (size > kMaxBlockSize) + size = kMaxBlockSize; + const size_t remain = Size - Pos; + if (size > remain) + size = (UInt32)remain; + + if (size != 0) + memcpy(data, Data + Pos, size); + + Pos += size; + if (processedSize) + *processedSize = size; + return S_OK; +} + +class CBenchmarkOutStream: + public ISequentialOutStream, + public CMidAlignedBuffer, + public CMyUnknownImp +{ + // bool _overflow; +public: + size_t Pos; + bool RealCopy; + bool CalcCrc; + UInt32 Crc; + + // CBenchmarkOutStream(): _overflow(false) {} + void Init(bool realCopy, bool calcCrc) + { + Crc = CRC_INIT_VAL; + RealCopy = realCopy; + CalcCrc = calcCrc; + // _overflow = false; + Pos = 0; + } + + void InitCrc() + { + Crc = CRC_INIT_VAL; + } + + void Calc(const void *data, size_t size) + { + Crc = CrcUpdate(Crc, data, size); + } + + size_t GetPos() const { return Pos; } + + // void Print() { printf("\n%8d %8d\n", (unsigned)BufferSize, (unsigned)Pos); } + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t curSize = Size() - Pos; + if (curSize > size) + curSize = size; + if (curSize != 0) + { + if (RealCopy) + memcpy(((Byte *)*this) + Pos, data, curSize); + if (CalcCrc) + Calc(data, curSize); + Pos += curSize; + } + if (processedSize) + *processedSize = (UInt32)curSize; + if (curSize != size) + { + // _overflow = true; + return E_FAIL; + } + return S_OK; +} + + +class CCrcOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + bool CalcCrc; + UInt32 Crc; + UInt64 Pos; + + MY_UNKNOWN_IMP + + CCrcOutStream(): CalcCrc(true) {}; + void Init() { Crc = CRC_INIT_VAL; Pos = 0; } + void Calc(const void *data, size_t size) + { + Crc = CrcUpdate(Crc, data, size); + } + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (CalcCrc) + Calc(data, size); + Pos += size; + if (processedSize) + *processedSize = size; + return S_OK; +} + +// #include "../../../../C/My_sys_time.h" + +static UInt64 GetTimeCount() +{ + #ifdef USE_POSIX_TIME + #ifdef USE_POSIX_TIME2 + timeval v; + if (gettimeofday(&v, 0) == 0) + return (UInt64)(v.tv_sec) * 1000000 + (UInt64)v.tv_usec; + return (UInt64)time(NULL) * 1000000; + #else + return time(NULL); + #endif + #else + LARGE_INTEGER value; + if (::QueryPerformanceCounter(&value)) + return (UInt64)value.QuadPart; + return GetTickCount(); + #endif +} + +static UInt64 GetFreq() +{ + #ifdef USE_POSIX_TIME + #ifdef USE_POSIX_TIME2 + return 1000000; + #else + return 1; + #endif + #else + LARGE_INTEGER value; + if (::QueryPerformanceFrequency(&value)) + return (UInt64)value.QuadPart; + return 1000; + #endif +} + + +#ifdef USE_POSIX_TIME + +struct CUserTime +{ + UInt64 Sum; + clock_t Prev; + + void Init() + { + // Prev = clock(); + Sum = 0; + Prev = 0; + Update(); + Sum = 0; + } + + void Update() + { + tms t; + /* clock_t res = */ times(&t); + clock_t newVal = t.tms_utime + t.tms_stime; + Sum += (UInt64)(newVal - Prev); + Prev = newVal; + + /* + clock_t v = clock(); + if (v != -1) + { + Sum += v - Prev; + Prev = v; + } + */ + } + UInt64 GetUserTime() + { + Update(); + return Sum; + } +}; + +#else + + +struct CUserTime +{ + bool UseTick; + DWORD Prev_Tick; + UInt64 Prev; + UInt64 Sum; + + void Init() + { + UseTick = false; + Prev_Tick = 0; + Prev = 0; + Sum = 0; + Update(); + Sum = 0; + } + UInt64 GetUserTime() + { + Update(); + return Sum; + } + void Update(); +}; + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +void CUserTime::Update() +{ + DWORD new_Tick = GetTickCount(); + FILETIME creationTime, exitTime, kernelTime, userTime; + if (!UseTick && + #ifdef UNDER_CE + ::GetThreadTimes(::GetCurrentThread() + #else + ::GetProcessTimes(::GetCurrentProcess() + #endif + , &creationTime, &exitTime, &kernelTime, &userTime)) + { + UInt64 newVal = GetTime64(userTime) + GetTime64(kernelTime); + Sum += newVal - Prev; + Prev = newVal; + } + else + { + UseTick = true; + Sum += (UInt64)(new_Tick - (DWORD)Prev_Tick) * 10000; + } + Prev_Tick = new_Tick; +} + + +#endif + +static UInt64 GetUserFreq() +{ + #ifdef USE_POSIX_TIME + // return CLOCKS_PER_SEC; + return (UInt64)sysconf(_SC_CLK_TCK); + #else + return 10000000; + #endif +} + +class CBenchProgressStatus +{ + #ifndef _7ZIP_ST + NSynchronization::CCriticalSection CS; + #endif +public: + HRESULT Res; + bool EncodeMode; + void SetResult(HRESULT res) + { + #ifndef _7ZIP_ST + NSynchronization::CCriticalSectionLock lock(CS); + #endif + Res = res; + } + HRESULT GetResult() + { + #ifndef _7ZIP_ST + NSynchronization::CCriticalSectionLock lock(CS); + #endif + return Res; + } +}; + +struct CBenchInfoCalc +{ + CBenchInfo BenchInfo; + CUserTime UserTime; + + void SetStartTime(); + void SetFinishTime(CBenchInfo &dest); +}; + +void CBenchInfoCalc::SetStartTime() +{ + BenchInfo.GlobalFreq = GetFreq(); + BenchInfo.UserFreq = GetUserFreq(); + BenchInfo.GlobalTime = ::GetTimeCount(); + BenchInfo.UserTime = 0; + UserTime.Init(); +} + +void CBenchInfoCalc::SetFinishTime(CBenchInfo &dest) +{ + dest = BenchInfo; + dest.GlobalTime = ::GetTimeCount() - BenchInfo.GlobalTime; + dest.UserTime = UserTime.GetUserTime(); +} + +class CBenchProgressInfo: + public ICompressProgressInfo, + public CMyUnknownImp, + public CBenchInfoCalc +{ +public: + CBenchProgressStatus *Status; + IBenchCallback *Callback; + + CBenchProgressInfo(): Callback(NULL) {} + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + + +STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + HRESULT res = Status->GetResult(); + if (res != S_OK) + return res; + if (!Callback) + return res; + + /* + static UInt64 inSizePrev = 0; + static UInt64 outSizePrev = 0; + UInt64 delta1 = 0, delta2 = 0, val1 = 0, val2 = 0; + if (inSize) { val1 = *inSize; delta1 = val1 - inSizePrev; inSizePrev = val1; } + if (outSize) { val2 = *outSize; delta2 = val2 - outSizePrev; outSizePrev = val2; } + UInt64 percents = delta2 * 1000; + if (delta1 != 0) + percents /= delta1; + printf("=== %7d %7d %7d %7d ratio = %4d\n", + (unsigned)(val1 >> 10), (unsigned)(delta1 >> 10), + (unsigned)(val2 >> 10), (unsigned)(delta2 >> 10), + (unsigned)percents); + */ + + CBenchInfo info; + SetFinishTime(info); + if (Status->EncodeMode) + { + info.UnpackSize = BenchInfo.UnpackSize + *inSize; + info.PackSize = BenchInfo.PackSize + *outSize; + res = Callback->SetEncodeResult(info, false); + } + else + { + info.PackSize = BenchInfo.PackSize + *inSize; + info.UnpackSize = BenchInfo.UnpackSize + *outSize; + res = Callback->SetDecodeResult(info, false); + } + if (res != S_OK) + Status->SetResult(res); + return res; +} + +static const unsigned kSubBits = 8; + +static UInt32 GetLogSize(UInt64 size) +{ + if (size <= 1) + return 0; + unsigned i; + for (i = 2; i < 64; i++) + if (size < ((UInt64)1 << i)) + break; + i--; + UInt32 v; + if (i <= kSubBits) + v = (UInt32)(size) << (kSubBits - i); + else + v = (UInt32)(size >> (i - kSubBits)); + return ((UInt32)i << kSubBits) + (v & (((UInt32)1 << kSubBits) - 1)); +} + +static void NormalizeVals(UInt64 &v1, UInt64 &v2) +{ + while (v1 >= ((UInt32)1 << ((64 - kBenchmarkUsageMultBits) / 2))) + { + v1 >>= 1; + v2 >>= 1; + } +} + +UInt64 CBenchInfo::GetUsage() const +{ + UInt64 userTime = UserTime; + UInt64 userFreq = UserFreq; + UInt64 globalTime = GlobalTime; + UInt64 globalFreq = GlobalFreq; + NormalizeVals(userTime, userFreq); + NormalizeVals(globalFreq, globalTime); + if (userFreq == 0) + userFreq = 1; + if (globalTime == 0) + globalTime = 1; + return userTime * globalFreq * kBenchmarkUsageMult / userFreq / globalTime; +} + +UInt64 CBenchInfo::GetRatingPerUsage(UInt64 rating) const +{ + UInt64 userTime = UserTime; + UInt64 userFreq = UserFreq; + UInt64 globalTime = GlobalTime; + UInt64 globalFreq = GlobalFreq; + NormalizeVals(userFreq, userTime); + NormalizeVals(globalTime, globalFreq); + if (globalFreq == 0) + globalFreq = 1; + if (userTime == 0) + { + return 0; + // userTime = 1; + } + return userFreq * globalTime / globalFreq * rating / userTime; +} + +static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) +{ + UInt64 elTime = elapsedTime; + NormalizeVals(freq, elTime); + if (elTime == 0) + elTime = 1; + return value * freq / elTime; +} + +UInt64 CBenchInfo::GetSpeed(UInt64 numUnits) const +{ + return MyMultDiv64(numUnits, GlobalTime, GlobalFreq); +} + +struct CBenchProps +{ + bool LzmaRatingMode; + + UInt32 EncComplex; + UInt32 DecComplexCompr; + UInt32 DecComplexUnc; + + unsigned KeySize; + + CBenchProps(): + LzmaRatingMode(false), + KeySize(0) + {} + + void SetLzmaCompexity(); + + UInt64 GeComprCommands(UInt64 unpackSize) + { + const UInt32 kMinSize = 100; + if (unpackSize < kMinSize) + unpackSize = kMinSize; + return unpackSize * EncComplex; + } + + UInt64 GeDecomprCommands(UInt64 packSize, UInt64 unpackSize) + { + return (packSize * DecComplexCompr + unpackSize * DecComplexUnc); + } + + UInt64 GetCompressRating(UInt64 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size); + UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations); +}; + +void CBenchProps::SetLzmaCompexity() +{ + EncComplex = 1200; + DecComplexUnc = 4; + DecComplexCompr = 190; + LzmaRatingMode = true; +} + +UInt64 CBenchProps::GetCompressRating(UInt64 dictSize, UInt64 elapsedTime, UInt64 freq, UInt64 size) +{ + if (dictSize < (1 << kBenchMinDicLogSize)) + dictSize = (1 << kBenchMinDicLogSize); + UInt64 encComplex = EncComplex; + if (LzmaRatingMode) + { + /* + for (UInt64 uu = 0; uu < (UInt64)0xf << 60;) + { + unsigned rr = GetLogSize(uu); + printf("\n%16I64x , log = %4x", uu, rr); + uu += 1; + uu += uu / 50; + } + */ + // throw 1; + const UInt32 t = GetLogSize(dictSize) - (kBenchMinDicLogSize << kSubBits); + encComplex = 870 + ((t * t * 5) >> (2 * kSubBits)); + } + const UInt64 numCommands = (UInt64)size * encComplex; + return MyMultDiv64(numCommands, elapsedTime, freq); +} + +UInt64 CBenchProps::GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt64 numIterations) +{ + const UInt64 numCommands = (inSize * DecComplexCompr + outSize * DecComplexUnc) * numIterations; + return MyMultDiv64(numCommands, elapsedTime, freq); +} + + + +UInt64 CBenchInfo::GetRating_LzmaEnc(UInt64 dictSize) const +{ + CBenchProps props; + props.SetLzmaCompexity(); + return props.GetCompressRating(dictSize, GlobalTime, GlobalFreq, UnpackSize * NumIterations); +} + +UInt64 CBenchInfo::GetRating_LzmaDec() const +{ + CBenchProps props; + props.SetLzmaCompexity(); + return props.GetDecompressRating(GlobalTime, GlobalFreq, UnpackSize, PackSize, NumIterations); +} + + +#ifndef _7ZIP_ST + +#define NUM_CPU_LEVELS_MAX 3 + +struct CAffinityMode +{ + unsigned NumBundleThreads; + unsigned NumLevels; + unsigned NumCoreThreads; + unsigned NumCores; + // unsigned DivideNum; + UInt32 Sizes[NUM_CPU_LEVELS_MAX]; + + void SetLevels(unsigned numCores, unsigned numCoreThreads); + DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; + bool NeedAffinity() const { return NumBundleThreads != 0; } + + WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter, UInt32 bundleIndex) const + { + if (NeedAffinity()) + { + CCpuSet cpuSet; + GetAffinityMask(bundleIndex, &cpuSet); + return thread.Create_With_CpuSet(startAddress, parameter, &cpuSet); + } + return thread.Create(startAddress, parameter); + } + + CAffinityMode(): + NumBundleThreads(0), + NumLevels(0), + NumCoreThreads(1) + // DivideNum(1) + {} +}; + +void CAffinityMode::SetLevels(unsigned numCores, unsigned numCoreThreads) +{ + NumCores = numCores; + NumCoreThreads = numCoreThreads; + NumLevels = 0; + if (numCoreThreads == 0 || numCores == 0 || numCores % numCoreThreads != 0) + return; + UInt32 c = numCores / numCoreThreads; + UInt32 c2 = 1; + while ((c & 1) == 0) + { + c >>= 1; + c2 <<= 1; + } + if (c2 != 1) + Sizes[NumLevels++] = c2; + if (c != 1) + Sizes[NumLevels++] = c; + if (numCoreThreads != 1) + Sizes[NumLevels++] = numCoreThreads; + if (NumLevels == 0) + Sizes[NumLevels++] = 1; + + /* + printf("\n Cores:"); + for (unsigned i = 0; i < NumLevels; i++) + { + printf(" %d", Sizes[i]); + } + printf("\n"); + */ +} + + +DWORD_PTR CAffinityMode::GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const +{ + CpuSet_Zero(cpuSet); + + if (NumLevels == 0) + return 0; + + // printf("\n%2d", bundleIndex); + + /* + UInt32 low = 0; + if (DivideNum != 1) + { + low = bundleIndex % DivideNum; + bundleIndex /= DivideNum; + } + */ + + UInt32 numGroups = NumCores / NumBundleThreads; + UInt32 m = bundleIndex % numGroups; + UInt32 v = 0; + for (unsigned i = 0; i < NumLevels; i++) + { + UInt32 size = Sizes[i]; + while ((size & 1) == 0) + { + v *= 2; + v |= (m & 1); + m >>= 1; + size >>= 1; + } + v *= size; + v += m % size; + m /= size; + } + + // UInt32 nb = NumBundleThreads / DivideNum; + UInt32 nb = NumBundleThreads; + + DWORD_PTR mask = ((DWORD_PTR)1 << nb) - 1; + // v += low; + mask <<= v; + + // printf(" %2d %8x \n ", v, (unsigned)mask); + #ifdef _WIN32 + *cpuSet = mask; + #else + { + for (unsigned k = 0; k < nb; k++) + CpuSet_Set(cpuSet, v + k); + } + #endif + + return mask; +} + + +struct CBenchSyncCommon +{ + bool ExitMode; + NSynchronization::CManualResetEvent StartEvent; + + CBenchSyncCommon(): ExitMode(false) {} +}; + +#endif + + + +class CEncoderInfo; + +class CEncoderInfo +{ + CLASS_NO_COPY(CEncoderInfo) + +public: + + #ifndef _7ZIP_ST + NWindows::CThread thread[2]; + NSynchronization::CManualResetEvent ReadyEvent; + UInt32 NumDecoderSubThreads; + CBenchSyncCommon *Common; + UInt32 EncoderIndex; + UInt32 NumEncoderInternalThreads; + CAffinityMode AffinityMode; + #endif + + CMyComPtr _encoder; + CMyComPtr _encoderFilter; + CBenchProgressInfo *progressInfoSpec[2]; + CMyComPtr progressInfo[2]; + UInt64 NumIterations; + + UInt32 Salt; + + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + + unsigned KeySize; + Byte _key[32]; + Byte _iv[16]; + + HRESULT Set_Key_and_IV(ICryptoProperties *cp) + { + RINOK(cp->SetKey(_key, KeySize)); + return cp->SetInitVector(_iv, sizeof(_iv)); + } + + Byte _psw[16]; + + bool CheckCrc_Enc; + bool CheckCrc_Dec; + + struct CDecoderInfo + { + CEncoderInfo *Encoder; + UInt32 DecoderIndex; + bool CallbackMode; + + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + }; + CDecoderInfo decodersInfo[2]; + + CMyComPtr _decoders[2]; + CMyComPtr _decoderFilter; + + HRESULT Results[2]; + CBenchmarkOutStream *outStreamSpec; + CMyComPtr outStream; + IBenchCallback *callback; + IBenchPrintCallback *printCallback; + UInt32 crc; + size_t kBufferSize; + size_t compressedSize; + const Byte *uncompressedDataPtr; + + const Byte *fileData; + CBenchRandomGenerator rg; + + CMidAlignedBuffer rgCopy; // it must be 16-byte aligned !!! + + // CBenchmarkOutStream *propStreamSpec; + Byte propsData[kMaxMethodPropSize]; + CBufPtrSeqOutStream *propStreamSpec; + CMyComPtr propStream; + + unsigned generateDictBits; + COneMethodInfo _method; + + // for decode + size_t _uncompressedDataSize; + + HRESULT Generate(); + HRESULT Encode(); + HRESULT Decode(UInt32 decoderIndex); + + CEncoderInfo(): + #ifndef _7ZIP_ST + Common(NULL), + #endif + Salt(0), + KeySize(0), + CheckCrc_Enc(true), + CheckCrc_Dec(true), + outStreamSpec(NULL), + callback(NULL), + printCallback(NULL), + fileData(NULL), + propStreamSpec(NULL) + {} + + #ifndef _7ZIP_ST + + static THREAD_FUNC_DECL EncodeThreadFunction(void *param) + { + HRESULT res; + CEncoderInfo *encoder = (CEncoderInfo *)param; + try + { + #ifdef USE_ALLOCA + alloca(encoder->AllocaSize); + #endif + + res = encoder->Encode(); + } + catch(...) + { + res = E_FAIL; + } + encoder->Results[0] = res; + if (res != S_OK) + encoder->progressInfoSpec[0]->Status->SetResult(res); + encoder->ReadyEvent.Set(); + return 0; + } + + static THREAD_FUNC_DECL DecodeThreadFunction(void *param) + { + CDecoderInfo *decoder = (CDecoderInfo *)param; + + #ifdef USE_ALLOCA + alloca(decoder->AllocaSize); + #endif + + CEncoderInfo *encoder = decoder->Encoder; + encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); + return 0; + } + + HRESULT CreateEncoderThread() + { + WRes res = 0; + if (!ReadyEvent.IsCreated()) + res = ReadyEvent.Create(); + if (res == 0) + res = AffinityMode.CreateThread_WithAffinity(thread[0], EncodeThreadFunction, this, + EncoderIndex); + return HRESULT_FROM_WIN32(res); + } + + HRESULT CreateDecoderThread(unsigned index, bool callbackMode + #ifdef USE_ALLOCA + , size_t allocaSize + #endif + ) + { + CDecoderInfo &decoder = decodersInfo[index]; + decoder.DecoderIndex = index; + decoder.Encoder = this; + + #ifdef USE_ALLOCA + decoder.AllocaSize = allocaSize; + #endif + + decoder.CallbackMode = callbackMode; + + WRes res = AffinityMode.CreateThread_WithAffinity(thread[index], DecodeThreadFunction, &decoder, + // EncoderIndex * NumEncoderInternalThreads + index + EncoderIndex + ); + + return HRESULT_FROM_WIN32(res); + } + + #endif +}; + + + + +static size_t GetBenchCompressedSize(size_t bufferSize) +{ + return kCompressedAdditionalSize + bufferSize + bufferSize / 16; + // kBufferSize / 2; +} + + +HRESULT CEncoderInfo::Generate() +{ + const COneMethodInfo &method = _method; + + // we need extra space, if input data is already compressed + const size_t kCompressedBufferSize = GetBenchCompressedSize(kBufferSize); + + if (kCompressedBufferSize < kBufferSize) + return E_FAIL; + + uncompressedDataPtr = fileData; + + if (!fileData) + { + ALLOC_WITH_HRESULT(&rg, kBufferSize); + + // DWORD ttt = GetTickCount(); + if (generateDictBits == 0) + rg.GenerateSimpleRandom(Salt); + else + { + if (generateDictBits >= sizeof(size_t) * 8 + && kBufferSize > ((size_t)1 << (sizeof(size_t) * 8 - 1))) + return E_INVALIDARG; + rg.GenerateLz(generateDictBits, Salt); + // return E_ABORT; // for debug + } + // printf("\n%d\n ", GetTickCount() - ttt); + + crc = CrcCalc((const Byte *)rg, rg.Size()); + uncompressedDataPtr = (const Byte *)rg; + } + + if (_encoderFilter) + { + ALLOC_WITH_HRESULT(&rgCopy, kBufferSize); + } + + + if (!outStream) + { + outStreamSpec = new CBenchmarkOutStream; + outStream = outStreamSpec; + } + + ALLOC_WITH_HRESULT(outStreamSpec, kCompressedBufferSize) + + if (!propStream) + { + propStreamSpec = new CBufPtrSeqOutStream; // CBenchmarkOutStream; + propStream = propStreamSpec; + } + // ALLOC_WITH_HRESULT_2(propStreamSpec, kMaxMethodPropSize); + // propStreamSpec->Init(true, false); + propStreamSpec->Init(propsData, sizeof(propsData)); + + + CMyComPtr coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; + { + CMyComPtr scp; + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + const UInt64 reduceSize = kBufferSize; + + /* in posix new thread uses same affinity as parent thread, + so we don't need to send affinity to coder in posix */ + UInt64 affMask; + #if !defined(_7ZIP_ST) && defined(_WIN32) + { + CCpuSet cpuSet; + affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); + } + #else + affMask = 0; + #endif + // affMask <<= 3; // debug line: to test no affinity in coder; + // affMask = 0; + + RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, (affMask != 0 ? &affMask : NULL))); + } + else + { + if (method.AreThereNonOptionalProps()) + return E_INVALIDARG; + } + + CMyComPtr writeCoderProps; + coder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProps); + if (writeCoderProps) + { + RINOK(writeCoderProps->WriteCoderProperties(propStream)); + } + + { + CMyComPtr sp; + coder.QueryInterface(IID_ICryptoSetPassword, &sp); + if (sp) + { + RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))); + + // we must call encoding one time to calculate password key for key cache. + // it must be after WriteCoderProperties! + Byte temp[16]; + memset(temp, 0, sizeof(temp)); + + if (_encoderFilter) + { + _encoderFilter->Init(); + _encoderFilter->Filter(temp, sizeof(temp)); + } + else + { + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + inStreamSpec->Init(temp, sizeof(temp)); + + CCrcOutStream *crcStreamSpec = new CCrcOutStream; + CMyComPtr crcStream = crcStreamSpec; + crcStreamSpec->Init(); + + RINOK(_encoder->Code(inStream, crcStream, 0, 0, NULL)); + } + } + } + } + + return S_OK; +} + + +static void My_FilterBench(ICompressFilter *filter, Byte *data, size_t size) +{ + while (size != 0) + { + UInt32 cur = (UInt32)1 << 31; + if (cur > size) + cur = (UInt32)size; + UInt32 processed = filter->Filter(data, cur); + data += processed; + // if (processed > size) (in AES filter), we must fill last block with zeros. + // but it is not important for benchmark. So we just copy that data without filtering. + if (processed > size || processed == 0) + break; + size -= processed; + } +} + + +HRESULT CEncoderInfo::Encode() +{ + // printf("\nCEncoderInfo::Generate\n"); + + RINOK(Generate()); + + // printf("\n2222\n"); + + #ifndef _7ZIP_ST + if (Common) + { + Results[0] = S_OK; + WRes wres = ReadyEvent.Set(); + if (wres == 0) + wres = Common->StartEvent.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + if (Common->ExitMode) + return S_OK; + } + else + #endif + { + CBenchProgressInfo *bpi = progressInfoSpec[0]; + bpi->SetStartTime(); + } + + + CBenchInfo &bi = progressInfoSpec[0]->BenchInfo; + bi.UnpackSize = 0; + bi.PackSize = 0; + CMyComPtr cp; + CMyComPtr coder; + if (_encoderFilter) + coder = _encoderFilter; + else + coder = _encoder; + coder.QueryInterface(IID_ICryptoProperties, &cp); + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + + if (cp) + { + RINOK(Set_Key_and_IV(cp)); + } + + compressedSize = 0; + if (_encoderFilter) + compressedSize = kBufferSize; + + // CBenchmarkOutStream *outStreamSpec = this->outStreamSpec; + UInt64 prev = 0; + const UInt32 mask = (CheckCrc_Enc ? 0 : 0xFFF); + bool useCrc = (mask < NumIterations); + bool crcPrev_defined = false; + UInt32 crcPrev = 0; + UInt64 i = NumIterations; + // printCallback->NewLine(); + + while (i != 0) + { + i--; + if (printCallback && bi.UnpackSize - prev >= (1 << 24)) + { + RINOK(printCallback->CheckBreak()); + prev = bi.UnpackSize; + } + + /* + CBenchInfo info; + progressInfoSpec[0]->SetStartTime(); + */ + + bool calcCrc = false; + if (useCrc) + calcCrc = (((UInt32)i & mask) == 0); + + if (_encoderFilter) + { + // if (needRealData) + memcpy((Byte *)*outStreamSpec, uncompressedDataPtr, kBufferSize); + _encoderFilter->Init(); + My_FilterBench(_encoderFilter, (Byte *)*outStreamSpec, kBufferSize); + if (calcCrc) + { + outStreamSpec->InitCrc(); + outStreamSpec->Calc((Byte *)*outStreamSpec, kBufferSize); + } + } + else + { + outStreamSpec->Init(true, calcCrc); // write real data for speed consistency at any number of iterations + inStreamSpec->Init(uncompressedDataPtr, kBufferSize); + RINOK(_encoder->Code(inStream, outStream, NULL, NULL, progressInfo[0])); + if (!inStreamSpec->WasFinished()) + return E_FAIL; + if (compressedSize != outStreamSpec->Pos) + { + if (compressedSize != 0) + return E_FAIL; + compressedSize = outStreamSpec->Pos; + } + } + + // outStreamSpec->Print(); + + if (calcCrc) + { + const UInt32 crc2 = CRC_GET_DIGEST(outStreamSpec->Crc); + if (crcPrev_defined && crcPrev != crc2) + return E_FAIL; + crcPrev = crc2; + crcPrev_defined = true; + } + + bi.UnpackSize += kBufferSize; + bi.PackSize += compressedSize; + + /* + { + progressInfoSpec[0]->SetFinishTime(info); + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = 1; + + info.UnpackSize = kBufferSize; + info.PackSize = compressedSize; + // printf("\n%7d\n", encoder.compressedSize); + + RINOK(callback->SetEncodeResult(info, true)); + printCallback->NewLine(); + } + */ + + } + + _encoder.Release(); + _encoderFilter.Release(); + return S_OK; +} + + +HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) +{ + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + CMyComPtr inStream = inStreamSpec; + CMyComPtr &decoder = _decoders[decoderIndex]; + CMyComPtr coder; + if (_decoderFilter) + { + if (decoderIndex != 0) + return E_FAIL; + coder = _decoderFilter; + } + else + coder = decoder; + + CMyComPtr setDecProps; + coder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecProps); + if (!setDecProps && propStreamSpec->GetPos() != 0) + return E_FAIL; + + CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; + CMyComPtr crcOutStream = crcOutStreamSpec; + + CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; + pi->BenchInfo.UnpackSize = 0; + pi->BenchInfo.PackSize = 0; + + #ifndef _7ZIP_ST + { + CMyComPtr setCoderMt; + coder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(NumDecoderSubThreads)); + } + } + #endif + + CMyComPtr scp; + coder.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + const UInt64 reduceSize = _uncompressedDataSize; + RINOK(_method.SetCoderProps(scp, &reduceSize)); + } + + CMyComPtr cp; + coder.QueryInterface(IID_ICryptoProperties, &cp); + + if (setDecProps) + { + RINOK(setDecProps->SetDecoderProperties2( + /* (const Byte *)*propStreamSpec, */ + propsData, + (UInt32)propStreamSpec->GetPos())); + } + + { + CMyComPtr sp; + coder.QueryInterface(IID_ICryptoSetPassword, &sp); + if (sp) + { + RINOK(sp->CryptoSetPassword(_psw, sizeof(_psw))); + } + } + + UInt64 prev = 0; + + if (cp) + { + RINOK(Set_Key_and_IV(cp)); + } + + CMyComPtr setFinishMode; + + if (_decoderFilter) + { + if (compressedSize > rgCopy.Size()) + return E_FAIL; + } + else + { + decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode); + } + + const UInt64 numIterations = this->NumIterations; + const UInt32 mask = (CheckCrc_Dec ? 0 : 0xFFF); + + for (UInt64 i = 0; i < numIterations; i++) + { + if (printCallback && pi->BenchInfo.UnpackSize - prev >= (1 << 24)) + { + RINOK(printCallback->CheckBreak()); + prev = pi->BenchInfo.UnpackSize; + } + + const UInt64 outSize = kBufferSize; + bool calcCrc = false; + if (((UInt32)i & mask) == 0) + calcCrc = true; + crcOutStreamSpec->Init(); + + if (_decoderFilter) + { + if (calcCrc) // for pure filter speed test without multi-iteration consistency + // if (needRealData) + memcpy((Byte *)rgCopy, (const Byte *)*outStreamSpec, compressedSize); + _decoderFilter->Init(); + My_FilterBench(_decoderFilter, (Byte *)rgCopy, compressedSize); + if (calcCrc) + crcOutStreamSpec->Calc((const Byte *)rgCopy, compressedSize); + } + else + { + crcOutStreamSpec->CalcCrc = calcCrc; + inStreamSpec->Init((const Byte *)*outStreamSpec, compressedSize); + + if (setFinishMode) + { + RINOK(setFinishMode->SetFinishMode(BoolToUInt(true))); + } + + RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); + + if (setFinishMode) + { + if (!inStreamSpec->WasFinished()) + return S_FALSE; + + CMyComPtr getInStreamProcessedSize; + decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize); + + if (getInStreamProcessedSize) + { + UInt64 processed; + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed)); + if (processed != compressedSize) + return S_FALSE; + } + } + + if (crcOutStreamSpec->Pos != outSize) + return S_FALSE; + } + + if (calcCrc && CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) + return S_FALSE; + + pi->BenchInfo.UnpackSize += kBufferSize; + pi->BenchInfo.PackSize += compressedSize; + } + + decoder.Release(); + _decoderFilter.Release(); + return S_OK; +} + + +static const UInt32 kNumThreadsMax = (1 << 12); + +struct CBenchEncoders +{ + CEncoderInfo *encoders; + CBenchEncoders(UInt32 num): encoders(NULL) { encoders = new CEncoderInfo[num]; } + ~CBenchEncoders() { delete []encoders; } +}; + + +static UInt64 GetNumIterations(UInt64 numCommands, UInt64 complexInCommands) +{ + if (numCommands < (1 << 4)) + numCommands = (1 << 4); + UInt64 res = complexInCommands / numCommands; + return (res == 0 ? 1 : res); +} + + + +#ifndef _7ZIP_ST + +// ---------- CBenchThreadsFlusher ---------- + +struct CBenchThreadsFlusher +{ + CBenchEncoders *EncodersSpec; + CBenchSyncCommon Common; + unsigned NumThreads; + bool NeedClose; + + CBenchThreadsFlusher(): NumThreads(0), NeedClose(false) {} + + ~CBenchThreadsFlusher() + { + StartAndWait(true); + } + + WRes StartAndWait(bool exitMode = false); +}; + + +WRes CBenchThreadsFlusher::StartAndWait(bool exitMode) +{ + if (!NeedClose) + return 0; + + Common.ExitMode = exitMode; + WRes res = Common.StartEvent.Set(); + + for (unsigned i = 0; i < NumThreads; i++) + { + NWindows::CThread &t = EncodersSpec->encoders[i].thread[0]; + if (t.IsCreated()) + { + WRes res2 = t.Wait_Close(); + if (res == 0) + res = res2; + } + } + NeedClose = false; + return res; +} + +#endif // _7ZIP_ST + + + +static void SetPseudoRand(Byte *data, size_t size, UInt32 startValue) +{ + for (size_t i = 0; i < size; i++) + { + data[i] = (Byte)startValue; + startValue++; + } +} + + + +static HRESULT MethodBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + #ifndef _7ZIP_ST + bool oldLzmaBenchMode, + UInt32 numThreads, + const CAffinityMode *affinityMode, + #endif + const COneMethodInfo &method2, + size_t uncompressedDataSize, + const Byte *fileData, + unsigned generateDictBits, + + IBenchPrintCallback *printCallback, + IBenchCallback *callback, + CBenchProps *benchProps) +{ + COneMethodInfo method = method2; + UInt64 methodId; + UInt32 numStreams; + const int codecIndex = FindMethod_Index( + EXTERNAL_CODECS_LOC_VARS + method.MethodName, true, + methodId, numStreams); + if (codecIndex < 0) + return E_NOTIMPL; + if (numStreams != 1) + return E_INVALIDARG; + + UInt32 numEncoderThreads = 1; + UInt32 numSubDecoderThreads = 1; + + #ifndef _7ZIP_ST + numEncoderThreads = numThreads; + + if (oldLzmaBenchMode) + if (methodId == k_LZMA) + { + if (numThreads == 1 && method.Get_NumThreads() < 0) + method.AddProp_NumThreads(1); + const UInt32 numLzmaThreads = method.Get_Lzma_NumThreads(); + if (numThreads > 1 && numLzmaThreads > 1) + { + numEncoderThreads = (numThreads + 1) / 2; // 20.03 + numSubDecoderThreads = 2; + } + } + + bool mtEncMode = (numEncoderThreads > 1) || affinityMode->NeedAffinity(); + + #endif + + CBenchEncoders encodersSpec(numEncoderThreads); + CEncoderInfo *encoders = encodersSpec.encoders; + + UInt32 i; + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + encoder.callback = (i == 0) ? callback : 0; + encoder.printCallback = printCallback; + + #ifndef _7ZIP_ST + encoder.EncoderIndex = i; + encoder.NumEncoderInternalThreads = numSubDecoderThreads; + encoder.AffinityMode = *affinityMode; + + /* + if (numSubDecoderThreads > 1) + if (encoder.AffinityMode.NeedAffinity() + && encoder.AffinityMode.NumBundleThreads == 1) + { + // if old LZMA benchmark uses two threads in coder, we increase (NumBundleThreads) for old LZMA benchmark uses two threads instead of one + if (encoder.AffinityMode.NumBundleThreads * 2 <= encoder.AffinityMode.NumCores) + encoder.AffinityMode.NumBundleThreads *= 2; + } + */ + + #endif + + { + CCreatedCoder cod; + RINOK(CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)codecIndex, true, encoder._encoderFilter, cod)); + encoder._encoder = cod.Coder; + if (!encoder._encoder && !encoder._encoderFilter) + return E_NOTIMPL; + } + + encoder.CheckCrc_Enc = (benchProps->EncComplex) > 30; + encoder.CheckCrc_Dec = (benchProps->DecComplexCompr + benchProps->DecComplexUnc) > 30; + + SetPseudoRand(encoder._iv, sizeof(encoder._iv), 17); + SetPseudoRand(encoder._key, sizeof(encoder._key), 51); + SetPseudoRand(encoder._psw, sizeof(encoder._psw), 123); + + for (UInt32 j = 0; j < numSubDecoderThreads; j++) + { + CCreatedCoder cod; + CMyComPtr &decoder = encoder._decoders[j]; + RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodId, false, encoder._decoderFilter, cod)); + decoder = cod.Coder; + if (!encoder._decoderFilter && !decoder) + return E_NOTIMPL; + } + } + + UInt32 crc = 0; + if (fileData) + crc = CrcCalc(fileData, uncompressedDataSize); + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + encoder._method = method; + encoder.generateDictBits = generateDictBits; + encoder._uncompressedDataSize = uncompressedDataSize; + encoder.kBufferSize = uncompressedDataSize; + encoder.fileData = fileData; + encoder.crc = crc; + } + + CBenchProgressStatus status; + status.Res = S_OK; + status.EncodeMode = true; + + #ifndef _7ZIP_ST + CBenchThreadsFlusher encoderFlusher; + if (mtEncMode) + { + WRes wres = encoderFlusher.Common.StartEvent.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + encoderFlusher.NumThreads = numEncoderThreads; + encoderFlusher.EncodersSpec = &encodersSpec; + encoderFlusher.NeedClose = true; + } + #endif + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + encoder.NumIterations = GetNumIterations(benchProps->GeComprCommands(uncompressedDataSize), complexInCommands); + // encoder.NumIterations = 3; + encoder.Salt = g_CrcTable[i & 0xFF]; + encoder.Salt ^= (g_CrcTable[(i >> 8) & 0xFF] << 3); + // (g_CrcTable[0] == 0), and (encoder.Salt == 0) for first thread + // printf(" %8x", encoder.Salt); + + encoder.KeySize = benchProps->KeySize; + + for (int j = 0; j < 2; j++) + { + CBenchProgressInfo *spec = new CBenchProgressInfo; + encoder.progressInfoSpec[j] = spec; + encoder.progressInfo[j] = spec; + spec->Status = &status; + } + + if (i == 0) + { + CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; + bpi->Callback = callback; + bpi->BenchInfo.NumIterations = numEncoderThreads; + } + + #ifndef _7ZIP_ST + if (mtEncMode) + { + #ifdef USE_ALLOCA + encoder.AllocaSize = (i * 16 * 21) & 0x7FF; + #endif + + encoder.Common = &encoderFlusher.Common; + RINOK(encoder.CreateEncoderThread()) + } + #endif + } + + if (printCallback) + { + RINOK(printCallback->CheckBreak()); + } + + #ifndef _7ZIP_ST + if (mtEncMode) + { + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + WRes wres = encoder.ReadyEvent.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + RINOK(encoder.Results[0]); + } + + CBenchProgressInfo *bpi = encoders[0].progressInfoSpec[0]; + bpi->SetStartTime(); + + WRes wres = encoderFlusher.StartAndWait(); + if (status.Res == 0 && wres != 0) + return HRESULT_FROM_WIN32(wres); + } + else + #endif + { + RINOK(encoders[0].Encode()); + } + + RINOK(status.Res); + + CBenchInfo info; + + encoders[0].progressInfoSpec[0]->SetFinishTime(info); + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = encoders[0].NumIterations; + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + info.UnpackSize += encoder.kBufferSize; + info.PackSize += encoder.compressedSize; + // printf("\n%7d\n", encoder.compressedSize); + } + + RINOK(callback->SetEncodeResult(info, true)); + + + + + // ---------- Decode ---------- + + status.Res = S_OK; + status.EncodeMode = false; + + const UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; + #ifndef _7ZIP_ST + const bool mtDecoderMode = (numDecoderThreads > 1) || affinityMode->NeedAffinity(); + #endif + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + + /* + #ifndef _7ZIP_ST + // encoder.affinityMode = *affinityMode; + if (encoder.NumEncoderInternalThreads != 1) + encoder.AffinityMode.DivideNum = encoder.NumEncoderInternalThreads; + #endif + */ + + + if (i == 0) + { + encoder.NumIterations = GetNumIterations(benchProps->GeDecomprCommands(encoder.compressedSize, encoder.kBufferSize), complexInCommands); + CBenchProgressInfo *bpi = encoder.progressInfoSpec[0]; + bpi->Callback = callback; + bpi->BenchInfo.NumIterations = numDecoderThreads; + bpi->SetStartTime(); + } + else + encoder.NumIterations = encoders[0].NumIterations; + + #ifndef _7ZIP_ST + { + int numSubThreads = method.Get_NumThreads(); + encoder.NumDecoderSubThreads = (numSubThreads <= 0) ? 1 : (unsigned)numSubThreads; + } + if (mtDecoderMode) + { + for (UInt32 j = 0; j < numSubDecoderThreads; j++) + { + HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) + #ifdef USE_ALLOCA + , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF + #endif + ); + RINOK(res); + } + } + else + #endif + { + RINOK(encoder.Decode(0)); + } + } + + #ifndef _7ZIP_ST + if (mtDecoderMode) + { + WRes wres = 0; + HRESULT res = S_OK; + for (i = 0; i < numEncoderThreads; i++) + for (UInt32 j = 0; j < numSubDecoderThreads; j++) + { + CEncoderInfo &encoder = encoders[i]; + WRes wres2 = encoder.thread[j]. + // Wait(); // later we can get thread times from thread in UNDER_CE + Wait_Close(); + if (wres == 0 && wres2 != 0) + wres = wres2; + HRESULT res2 = encoder.Results[j]; + if (res == 0 && res2 != 0) + res = res2; + } + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + RINOK(res); + } + #endif // _7ZIP_ST + + RINOK(status.Res); + encoders[0].progressInfoSpec[0]->SetFinishTime(info); + + /* + #ifndef _7ZIP_ST + #ifdef UNDER_CE + if (mtDecoderMode) + for (i = 0; i < numEncoderThreads; i++) + for (UInt32 j = 0; j < numSubDecoderThreads; j++) + { + FILETIME creationTime, exitTime, kernelTime, userTime; + if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0) + info.UserTime += GetTime64(userTime) + GetTime64(kernelTime); + } + #endif + #endif + */ + + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; + + for (i = 0; i < numEncoderThreads; i++) + { + CEncoderInfo &encoder = encoders[i]; + info.UnpackSize += encoder.kBufferSize; + info.PackSize += encoder.compressedSize; + } + + // RINOK(callback->SetDecodeResult(info, false)); // why we called before 21.03 ?? + RINOK(callback->SetDecodeResult(info, true)); + + return S_OK; +} + + + +static inline UInt64 GetDictSizeFromLog(unsigned dictSizeLog) +{ + /* + if (dictSizeLog < 32) + return (UInt32)1 << dictSizeLog; + else + return (UInt32)(Int32)-1; + */ + return (UInt64)1 << dictSizeLog; +} + + +// it's limit of current LZMA implementation that can be changed later +#define kLzmaMaxDictSize ((UInt32)15 << 28) + +static inline UInt64 GetLZMAUsage(bool multiThread, int btMode, UInt64 dict) +{ + if (dict == 0) + dict = 1; + if (dict > kLzmaMaxDictSize) + dict = kLzmaMaxDictSize; + UInt32 hs = (UInt32)dict - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + hs++; + hs += (1 << 16); + + const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16); + UInt64 blockSize = (UInt64)dict + (1 << 16) + + (multiThread ? (1 << 20) : 0); + blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2)); + if (blockSize >= kBlockSizeMax) + blockSize = kBlockSizeMax; + + UInt64 son = (UInt64)dict; + if (btMode) + son *= 2; + const UInt64 v = (hs + son) * 4 + blockSize + + (1 << 20) + (multiThread ? (6 << 20) : 0); + + // printf("\nGetLZMAUsage = %d\n", (UInt32)(v >> 20)); + // printf("\nblockSize = %d\n", (UInt32)(blockSize >> 20)); + return v; +} + + +UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench) +{ + const size_t kBufferSize = (size_t)dictionary + kAdditionalSize; + const UInt64 kCompressedBufferSize = GetBenchCompressedSize(kBufferSize); // / 2; + if (level < 0) + level = 5; + const int algo = (level < 5 ? 0 : 1); + const int btMode = (algo == 0 ? 0 : 1); + + UInt32 numBigThreads = numThreads; + bool lzmaMt = (totalBench || (numThreads > 1 && btMode)); + if (btMode) + { + if (!totalBench && lzmaMt) + numBigThreads /= 2; + } + return ((UInt64)kBufferSize + kCompressedBufferSize + + GetLZMAUsage(lzmaMt, btMode, dictionary) + (2 << 20)) * numBigThreads; +} + +static UInt64 GetBenchMemoryUsage_Hash(UInt32 numThreads, UInt64 dictionary) +{ + // dictionary += (dictionary >> 9); // for page tables (virtual memory) + return (UInt64)(dictionary + (1 << 15)) * numThreads + (2 << 20); +} + + +// ---------- CRC and HASH ---------- + +struct CCrcInfo_Base +{ + CMidAlignedBuffer Buffer; + const Byte *Data; + size_t Size; + bool CreateLocalBuf; + UInt32 CheckSum_Res; + + CCrcInfo_Base(): CreateLocalBuf(true), CheckSum_Res(0) {} + + HRESULT Generate(const Byte *data, size_t size); + HRESULT CrcProcess(UInt64 numIterations, + const UInt32 *checkSum, IHasher *hf, + IBenchPrintCallback *callback); +}; + + +HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) +{ + Size = size; + Data = data; + if (!data || CreateLocalBuf) + { + ALLOC_WITH_HRESULT(&Buffer, size) + Data = Buffer; + } + if (!data) + RandGen(Buffer, size); + else if (CreateLocalBuf && size != 0) + memcpy(Buffer, data, size); + return S_OK; +} + + +HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, + const UInt32 *checkSum, IHasher *hf, + IBenchPrintCallback *callback) +{ + MY_ALIGN(16) + Byte hash[64]; + memset(hash, 0, sizeof(hash)); + + CheckSum_Res = 0; + + const UInt32 hashSize = hf->GetDigestSize(); + if (hashSize > sizeof(hash)) + return S_FALSE; + + const Byte *buf = Data; + const size_t size = Size; + UInt32 checkSum_Prev = 0; + + UInt64 prev = 0; + UInt64 cur = 0; + + for (UInt64 i = 0; i < numIterations; i++) + { + hf->Init(); + size_t pos = 0; + do + { + const size_t rem = size - pos; + const UInt32 kStep = ((UInt32)1 << 31); + const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; + hf->Update(buf + pos, curSize); + pos += curSize; + } + while (pos != size); + + hf->Final(hash); + UInt32 sum = 0; + for (UInt32 j = 0; j < hashSize; j += 4) + { + sum = rotlFixed(sum, 11); + sum += GetUi32(hash + j); + } + if (checkSum) + { + if (sum != *checkSum) + return S_FALSE; + } + else + { + checkSum_Prev = sum; + checkSum = &checkSum_Prev; + } + if (callback) + { + cur += size; + if (cur - prev >= ((UInt32)1 << 30)) + { + prev = cur; + RINOK(callback->CheckBreak()); + } + } + } + CheckSum_Res = checkSum_Prev; + return S_OK; +} + +extern +UInt32 g_BenchCpuFreqTemp; // we need non-static variavble to disable compiler optimization +UInt32 g_BenchCpuFreqTemp = 1; + +#define YY1 sum += val; sum ^= val; +#define YY3 YY1 YY1 YY1 YY1 +#define YY5 YY3 YY3 YY3 YY3 +#define YY7 YY5 YY5 YY5 YY5 +static const UInt32 kNumFreqCommands = 128; + +EXTERN_C_BEGIN + +static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val) +{ + for (UInt32 i = 0; i < num; i++) + { + YY7 + } + return sum; +} + +EXTERN_C_END + + +#ifndef _7ZIP_ST + +struct CBaseThreadInfo +{ + NWindows::CThread Thread; + IBenchPrintCallback *Callback; + HRESULT CallbackRes; + + WRes Wait_If_Created() + { + if (!Thread.IsCreated()) + return 0; + return Thread.Wait_Close(); + } +}; + +struct CFreqInfo: public CBaseThreadInfo +{ + UInt32 ValRes; + UInt32 Size; + UInt64 NumIterations; +}; + +static THREAD_FUNC_DECL FreqThreadFunction(void *param) +{ + CFreqInfo *p = (CFreqInfo *)param; + + UInt32 sum = g_BenchCpuFreqTemp; + for (UInt64 k = p->NumIterations; k > 0; k--) + { + if (p->Callback) + { + p->CallbackRes = p->Callback->CheckBreak(); + if (p->CallbackRes != S_OK) + return 0; + } + sum = CountCpuFreq(sum, p->Size, g_BenchCpuFreqTemp); + } + p->ValRes = sum; + return 0; +} + +struct CFreqThreads +{ + CFreqInfo *Items; + UInt32 NumThreads; + + CFreqThreads(): Items(NULL), NumThreads(0) {} + + WRes WaitAll() + { + WRes wres = 0; + for (UInt32 i = 0; i < NumThreads; i++) + { + WRes wres2 = Items[i].Wait_If_Created(); + if (wres == 0 && wres2 != 0) + wres = wres2; + } + NumThreads = 0; + return wres; + } + + ~CFreqThreads() + { + WaitAll(); + delete []Items; + } +}; + + +static THREAD_FUNC_DECL CrcThreadFunction(void *param); + +struct CCrcInfo: public CBaseThreadInfo +{ + const Byte *Data; + size_t Size; + UInt64 NumIterations; + bool CheckSumDefined; + UInt32 CheckSum; + CMyComPtr Hasher; + HRESULT Res; + UInt32 CheckSum_Res; + + #ifndef _7ZIP_ST + NSynchronization::CManualResetEvent ReadyEvent; + UInt32 ThreadIndex; + CBenchSyncCommon *Common; + CAffinityMode AffinityMode; + #endif + + // we want to call CCrcInfo_Base::Buffer.Free() in main thread. + // so we uses non-local CCrcInfo_Base. + CCrcInfo_Base crcib; + + HRESULT CreateThread() + { + WRes res = 0; + if (!ReadyEvent.IsCreated()) + res = ReadyEvent.Create(); + if (res == 0) + res = AffinityMode.CreateThread_WithAffinity(Thread, CrcThreadFunction, this, + ThreadIndex); + return HRESULT_FROM_WIN32(res); + } + + #ifdef USE_ALLOCA + size_t AllocaSize; + #endif + + void Process(); + + CCrcInfo(): Res(E_FAIL) {} +}; + +static const bool k_Crc_CreateLocalBuf_For_File = true; // for total BW test +// static const bool k_Crc_CreateLocalBuf_For_File = false; // for shared memory read test + +void CCrcInfo::Process() +{ + crcib.CreateLocalBuf = k_Crc_CreateLocalBuf_For_File; + // we can use additional Generate() passes to reduce some time effects for new page allocation + // for (unsigned y = 0; y < 10; y++) + Res = crcib.Generate(Data, Size); + + // if (Common) + { + WRes wres = ReadyEvent.Set(); + if (wres != 0) + { + if (Res == 0) + Res = HRESULT_FROM_WIN32(wres); + return; + } + if (Res != 0) + return; + + wres = Common->StartEvent.Lock(); + + if (wres != 0) + { + Res = HRESULT_FROM_WIN32(wres); + return; + } + if (Common->ExitMode) + return; + } + + Res = crcib.CrcProcess(NumIterations, + CheckSumDefined ? &CheckSum : NULL, Hasher, + Callback); + CheckSum_Res = crcib.CheckSum_Res; + /* + We don't want to include the time of slow CCrcInfo_Base::Buffer.Free() + to time of benchmark. So we don't free Buffer here + */ + // crcib.Buffer.Free(); +} + + +static THREAD_FUNC_DECL CrcThreadFunction(void *param) +{ + CCrcInfo *p = (CCrcInfo *)param; + + #ifdef USE_ALLOCA + alloca(p->AllocaSize); + #endif + p->Process(); + return 0; +} + + +struct CCrcThreads +{ + CCrcInfo *Items; + unsigned NumThreads; + CBenchSyncCommon Common; + bool NeedClose; + + CCrcThreads(): Items(NULL), NumThreads(0), NeedClose(false) {} + + WRes StartAndWait(bool exitMode = false); + + ~CCrcThreads() + { + StartAndWait(true); + delete []Items; + } +}; + + +WRes CCrcThreads::StartAndWait(bool exitMode) +{ + if (!NeedClose) + return 0; + + Common.ExitMode = exitMode; + WRes wres = Common.StartEvent.Set(); + + for (unsigned i = 0; i < NumThreads; i++) + { + WRes wres2 = Items[i].Wait_If_Created(); + if (wres == 0 && wres2 != 0) + wres = wres2; + } + NumThreads = 0; + NeedClose = false; + return wres; +} + +#endif + + +static UInt32 CrcCalc1(const Byte *buf, size_t size) +{ + UInt32 crc = CRC_INIT_VAL;; + for (size_t i = 0; i < size; i++) + crc = CRC_UPDATE_BYTE(crc, buf[i]); + return CRC_GET_DIGEST(crc); +} + +/* +static UInt32 RandGenCrc(Byte *buf, size_t size, CBaseRandomGenerator &RG) +{ + RandGen(buf, size, RG); + return CrcCalc1(buf, size); +} +*/ + +static bool CrcInternalTest() +{ + CAlignedBuffer buffer; + const size_t kBufferSize0 = (1 << 8); + const size_t kBufferSize1 = (1 << 10); + const unsigned kCheckSize = (1 << 5); + buffer.Alloc(kBufferSize0 + kBufferSize1); + if (!buffer.IsAllocated()) + return false; + Byte *buf = (Byte *)buffer; + size_t i; + for (i = 0; i < kBufferSize0; i++) + buf[i] = (Byte)i; + UInt32 crc1 = CrcCalc1(buf, kBufferSize0); + if (crc1 != 0x29058C73) + return false; + RandGen(buf + kBufferSize0, kBufferSize1); + for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) + for (unsigned j = 0; j < kCheckSize; j++) + if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) + return false; + return true; +} + +struct CBenchMethod +{ + unsigned Weight; + unsigned DictBits; + UInt32 EncComplex; + UInt32 DecComplexCompr; + UInt32 DecComplexUnc; + const char *Name; + // unsigned KeySize; +}; + +// #define USE_SW_CMPLX + +#ifdef USE_SW_CMPLX +#define CMPLX(x) ((x) * 1000) +#else +#define CMPLX(x) (x) +#endif + +static const CBenchMethod g_Bench[] = +{ + // { 40, 17, 357, 145, 20, "LZMA:x1" }, + // { 20, 18, 360, 145, 20, "LZMA2:x1:mt2" }, + + { 20, 18, 360, 145, 20, "LZMA:x1" }, + { 20, 22, 600, 145, 20, "LZMA:x3" }, + + { 80, 24, 1220, 145, 20, "LZMA:x5:mt1" }, + { 80, 24, 1220, 145, 20, "LZMA:x5:mt2" }, + + { 10, 16, 124, 40, 14, "Deflate:x1" }, + { 20, 16, 376, 40, 14, "Deflate:x5" }, + { 10, 16, 1082, 40, 14, "Deflate:x7" }, + { 10, 17, 422, 40, 14, "Deflate64:x5" }, + + { 10, 15, 590, 69, 69, "BZip2:x1" }, + { 20, 19, 815, 122, 122, "BZip2:x5" }, + { 10, 19, 815, 122, 122, "BZip2:x5:mt2" }, + { 10, 19, 2530, 122, 122, "BZip2:x7" }, + + // { 10, 18, 1010, 0, 1150, "PPMDZip:x1" }, + { 10, 18, 1010, 0, 1150, "PPMD:x1" }, + // { 10, 22, 1655, 0, 1830, "PPMDZip:x5" }, + { 10, 22, 1655, 0, 1830, "PPMD:x5" }, + + // { 2, 0, 3, 0, 4, "Delta:1" }, + // { 2, 0, 3, 0, 4, "Delta:2" }, + // { 2, 0, 3, 0, 4, "Delta:3" }, + { 2, 0, 3, 0, 4, "Delta:4" }, + // { 2, 0, 3, 0, 4, "Delta:8" }, + // { 2, 0, 3, 0, 4, "Delta:32" }, + + { 2, 0, 4, 0, 4, "BCJ" }, + + // { 10, 0, 18, 0, 18, "AES128CBC:1" }, + // { 10, 0, 21, 0, 21, "AES192CBC:1" }, + { 10, 0, 24, 0, 24, "AES256CBC:1" }, + + // { 10, 0, 18, 0, 18, "AES128CTR:1" }, + // { 10, 0, 21, 0, 21, "AES192CTR:1" }, + // { 10, 0, 24, 0, 24, "AES256CTR:1" }, + // { 2, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:2" }, + // { 2, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:2" }, + { 2, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:2" }, + + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:2" }, + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:2" }, + // { 2, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:2" }, + + // { 1, 0, CMPLX(6), 0, CMPLX(1), "AES128CBC:3" }, + // { 1, 0, CMPLX(7), 0, CMPLX(1), "AES192CBC:3" }, + { 1, 0, CMPLX(8), 0, CMPLX(1), "AES256CBC:3" } + + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES128CTR:3" }, + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES192CTR:3" }, + // { 1, 0, CMPLX(1), 0, CMPLX(1), "AES256CTR:3" }, +}; + +struct CBenchHash +{ + unsigned Weight; + UInt32 Complex; + UInt32 CheckSum; + const char *Name; +}; + +// #define ARM_CRC_MUL 100 +#define ARM_CRC_MUL 1 + +static const CBenchHash g_Hash[] = +{ + { 1, 1820, 0x21e207bb, "CRC32:1" }, + { 10, 558, 0x21e207bb, "CRC32:4" }, + { 10, 339, 0x21e207bb, "CRC32:8" } , + { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, + { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, + { 10, 512, 0x41b901d1, "CRC64" }, + + { 10, 5100, 0x7913ba03, "SHA256:1" }, + { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, + + { 10, 2340, 0xff769021, "SHA1:1" }, + { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, + + { 2, 5500, 0x85189d02, "BLAKE2sp" } +}; + +static void PrintNumber(IBenchPrintCallback &f, UInt64 value, unsigned size) +{ + char s[128]; + unsigned startPos = (unsigned)sizeof(s) - 32; + memset(s, ' ', startPos); + ConvertUInt64ToString(value, s + startPos); + // if (withSpace) + { + startPos--; + size++; + } + unsigned len = (unsigned)strlen(s + startPos); + if (size > len) + { + size -= len; + if (startPos < size) + startPos = 0; + else + startPos -= size; + } + f.Print(s + startPos); +} + +static const unsigned kFieldSize_Name = 12; +static const unsigned kFieldSize_SmallName = 4; +static const unsigned kFieldSize_Speed = 9; +static const unsigned kFieldSize_Usage = 5; +static const unsigned kFieldSize_RU = 6; +static const unsigned kFieldSize_Rating = 6; +static const unsigned kFieldSize_EU = 5; +static const unsigned kFieldSize_Effec = 5; + +static const unsigned kFieldSize_TotalSize = 4 + kFieldSize_Speed + kFieldSize_Usage + kFieldSize_RU + kFieldSize_Rating; +static const unsigned kFieldSize_EUAndEffec = 2 + kFieldSize_EU + kFieldSize_Effec; + + +static void PrintRating(IBenchPrintCallback &f, UInt64 rating, unsigned size) +{ + PrintNumber(f, (rating + 500000) / 1000000, size); +} + + +static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, unsigned size) +{ + UInt64 v = 0; + if (divider != 0) + v = (val * 100 + divider / 2) / divider; + PrintNumber(f, v, size); +} + +static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) +{ + char s[256]; + memset(s, (Byte)c, size); + s[size] = 0; + f.Print(s); +} + +static void PrintSpaces(IBenchPrintCallback &f, unsigned size) +{ + PrintChars(f, ' ', size); +} + +static void PrintUsage(IBenchPrintCallback &f, UInt64 usage, unsigned size) +{ + PrintNumber(f, Benchmark_GetUsage_Percents(usage), size); +} + +static void PrintResults(IBenchPrintCallback &f, UInt64 usage, UInt64 rpu, UInt64 rating, bool showFreq, UInt64 cpuFreq) +{ + PrintUsage(f, usage, kFieldSize_Usage); + PrintRating(f, rpu, kFieldSize_RU); + PrintRating(f, rating, kFieldSize_Rating); + if (showFreq) + { + if (cpuFreq == 0) + PrintSpaces(f, kFieldSize_EUAndEffec); + else + { + PrintPercents(f, rating, cpuFreq * usage / kBenchmarkUsageMult, kFieldSize_EU); + PrintPercents(f, rating, cpuFreq, kFieldSize_Effec); + } + } +} + + +void CTotalBenchRes::Generate_From_BenchInfo(const CBenchInfo &info) +{ + Speed = info.GetUnpackSizeSpeed(); + Usage = info.GetUsage(); + RPU = info.GetRatingPerUsage(Rating); +} + +void CTotalBenchRes::Mult_For_Weight(unsigned weight) +{ + NumIterations2 *= weight; + RPU *= weight; + Rating *= weight; + Usage += weight; + Speed += weight; +} + +void CTotalBenchRes::Update_With_Res(const CTotalBenchRes &r) +{ + Rating += r.Rating; + Usage += r.Usage; + RPU += r.RPU; + Speed += r.Speed; + // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1); + NumIterations2 += r.NumIterations2; +} + +static void PrintResults(IBenchPrintCallback *f, + const CBenchInfo &info, + unsigned weight, + UInt64 rating, + bool showFreq, UInt64 cpuFreq, + CTotalBenchRes *res) +{ + CTotalBenchRes t; + t.Rating = rating; + t.NumIterations2 = 1; + t.Generate_From_BenchInfo(info); + + if (f) + { + if (t.Speed != 0) + PrintNumber(*f, t.Speed / 1024, kFieldSize_Speed); + else + PrintSpaces(*f, 1 + kFieldSize_Speed); + } + if (f) + { + PrintResults(*f, t.Usage, t.RPU, rating, showFreq, cpuFreq); + } + + if (res) + { + // res->NumIterations1++; + t.Mult_For_Weight(weight); + res->Update_With_Res(t); + } +} + +static void PrintTotals(IBenchPrintCallback &f, + bool showFreq, UInt64 cpuFreq, bool showSpeed, const CTotalBenchRes &res) +{ + const UInt64 numIterations2 = res.NumIterations2 ? res.NumIterations2 : 1; + const UInt64 speed = res.Speed / numIterations2; + if (showSpeed && speed != 0) + PrintNumber(f, speed / 1024, kFieldSize_Speed); + else + PrintSpaces(f, 1 + kFieldSize_Speed); + + // PrintSpaces(f, 1 + kFieldSize_Speed); + // UInt64 numIterations1 = res.NumIterations1; if (numIterations1 == 0) numIterations1 = 1; + PrintResults(f, res.Usage / numIterations2, res.RPU / numIterations2, res.Rating / numIterations2, showFreq, cpuFreq); +} + + +static void PrintHex(AString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} + +AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) +{ + AString s; + // s.Add_UInt32(ti.numProcessThreads); + unsigned numSysThreads = ti.GetNumSystemThreads(); + if (ti.GetNumProcessThreads() != numSysThreads) + { + // if (ti.numProcessThreads != ti.numSysThreads) + { + s += " / "; + s.Add_UInt32(numSysThreads); + } + s += " : "; + #ifdef _WIN32 + PrintHex(s, ti.processAffinityMask); + s += " / "; + PrintHex(s, ti.systemAffinityMask); + #else + unsigned i = (numSysThreads + 3) & ~(unsigned)3; + if (i == 0) + i = 4; + for (; i >= 4; ) + { + i -= 4; + unsigned val = 0; + for (unsigned k = 0; k < 4; k++) + { + const unsigned bit = (ti.IsCpuSet(i + k) ? 1 : 0); + val += (bit << k); + } + PrintHex(s, val); + } + #endif + } + return s; +} + + +#ifdef _7ZIP_LARGE_PAGES + +#ifdef _WIN32 +extern bool g_LargePagesMode; +extern "C" +{ + extern SIZE_T g_LargePageSize; +} +#endif + +void Add_LargePages_String(AString &s) +{ + #ifdef _WIN32 + if (g_LargePagesMode || g_LargePageSize != 0) + { + s.Add_OptSpaced("(LP-"); + PrintSize_KMGT_Or_Hex(s, g_LargePageSize); + #ifdef MY_CPU_X86_OR_AMD64 + if (CPU_IsSupported_PageGB()) + s += "-1G"; + #endif + if (!g_LargePagesMode) + s += "-NA"; + s += ")"; + } + #else + s += ""; + #endif +} + +#endif + + + +static void PrintRequirements(IBenchPrintCallback &f, const char *sizeString, + bool size_Defined, UInt64 size, const char *threadsString, UInt32 numThreads) +{ + f.Print("RAM "); + f.Print(sizeString); + if (size_Defined) + PrintNumber(f, (size >> 20), 6); + else + f.Print(" ?"); + f.Print(" MB"); + + #ifdef _7ZIP_LARGE_PAGES + { + AString s; + Add_LargePages_String(s); + f.Print(s); + } + #endif + + f.Print(", # "); + f.Print(threadsString); + PrintNumber(f, numThreads, 3); +} + + + +struct CBenchCallbackToPrint: public IBenchCallback +{ + CBenchProps BenchProps; + CTotalBenchRes EncodeRes; + CTotalBenchRes DecodeRes; + IBenchPrintCallback *_file; + UInt64 DictSize; + + bool Use2Columns; + unsigned NameFieldSize; + + bool ShowFreq; + UInt64 CpuFreq; + + unsigned EncodeWeight; + unsigned DecodeWeight; + + CBenchCallbackToPrint(): + Use2Columns(false), + NameFieldSize(0), + ShowFreq(false), + CpuFreq(0), + EncodeWeight(1), + DecodeWeight(1) + {} + + void Init() { EncodeRes.Init(); DecodeRes.Init(); } + void Print(const char *s); + void NewLine(); + + HRESULT SetFreq(bool showFreq, UInt64 cpuFreq); + HRESULT SetEncodeResult(const CBenchInfo &info, bool final); + HRESULT SetDecodeResult(const CBenchInfo &info, bool final); +}; + +HRESULT CBenchCallbackToPrint::SetFreq(bool showFreq, UInt64 cpuFreq) +{ + ShowFreq = showFreq; + CpuFreq = cpuFreq; + return S_OK; +} + +HRESULT CBenchCallbackToPrint::SetEncodeResult(const CBenchInfo &info, bool final) +{ + RINOK(_file->CheckBreak()); + if (final) + { + UInt64 rating = BenchProps.GetCompressRating(DictSize, info.GlobalTime, info.GlobalFreq, info.UnpackSize * info.NumIterations); + PrintResults(_file, info, + EncodeWeight, rating, + ShowFreq, CpuFreq, &EncodeRes); + if (!Use2Columns) + _file->NewLine(); + } + return S_OK; +} + +static const char * const kSep = " | "; + +HRESULT CBenchCallbackToPrint::SetDecodeResult(const CBenchInfo &info, bool final) +{ + RINOK(_file->CheckBreak()); + if (final) + { + UInt64 rating = BenchProps.GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); + if (Use2Columns) + _file->Print(kSep); + else + PrintSpaces(*_file, NameFieldSize); + CBenchInfo info2 = info; + info2.UnpackSize *= info2.NumIterations; + info2.PackSize *= info2.NumIterations; + info2.NumIterations = 1; + PrintResults(_file, info2, + DecodeWeight, rating, + ShowFreq, CpuFreq, &DecodeRes); + } + return S_OK; +} + +void CBenchCallbackToPrint::Print(const char *s) +{ + _file->Print(s); +} + +void CBenchCallbackToPrint::NewLine() +{ + _file->NewLine(); +} + +static void PrintLeft(IBenchPrintCallback &f, const char *s, unsigned size) +{ + f.Print(s); + int numSpaces = (int)size - (int)MyStringLen(s); + if (numSpaces > 0) + PrintSpaces(f, (unsigned)numSpaces); +} + +static void PrintRight(IBenchPrintCallback &f, const char *s, unsigned size) +{ + int numSpaces = (int)size - (int)MyStringLen(s); + if (numSpaces > 0) + PrintSpaces(f, (unsigned)numSpaces); + f.Print(s); +} + +static HRESULT TotalBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + #ifndef _7ZIP_ST + UInt32 numThreads, + const CAffinityMode *affinityMode, + #endif + bool forceUnpackSize, + size_t unpackSize, + const Byte *fileData, + IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_Bench); i++) + { + const CBenchMethod &bench = g_Bench[i]; + PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); + { + unsigned keySize = 32; + if (IsString1PrefixedByString2(bench.Name, "AES128")) keySize = 16; + else if (IsString1PrefixedByString2(bench.Name, "AES192")) keySize = 24; + callback->BenchProps.KeySize = keySize; + } + callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; + callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; + callback->BenchProps.EncComplex = bench.EncComplex; + + COneMethodInfo method; + NCOM::CPropVariant propVariant; + propVariant = bench.Name; + RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)); + + size_t unpackSize2 = unpackSize; + if (!forceUnpackSize && bench.DictBits == 0) + unpackSize2 = kFilterUnpackSize; + + callback->EncodeWeight = bench.Weight; + callback->DecodeWeight = bench.Weight; + + HRESULT res = MethodBench( + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + #ifndef _7ZIP_ST + false, numThreads, affinityMode, + #endif + method, + unpackSize2, fileData, + bench.DictBits, + printCallback, callback, &callback->BenchProps); + + if (res == E_NOTIMPL) + { + // callback->Print(" ---"); + // we need additional empty line as line for decompression results + if (!callback->Use2Columns) + callback->NewLine(); + } + else + { + RINOK(res); + } + + callback->NewLine(); + } + return S_OK; +} + + +struct CFreqBench +{ + // in: + UInt64 complexInCommands; + UInt32 numThreads; + bool showFreq; + UInt64 specifiedFreq; + + // out: + UInt64 CpuFreqRes; + UInt64 UsageRes; + UInt32 res; + + CFreqBench() + {} + + HRESULT FreqBench(IBenchPrintCallback *_file + #ifndef _7ZIP_ST + , const CAffinityMode *affinityMode + #endif + ); +}; + + +HRESULT CFreqBench::FreqBench(IBenchPrintCallback *_file + #ifndef _7ZIP_ST + , const CAffinityMode *affinityMode + #endif + ) +{ + res = 0; + CpuFreqRes = 0; + UsageRes = 0; + + if (numThreads == 0) + numThreads = 1; + + #ifdef _7ZIP_ST + numThreads = 1; + #endif + + const UInt32 complexity = kNumFreqCommands; + UInt64 numIterations = complexInCommands / complexity; + UInt32 numIterations2 = 1 << 30; + if (numIterations > numIterations2) + numIterations /= numIterations2; + else + { + numIterations2 = (UInt32)numIterations; + numIterations = 1; + } + + CBenchInfoCalc progressInfoSpec; + + #ifndef _7ZIP_ST + + bool mtMode = (numThreads > 1) || affinityMode->NeedAffinity(); + + if (mtMode) + { + CFreqThreads threads; + threads.Items = new CFreqInfo[numThreads]; + UInt32 i; + for (i = 0; i < numThreads; i++) + { + CFreqInfo &info = threads.Items[i]; + info.Callback = _file; + info.CallbackRes = S_OK; + info.NumIterations = numIterations; + info.Size = numIterations2; + } + progressInfoSpec.SetStartTime(); + for (i = 0; i < numThreads; i++) + { + // Sleep(10); + CFreqInfo &info = threads.Items[i]; + WRes wres = affinityMode->CreateThread_WithAffinity(info.Thread, FreqThreadFunction, &info, i); + if (info.Thread.IsCreated()) + threads.NumThreads++; + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + } + WRes wres = threads.WaitAll(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + for (i = 0; i < numThreads; i++) + { + RINOK(threads.Items[i].CallbackRes); + } + } + else + #endif + { + progressInfoSpec.SetStartTime(); + UInt32 sum = g_BenchCpuFreqTemp; + for (UInt64 k = numIterations; k > 0; k--) + { + sum = CountCpuFreq(sum, numIterations2, g_BenchCpuFreqTemp); + if (_file) + { + RINOK(_file->CheckBreak()); + } + } + res += sum; + } + + if (res == 0x12345678) + if (_file) + { + RINOK(_file->CheckBreak()); + } + + CBenchInfo info; + progressInfoSpec.SetFinishTime(info); + + info.UnpackSize = 0; + info.PackSize = 0; + info.NumIterations = 1; + + const UInt64 numCommands = (UInt64)numIterations * numIterations2 * numThreads * complexity; + const UInt64 rating = info.GetSpeed(numCommands); + CpuFreqRes = rating / numThreads; + UsageRes = info.GetUsage(); + + if (_file) + { + PrintResults(_file, info, + 0, // weight + rating, + showFreq, showFreq ? (specifiedFreq != 0 ? specifiedFreq : CpuFreqRes) : 0, NULL); + RINOK(_file->CheckBreak()); + } + + return S_OK; +} + + + +static HRESULT CrcBench( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + UInt32 numThreads, + const size_t bufferSize, + const Byte *fileData, + + UInt64 &speed, + UInt64 &usage, + + UInt32 complexity, unsigned benchWeight, + const UInt32 *checkSum, + const COneMethodInfo &method, + IBenchPrintCallback *_file, + #ifndef _7ZIP_ST + const CAffinityMode *affinityMode, + #endif + bool showRating, + CTotalBenchRes *encodeRes, + bool showFreq, UInt64 cpuFreq) +{ + if (numThreads == 0) + numThreads = 1; + + #ifdef _7ZIP_ST + numThreads = 1; + #endif + + const AString &methodName = method.MethodName; + // methodName.RemoveChar(L'-'); + CMethodId hashID; + if (!FindHashMethod( + EXTERNAL_CODECS_LOC_VARS + methodName, hashID)) + return E_NOTIMPL; + + /* + // if will generate random data in each thread, instead of global data + CMidAlignedBuffer buffer; + if (!fileData) + { + ALLOC_WITH_HRESULT(&buffer, bufferSize) + RandGen(buffer, bufferSize); + fileData = buffer; + } + */ + + const size_t bsize = (bufferSize == 0 ? 1 : bufferSize); + UInt64 numIterations = complexInCommands * 256 / complexity / bsize; + if (numIterations == 0) + numIterations = 1; + + CBenchInfoCalc progressInfoSpec; + CBenchInfo info; + + #ifndef _7ZIP_ST + bool mtEncMode = (numThreads > 1) || affinityMode->NeedAffinity(); + + if (mtEncMode) + { + CCrcThreads threads; + threads.Items = new CCrcInfo[numThreads]; + { + WRes wres = threads.Common.StartEvent.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + threads.NeedClose = true; + } + + UInt32 i; + for (i = 0; i < numThreads; i++) + { + CCrcInfo &ci = threads.Items[i]; + AString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, ci.Hasher)); + if (!ci.Hasher) + return E_NOTIMPL; + CMyComPtr scp; + ci.Hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + RINOK(method.SetCoderProps(scp)); + } + + ci.Callback = _file; + ci.Data = fileData; + ci.NumIterations = numIterations; + ci.Size = bufferSize; + ci.CheckSumDefined = false; + if (checkSum) + { + ci.CheckSum = *checkSum; + ci.CheckSumDefined = true; + } + + #ifdef USE_ALLOCA + ci.AllocaSize = (i * 16 * 21) & 0x7FF; + #endif + } + + for (i = 0; i < numThreads; i++) + { + CCrcInfo &ci = threads.Items[i]; + ci.ThreadIndex = i; + ci.Common = &threads.Common; + ci.AffinityMode = *affinityMode; + HRESULT hres = ci.CreateThread(); + if (ci.Thread.IsCreated()) + threads.NumThreads++; + if (hres != 0) + return hres; + } + + for (i = 0; i < numThreads; i++) + { + CCrcInfo &ci = threads.Items[i]; + WRes wres = ci.ReadyEvent.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + RINOK(ci.Res); + } + + progressInfoSpec.SetStartTime(); + + WRes wres = threads.StartAndWait(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + + progressInfoSpec.SetFinishTime(info); + + for (i = 0; i < numThreads; i++) + { + RINOK(threads.Items[i].Res); + if (i != 0) + if (threads.Items[i].CheckSum_Res != + threads.Items[i - 1].CheckSum_Res) + return S_FALSE; + } + } + else + #endif + { + CMyComPtr hasher; + AString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS hashID, name, hasher)); + if (!hasher) + return E_NOTIMPL; + CMyComPtr scp; + hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + { + RINOK(method.SetCoderProps(scp)); + } + CCrcInfo_Base crcib; + crcib.CreateLocalBuf = false; + RINOK(crcib.Generate(fileData, bufferSize)); + progressInfoSpec.SetStartTime(); + RINOK(crcib.CrcProcess(numIterations, checkSum, hasher, _file)); + progressInfoSpec.SetFinishTime(info); + } + + + UInt64 unpSize = numIterations * bufferSize; + UInt64 unpSizeThreads = unpSize * numThreads; + info.UnpackSize = unpSizeThreads; + info.PackSize = unpSizeThreads; + info.NumIterations = 1; + + if (_file) + { + if (showRating) + { + UInt64 unpSizeThreads2 = unpSizeThreads; + if (unpSizeThreads2 == 0) + unpSizeThreads2 = numIterations * 1 * numThreads; + const UInt64 numCommands = unpSizeThreads2 * complexity / 256; + const UInt64 rating = info.GetSpeed(numCommands); + PrintResults(_file, info, + benchWeight, rating, + showFreq, cpuFreq, encodeRes); + } + RINOK(_file->CheckBreak()); + } + + speed = info.GetSpeed(unpSizeThreads); + usage = info.GetUsage(); + + return S_OK; +} + + + +static HRESULT TotalBench_Hash( + DECL_EXTERNAL_CODECS_LOC_VARS + UInt64 complexInCommands, + UInt32 numThreads, + size_t bufSize, + const Byte *fileData, + IBenchPrintCallback *printCallback, CBenchCallbackToPrint *callback, + #ifndef _7ZIP_ST + const CAffinityMode *affinityMode, + #endif + CTotalBenchRes *encodeRes, + bool showFreq, UInt64 cpuFreq) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_Hash); i++) + { + const CBenchHash &bench = g_Hash[i]; + PrintLeft(*callback->_file, bench.Name, kFieldSize_Name); + // callback->BenchProps.DecComplexUnc = bench.DecComplexUnc; + // callback->BenchProps.DecComplexCompr = bench.DecComplexCompr; + // callback->BenchProps.EncComplex = bench.EncComplex; + + COneMethodInfo method; + NCOM::CPropVariant propVariant; + propVariant = bench.Name; + RINOK(method.ParseMethodFromPROPVARIANT(UString(), propVariant)); + + UInt64 speed, usage; + + HRESULT res = CrcBench( + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + numThreads, bufSize, fileData, + speed, usage, + bench.Complex, bench.Weight, + (!fileData && bufSize == (1 << kNumHashDictBits)) ? &bench.CheckSum : NULL, + method, + printCallback, + #ifndef _7ZIP_ST + affinityMode, + #endif + true, // showRating + encodeRes, showFreq, cpuFreq); + if (res == E_NOTIMPL) + { + // callback->Print(" ---"); + } + else + { + RINOK(res); + } + callback->NewLine(); + } + return S_OK; +} + +struct CTempValues +{ + UInt64 *Values; + CTempValues(UInt32 num) { Values = new UInt64[num]; } + ~CTempValues() { delete []Values; } +}; + +static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) +{ + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) + prop = s; + else if (result <= (UInt32)0xFFFFFFFF) + prop = (UInt32)result; + else + prop = result; +} + + +static bool AreSameMethodNames(const char *fullName, const char *shortName) +{ + return StringsAreEqualNoCase_Ascii(fullName, shortName); +} + + + + +static void Print_Usage_and_Threads(IBenchPrintCallback &f, UInt64 usage, UInt32 threads) +{ + PrintRequirements(f, "usage:", true, usage, "Benchmark threads: ", threads); +} + + +HRESULT Bench( + DECL_EXTERNAL_CODECS_LOC_VARS + IBenchPrintCallback *printCallback, + IBenchCallback *benchCallback, + const CObjectVector &props, + UInt32 numIterations, + bool multiDict, + IBenchFreqCallback *freqCallback) +{ + if (!CrcInternalTest()) + return E_FAIL; + + UInt32 numCPUs = 1; + UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; + + NSystem::CProcessAffinity threadsInfo; + threadsInfo.InitST(); + + #ifndef _7ZIP_ST + + if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0) + numCPUs = threadsInfo.GetNumProcessThreads(); + else + numCPUs = NSystem::GetNumberOfProcessors(); + + #endif + + // numCPUs = 24; + /* + { + DWORD_PTR mask = (1 << 0); + DWORD_PTR old = SetThreadAffinityMask(GetCurrentThread(), mask); + old = old; + DWORD_PTR old2 = SetThreadAffinityMask(GetCurrentThread(), mask); + old2 = old2; + return 0; + } + */ + + bool ramSize_Defined = NSystem::GetRamSize(ramSize); + + UInt32 numThreadsSpecified = numCPUs; + bool needSetComplexity = false; + UInt32 testTimeMs = kComplexInMs; + UInt32 startDicLog = 22; + bool startDicLog_Defined = false; + UInt64 specifiedFreq = 0; + bool multiThreadTests = false; + UInt64 complexInCommands = kComplexInCommands; + UInt32 numThreads_Start = 1; + + #ifndef _7ZIP_ST + CAffinityMode affinityMode; + #endif + + + COneMethodInfo method; + + CMidAlignedBuffer fileDataBuffer; + bool use_fileData = false; + bool isFixedDict = false; + + { + unsigned i; + + if (printCallback) + { + for (i = 0; i < props.Size(); i++) + { + const CProperty &property = props[i]; + printCallback->Print(" "); + printCallback->Print(GetAnsiString(property.Name)); + if (!property.Value.IsEmpty()) + { + printCallback->Print("="); + printCallback->Print(GetAnsiString(property.Value)); + } + } + if (!props.IsEmpty()) + printCallback->NewLine(); + } + + + for (i = 0; i < props.Size(); i++) + { + const CProperty &property = props[i]; + UString name (property.Name); + name.MakeLower_Ascii(); + + if (name.IsEqualTo("file")) + { + if (property.Value.IsEmpty()) + return E_INVALIDARG; + + NFile::NIO::CInFile file; + if (!file.Open(us2fs(property.Value))) + return GetLastError_noZero_HRESULT(); + size_t len; + { + UInt64 len64; + if (!file.GetLength(len64)) + return GetLastError_noZero_HRESULT(); + if (printCallback) + { + printCallback->Print("file size ="); + PrintNumber(*printCallback, len64, 0); + printCallback->NewLine(); + } + len = (size_t)len64; + if (len != len64) + return E_INVALIDARG; + } + + // (len == 0) is allowed. Also it's allowed if Alloc(0) returns NULL here + + ALLOC_WITH_HRESULT(&fileDataBuffer, len); + use_fileData = true; + + { + size_t processed; + if (!file.ReadFull((Byte *)fileDataBuffer, len, processed)) + return GetLastError_noZero_HRESULT(); + if (processed != len) + return E_FAIL; + } + continue; + } + + NCOM::CPropVariant propVariant; + if (!property.Value.IsEmpty()) + ParseNumberString(property.Value, propVariant); + + if (name.IsEqualTo("time")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)); + needSetComplexity = true; + testTimeMs *= 1000; + continue; + } + + if (name.IsEqualTo("timems")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, testTimeMs)); + needSetComplexity = true; + continue; + } + + if (name.IsEqualTo("tic")) + { + UInt32 v; + RINOK(ParsePropToUInt32(UString(), propVariant, v)); + if (v >= 64) + return E_INVALIDARG; + complexInCommands = (UInt64)1 << v; + continue; + } + + const bool isCurrent_fixedDict = name.IsEqualTo("df"); + if (isCurrent_fixedDict) + isFixedDict = true; + if (isCurrent_fixedDict || name.IsEqualTo("ds")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, startDicLog)); + if (startDicLog > 32) + return E_INVALIDARG; + startDicLog_Defined = true; + continue; + } + + if (name.IsEqualTo("mts")) + { + RINOK(ParsePropToUInt32(UString(), propVariant, numThreads_Start)); + continue; + } + + if (name.IsEqualTo("af")) + { + UInt32 bundle; + RINOK(ParsePropToUInt32(UString(), propVariant, bundle)); + if (bundle > 0 && bundle < numCPUs) + { + #ifndef _7ZIP_ST + affinityMode.SetLevels(numCPUs, 2); + affinityMode.NumBundleThreads = bundle; + #endif + } + continue; + } + + if (name.IsEqualTo("freq")) + { + UInt32 freq32 = 0; + RINOK(ParsePropToUInt32(UString(), propVariant, freq32)); + if (freq32 == 0) + return E_INVALIDARG; + specifiedFreq = (UInt64)freq32 * 1000000; + + if (printCallback) + { + printCallback->Print("freq="); + PrintNumber(*printCallback, freq32, 0); + printCallback->NewLine(); + } + + continue; + } + + if (name.IsPrefixedBy_Ascii_NoCase("mt")) + { + UString s = name.Ptr(2); + if (s.IsEqualTo("*") + || (s.IsEmpty() + && propVariant.vt == VT_BSTR + && StringsAreEqual_Ascii(propVariant.bstrVal, "*"))) + { + multiThreadTests = true; + continue; + } + #ifndef _7ZIP_ST + RINOK(ParseMtProp(s, propVariant, numCPUs, numThreadsSpecified)); + #endif + continue; + } + + RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant)); + } + } + + if (printCallback) + { + AString s; + + #ifndef _WIN32 + s += "Compiler: "; + GetCompiler(s); + printCallback->Print(s); + printCallback->NewLine(); + s.Empty(); + #endif + + GetSystemInfoText(s); + printCallback->Print(s); + printCallback->NewLine(); + } + + if (printCallback) + { + printCallback->Print("1T CPU Freq (MHz):"); + } + + if (printCallback || freqCallback) + { + UInt64 numMilCommands = 1 << 6; + if (specifiedFreq != 0) + { + while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000)) + numMilCommands >>= 1; + } + + for (int jj = 0;; jj++) + { + if (printCallback) + RINOK(printCallback->CheckBreak()); + + UInt64 start = ::GetTimeCount(); + UInt32 sum = (UInt32)start; + sum = CountCpuFreq(sum, (UInt32)(numMilCommands * 1000000 / kNumFreqCommands), g_BenchCpuFreqTemp); + if (sum == 0xF1541213) + if (printCallback) + printCallback->Print(""); + const UInt64 realDelta = ::GetTimeCount() - start; + start = realDelta; + if (start == 0) + start = 1; + if (start > (UInt64)1 << 61) + start = 1; + const UInt64 freq = GetFreq(); + // mips is constant in some compilers + const UInt64 hz = MyMultDiv64(numMilCommands * 1000000, start, freq); + const UInt64 mipsVal = numMilCommands * freq / start; + if (printCallback) + { + if (realDelta == 0) + { + printCallback->Print(" -"); + } + else + { + // PrintNumber(*printCallback, start, 0); + PrintNumber(*printCallback, mipsVal, 5); + } + } + if (freqCallback) + { + RINOK(freqCallback->AddCpuFreq(1, hz, kBenchmarkUsageMult)); + } + + if (jj >= 1) + { + bool needStop = (numMilCommands >= (1 << + #ifdef _DEBUG + 7 + #else + 11 + #endif + )); + if (start >= freq * 16) + { + printCallback->Print(" (Cmplx)"); + if (!freqCallback) // we don't want complexity change for old gui lzma benchmark + { + needSetComplexity = true; + } + needStop = true; + } + if (needSetComplexity) + SetComplexCommandsMs(testTimeMs, false, mipsVal * 1000000, complexInCommands); + if (needStop) + break; + numMilCommands <<= 1; + } + } + if (freqCallback) + { + RINOK(freqCallback->FreqsFinished(1)); + } + } + + if (numThreadsSpecified >= 2) + if (printCallback || freqCallback) + { + if (printCallback) + printCallback->NewLine(); + + /* it can show incorrect frequency for HT threads. + so we reduce freq test to (numCPUs / 2) */ + + UInt32 numThreads = numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2: numThreadsSpecified; + if (numThreads < 1) + numThreads = 1; + + if (printCallback) + { + char s[128]; + ConvertUInt64ToString(numThreads, s); + printCallback->Print(s); + printCallback->Print("T CPU Freq (MHz):"); + } + UInt64 numMilCommands = 1 << 10; + if (specifiedFreq != 0) + { + while (numMilCommands > 1 && specifiedFreq < (numMilCommands * 1000000)) + numMilCommands >>= 1; + } + + for (int jj = 0;; jj++) + { + if (printCallback) + RINOK(printCallback->CheckBreak()); + + { + // PrintLeft(f, "CPU", kFieldSize_Name); + + // UInt32 resVal; + + CFreqBench fb; + fb.complexInCommands = numMilCommands * 1000000; + fb.numThreads = numThreads; + // showFreq; + // fb.showFreq = (freqTest == kNumCpuTests - 1 || specifiedFreq != 0); + fb.showFreq = true; + fb.specifiedFreq = 1; + + HRESULT res = fb.FreqBench(NULL /* printCallback */ + #ifndef _7ZIP_ST + , &affinityMode + #endif + ); + RINOK(res); + + if (freqCallback) + { + RINOK(freqCallback->AddCpuFreq(numThreads, fb.CpuFreqRes, fb.UsageRes)); + } + + if (printCallback) + { + /* + if (realDelta == 0) + { + printCallback->Print(" -"); + } + else + */ + { + // PrintNumber(*printCallback, start, 0); + PrintUsage(*printCallback, fb.UsageRes, 3); + printCallback->Print("%"); + PrintNumber(*printCallback, fb.CpuFreqRes / 1000000, 0); + printCallback->Print(" "); + + // PrintNumber(*printCallback, fb.UsageRes, 5); + } + } + } + // if (jj >= 1) + { + bool needStop = (numMilCommands >= (1 << + #ifdef _DEBUG + 7 + #else + 11 + #endif + )); + if (needStop) + break; + numMilCommands <<= 1; + } + } + if (freqCallback) + { + RINOK(freqCallback->FreqsFinished(numThreads)); + } + } + + + if (printCallback) + { + printCallback->NewLine(); + printCallback->NewLine(); + PrintRequirements(*printCallback, "size: ", ramSize_Defined, ramSize, "CPU hardware threads:", numCPUs); + printCallback->Print(GetProcessThreadsInfo(threadsInfo)); + printCallback->NewLine(); + } + + if (numThreadsSpecified < 1 || numThreadsSpecified > kNumThreadsMax) + return E_INVALIDARG; + + UInt64 dict = (UInt64)1 << startDicLog; + const bool dictIsDefined = (isFixedDict || method.Get_DicSize(dict)); + + const int level = method.GetLevel(); + + if (method.MethodName.IsEmpty()) + method.MethodName = "LZMA"; + + if (benchCallback) + { + CBenchProps benchProps; + benchProps.SetLzmaCompexity(); + const UInt64 dictSize = method.Get_Lzma_DicSize(); + + size_t uncompressedDataSize; + if (use_fileData) + { + uncompressedDataSize = fileDataBuffer.Size(); + } + else + { + uncompressedDataSize = kAdditionalSize + (size_t)dictSize; + if (uncompressedDataSize < dictSize) + return E_INVALIDARG; + } + + return MethodBench( + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + #ifndef _7ZIP_ST + true, numThreadsSpecified, + &affinityMode, + #endif + method, + uncompressedDataSize, (const Byte *)fileDataBuffer, + kOldLzmaDictBits, printCallback, benchCallback, &benchProps); + } + + AString methodName (method.MethodName); + if (methodName.IsEqualTo_Ascii_NoCase("CRC")) + methodName = "crc32"; + method.MethodName = methodName; + CMethodId hashID; + + if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, hashID)) + { + if (!printCallback) + return S_FALSE; + IBenchPrintCallback &f = *printCallback; + + UInt64 dict64 = dict; + if (!dictIsDefined) + dict64 = (1 << 27); + if (use_fileData) + { + if (!dictIsDefined) + dict64 = fileDataBuffer.Size(); + else if (dict64 > fileDataBuffer.Size()) + dict64 = fileDataBuffer.Size(); + } + + // methhodName.RemoveChar(L'-'); + UInt32 complexity = 10000; + const UInt32 *checkSum = NULL; + { + unsigned i; + for (i = 0; i < ARRAY_SIZE(g_Hash); i++) + { + const CBenchHash &h = g_Hash[i]; + AString benchMethod (h.Name); + AString benchProps; + int propPos = benchMethod.Find(':'); + if (propPos >= 0) + { + benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); + benchMethod.DeleteFrom((unsigned)propPos); + } + + if (AreSameMethodNames(benchMethod, methodName)) + { + bool isMainMathed = method.PropsString.IsEmpty(); + if (isMainMathed) + isMainMathed = !checkSum + || (benchMethod.IsEqualTo_Ascii_NoCase("crc32") && benchProps.IsEqualTo_Ascii_NoCase("8")); + const bool sameProps = method.PropsString.IsEqualTo_Ascii_NoCase(benchProps); + if (sameProps || isMainMathed) + { + complexity = h.Complex; + checkSum = &h.CheckSum; + if (sameProps) + break; + } + } + } + if (!checkSum) + return E_NOTIMPL; + } + + { + UInt64 usage = 1 << 20; + UInt64 bufSize = dict64; + if (use_fileData) + { + usage += fileDataBuffer.Size(); + if (bufSize > fileDataBuffer.Size()) + bufSize = fileDataBuffer.Size(); + #ifndef _7ZIP_ST + if (numThreadsSpecified != 1) + usage += bufSize * numThreadsSpecified * (k_Crc_CreateLocalBuf_For_File ? 1 : 0); + #endif + } + else + usage += numThreadsSpecified * bufSize; + Print_Usage_and_Threads(f, usage, numThreadsSpecified); + } + + f.NewLine(); + + const unsigned kFieldSize_CrcSpeed = 7; + CUIntVector numThreadsVector; + { + unsigned nt = numThreads_Start; + for (;;) + { + if (nt > numThreadsSpecified) + break; + numThreadsVector.Add(nt); + unsigned next = nt * 2; + UInt32 ntHalf= numThreadsSpecified / 2; + if (ntHalf > nt && ntHalf < next) + numThreadsVector.Add(ntHalf); + if (numThreadsSpecified > nt && numThreadsSpecified < next) + numThreadsVector.Add(numThreadsSpecified); + nt = next; + } + { + f.NewLine(); + f.Print("THRD"); + FOR_VECTOR (ti, numThreadsVector) + { + PrintNumber(f, numThreadsVector[ti], 1 + kFieldSize_Usage + kFieldSize_CrcSpeed); + } + } + { + f.NewLine(); + f.Print(" "); + FOR_VECTOR (ti, numThreadsVector) + { + PrintRight(f, "Usage", kFieldSize_Usage + 1); + PrintRight(f, "BW", kFieldSize_CrcSpeed + 1); + } + } + { + f.NewLine(); + f.Print("Size"); + FOR_VECTOR (ti, numThreadsVector) + { + PrintRight(f, "%", kFieldSize_Usage + 1); + PrintRight(f, "MB/s", kFieldSize_CrcSpeed + 1); + } + } + } + + f.NewLine(); + f.NewLine(); + + CTempValues speedTotals(numThreadsVector.Size()); + CTempValues usageTotals(numThreadsVector.Size()); + { + FOR_VECTOR (ti, numThreadsVector) + { + speedTotals.Values[ti] = 0; + usageTotals.Values[ti] = 0; + } + } + + UInt64 numSteps = 0; + + for (UInt32 i = 0; i < numIterations; i++) + { + unsigned pow = 10; // kNumHashDictBits + if (startDicLog_Defined) + pow = startDicLog; + for (;; pow++) + { + const UInt64 bufSize = (UInt64)1 << pow; + char s[16]; + ConvertUInt32ToString(pow, s); + unsigned pos = MyStringLen(s); + s[pos++] = ':'; + s[pos++] = ' '; + s[pos] = 0; + PrintRight(f, s, 4); + + size_t dataSize = fileDataBuffer.Size(); + if (dataSize > bufSize || !use_fileData) + dataSize = (size_t)bufSize; + + FOR_VECTOR (ti, numThreadsVector) + { + RINOK(f.CheckBreak()); + const UInt32 t = numThreadsVector[ti]; + UInt64 speed = 0; + UInt64 usage = 0; + + HRESULT res = CrcBench(EXTERNAL_CODECS_LOC_VARS complexInCommands, + t, + dataSize, (const Byte *)fileDataBuffer, + speed, usage, + complexity, + 1, // benchWeight, + (pow == kNumHashDictBits && !use_fileData) ? checkSum : NULL, + method, + &f, + #ifndef _7ZIP_ST + &affinityMode, + #endif + false, // showRating + NULL, false, 0); + + RINOK(res); + + PrintUsage(f, usage, kFieldSize_Usage); + PrintNumber(f, speed / 1000000, kFieldSize_CrcSpeed); + speedTotals.Values[ti] += speed; + usageTotals.Values[ti] += usage; + } + + f.NewLine(); + numSteps++; + if (dataSize >= dict64) + break; + } + } + if (numSteps != 0) + { + f.NewLine(); + f.Print("Avg:"); + for (unsigned ti = 0; ti < numThreadsVector.Size(); ti++) + { + PrintUsage(f, usageTotals.Values[ti] / numSteps, kFieldSize_Usage); + PrintNumber(f, speedTotals.Values[ti] / numSteps / 1000000, kFieldSize_CrcSpeed); + } + f.NewLine(); + } + return S_OK; + } + + bool use2Columns = false; + + bool totalBenchMode = (method.MethodName.IsEqualTo_Ascii_NoCase("*")); + bool onlyHashBench = false; + if (method.MethodName.IsEqualTo_Ascii_NoCase("hash")) + { + onlyHashBench = true; + totalBenchMode = true; + } + + // ---------- Threads loop ---------- + for (unsigned threadsPassIndex = 0; threadsPassIndex < 3; threadsPassIndex++) + { + + UInt32 numThreads = numThreadsSpecified; + + if (!multiThreadTests) + { + if (threadsPassIndex != 0) + break; + } + else + { + numThreads = 1; + if (threadsPassIndex != 0) + { + if (numCPUs < 2) + break; + numThreads = numCPUs; + if (threadsPassIndex == 1) + { + if (numCPUs >= 4) + numThreads = numCPUs / 2; + } + else if (numCPUs < 4) + break; + } + } + + CBenchCallbackToPrint callback; + callback.Init(); + callback._file = printCallback; + + IBenchPrintCallback &f = *printCallback; + + if (threadsPassIndex > 0) + { + f.NewLine(); + f.NewLine(); + } + + if (!dictIsDefined && !onlyHashBench) + { + const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); + unsigned dicSizeLog = dicSizeLog_Main; + + #ifdef UNDER_CE + dicSizeLog = (UInt64)1 << 20; + #endif + + if (ramSize_Defined) + for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) + if (GetBenchMemoryUsage(numThreads, level, ((UInt64)1 << dicSizeLog), totalBenchMode) + (8 << 20) <= ramSize) + break; + + dict = (UInt64)1 << dicSizeLog; + + if (totalBenchMode && dicSizeLog != dicSizeLog_Main) + { + f.Print("Dictionary reduced to: "); + PrintNumber(f, dicSizeLog, 1); + f.NewLine(); + } + } + + Print_Usage_and_Threads(f, + onlyHashBench ? + GetBenchMemoryUsage_Hash(numThreads, dict) : + GetBenchMemoryUsage(numThreads, level, dict, totalBenchMode), + numThreads); + + f.NewLine(); + + f.NewLine(); + + if (totalBenchMode) + { + callback.NameFieldSize = kFieldSize_Name; + use2Columns = false; + } + else + { + callback.NameFieldSize = kFieldSize_SmallName; + use2Columns = true; + } + callback.Use2Columns = use2Columns; + + bool showFreq = false; + UInt64 cpuFreq = 0; + + if (totalBenchMode) + { + showFreq = true; + } + + unsigned fileldSize = kFieldSize_TotalSize; + if (showFreq) + fileldSize += kFieldSize_EUAndEffec; + + if (use2Columns) + { + PrintSpaces(f, callback.NameFieldSize); + PrintRight(f, "Compressing", fileldSize); + f.Print(kSep); + PrintRight(f, "Decompressing", fileldSize); + } + f.NewLine(); + PrintLeft(f, totalBenchMode ? "Method" : "Dict", callback.NameFieldSize); + + int j; + + for (j = 0; j < 2; j++) + { + PrintRight(f, "Speed", kFieldSize_Speed + 1); + PrintRight(f, "Usage", kFieldSize_Usage + 1); + PrintRight(f, "R/U", kFieldSize_RU + 1); + PrintRight(f, "Rating", kFieldSize_Rating + 1); + if (showFreq) + { + PrintRight(f, "E/U", kFieldSize_EU + 1); + PrintRight(f, "Effec", kFieldSize_Effec + 1); + } + if (!use2Columns) + break; + if (j == 0) + f.Print(kSep); + } + + f.NewLine(); + PrintSpaces(f, callback.NameFieldSize); + + for (j = 0; j < 2; j++) + { + PrintRight(f, "KiB/s", kFieldSize_Speed + 1); + PrintRight(f, "%", kFieldSize_Usage + 1); + PrintRight(f, "MIPS", kFieldSize_RU + 1); + PrintRight(f, "MIPS", kFieldSize_Rating + 1); + if (showFreq) + { + PrintRight(f, "%", kFieldSize_EU + 1); + PrintRight(f, "%", kFieldSize_Effec + 1); + } + if (!use2Columns) + break; + if (j == 0) + f.Print(kSep); + } + + f.NewLine(); + f.NewLine(); + + if (specifiedFreq != 0) + cpuFreq = specifiedFreq; + + // bool showTotalSpeed = false; + + if (totalBenchMode) + { + for (UInt32 i = 0; i < numIterations; i++) + { + if (i != 0) + printCallback->NewLine(); + + const unsigned kNumCpuTests = 3; + for (unsigned freqTest = 0; freqTest < kNumCpuTests; freqTest++) + { + PrintLeft(f, "CPU", kFieldSize_Name); + + // UInt32 resVal; + + CFreqBench fb; + fb.complexInCommands = complexInCommands; + fb.numThreads = numThreads; + // showFreq; + fb.showFreq = (freqTest == kNumCpuTests - 1 || specifiedFreq != 0); + fb.specifiedFreq = specifiedFreq; + + HRESULT res = fb.FreqBench(printCallback + #ifndef _7ZIP_ST + , &affinityMode + #endif + ); + RINOK(res); + + cpuFreq = fb.CpuFreqRes; + callback.NewLine(); + + if (specifiedFreq != 0) + cpuFreq = specifiedFreq; + + if (testTimeMs >= 1000) + if (freqTest == kNumCpuTests - 1) + { + // SetComplexCommandsMs(testTimeMs, specifiedFreq != 0, cpuFreq, complexInCommands); + } + } + callback.NewLine(); + + // return S_OK; // change it + + callback.SetFreq(true, cpuFreq); + + if (!onlyHashBench) + { + size_t dataSize = (size_t)dict; + if (use_fileData) + { + dataSize = fileDataBuffer.Size(); + if (dictIsDefined && dataSize > dict) + dataSize = (size_t)dict; + } + + HRESULT res = TotalBench(EXTERNAL_CODECS_LOC_VARS + complexInCommands, + #ifndef _7ZIP_ST + numThreads, + &affinityMode, + #endif + dictIsDefined || use_fileData, // forceUnpackSize + dataSize, + (const Byte *)fileDataBuffer, + printCallback, &callback); + RINOK(res); + } + + { + size_t dataSize = (size_t)1 << kNumHashDictBits; + if (dictIsDefined) + { + dataSize = (size_t)dict; + if (dataSize != dict) + return E_OUTOFMEMORY; + } + if (use_fileData) + { + dataSize = fileDataBuffer.Size(); + if (dictIsDefined && dataSize > dict) + dataSize = (size_t)dict; + } + + HRESULT res = TotalBench_Hash(EXTERNAL_CODECS_LOC_VARS complexInCommands, numThreads, + dataSize, (const Byte *)fileDataBuffer, + printCallback, &callback, + #ifndef _7ZIP_ST + &affinityMode, + #endif + &callback.EncodeRes, true, cpuFreq); + RINOK(res); + } + + callback.NewLine(); + { + PrintLeft(f, "CPU", kFieldSize_Name); + + CFreqBench fb; + fb.complexInCommands = complexInCommands; + fb.numThreads = numThreads; + // showFreq; + fb.showFreq = (specifiedFreq != 0); + fb.specifiedFreq = specifiedFreq; + + HRESULT res = fb.FreqBench(printCallback + #ifndef _7ZIP_ST + , &affinityMode + #endif + ); + RINOK(res); + callback.NewLine(); + } + } + } + else + { + needSetComplexity = true; + if (!methodName.IsEqualTo_Ascii_NoCase("LZMA")) + { + unsigned i; + for (i = 0; i < ARRAY_SIZE(g_Bench); i++) + { + const CBenchMethod &h = g_Bench[i]; + AString benchMethod (h.Name); + AString benchProps; + int propPos = benchMethod.Find(':'); + if (propPos >= 0) + { + benchProps = benchMethod.Ptr((unsigned)(propPos + 1)); + benchMethod.DeleteFrom((unsigned)propPos); + } + + if (AreSameMethodNames(benchMethod, methodName)) + { + if (benchProps.IsEmpty() + || (benchProps == "x5" && method.PropsString.IsEmpty()) + || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) + { + callback.BenchProps.EncComplex = h.EncComplex; + callback.BenchProps.DecComplexCompr = h.DecComplexCompr; + callback.BenchProps.DecComplexUnc = h.DecComplexUnc;; + needSetComplexity = false; + break; + } + } + } + if (i == ARRAY_SIZE(g_Bench)) + return E_NOTIMPL; + } + if (needSetComplexity) + callback.BenchProps.SetLzmaCompexity(); + + if (startDicLog < kBenchMinDicLogSize) + startDicLog = kBenchMinDicLogSize; + + for (unsigned i = 0; i < numIterations; i++) + { + unsigned pow = (dict < GetDictSizeFromLog(startDicLog)) ? kBenchMinDicLogSize : (unsigned)startDicLog; + if (!multiDict) + pow = 32; + while (GetDictSizeFromLog(pow) > dict && pow > 0) + pow--; + for (; GetDictSizeFromLog(pow) <= dict; pow++) + { + char s[16]; + ConvertUInt32ToString(pow, s); + unsigned pos = MyStringLen(s); + s[pos++] = ':'; + s[pos] = 0; + PrintLeft(f, s, kFieldSize_SmallName); + callback.DictSize = (UInt64)1 << pow; + + COneMethodInfo method2 = method; + + if (StringsAreEqualNoCase_Ascii(method2.MethodName, "LZMA")) + { + // We add dictionary size property. + // method2 can have two different dictionary size properties. + // And last property is main. + NCOM::CPropVariant propVariant = (UInt32)pow; + RINOK(method2.ParseMethodFromPROPVARIANT((UString)"d", propVariant)); + } + + size_t uncompressedDataSize; + if (use_fileData) + { + uncompressedDataSize = fileDataBuffer.Size(); + } + else + { + uncompressedDataSize = (size_t)callback.DictSize; + if (uncompressedDataSize != callback.DictSize) + return E_OUTOFMEMORY; + if (uncompressedDataSize >= (1 << 18)) + uncompressedDataSize += kAdditionalSize; + } + + HRESULT res = MethodBench( + EXTERNAL_CODECS_LOC_VARS + complexInCommands, + #ifndef _7ZIP_ST + true, numThreads, + &affinityMode, + #endif + method2, + uncompressedDataSize, (const Byte *)fileDataBuffer, + kOldLzmaDictBits, printCallback, &callback, &callback.BenchProps); + f.NewLine(); + RINOK(res); + if (!multiDict) + break; + } + } + } + + PrintChars(f, '-', callback.NameFieldSize + fileldSize); + + if (use2Columns) + { + f.Print(kSep); + PrintChars(f, '-', fileldSize); + } + + f.NewLine(); + + if (use2Columns) + { + PrintLeft(f, "Avr:", callback.NameFieldSize); + PrintTotals(f, showFreq, cpuFreq, !totalBenchMode, callback.EncodeRes); + f.Print(kSep); + PrintTotals(f, showFreq, cpuFreq, !totalBenchMode, callback.DecodeRes); + f.NewLine(); + } + + PrintLeft(f, "Tot:", callback.NameFieldSize); + CTotalBenchRes midRes; + midRes = callback.EncodeRes; + midRes.Update_With_Res(callback.DecodeRes); + + // midRes.SetSum(callback.EncodeRes, callback.DecodeRes); + PrintTotals(f, showFreq, cpuFreq, false, midRes); + f.NewLine(); + + } + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.h new file mode 100644 index 0000000..ab0c304 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Bench.h @@ -0,0 +1,122 @@ +// Bench.h + +#ifndef __7ZIP_BENCH_H +#define __7ZIP_BENCH_H + +#include "../../../Windows/System.h" + +#include "../../Common/CreateCoder.h" +#include "../../UI/Common/Property.h" + +UInt64 Benchmark_GetUsage_Percents(UInt64 usage); + +struct CBenchInfo +{ + UInt64 GlobalTime; + UInt64 GlobalFreq; + UInt64 UserTime; + UInt64 UserFreq; + UInt64 UnpackSize; + UInt64 PackSize; + UInt64 NumIterations; + + /* + during Code(): we track benchInfo only from one thread (theads with index[0]) + NumIterations means number of threads + UnpackSize and PackSize are total sizes of all iterations of current thread + after Code(): + NumIterations means the number of Iterations + UnpackSize and PackSize are total sizes of all threads + */ + + CBenchInfo(): NumIterations(0) {} + + UInt64 GetUsage() const; + UInt64 GetRatingPerUsage(UInt64 rating) const; + UInt64 GetSpeed(UInt64 numUnits) const; + UInt64 GetUnpackSizeSpeed() const { return GetSpeed(UnpackSize * NumIterations); } + + UInt64 Get_UnpackSize_Full() const { return UnpackSize * NumIterations; } + + UInt64 GetRating_LzmaEnc(UInt64 dictSize) const; + UInt64 GetRating_LzmaDec() const; +}; + + +struct CTotalBenchRes +{ + // UInt64 NumIterations1; // for Usage + UInt64 NumIterations2; // for Rating / RPU + + UInt64 Rating; + UInt64 Usage; + UInt64 RPU; + UInt64 Speed; + + void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; Speed = 0; } + + void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2) + { + Rating = (r1.Rating + r2.Rating); + Usage = (r1.Usage + r2.Usage); + RPU = (r1.RPU + r2.RPU); + Speed = (r1.Speed + r2.Speed); + // NumIterations1 = (r1.NumIterations1 + r2.NumIterations1); + NumIterations2 = (r1.NumIterations2 + r2.NumIterations2); + } + + void Generate_From_BenchInfo(const CBenchInfo &info); + void Mult_For_Weight(unsigned weight); + void Update_With_Res(const CTotalBenchRes &r); +}; + + + +struct IBenchCallback +{ + // virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0; + virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; + virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; +}; + + + +const unsigned kBenchMinDicLogSize = 18; + +UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench); + +struct IBenchPrintCallback +{ + virtual void Print(const char *s) = 0; + virtual void NewLine() = 0; + virtual HRESULT CheckBreak() = 0; +}; + +struct IBenchFreqCallback +{ + virtual HRESULT AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage) = 0; + virtual HRESULT FreqsFinished(unsigned numThreads) = 0; +}; + +HRESULT Bench( + DECL_EXTERNAL_CODECS_LOC_VARS + IBenchPrintCallback *printCallback, + IBenchCallback *benchCallback, + const CObjectVector &props, + UInt32 numIterations, + bool multiDict, + IBenchFreqCallback *freqCallback = NULL); + +AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti); + +void GetSysInfo(AString &s1, AString &s2); +void GetCpuName(AString &s); +void AddCpuFeatures(AString &s); + +#ifdef _7ZIP_LARGE_PAGES +void Add_LargePages_String(AString &s); +#else +// #define Add_LargePages_String +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.cpp new file mode 100644 index 0000000..8c34ffc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.cpp @@ -0,0 +1,37 @@ +// DefaultName.cpp + +#include "StdAfx.h" + +#include "DefaultName.h" + +static UString GetDefaultName3(const UString &fileName, + const UString &extension, const UString &addSubExtension) +{ + const unsigned extLen = extension.Len(); + const unsigned fileNameLen = fileName.Len(); + + if (fileNameLen > extLen + 1) + { + const unsigned dotPos = fileNameLen - (extLen + 1); + if (fileName[dotPos] == '.') + if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1))) + return fileName.Left(dotPos) + addSubExtension; + } + + int dotPos = fileName.ReverseFind_Dot(); + if (dotPos > 0) + return fileName.Left((unsigned)dotPos) + addSubExtension; + + if (addSubExtension.IsEmpty()) + return fileName + L'~'; + else + return fileName + addSubExtension; +} + +UString GetDefaultName2(const UString &fileName, + const UString &extension, const UString &addSubExtension) +{ + UString name = GetDefaultName3(fileName, extension, addSubExtension); + name.TrimRight(); + return name; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.h new file mode 100644 index 0000000..df16456 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DefaultName.h @@ -0,0 +1,11 @@ +// DefaultName.h + +#ifndef __DEFAULT_NAME_H +#define __DEFAULT_NAME_H + +#include "../../../Common/MyString.h" + +UString GetDefaultName2(const UString &fileName, + const UString &extension, const UString &addSubExtension); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DirItem.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DirItem.h new file mode 100644 index 0000000..337cd1a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/DirItem.h @@ -0,0 +1,212 @@ +// DirItem.h + +#ifndef __DIR_ITEM_H +#define __DIR_ITEM_H + +#ifdef _WIN32 +#include "../../../Common/MyLinux.h" +#endif + +#include "../../../Common/MyString.h" + +#include "../../../Windows/FileFind.h" + +#include "../../Common/UniqBlocks.h" + +#include "../../Archive/IArchive.h" + +struct CDirItemsStat +{ + UInt64 NumDirs; + UInt64 NumFiles; + UInt64 NumAltStreams; + UInt64 FilesSize; + UInt64 AltStreamsSize; + + UInt64 NumErrors; + + // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; } + UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; } + UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; } + + bool IsEmpty() const { return + 0 == NumDirs + && 0 == NumFiles + && 0 == NumAltStreams + && 0 == FilesSize + && 0 == AltStreamsSize + && 0 == NumErrors; } + + CDirItemsStat(): + NumDirs(0), + NumFiles(0), + NumAltStreams(0), + FilesSize(0), + AltStreamsSize(0), + NumErrors(0) + {} +}; + + +struct CDirItemsStat2: public CDirItemsStat +{ + UInt64 Anti_NumDirs; + UInt64 Anti_NumFiles; + UInt64 Anti_NumAltStreams; + + // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); } + UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); } + + bool IsEmpty() const { return CDirItemsStat::IsEmpty() + && 0 == Anti_NumDirs + && 0 == Anti_NumFiles + && 0 == Anti_NumAltStreams; } + + CDirItemsStat2(): + Anti_NumDirs(0), + Anti_NumFiles(0), + Anti_NumAltStreams(0) + {} +}; + + + +#define INTERFACE_IDirItemsCallback(x) \ + virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \ + virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \ + +struct IDirItemsCallback +{ + INTERFACE_IDirItemsCallback(=0) +}; + +struct CDirItem +{ + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + UString Name; + + #ifndef UNDER_CE + CByteBuffer ReparseData; + + #ifdef _WIN32 + // UString ShortName; + CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format + bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } + #else + bool AreReparseData() const { return ReparseData.Size() != 0; } + #endif // _WIN32 + + #endif // !UNDER_CE + + UInt32 Attrib; + int PhyParent; + int LogParent; + int SecureIndex; + + bool IsAltStream; + + CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {} + + bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } + bool IsReadOnly() const { return (Attrib & FILE_ATTRIBUTE_READONLY) != 0; } + bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } + + #ifdef _WIN32 + UInt32 GetPosixAttrib() const + { + UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; + v |= (IsReadOnly() ? 0555 : 0777); + return v; + } + #endif +}; + + + +class CDirItems +{ + UStringVector Prefixes; + CIntVector PhyParents; + CIntVector LogParents; + + UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; + + HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); + +public: + CObjectVector Items; + + bool SymLinks; + bool ScanAltStreams; + + CDirItemsStat Stat; + + #if !defined(UNDER_CE) + HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, + const FString &phyPrefix); + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + CUniqBlocks SecureBlocks; + CByteBuffer TempSecureBuf; + bool _saclEnabled; + bool ReadSecure; + + HRESULT AddSecurityItem(const FString &path, int &secureIndex); + HRESULT FillFixedReparse(); + + #endif + + IDirItemsCallback *Callback; + + CDirItems(); + + void AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NWindows::NFile::NFind::CFileInfo &fi); + + HRESULT AddError(const FString &path, DWORD errorCode); + HRESULT AddError(const FString &path); + + HRESULT ScanProgress(const FString &path); + + // unsigned GetNumFolders() const { return Prefixes.Size(); } + FString GetPhyPath(unsigned index) const; + UString GetLogPath(unsigned index) const; + + unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); + void DeleteLastPrefix(); + + // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector &files); + HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector &files); + + HRESULT EnumerateItems2( + const FString &phyPrefix, + const UString &logPrefix, + const FStringVector &filePaths, + FStringVector *requestedPaths); + + void ReserveDown(); +}; + + +struct CArcItem +{ + UInt64 Size; + FILETIME MTime; + UString Name; + bool IsDir; + bool IsAltStream; + bool SizeDefined; + bool MTimeDefined; + bool Censored; + UInt32 IndexInServer; + int TimeType; + + CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.cpp new file mode 100644 index 0000000..7a2dd00 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -0,0 +1,1403 @@ +// EnumDirItems.cpp + +#include "StdAfx.h" + +#include +// #include + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/FileName.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + +#include "EnumDirItems.h" +#include "SortUtils.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex, + const NFind::CFileInfo &fi) +{ + CDirItem di; + di.Size = fi.Size; + di.CTime = fi.CTime; + di.ATime = fi.ATime; + di.MTime = fi.MTime; + di.Attrib = fi.Attrib; + di.IsAltStream = fi.IsAltStream; + di.PhyParent = phyParent; + di.LogParent = logParent; + di.SecureIndex = secureIndex; + di.Name = fs2us(fi.Name); + #if defined(_WIN32) && !defined(UNDER_CE) + // di.ShortName = fs2us(fi.ShortName); + #endif + Items.Add(di); + + if (fi.IsDir()) + Stat.NumDirs++; + else if (fi.IsAltStream) + { + Stat.NumAltStreams++; + Stat.AltStreamsSize += fi.Size; + } + else + { + Stat.NumFiles++; + Stat.FilesSize += fi.Size; + } +} + +// (DWORD)E_FAIL +#define DI_DEFAULT_ERROR ERROR_INVALID_FUNCTION + +HRESULT CDirItems::AddError(const FString &path, DWORD errorCode) +{ + if (errorCode == 0) + errorCode = DI_DEFAULT_ERROR; + Stat.NumErrors++; + if (Callback) + return Callback->ScanError(path, errorCode); + return S_OK; +} + +HRESULT CDirItems::AddError(const FString &path) +{ + return AddError(path, ::GetLastError()); +} + +static const unsigned kScanProgressStepMask = (1 << 12) - 1; + +HRESULT CDirItems::ScanProgress(const FString &dirPath) +{ + if (Callback) + return Callback->ScanProgress(Stat, dirPath, true); + return S_OK; +} + +UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const +{ + UString path; + unsigned len = name.Len(); + + int i; + for (i = index; i >= 0; i = parents[(unsigned)i]) + len += Prefixes[(unsigned)i].Len(); + + wchar_t *p = path.GetBuf_SetEnd(len) + len; + + p -= name.Len(); + wmemcpy(p, (const wchar_t *)name, name.Len()); + + for (i = index; i >= 0; i = parents[(unsigned)i]) + { + const UString &s = Prefixes[(unsigned)i]; + p -= s.Len(); + wmemcpy(p, (const wchar_t *)s, s.Len()); + } + + return path; +} + +FString CDirItems::GetPhyPath(unsigned index) const +{ + const CDirItem &di = Items[index]; + return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name)); +} + +UString CDirItems::GetLogPath(unsigned index) const +{ + const CDirItem &di = Items[index]; + return GetPrefixesPath(LogParents, di.LogParent, di.Name); +} + +void CDirItems::ReserveDown() +{ + Prefixes.ReserveDown(); + PhyParents.ReserveDown(); + LogParents.ReserveDown(); + Items.ReserveDown(); +} + +unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) +{ + PhyParents.Add(phyParent); + LogParents.Add(logParent); + return Prefixes.Add(prefix); +} + +void CDirItems::DeleteLastPrefix() +{ + PhyParents.DeleteBack(); + LogParents.DeleteBack(); + Prefixes.DeleteBack(); +} + +bool InitLocalPrivileges(); + +CDirItems::CDirItems(): + SymLinks(false), + ScanAltStreams(false) + #ifdef _USE_SECURITY_CODE + , ReadSecure(false) + #endif + , Callback(NULL) +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} + + +#ifdef _USE_SECURITY_CODE + +HRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex) +{ + secureIndex = -1; + + SECURITY_INFORMATION securInfo = + DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + OWNER_SECURITY_INFORMATION; + if (_saclEnabled) + securInfo |= SACL_SECURITY_INFORMATION; + + DWORD errorCode = 0; + DWORD secureSize; + + BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + + if (res) + { + if (secureSize == 0) + return S_OK; + if (secureSize > TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + } + else + { + errorCode = GetLastError(); + if (errorCode == ERROR_INSUFFICIENT_BUFFER) + { + if (secureSize <= TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION; + else + { + TempSecureBuf.Alloc(secureSize); + res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize); + if (res) + { + if (secureSize != TempSecureBuf.Size()) + errorCode = ERROR_INVALID_FUNCTION;; + } + else + errorCode = GetLastError(); + } + } + } + + if (res) + { + secureIndex = (int)SecureBlocks.AddUniq(TempSecureBuf, secureSize); + return S_OK; + } + + return AddError(path, errorCode); +} + +#endif // _USE_SECURITY_CODE + + +HRESULT CDirItems::EnumerateOneDir(const FString &phyPrefix, CObjectVector &files) +{ + NFind::CEnumerator enumerator; + // printf("\n enumerator.SetDirPrefix(phyPrefix) \n"); + + enumerator.SetDirPrefix(phyPrefix); + + #ifdef _WIN32 + + NFind::CFileInfo fi; + + for (unsigned ttt = 0; ; ttt++) + { + bool found; + if (!enumerator.Next(fi, found)) + return AddError(phyPrefix); + if (!found) + return S_OK; + files.Add(fi); + if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + } + + #else // _WIN32 + + // enumerator.SolveLinks = !SymLinks; + + CObjectVector entries; + + for (unsigned ttt = 0; ; ttt++) + { + bool found; + NFind::CDirEntry de; + if (!enumerator.Next(de, found)) + { + return AddError(phyPrefix); + } + if (!found) + break; + entries.Add(de); + } + + FOR_VECTOR(i, entries) + { + const NFind::CDirEntry &de = entries[i]; + NFind::CFileInfo fi; + if (!enumerator.Fill_FileInfo(de, fi, !SymLinks)) + // if (!fi.Find_AfterEnumerator(path)) + { + const FString path = phyPrefix + de.Name; + { + RINOK(AddError(path)); + continue; + } + } + + files.Add(fi); + + if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + } + + return S_OK; + + #endif // _WIN32 +} + + + + +HRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix) +{ + RINOK(ScanProgress(phyPrefix)); + + CObjectVector files; + RINOK(EnumerateOneDir(phyPrefix, files)); + + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + const NFind::CFileInfo &fi = files[i]; + #else + const NFind::CFileInfo &fi = files[i]; + /* + NFind::CFileInfo fi; + { + const NFind::CDirEntry &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(AddError(path)); + continue; + } + fi.Name = di.Name; + } + */ + #endif + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + { + RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex)); + } + #endif + + AddDirFileInfo(phyParent, logParent, secureIndex, fi); + + if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(ScanProgress(phyPrefix)); + } + + if (fi.IsDir()) + { + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2)); + RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + name2)); + } + } + return S_OK; +} + + +/* +EnumerateItems2() + const FStringVector &filePaths - are path without tail slashes. + All dir prefixes of filePaths will be not stores in logical paths +fix it: we can scan AltStream also. +*/ + +#ifdef _WIN32 +// #define FOLLOW_LINK_PARAM +// #define FOLLOW_LINK_PARAM2 +#define FOLLOW_LINK_PARAM , (!SymLinks) +#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) +#else +#define FOLLOW_LINK_PARAM , (!SymLinks) +#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks) +#endif + +HRESULT CDirItems::EnumerateItems2( + const FString &phyPrefix, + const UString &logPrefix, + const FStringVector &filePaths, + FStringVector *requestedPaths) +{ + const int phyParent = phyPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, fs2us(phyPrefix)); + const int logParent = logPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, logPrefix); + + FOR_VECTOR (i, filePaths) + { + const FString &filePath = filePaths[i]; + NFind::CFileInfo fi; + const FString phyPath = phyPrefix + filePath; + if (!fi.Find(phyPath FOLLOW_LINK_PARAM)) + { + RINOK(AddError(phyPath)); + continue; + } + if (requestedPaths) + requestedPaths->Add(phyPath); + + const int delimiter = filePath.ReverseFind_PathSepar(); + FString phyPrefixCur; + int phyParentCur = phyParent; + if (delimiter >= 0) + { + phyPrefixCur.SetFrom(filePath, (unsigned)(delimiter + 1)); + phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); + } + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (ReadSecure) + { + RINOK(AddSecurityItem(phyPath, secureIndex)); + } + #endif + + AddDirFileInfo(phyParentCur, logParent, secureIndex, fi); + + if (fi.IsDir()) + { + const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; + unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); + RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + phyPrefixCur + name2)); + } + } + + ReserveDown(); + return S_OK; +} + + + + +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, + const int phyParent, const int logParent, + const FString &phyPrefix, + const UStringVector &addParts, // additional parts from curNode + CDirItems &dirItems, + bool enterToSubFolders); + + +/* EnumerateDirItems_Spec() + adds new Dir item prefix, and enumerates dir items, + then it can remove that Dir item prefix, if there are no items in that dir. +*/ + + +/* + EnumerateDirItems_Spec() + it's similar to EnumerateDirItems, but phyPrefix doesn't include (curFolderName) +*/ + +static HRESULT EnumerateDirItems_Spec( + const NWildcard::CCensorNode &curNode, + const int phyParent, const int logParent, const FString &curFolderName, + const FString &phyPrefix, // without (curFolderName) + const UStringVector &addParts, // (curNode + addParts) includes (curFolderName) + CDirItems &dirItems, + bool enterToSubFolders) +{ + const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR; + const unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2)); + const unsigned numItems = dirItems.Items.Size(); + HRESULT res = EnumerateDirItems( + curNode, (int)parent, (int)parent, phyPrefix + name2, + addParts, dirItems, enterToSubFolders); + if (numItems == dirItems.Items.Size()) + dirItems.DeleteLastPrefix(); + return res; +} + + +#ifndef UNDER_CE + +#ifdef _WIN32 + +static HRESULT EnumerateAltStreams( + const NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + const int phyParent, const int logParent, + const FString &phyPath, // with (fi.Name), without tail slash for folders + const UStringVector &addParts, // with (fi.Name), prefix parts from curNode + bool addAllSubStreams, + CDirItems &dirItems) +{ + NFind::CStreamEnumerator enumerator(phyPath); + for (;;) + { + NFind::CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + { + return dirItems.AddError(phyPath + FTEXT(":*")); // , (DWORD)E_FAIL + } + if (!found) + return S_OK; + if (si.IsMainStream()) + continue; + UStringVector parts = addParts; + const UString reducedName = si.GetReducedName(); + parts.Back() += reducedName; + if (curNode.CheckPathToRoot(false, parts, true)) + continue; + if (!addAllSubStreams) + if (!curNode.CheckPathToRoot(true, parts, true)) + continue; + + NFind::CFileInfo fi2 = fi; + fi2.Name += us2fs(reducedName); + fi2.Size = si.Size; + fi2.Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); + fi2.IsAltStream = true; + dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2); + } +} + +#endif // _WIN32 + + +/* We get Reparse data and parse it. + If there is Reparse error, we free dirItem.Reparse data. + Do we need to work with empty reparse data? +*/ + +HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi, + const FString &phyPrefix) +{ + if (!SymLinks) + return S_OK; + + #ifdef _WIN32 + if (!fi.HasReparsePoint() || fi.IsAltStream) + #else // _WIN32 + if (!fi.IsPosixLink()) + #endif // _WIN32 + return S_OK; + + const FString path = phyPrefix + fi.Name; + CByteBuffer &buf = dirItem.ReparseData; + if (NIO::GetReparseData(path, buf)) + { + // if (dirItem.ReparseData.Size() != 0) + Stat.FilesSize -= fi.Size; + return S_OK; + } + + DWORD res = ::GetLastError(); + buf.Free(); + return AddError(path, res); +} + +#endif // UNDER_CE + + + +static HRESULT EnumerateForItem( + const NFind::CFileInfo &fi, + const NWildcard::CCensorNode &curNode, + const int phyParent, const int logParent, const FString &phyPrefix, + const UStringVector &addParts, // additional parts from curNode, without (fi.Name) + CDirItems &dirItems, + bool enterToSubFolders) +{ + const UString name = fs2us(fi.Name); + UStringVector newParts = addParts; + newParts.Add(name); + + // check the path in exclude rules + if (curNode.CheckPathToRoot(false, newParts, !fi.IsDir())) + return S_OK; + + #if !defined(UNDER_CE) + int dirItemIndex = -1; + #if defined(_WIN32) + bool addAllSubStreams = false; + #endif // _WIN32 + #endif // !defined(UNDER_CE) + + // check the path in inlcude rules + if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir())) + { + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (dirItems.ReadSecure) + { + RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex)); + } + #endif + + #if !defined(UNDER_CE) + dirItemIndex = (int)dirItems.Items.Size(); + #if defined(_WIN32) + // we will not check include rules for substreams. + addAllSubStreams = true; + #endif // _WIN32 + #endif // !defined(UNDER_CE) + + dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); + if (fi.IsDir()) + enterToSubFolders = true; + } + + #if !defined(UNDER_CE) + + // we don't scan AltStreams for link files + + if (dirItemIndex >= 0) + { + CDirItem &dirItem = dirItems.Items[(unsigned)dirItemIndex]; + RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); + if (dirItem.ReparseData.Size() != 0) + return S_OK; + } + + #if defined(_WIN32) + if (dirItems.ScanAltStreams) + { + RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, + phyPrefix + fi.Name, // with (fi.Name) + newParts, // with (fi.Name) + addAllSubStreams, + dirItems)); + } + #endif + + #endif // !defined(UNDER_CE) + + + #ifndef _WIN32 + if (!fi.IsPosixLink()) // posix link can follow to dir + #endif + if (!fi.IsDir()) + return S_OK; + + const NWildcard::CCensorNode *nextNode = NULL; + + if (addParts.IsEmpty()) + { + int index = curNode.FindSubNode(name); + if (index >= 0) + { + nextNode = &curNode.SubNodes[(unsigned)index]; + newParts.Clear(); + } + } + + if (!nextNode) + { + if (!enterToSubFolders) + return S_OK; + + #ifndef _WIN32 + if (fi.IsPosixLink()) + { + // here we can try to resolve posix link + // if the link to dir, then can we follow it + return S_OK; // we don't follow posix link + } + #endif + + if (dirItems.SymLinks && fi.HasReparsePoint()) + { + /* 20.03: in SymLinks mode: we don't enter to directory that + has reparse point and has no CCensorNode + NOTE: (curNode and parent nodes) still can have wildcard rules + to include some items of target directory (of reparse point), + but we ignore these rules here. + */ + return S_OK; + } + nextNode = &curNode; + } + + return EnumerateDirItems_Spec( + *nextNode, phyParent, logParent, fi.Name, + phyPrefix, // without (fi.Name) + newParts, // relative to (*nextNode). (*nextNode + newParts) includes (fi.Name) + dirItems, + enterToSubFolders); +} + + +static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode) +{ + FOR_VECTOR (i, curNode.IncludeItems) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() != 1) + return false; + const UString &name = item.PathParts.Front(); + /* + if (name.IsEmpty()) + return false; + */ + + /* Windows doesn't support file name with wildcard + But if another system supports file name with wildcard, + and wildcard mode is disabled, we can ignore wildcard in name + */ + /* + #ifndef _WIN32 + if (!item.WildcardParsing) + continue; + #endif + */ + if (DoesNameContainWildcard(name)) + return false; + } + return true; +} + + +#if defined(_WIN32) && !defined(UNDER_CE) + +static bool IsVirtualFsFolder(const FString &prefix, const UString &name) +{ + UString s = fs2us(prefix); + s += name; + s.Add_PathSepar(); + // it returns (true) for non real FS folder path like - "\\SERVER\" + return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0; +} + +#endif + + + +static HRESULT EnumerateDirItems( + const NWildcard::CCensorNode &curNode, + const int phyParent, const int logParent, const FString &phyPrefix, + const UStringVector &addParts, // prefix from curNode including + CDirItems &dirItems, + bool enterToSubFolders) +{ + if (!enterToSubFolders) + { + /* if there are IncludeItems censor rules that affect items in subdirs, + then we will enter to all subfolders */ + if (curNode.NeedCheckSubDirs()) + enterToSubFolders = true; + } + + RINOK(dirItems.ScanProgress(phyPrefix)); + + // try direct_names case at first + if (addParts.IsEmpty() && !enterToSubFolders) + { + if (CanUseFsDirect(curNode)) + { + // all names are direct (no wildcards) + // so we don't need file_system's dir enumerator + CRecordVector needEnterVector; + unsigned i; + + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + const UString &name = item.PathParts.Front(); + FString fullPath = phyPrefix + us2fs(name); + + #if defined(_WIN32) && !defined(UNDER_CE) + bool needAltStreams = true; + #endif + + #ifdef _USE_SECURITY_CODE + bool needSecurity = true; + #endif + + if (phyPrefix.IsEmpty()) + { + if (!item.ForFile) + { + /* we don't like some names for alt streams inside archive: + ":sname" for "\" + "c:::sname" for "C:\" + So we ignore alt streams for these cases */ + if (name.IsEmpty()) + { + #if defined(_WIN32) && !defined(UNDER_CE) + needAltStreams = false; + #endif + + /* + // do we need to ignore security info for "\\" folder ? + #ifdef _USE_SECURITY_CODE + needSecurity = false; + #endif + */ + + fullPath = CHAR_PATH_SEPARATOR; + } + #if defined(_WIN32) && !defined(UNDER_CE) + else if (item.IsDriveItem()) + { + needAltStreams = false; + fullPath.Add_PathSepar(); + } + #endif + } + } + + NFind::CFileInfo fi; + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsVirtualFsFolder(phyPrefix, name)) + { + fi.SetAsDir(); + fi.Name = us2fs(name); + } + else + #endif + if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) + { + RINOK(dirItems.AddError(fullPath)); + continue; + } + + const bool isDir = fi.IsDir(); + if ((isDir && !item.ForDir) || (!isDir && !item.ForFile)) + { + RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)); + continue; + } + { + UStringVector pathParts; + pathParts.Add(fs2us(fi.Name)); + if (curNode.CheckPathToRoot(false, pathParts, !isDir)) + continue; + } + + int secureIndex = -1; + #ifdef _USE_SECURITY_CODE + if (needSecurity && dirItems.ReadSecure) + { + RINOK(dirItems.AddSecurityItem(fullPath, secureIndex)); + } + #endif + + dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi); + + // we don't scan AltStreams for link files + + #if !defined(UNDER_CE) + { + CDirItem &dirItem = dirItems.Items.Back(); + RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix)); + if (dirItem.ReparseData.Size() != 0) + continue; + } + + #if defined(_WIN32) + if (needAltStreams && dirItems.ScanAltStreams) + { + UStringVector pathParts; + pathParts.Add(fs2us(fi.Name)); + RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, + fullPath, // including (name) + pathParts, // including (fi.Name) + true, /* addAllSubStreams */ + dirItems)); + } + #endif // defined(_WIN32) + + #endif // !defined(UNDER_CE) + + + #ifndef _WIN32 + if (!fi.IsPosixLink()) // posix link can follow to dir + #endif + if (!isDir) + continue; + + UStringVector newParts; + const NWildcard::CCensorNode *nextNode = NULL; + int index = curNode.FindSubNode(name); + if (index >= 0) + { + for (int t = (int)needEnterVector.Size(); t <= index; t++) + needEnterVector.Add(true); + needEnterVector[(unsigned)index] = false; + nextNode = &curNode.SubNodes[(unsigned)index]; + } + else + { + #ifndef _WIN32 + if (fi.IsPosixLink()) + { + // here we can try to resolve posix link + // if the link to dir, then can we follow it + continue; // we don't follow posix link + } + #endif + + if (dirItems.SymLinks) + { + if (fi.HasReparsePoint()) + { + /* 20.03: in SymLinks mode: we don't enter to directory that + has reparse point and has no CCensorNode */ + continue; + } + } + nextNode = &curNode; + newParts.Add(name); // don't change it to fi.Name. It's for shortnames support + } + + RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, + newParts, dirItems, true)); + } + + for (i = 0; i < curNode.SubNodes.Size(); i++) + { + if (i < needEnterVector.Size()) + if (!needEnterVector[i]) + continue; + const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; + FString fullPath = phyPrefix + us2fs(nextNode.Name); + NFind::CFileInfo fi; + + if (phyPrefix.IsEmpty()) + { + { + if (nextNode.Name.IsEmpty()) + fullPath = CHAR_PATH_SEPARATOR; + #ifdef _WIN32 + else if (NWildcard::IsDriveColonName(nextNode.Name)) + fullPath.Add_PathSepar(); + #endif + } + } + + // we don't want to call fi.Find() for root folder or virtual folder + if ((phyPrefix.IsEmpty() && nextNode.Name.IsEmpty()) + #if defined(_WIN32) && !defined(UNDER_CE) + || IsVirtualFsFolder(phyPrefix, nextNode.Name) + #endif + ) + { + fi.SetAsDir(); + fi.Name = us2fs(nextNode.Name); + } + else + { + if (!fi.Find(fullPath FOLLOW_LINK_PARAM2)) + { + if (!nextNode.AreThereIncludeItems()) + continue; + RINOK(dirItems.AddError(fullPath)); + continue; + } + + if (!fi.IsDir()) + { + RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR)); + continue; + } + } + + RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, + UStringVector(), dirItems, false)); + } + + return S_OK; + } + } + + #ifdef _WIN32 + #ifndef UNDER_CE + + // scan drives, if wildcard is "*:\" + + if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0) + { + unsigned i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.PathParts.Size() < 1) + break; + const UString &name = item.PathParts.Front(); + if (name.Len() != 2 || name[1] != ':') + break; + if (item.PathParts.Size() == 1) + if (item.ForFile || !item.ForDir) + break; + if (NWildcard::IsDriveColonName(name)) + continue; + if (name[0] != '*' && name[0] != '?') + break; + } + if (i == curNode.IncludeItems.Size()) + { + FStringVector driveStrings; + NFind::MyGetLogicalDriveStrings(driveStrings); + for (i = 0; i < driveStrings.Size(); i++) + { + FString driveName = driveStrings[i]; + if (driveName.Len() < 3 || driveName.Back() != '\\') + return E_FAIL; + driveName.DeleteBack(); + NFind::CFileInfo fi; + fi.SetAsDir(); + fi.Name = driveName; + + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addParts, dirItems, enterToSubFolders)); + } + return S_OK; + } + } + + #endif + #endif + + + CObjectVector files; + + // for (int y = 0; y < 1; y++) + { + // files.Clear(); + RINOK(dirItems.EnumerateOneDir(phyPrefix, files)); + /* + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + // const NFind::CFileInfo &fi = files[i]; + #else + NFind::CFileInfo &fi = files[i]; + { + const NFind::CFileInfo &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(dirItems.AddError(path)); + continue; + } + fi.Name = di.Name; + } + #endif + + } + */ + } + + FOR_VECTOR (i, files) + { + #ifdef _WIN32 + const NFind::CFileInfo &fi = files[i]; + #else + const NFind::CFileInfo &fi = files[i]; + /* + NFind::CFileInfo fi; + { + const NFind::CDirEntry &di = files[i]; + const FString path = phyPrefix + di.Name; + if (!fi.Find_AfterEnumerator(path)) + { + RINOK(dirItems.AddError(path)); + continue; + } + fi.Name = di.Name; + } + */ + #endif + + RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix, + addParts, dirItems, enterToSubFolders)); + if (dirItems.Callback && (i & kScanProgressStepMask) == kScanProgressStepMask) + { + RINOK(dirItems.ScanProgress(phyPrefix)); + } + } + + return S_OK; +} + + + + +HRESULT EnumerateItems( + const NWildcard::CCensor &censor, + const NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, // prefix that will be added to Logical Path + CDirItems &dirItems) +{ + FOR_VECTOR (i, censor.Pairs) + { + const NWildcard::CPair &pair = censor.Pairs[i]; + const int phyParent = pair.Prefix.IsEmpty() ? -1 : (int)dirItems.AddPrefix(-1, -1, pair.Prefix); + int logParent = -1; + + if (pathMode == NWildcard::k_AbsPath) + logParent = phyParent; + else + { + if (!addPathPrefix.IsEmpty()) + logParent = (int)dirItems.AddPrefix(-1, -1, addPathPrefix); + } + + RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(), + dirItems, + false // enterToSubFolders + )); + } + dirItems.ReserveDown(); + + #if defined(_WIN32) && !defined(UNDER_CE) + RINOK(dirItems.FillFixedReparse()); + #endif + + return S_OK; +} + + + +#if defined(_WIN32) && !defined(UNDER_CE) + +HRESULT CDirItems::FillFixedReparse() +{ + FOR_VECTOR(i, Items) + { + CDirItem &item = Items[i]; + + if (!SymLinks) + { + // continue; // for debug + if (!item.Has_Attrib_ReparsePoint()) + continue; + + // if (item.IsDir()) continue; + + const FString phyPath = GetPhyPath(i); + + NFind::CFileInfo fi; + if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() + { + item.Size = fi.Size; + item.CTime = fi.CTime; + item.ATime = fi.ATime; + item.MTime = fi.MTime; + item.Attrib = fi.Attrib; + continue; + } + + /* + // we request properties of target file instead of properies of symbolic link + // here we also can manually parse unsupported links (like WSL links) + NIO::CInFile inFile; + if (inFile.Open(phyPath)) + { + BY_HANDLE_FILE_INFORMATION info; + if (inFile.GetFileInformation(&info)) + { + // Stat.FilesSize doesn't contain item.Size already + // Stat.FilesSize -= item.Size; + item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + Stat.FilesSize += item.Size; + item.CTime = info.ftCreationTime; + item.ATime = info.ftLastAccessTime; + item.MTime = info.ftLastWriteTime; + item.Attrib = info.dwFileAttributes; + continue; + } + } + */ + + RINOK(AddError(phyPath)); + continue; + } + + // (SymLinks == true) here + + if (item.ReparseData.Size() == 0) + continue; + + // if (item.Size == 0) + { + // 20.03: we use Reparse Data instead of real data + item.Size = item.ReparseData.Size(); + } + + CReparseAttr attr; + if (!attr.Parse(item.ReparseData, item.ReparseData.Size())) + { + const FString phyPath = GetPhyPath(i); + AddError(phyPath, attr.ErrorCode); + continue; + } + + /* imagex/WIM reduces absolute paths in links (raparse data), + if we archive non root folder. We do same thing here */ + + bool isWSL = false; + if (attr.IsSymLink_WSL()) + { + // isWSL = true; + // we don't change WSL symlinks + continue; + } + else + { + if (attr.IsRelative_Win()) + continue; + } + + const UString &link = attr.GetPath(); + if (!IsDrivePath(link)) + continue; + // maybe we need to support networks paths also ? + + FString fullPathF; + if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF)) + continue; + const UString fullPath = fs2us(fullPathF); + const UString logPath = GetLogPath(i); + if (logPath.Len() >= fullPath.Len()) + continue; + if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0) + continue; + + const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len()); + if (!IsPathSepar(prefix.Back())) + continue; + + const unsigned rootPrefixSize = GetRootPrefixSize(prefix); + if (rootPrefixSize == 0) + continue; + if (rootPrefixSize == prefix.Len()) + continue; // simple case: paths are from root + + if (link.Len() <= prefix.Len()) + continue; + + if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) + continue; + + UString newLink = prefix.Left(rootPrefixSize); + newLink += link.Ptr(prefix.Len()); + + CByteBuffer data; + bool isSymLink = !attr.IsMountPoint(); + if (!FillLinkData(data, newLink, isSymLink, isWSL)) + continue; + item.ReparseData2 = data; + } + return S_OK; +} + +#endif + + + +static const char * const kCannotFindArchive = "Cannot find archive"; + +HRESULT EnumerateDirItemsAndSort( + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode censorPathMode, + const UString &addPathPrefix, + UStringVector &sortedPaths, + UStringVector &sortedFullPaths, + CDirItemsStat &st, + IDirItemsCallback *callback) +{ + FStringVector paths; + + { + CDirItems dirItems; + dirItems.Callback = callback; + { + HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems); + st = dirItems.Stat; + RINOK(res); + } + + FOR_VECTOR (i, dirItems.Items) + { + const CDirItem &dirItem = dirItems.Items[i]; + if (!dirItem.IsDir()) + paths.Add(dirItems.GetPhyPath(i)); + } + } + + if (paths.Size() == 0) + { + // return S_OK; + throw CMessagePathException(kCannotFindArchive); + } + + UStringVector fullPaths; + + unsigned i; + + for (i = 0; i < paths.Size(); i++) + { + FString fullPath; + NFile::NDir::MyGetFullPathName(paths[i], fullPath); + fullPaths.Add(fs2us(fullPath)); + } + + CUIntVector indices; + SortFileNames(fullPaths, indices); + sortedPaths.ClearAndReserve(indices.Size()); + sortedFullPaths.ClearAndReserve(indices.Size()); + + for (i = 0; i < indices.Size(); i++) + { + unsigned index = indices[i]; + sortedPaths.AddInReserved(fs2us(paths[index])); + sortedFullPaths.AddInReserved(fullPaths[index]); + if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0) + throw CMessagePathException("Duplicate archive path:", sortedFullPaths[i]); + } + + return S_OK; +} + + + + +#ifdef _WIN32 + +// This code converts all short file names to long file names. + +static void ConvertToLongName(const UString &prefix, UString &name) +{ + if (name.IsEmpty() || DoesNameContainWildcard(name)) + return; + NFind::CFileInfo fi; + const FString path (us2fs(prefix + name)); + #ifndef UNDER_CE + if (NFile::NName::IsDevicePath(path)) + return; + #endif + if (fi.Find(path)) + name = fs2us(fi.Name); +} + +static void ConvertToLongNames(const UString &prefix, CObjectVector &items) +{ + FOR_VECTOR (i, items) + { + NWildcard::CItem &item = items[i]; + if (item.Recursive || item.PathParts.Size() != 1) + continue; + if (prefix.IsEmpty() && item.IsDriveItem()) + continue; + ConvertToLongName(prefix, item.PathParts.Front()); + } +} + +static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) +{ + ConvertToLongNames(prefix, node.IncludeItems); + ConvertToLongNames(prefix, node.ExcludeItems); + unsigned i; + for (i = 0; i < node.SubNodes.Size(); i++) + { + UString &name = node.SubNodes[i].Name; + if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name)) + continue; + ConvertToLongName(prefix, name); + } + // mix folders with same name + for (i = 0; i < node.SubNodes.Size(); i++) + { + NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; + for (unsigned j = i + 1; j < node.SubNodes.Size();) + { + const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; + if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name)) + { + nextNode1.IncludeItems += nextNode2.IncludeItems; + nextNode1.ExcludeItems += nextNode2.ExcludeItems; + node.SubNodes.Delete(j); + } + else + j++; + } + } + for (i = 0; i < node.SubNodes.Size(); i++) + { + NWildcard::CCensorNode &nextNode = node.SubNodes[i]; + ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode); + } +} + +void ConvertToLongNames(NWildcard::CCensor &censor) +{ + FOR_VECTOR (i, censor.Pairs) + { + NWildcard::CPair &pair = censor.Pairs[i]; + ConvertToLongNames(pair.Prefix, pair.Head); + } +} + +#endif + + +CMessagePathException::CMessagePathException(const char *a, const wchar_t *u) +{ + (*this) += a; + if (u) + { + Add_LF(); + (*this) += u; + } +} + +CMessagePathException::CMessagePathException(const wchar_t *a, const wchar_t *u) +{ + (*this) += a; + if (u) + { + Add_LF(); + (*this) += u; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.h new file mode 100644 index 0000000..9b17c60 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/EnumDirItems.h @@ -0,0 +1,38 @@ +// EnumDirItems.h + +#ifndef __ENUM_DIR_ITEMS_H +#define __ENUM_DIR_ITEMS_H + +#include "../../../Common/Wildcard.h" + +#include "DirItem.h" + + +HRESULT EnumerateItems( + const NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, + CDirItems &dirItems); + + +struct CMessagePathException: public UString +{ + CMessagePathException(const char *a, const wchar_t *u = NULL); + CMessagePathException(const wchar_t *a, const wchar_t *u = NULL); +}; + + +HRESULT EnumerateDirItemsAndSort( + NWildcard::CCensor &censor, + NWildcard::ECensorPathMode pathMode, + const UString &addPathPrefix, + UStringVector &sortedPaths, + UStringVector &sortedFullPaths, + CDirItemsStat &st, + IDirItemsCallback *callback); + +#ifdef _WIN32 +void ConvertToLongNames(NWildcard::CCensor &censor); +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExitCode.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExitCode.h new file mode 100644 index 0000000..b6d7d4d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExitCode.h @@ -0,0 +1,27 @@ +// ExitCode.h + +#ifndef __EXIT_CODE_H +#define __EXIT_CODE_H + +namespace NExitCode { + +enum EEnum { + + kSuccess = 0, // Successful operation + kWarning = 1, // Non fatal error(s) occurred + kFatalError = 2, // A fatal error occurred + // kCRCError = 3, // A CRC error occurred when unpacking + // kLockedArchive = 4, // Attempt to modify an archive previously locked + // kWriteError = 5, // Write to disk error + // kOpenError = 6, // Open file error + kUserError = 7, // Command line option error + kMemoryError = 8, // Not enough memory for operation + // kCreateFileError = 9, // Create file error + + kUserBreak = 255 // User stopped the process + +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.cpp new file mode 100644 index 0000000..18bd103 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.cpp @@ -0,0 +1,503 @@ +// Extract.cpp + +#include "StdAfx.h" + +#include "../../../../C/Sort.h" + +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../Common/ExtractingFilePath.h" + +#include "Extract.h" +#include "SetProperties.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + + +static void SetErrorMessage(const char *message, + const FString &path, HRESULT errorCode, + UString &s) +{ + s = message; + s += " : "; + s += NError::MyFormatMessage(errorCode); + s += " : "; + s += fs2us(path); +} + + +static HRESULT DecompressArchive( + CCodecs *codecs, + const CArchiveLink &arcLink, + UInt64 packSize, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + bool calcCrc, + IExtractCallbackUI *callback, + CArchiveExtractCallback *ecs, + UString &errorMessage, + UInt64 &stdInProcessed) +{ + const CArc &arc = arcLink.Arcs.Back(); + stdInProcessed = 0; + IInArchive *archive = arc.Archive; + CRecordVector realIndices; + + UStringVector removePathParts; + + FString outDir = options.OutputDir; + UString replaceName = arc.DefaultName; + + if (arcLink.Arcs.Size() > 1) + { + // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1". + // So it extracts different archives to one folder. + // We will use top level archive name + const CArc &arc0 = arcLink.Arcs[0]; + if (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, "pe")) + replaceName = arc0.DefaultName; + } + + outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName))); + + bool elimIsPossible = false; + UString elimPrefix; // only pure name without dir delimiter + FString outDirReduced = outDir; + + if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths) + { + UString dirPrefix; + SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix); + if (!elimPrefix.IsEmpty()) + { + if (IsPathSepar(elimPrefix.Back())) + elimPrefix.DeleteBack(); + if (!elimPrefix.IsEmpty()) + { + outDirReduced = us2fs(dirPrefix); + elimIsPossible = true; + } + } + } + + bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); + + if (!options.StdInMode) + { + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + CReadArcItem item; + + for (UInt32 i = 0; i < numItems; i++) + { + if (elimIsPossible || !allFilesAreAllowed) + { + RINOK(arc.GetItem(i, item)); + } + else + { + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream = false; + if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream)); + } + #endif + } + + #ifdef SUPPORT_ALT_STREAMS + if (!options.NtOptions.AltStreams.Val && item.IsAltStream) + continue; + #endif + + if (elimIsPossible) + { + const UString &s = + #ifdef SUPPORT_ALT_STREAMS + item.MainPath; + #else + item.Path; + #endif + if (!IsPath1PrefixedByPath2(s, elimPrefix)) + elimIsPossible = false; + else + { + wchar_t c = s[elimPrefix.Len()]; + if (c == 0) + { + if (!item.MainIsDir) + elimIsPossible = false; + } + else if (!IsPathSepar(c)) + elimIsPossible = false; + } + } + + if (!allFilesAreAllowed) + { + if (!CensorNode_CheckPath(wildcardCensor, item)) + continue; + } + + realIndices.Add(i); + } + + if (realIndices.Size() == 0) + { + callback->ThereAreNoFiles(); + return callback->ExtractResult(S_OK); + } + } + + if (elimIsPossible) + { + removePathParts.Add(elimPrefix); + // outDir = outDirReduced; + } + + #ifdef _WIN32 + // GetCorrectFullFsPath doesn't like "..". + // outDir.TrimRight(); + // outDir = GetCorrectFullFsPath(outDir); + #endif + + if (outDir.IsEmpty()) + outDir = "." STRING_PATH_SEPARATOR; + /* + #ifdef _WIN32 + else if (NName::IsAltPathPrefix(outDir)) {} + #endif + */ + else if (!CreateComplexDir(outDir)) + { + const HRESULT res = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot create output directory", outDir, res, errorMessage); + return res; + } + + ecs->Init( + options.NtOptions, + options.StdInMode ? &wildcardCensor : NULL, + &arc, + callback, + options.StdOutMode, options.TestMode, + outDir, + removePathParts, false, + packSize); + + + #ifdef SUPPORT_LINKS + + if (!options.StdInMode && + !options.TestMode && + options.NtOptions.HardLinks.Val) + { + RINOK(ecs->PrepareHardLinks(&realIndices)); + } + + #endif + + + HRESULT result; + Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0; + + CArchiveExtractCallback_Closer ecsCloser(ecs); + + if (options.StdInMode) + { + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs); + NCOM::CPropVariant prop; + if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) + ConvertPropVariantToUInt64(prop, stdInProcessed); + } + else + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); + + HRESULT res2 = ecsCloser.Close(); + if (result == S_OK) + result = res2; + + return callback->ExtractResult(result); +} + +/* v9.31: BUG was fixed: + Sorted list for file paths was sorted with case insensitive compare function. + But FindInSorted function did binary search via case sensitive compare function */ + +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name); +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name) +{ + unsigned left = 0, right = fileName.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const UString &midValue = fileName[mid]; + int compare = CompareFileNames(name, midValue); + if (compare == 0) + return (int)mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } + return -1; +} + + + +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, + UStringVector &arcPaths, UStringVector &arcPathsFull, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IOpenCallbackUI *openCallback, + IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif + UString &errorMessage, + CDecompressStat &st) +{ + st.Clear(); + UInt64 totalPackSize = 0; + CRecordVector arcSizes; + + unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size(); + + unsigned i; + + for (i = 0; i < numArcs; i++) + { + NFind::CFileInfo fi; + fi.Size = 0; + if (!options.StdInMode) + { + const FString arcPath = us2fs(arcPaths[i]); + if (!fi.Find_FollowLink(arcPath)) + { + const HRESULT errorCode = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot find archive file", arcPath, errorCode, errorMessage); + return errorCode; + } + if (fi.IsDir()) + { + HRESULT errorCode = E_FAIL; + SetErrorMessage("The item is a directory", arcPath, errorCode, errorMessage); + return errorCode; + } + } + arcSizes.Add(fi.Size); + totalPackSize += fi.Size; + } + + CBoolArr skipArcs(numArcs); + for (i = 0; i < numArcs; i++) + skipArcs[i] = false; + + CArchiveExtractCallback *ecs = new CArchiveExtractCallback; + CMyComPtr ec(ecs); + bool multi = (numArcs > 1); + ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode, + false // keepEmptyDirParts + ); + #ifndef _SFX + ecs->SetHashMethods(hash); + #endif + + if (multi) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + } + + UInt64 totalPackProcessed = 0; + bool thereAreNotOpenArcs = false; + + for (i = 0; i < numArcs; i++) + { + if (skipArcs[i]) + continue; + + const UString &arcPath = arcPaths[i]; + NFind::CFileInfo fi; + if (options.StdInMode) + { + fi.Size = 0; + fi.Attrib = 0; + } + else + { + if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir()) + { + const HRESULT errorCode = GetLastError_noZero_HRESULT(); + SetErrorMessage("Cannot find archive file", us2fs(arcPath), errorCode, errorMessage); + return errorCode; + } + } + + /* + #ifndef _NO_CRYPTO + openCallback->Open_Clear_PasswordWasAsked_Flag(); + #endif + */ + + RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode)); + CArchiveLink arcLink; + + CObjectVector types2 = types; + /* + #ifndef _SFX + if (types.IsEmpty()) + { + int pos = arcPath.ReverseFind(L'.'); + if (pos >= 0) + { + UString s = arcPath.Ptr(pos + 1); + int index = codecs->FindFormatForExtension(s); + if (index >= 0 && s == L"001") + { + s = arcPath.Left(pos); + pos = s.ReverseFind(L'.'); + if (pos >= 0) + { + int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1)); + if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0 + { + types2.Add(index2); + types2.Add(index); + } + } + } + } + } + #endif + */ + + COpenOptions op; + #ifndef _SFX + op.props = &options.Properties; + #endif + op.codecs = codecs; + op.types = &types2; + op.excludedFormats = &excludedFormats; + op.stdInMode = options.StdInMode; + op.stream = NULL; + op.filePath = arcPath; + + HRESULT result = arcLink.Open_Strict(op, openCallback); + + if (result == E_ABORT) + return result; + + // arcLink.Set_ErrorsText(); + RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result)); + + if (result != S_OK) + { + thereAreNotOpenArcs = true; + if (!options.StdInMode) + totalPackProcessed += fi.Size; + continue; + } + + if (!options.StdInMode) + { + // numVolumes += arcLink.VolumePaths.Size(); + // arcLink.VolumesSize; + + // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes); + // numArcs = arcPaths.Size(); + if (arcLink.VolumePaths.Size() != 0) + { + Int64 correctionSize = (Int64)arcLink.VolumesSize; + FOR_VECTOR (v, arcLink.VolumePaths) + { + int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); + if (index >= 0) + { + if ((unsigned)index > i) + { + skipArcs[(unsigned)index] = true; + correctionSize -= arcSizes[(unsigned)index]; + } + } + } + if (correctionSize != 0) + { + Int64 newPackSize = (Int64)totalPackSize + correctionSize; + if (newPackSize < 0) + newPackSize = 0; + totalPackSize = (UInt64)newPackSize; + RINOK(extractCallback->SetTotal(totalPackSize)); + } + } + } + + /* + // Now openCallback and extractCallback use same object. So we don't need to send password. + + #ifndef _NO_CRYPTO + bool passwordIsDefined; + UString password; + RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password)); + if (passwordIsDefined) + { + RINOK(extractCallback->SetPassword(password)); + } + #endif + */ + + CArc &arc = arcLink.Arcs.Back(); + arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); + arc.MTime = fi.MTime; + + UInt64 packProcessed; + bool calcCrc = + #ifndef _SFX + (hash != NULL); + #else + false; + #endif + + RINOK(DecompressArchive( + codecs, + arcLink, + fi.Size + arcLink.VolumesSize, + wildcardCensor, + options, + calcCrc, + extractCallback, ecs, errorMessage, packProcessed)); + + if (!options.StdInMode) + packProcessed = fi.Size + arcLink.VolumesSize; + totalPackProcessed += packProcessed; + ecs->LocalProgressSpec->InSize += packProcessed; + ecs->LocalProgressSpec->OutSize = ecs->UnpackSize; + if (!errorMessage.IsEmpty()) + return E_FAIL; + } + + if (multi || thereAreNotOpenArcs) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + RINOK(extractCallback->SetCompleted(&totalPackProcessed)); + } + + st.NumFolders = ecs->NumFolders; + st.NumFiles = ecs->NumFiles; + st.NumAltStreams = ecs->NumAltStreams; + st.UnpackSize = ecs->UnpackSize; + st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize; + st.NumArchives = arcPaths.Size(); + st.PackSize = ecs->LocalProgressSpec->InSize; + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.h new file mode 100644 index 0000000..bfabe19 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Extract.h @@ -0,0 +1,94 @@ +// Extract.h + +#ifndef __EXTRACT_H +#define __EXTRACT_H + +#include "../../../Windows/FileFind.h" + +#include "../../Archive/IArchive.h" + +#include "ArchiveExtractCallback.h" +#include "ArchiveOpenCallback.h" +#include "ExtractMode.h" +#include "Property.h" + +#include "../Common/LoadCodecs.h" + +struct CExtractOptionsBase +{ + CBoolPair ElimDup; + + bool PathMode_Force; + bool OverwriteMode_Force; + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + FString OutputDir; + CExtractNtOptions NtOptions; + + CExtractOptionsBase(): + PathMode_Force(false), + OverwriteMode_Force(false), + PathMode(NExtract::NPathMode::kFullPaths), + OverwriteMode(NExtract::NOverwriteMode::kAsk) + {} +}; + +struct CExtractOptions: public CExtractOptionsBase +{ + bool StdInMode; + bool StdOutMode; + bool YesToAll; + bool TestMode; + + // bool ShowDialog; + // bool PasswordEnabled; + // UString Password; + #ifndef _SFX + CObjectVector Properties; + #endif + + #ifdef EXTERNAL_CODECS + CCodecs *Codecs; + #endif + + CExtractOptions(): + StdInMode(false), + StdOutMode(false), + YesToAll(false), + TestMode(false) + {} +}; + +struct CDecompressStat +{ + UInt64 NumArchives; + UInt64 UnpackSize; + UInt64 AltStreams_UnpackSize; + UInt64 PackSize; + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 NumAltStreams; + + void Clear() + { + NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0; + } +}; + +HRESULT Extract( + CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, + UStringVector &archivePaths, UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IOpenCallbackUI *openCallback, + IExtractCallbackUI *extractCallback, + #ifndef _SFX + IHashCalc *hash, + #endif + UString &errorMessage, + CDecompressStat &st); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractMode.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractMode.h new file mode 100644 index 0000000..3b2b9a0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractMode.h @@ -0,0 +1,34 @@ +// ExtractMode.h + +#ifndef __EXTRACT_MODE_H +#define __EXTRACT_MODE_H + +namespace NExtract { + +namespace NPathMode +{ + enum EEnum + { + kFullPaths, + kCurPaths, + kNoPaths, + kAbsPaths, + kNoPathsAlt // alt streams must be extracted without name of base file + }; +} + +namespace NOverwriteMode +{ + enum EEnum + { + kAsk, + kOverwrite, + kSkip, + kRename, + kRenameExisting + }; +} + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.cpp new file mode 100644 index 0000000..21a306d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -0,0 +1,287 @@ +// ExtractingFilePath.cpp + +#include "StdAfx.h" + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileName.h" + +#include "ExtractingFilePath.h" + +extern +bool g_PathTrailReplaceMode; +bool g_PathTrailReplaceMode = + #ifdef _WIN32 + true + #else + false + #endif + ; + + +#ifdef _WIN32 +static void ReplaceIncorrectChars(UString &s) +{ + { + for (unsigned i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if ( + #ifdef _WIN32 + c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"' + || c == '/' + // || c == 0x202E // RLO + || + #endif + c == WCHAR_PATH_SEPARATOR) + s.ReplaceOneCharAtPos(i, + '_' // default + // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters + ); + } + } + + if (g_PathTrailReplaceMode) + { + /* + // if (g_PathTrailReplaceMode == 1) + { + if (!s.IsEmpty()) + { + wchar_t c = s.Back(); + if (c == '.' || c == ' ') + { + // s += (wchar_t)(0x9c); // STRING TERMINATOR + s += (wchar_t)'_'; + } + } + } + else + */ + { + unsigned i; + for (i = s.Len(); i != 0;) + { + wchar_t c = s[i - 1]; + if (c != '.' && c != ' ') + break; + i--; + s.ReplaceOneCharAtPos(i, '_'); + // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7)); + } + /* + if (g_PathTrailReplaceMode > 1 && i != s.Len()) + { + s.DeleteFrom(i); + } + */ + } + } +} +#endif + +/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream. + But colon in postfix ":$DATA" is allowed. + WIN32 functions don't allow empty alt stream name "name:" */ + +void Correct_AltStream_Name(UString &s) +{ + unsigned len = s.Len(); + const unsigned kPostfixSize = 6; + if (s.Len() >= kPostfixSize + && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) + len -= kPostfixSize; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = s[i]; + if (c == ':' || c == '\\' || c == '/' + || c == 0x202E // RLO + ) + s.ReplaceOneCharAtPos(i, '_'); + } + if (s.IsEmpty()) + s = '_'; +} + +#ifdef _WIN32 + +static const unsigned g_ReservedWithNum_Index = 4; + +static const char * const g_ReservedNames[] = +{ + "CON", "PRN", "AUX", "NUL", + "COM", "LPT" +}; + +static bool IsSupportedName(const UString &name) +{ + for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) + { + const char *reservedName = g_ReservedNames[i]; + unsigned len = MyStringLen(reservedName); + if (name.Len() < len) + continue; + if (!name.IsPrefixedBy_Ascii_NoCase(reservedName)) + continue; + if (i >= g_ReservedWithNum_Index) + { + wchar_t c = name[len]; + if (c < L'0' || c > L'9') + continue; + len++; + } + for (;;) + { + wchar_t c = name[len++]; + if (c == 0 || c == '.') + return false; + if (c != ' ') + break; + } + } + return true; +} + +static void CorrectUnsupportedName(UString &name) +{ + if (!IsSupportedName(name)) + name.InsertAtFront(L'_'); +} + +#endif + +static void Correct_PathPart(UString &s) +{ + // "." and ".." + if (s.IsEmpty()) + return; + + if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + s.Empty(); + #ifdef _WIN32 + else + ReplaceIncorrectChars(s); + #endif +} + +// static const char * const k_EmptyReplaceName = "[]"; +static const char k_EmptyReplaceName = '_'; + +UString Get_Correct_FsFile_Name(const UString &name) +{ + UString res = name; + Correct_PathPart(res); + + #ifdef _WIN32 + CorrectUnsupportedName(res); + #endif + + if (res.IsEmpty()) + res = k_EmptyReplaceName; + return res; +} + + +void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir) +{ + unsigned i = 0; + + if (absIsAllowed) + { + #if defined(_WIN32) && !defined(UNDER_CE) + bool isDrive = false; + #endif + + if (parts[0].IsEmpty()) + { + i = 1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (parts.Size() > 1 && parts[1].IsEmpty()) + { + i = 2; + if (parts.Size() > 2 && parts[2] == L"?") + { + i = 3; + if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) + { + isDrive = true; + i = 4; + } + } + } + #endif + } + #if defined(_WIN32) && !defined(UNDER_CE) + else if (NWindows::NFile::NName::IsDrivePath2(parts[0])) + { + isDrive = true; + i = 1; + } + + if (isDrive) + { + // we convert "c:name" to "c:\name", if absIsAllowed path. + UString &ds = parts[i - 1]; + if (ds.Len() > 2) + { + parts.Insert(i, ds.Ptr(2)); + ds.DeleteFrom(2); + } + } + #endif + } + + if (i != 0) + keepAndReplaceEmptyPrefixes = false; + + for (; i < parts.Size();) + { + UString &s = parts[i]; + + Correct_PathPart(s); + + if (s.IsEmpty()) + { + if (!keepAndReplaceEmptyPrefixes) + if (isDir || i != parts.Size() - 1) + { + parts.Delete(i); + continue; + } + s = k_EmptyReplaceName; + } + else + { + keepAndReplaceEmptyPrefixes = false; + #ifdef _WIN32 + CorrectUnsupportedName(s); + #endif + } + + i++; + } + + if (!isDir) + { + if (parts.IsEmpty()) + parts.Add((UString)k_EmptyReplaceName); + else + { + UString &s = parts.Back(); + if (s.IsEmpty()) + s = k_EmptyReplaceName; + } + } +} + +UString MakePathFromParts(const UStringVector &parts) +{ + UString s; + FOR_VECTOR (i, parts) + { + if (i != 0) + s.Add_PathSepar(); + s += parts[i]; + } + return s; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.h new file mode 100644 index 0000000..8f8f9f1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -0,0 +1,31 @@ +// ExtractingFilePath.h + +#ifndef __EXTRACTING_FILE_PATH_H +#define __EXTRACTING_FILE_PATH_H + +#include "../../../Common/MyString.h" + +// #ifdef _WIN32 +void Correct_AltStream_Name(UString &s); +// #endif + +// replaces unsuported characters, and replaces "." , ".." and "" to "[]" +UString Get_Correct_FsFile_Name(const UString &name); + +/* + Correct_FsPath() corrects path parts to prepare it for File System operations. + It also corrects empty path parts like "\\\\": + - frontal empty path parts : it removes them or changes them to "_" + - another empty path parts : it removes them + if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker + else + { + if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts + if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_" + } +*/ +void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir); + +UString MakePathFromParts(const UStringVector &parts); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.cpp new file mode 100644 index 0000000..c87be44 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.cpp @@ -0,0 +1,366 @@ +// HashCalc.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "../../../Common/StringToInt.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" +#include "../../Common/StreamObjects.h" + +#include "EnumDirItems.h" +#include "HashCalc.h" + +using namespace NWindows; + +class CHashMidBuf +{ + void *_data; +public: + CHashMidBuf(): _data(0) {} + operator void *() { return _data; } + bool Alloc(size_t size) + { + if (_data != 0) + return false; + _data = ::MidAlloc(size); + return _data != 0; + } + ~CHashMidBuf() { ::MidFree(_data); } +}; + +static const char * const k_DefaultHashMethod = "CRC32"; + +HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods) +{ + UStringVector names = hashMethods; + if (names.IsEmpty()) + names.Add(UString(k_DefaultHashMethod)); + + CRecordVector ids; + CObjectVector methods; + + unsigned i; + for (i = 0; i < names.Size(); i++) + { + COneMethodInfo m; + RINOK(m.ParseMethodFromString(names[i])); + + if (m.MethodName.IsEmpty()) + m.MethodName = k_DefaultHashMethod; + + if (m.MethodName == "*") + { + CRecordVector tempMethods; + GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); + methods.Clear(); + ids.Clear(); + FOR_VECTOR (t, tempMethods) + { + unsigned index = ids.AddToUniqueSorted(tempMethods[t]); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + break; + } + else + { + // m.MethodName.RemoveChar(L'-'); + CMethodId id; + if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id)) + return E_NOTIMPL; + unsigned index = ids.AddToUniqueSorted(id); + if (ids.Size() != methods.Size()) + methods.Insert(index, m); + } + } + + for (i = 0; i < ids.Size(); i++) + { + CMyComPtr hasher; + AString name; + RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher)); + if (!hasher) + throw "Can't create hasher"; + const COneMethodInfo &m = methods[i]; + { + CMyComPtr scp; + hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp); + if (scp) + RINOK(m.SetCoderProps(scp, NULL)); + } + UInt32 digestSize = hasher->GetDigestSize(); + if (digestSize > k_HashCalc_DigestSize_Max) + return E_NOTIMPL; + CHasherState &h = Hashers.AddNew(); + h.Hasher = hasher; + h.Name = name; + h.DigestSize = digestSize; + for (unsigned k = 0; k < k_HashCalc_NumGroups; k++) + memset(h.Digests[k], 0, digestSize); + } + + return S_OK; +} + +void CHashBundle::InitForNewFile() +{ + CurSize = 0; + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + h.Hasher->Init(); + memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize); + } +} + +void CHashBundle::Update(const void *data, UInt32 size) +{ + CurSize += size; + FOR_VECTOR (i, Hashers) + Hashers[i].Hasher->Update(data, size); +} + +void CHashBundle::SetSize(UInt64 size) +{ + CurSize = size; +} + +static void AddDigests(Byte *dest, const Byte *src, UInt32 size) +{ + unsigned next = 0; + for (UInt32 i = 0; i < size; i++) + { + next += (unsigned)dest[i] + (unsigned)src[i]; + dest[i] = (Byte)next; + next >>= 8; + } +} + +void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path) +{ + if (isDir) + NumDirs++; + else if (isAltStream) + { + NumAltStreams++; + AltStreamsSize += CurSize; + } + else + { + NumFiles++; + FilesSize += CurSize; + } + + Byte pre[16]; + memset(pre, 0, sizeof(pre)); + if (isDir) + pre[0] = 1; + + FOR_VECTOR (i, Hashers) + { + CHasherState &h = Hashers[i]; + if (!isDir) + { + h.Hasher->Final(h.Digests[0]); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize); + } + + h.Hasher->Init(); + h.Hasher->Update(pre, sizeof(pre)); + h.Hasher->Update(h.Digests[0], h.DigestSize); + + for (unsigned k = 0; k < path.Len(); k++) + { + wchar_t c = path[k]; + Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) }; + h.Hasher->Update(temp, 2); + } + + Byte tempDigest[k_HashCalc_DigestSize_Max]; + h.Hasher->Final(tempDigest); + if (!isAltStream) + AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize); + AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize); + } +} + + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + AString &errorInfo, + IHashCallbackUI *callback) +{ + CDirItems dirItems; + dirItems.Callback = callback; + + if (options.StdInMode) + { + CDirItem di; + di.Size = (UInt64)(Int64)-1; + di.Attrib = 0; + di.MTime.dwLowDateTime = 0; + di.MTime.dwHighDateTime = 0; + di.CTime = di.ATime = di.MTime; + dirItems.Items.Add(di); + } + else + { + RINOK(callback->StartScanning()); + + dirItems.SymLinks = options.SymLinks.Val; + dirItems.ScanAltStreams = options.AltStreamsMode; + + HRESULT res = EnumerateItems(censor, + options.PathMode, + UString(), + dirItems); + + if (res != S_OK) + { + if (res != E_ABORT) + errorInfo = "Scanning error"; + return res; + } + RINOK(callback->FinishScanning(dirItems.Stat)); + } + + unsigned i; + CHashBundle hb; + RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods)); + // hb.Init(); + + hb.NumErrors = dirItems.Stat.NumErrors; + + if (options.StdInMode) + { + RINOK(callback->SetNumFiles(1)); + } + else + { + RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes())); + } + + const UInt32 kBufSize = 1 << 15; + CHashMidBuf buf; + if (!buf.Alloc(kBufSize)) + return E_OUTOFMEMORY; + + UInt64 completeValue = 0; + + RINOK(callback->BeforeFirstFile(hb)); + + for (i = 0; i < dirItems.Items.Size(); i++) + { + CMyComPtr inStream; + UString path; + bool isDir = false; + bool isAltStream = false; + + if (options.StdInMode) + { + inStream = new CStdInFileStream; + } + else + { + path = dirItems.GetLogPath(i); + const CDirItem &di = dirItems.Items[i]; + isAltStream = di.IsAltStream; + + #ifndef UNDER_CE + // if (di.AreReparseData()) + if (di.ReparseData.Size() != 0) + { + CBufInStream *inStreamSpec = new CBufInStream(); + inStream = inStreamSpec; + inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); + } + else + #endif + { + CInFileStream *inStreamSpec = new CInFileStream; + inStreamSpec->File.PreserveATime = options.PreserveATime; + inStream = inStreamSpec; + isDir = di.IsDir(); + if (!isDir) + { + const FString phyPath = dirItems.GetPhyPath(i); + if (!inStreamSpec->OpenShared(phyPath, options.OpenShareForWrite)) + { + HRESULT res = callback->OpenFileError(phyPath, ::GetLastError()); + hb.NumErrors++; + if (res != S_FALSE) + return res; + continue; + } + } + } + } + + RINOK(callback->GetStream(path, isDir)); + UInt64 fileSize = 0; + + hb.InitForNewFile(); + if (!isDir) + { + for (UInt32 step = 0;; step++) + { + if ((step & 0xFF) == 0) + RINOK(callback->SetCompleted(&completeValue)); + UInt32 size; + RINOK(inStream->Read(buf, kBufSize, &size)); + if (size == 0) + break; + hb.Update(buf, size); + fileSize += size; + completeValue += size; + } + } + hb.Final(isDir, isAltStream, path); + RINOK(callback->SetOperationResult(fileSize, hb, !isDir)); + RINOK(callback->SetCompleted(&completeValue)); + } + return callback->AfterLastFile(hb); +} + + +static inline char GetHex(unsigned v) +{ + return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10))); +} + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size) +{ + dest[size * 2] = 0; + + if (!data) + { + for (UInt32 i = 0; i < size; i++) + { + dest[0] = ' '; + dest[1] = ' '; + dest += 2; + } + return; + } + + int step = 2; + if (size <= 8) + { + step = -2; + dest += size * 2 - 2; + } + + for (UInt32 i = 0; i < size; i++) + { + unsigned b = data[i]; + dest[0] = GetHex((b >> 4) & 0xF); + dest[1] = GetHex(b & 0xF); + dest += step; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.h new file mode 100644 index 0000000..b6d320b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/HashCalc.h @@ -0,0 +1,120 @@ +// HashCalc.h + +#ifndef __HASH_CALC_H +#define __HASH_CALC_H + +#include "../../../Common/Wildcard.h" + +#include "../../Common/CreateCoder.h" +#include "../../Common/MethodProps.h" + +#include "DirItem.h" + +const unsigned k_HashCalc_DigestSize_Max = 64; + +const unsigned k_HashCalc_NumGroups = 4; + +enum +{ + k_HashCalc_Index_Current, + k_HashCalc_Index_DataSum, + k_HashCalc_Index_NamesSum, + k_HashCalc_Index_StreamsSum +}; + +struct CHasherState +{ + CMyComPtr Hasher; + AString Name; + UInt32 DigestSize; + Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max]; +}; + +struct IHashCalc +{ + virtual void InitForNewFile() = 0; + virtual void Update(const void *data, UInt32 size) = 0; + virtual void SetSize(UInt64 size) = 0; + virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0; +}; + +struct CHashBundle: public IHashCalc +{ + CObjectVector Hashers; + + UInt64 NumDirs; + UInt64 NumFiles; + UInt64 NumAltStreams; + UInt64 FilesSize; + UInt64 AltStreamsSize; + UInt64 NumErrors; + + UInt64 CurSize; + + UString MainName; + UString FirstFileName; + + HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods); + + // void Init() {} + CHashBundle() + { + NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0; + } + + virtual ~CHashBundle() {}; + + void InitForNewFile(); + void Update(const void *data, UInt32 size); + void SetSize(UInt64 size); + void Final(bool isDir, bool isAltStream, const UString &path); +}; + +#define INTERFACE_IHashCallbackUI(x) \ + INTERFACE_IDirItemsCallback(x) \ + virtual HRESULT StartScanning() x; \ + virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \ + virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ + virtual HRESULT SetTotal(UInt64 size) x; \ + virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ + virtual HRESULT CheckBreak() x; \ + virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \ + virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \ + virtual HRESULT AfterLastFile(CHashBundle &hb) x; \ + +struct IHashCallbackUI: public IDirItemsCallback +{ + INTERFACE_IHashCallbackUI(=0) +}; + +struct CHashOptions +{ + UStringVector Methods; + bool PreserveATime; + bool OpenShareForWrite; + bool StdInMode; + bool AltStreamsMode; + CBoolPair SymLinks; + + NWildcard::ECensorPathMode PathMode; + + CHashOptions(): + PreserveATime(false), + OpenShareForWrite(false), + StdInMode(false), + AltStreamsMode(false), + PathMode(NWildcard::k_RelatPath) {}; +}; + +HRESULT HashCalc( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + AString &errorInfo, + IHashCallbackUI *callback); + +void AddHashHexToString(char *dest, const Byte *data, UInt32 size); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/IFileExtractCallback.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/IFileExtractCallback.h new file mode 100644 index 0000000..c456c86 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/IFileExtractCallback.h @@ -0,0 +1,114 @@ +// IFileExtractCallback.h + +#ifndef __I_FILE_EXTRACT_CALLBACK_H +#define __I_FILE_EXTRACT_CALLBACK_H + +#include "../../../Common/MyString.h" + +#include "../../IDecl.h" + +#include "LoadCodecs.h" +#include "OpenArchive.h" + +namespace NOverwriteAnswer +{ + enum EEnum + { + kYes, + kYesToAll, + kNo, + kNoToAll, + kAutoRename, + kCancel + }; +} + + +/* ---------- IFolderArchiveExtractCallback ---------- +is implemented by + Console/ExtractCallbackConsole.h CExtractCallbackConsole + FileManager/ExtractCallback.h CExtractCallbackImp + FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported) + +IID_IFolderArchiveExtractCallback is requested by: + - Agent/ArchiveFolder.cpp + CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback) + is sent to IArchiveFolder::Extract() + + - FileManager/PanelCopy.cpp + CPanel::CopyTo(), if (options->testMode) + is sent to IArchiveFolder::Extract() + + IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp +*/ + +#define INTERFACE_IFolderArchiveExtractCallback(x) \ + STDMETHOD(AskOverwrite)( \ + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \ + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \ + Int32 *answer) x; \ + STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \ + STDMETHOD(MessageError)(const wchar_t *message) x; \ + STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \ + +DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) +{ + INTERFACE_IFolderArchiveExtractCallback(PURE) +}; + +#define INTERFACE_IFolderArchiveExtractCallback2(x) \ + STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \ + +DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08) +{ + INTERFACE_IFolderArchiveExtractCallback2(PURE) +}; + +/* ---------- IExtractCallbackUI ---------- +is implemented by + Console/ExtractCallbackConsole.h CExtractCallbackConsole + FileManager/ExtractCallback.h CExtractCallbackImp +*/ + +#ifdef _NO_CRYPTO + #define INTERFACE_IExtractCallbackUI_Crypto(x) +#else + #define INTERFACE_IExtractCallbackUI_Crypto(x) \ + virtual HRESULT SetPassword(const UString &password) x; +#endif + +#define INTERFACE_IExtractCallbackUI(x) \ + virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \ + virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \ + virtual HRESULT ThereAreNoFiles() x; \ + virtual HRESULT ExtractResult(HRESULT result) x; \ + INTERFACE_IExtractCallbackUI_Crypto(x) + +struct IExtractCallbackUI: IFolderArchiveExtractCallback +{ + INTERFACE_IExtractCallbackUI(PURE) +}; + + + +#define INTERFACE_IGetProp(x) \ + STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \ + +DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20) +{ + INTERFACE_IGetProp(PURE) +}; + +#define INTERFACE_IFolderExtractToStreamCallback(x) \ + STDMETHOD(UseExtractToStream)(Int32 *res) x; \ + STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \ + STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, Int32 encrypted) x; \ + +DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30) +{ + INTERFACE_IFolderExtractToStreamCallback(PURE) +}; + + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.cpp new file mode 100644 index 0000000..b94720c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -0,0 +1,1205 @@ +// LoadCodecs.cpp + +/* +EXTERNAL_CODECS +--------------- + CCodecs::Load() tries to detect the directory with plugins. + It stops the checking, if it can find any of the following items: + - 7z.dll file + - "Formats" subdir + - "Codecs" subdir + The order of check: + 1) directory of client executable + 2) WIN32: directory for REGISTRY item [HKEY_*\Software\7-Zip\Path**] + The order for HKEY_* : Path** : + - HKEY_CURRENT_USER : PathXX + - HKEY_LOCAL_MACHINE : PathXX + - HKEY_CURRENT_USER : Path + - HKEY_LOCAL_MACHINE : Path + PathXX is Path32 in 32-bit code + PathXX is Path64 in 64-bit code + + +EXPORT_CODECS +------------- + if (EXTERNAL_CODECS) is defined, then the code exports internal + codecs of client from CCodecs object to external plugins. + 7-Zip doesn't use that feature. 7-Zip uses the scheme: + - client application without internal plugins. + - 7z.dll module contains all (or almost all) plugins. + 7z.dll can use codecs from another plugins, if required. +*/ + + +#include "StdAfx.h" + +#include "../../../../C/7zVersion.h" + +#include "../../../Common/MyCom.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileIO.h" +#include "../../../Windows/PropVariant.h" + +#include "LoadCodecs.h" + +using namespace NWindows; + +#ifdef NEW_FOLDER_INTERFACE +#include "../../../Common/StringToInt.h" +#endif + +#include "../../ICoder.h" +#include "../../Common/RegisterArc.h" + +#ifdef EXTERNAL_CODECS + +// #define EXPORT_CODECS + +#endif + +#ifdef NEW_FOLDER_INTERFACE +extern HINSTANCE g_hInstance; +#include "../../../Windows/ResourceString.h" +static const UINT kIconTypesResId = 100; +#endif + +#ifdef EXTERNAL_CODECS + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/DLL.h" + +#ifdef _WIN32 +#include "../../../Windows/FileName.h" +#include "../../../Windows/Registry.h" +#endif + +using namespace NFile; + + +#define kCodecsFolderName FTEXT("Codecs") +#define kFormatsFolderName FTEXT("Formats") + + +static CFSTR const kMainDll = + #ifdef _WIN32 + FTEXT("7z.dll"); + #else + FTEXT("7z.so"); + #endif + + +#ifdef _WIN32 + +static LPCTSTR const kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); +static LPCWSTR const kProgramPathValue = L"Path"; +static LPCWSTR const kProgramPath2Value = L"Path" + #ifdef _WIN64 + L"64"; + #else + L"32"; + #endif + +static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path) +{ + NRegistry::CKey key; + if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) + { + UString pathU; + if (key.QueryValue(value, pathU) == ERROR_SUCCESS) + { + path = us2fs(pathU); + NName::NormalizeDirPathPrefix(path); + return NFind::DoesFileExist_Raw(path + kMainDll); + } + } + return false; +} + +#endif // _WIN32 + +#endif // EXTERNAL_CODECS + + +static const unsigned kNumArcsMax = 64; +static unsigned g_NumArcs = 0; +static const CArcInfo *g_Arcs[kNumArcsMax]; + +void RegisterArc(const CArcInfo *arcInfo) throw() +{ + if (g_NumArcs < kNumArcsMax) + { + g_Arcs[g_NumArcs] = arcInfo; + g_NumArcs++; + } +} + +static void SplitString(const UString &srcString, UStringVector &destStrings) +{ + destStrings.Clear(); + UString s; + unsigned len = srcString.Len(); + if (len == 0) + return; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = srcString[i]; + if (c == L' ') + { + if (!s.IsEmpty()) + { + destStrings.Add(s); + s.Empty(); + } + } + else + s += c; + } + if (!s.IsEmpty()) + destStrings.Add(s); +} + +int CArcInfoEx::FindExtension(const UString &ext) const +{ + FOR_VECTOR (i, Exts) + if (ext.IsEqualTo_NoCase(Exts[i].Ext)) + return (int)i; + return -1; +} + +void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) +{ + UStringVector exts, addExts; + SplitString(ext, exts); + SplitString(addExt, addExts); + FOR_VECTOR (i, exts) + { + CArcExtInfo extInfo; + extInfo.Ext = exts[i]; + if (i < addExts.Size()) + { + extInfo.AddExt = addExts[i]; + if (extInfo.AddExt == L"*") + extInfo.AddExt.Empty(); + } + Exts.Add(extInfo); + } +} + +#ifndef _SFX + +static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector &signatures) +{ + signatures.Clear(); + while (size > 0) + { + unsigned len = *data++; + size--; + if (len > size) + return false; + signatures.AddNew().CopyFrom(data, len); + data += len; + size -= len; + } + return true; +} + +#endif // _SFX + +// #include + +#ifdef EXTERNAL_CODECS + +static FString GetBaseFolderPrefixFromRegistry() +{ + FString moduleFolderPrefix = NDLL::GetModuleDirPrefix(); + + #ifdef _WIN32 + if ( !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll) + && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName) + && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName)) + { + FString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; + } + #endif + + // printf("\nmoduleFolderPrefix = %s\n", (const char *)GetAnsiString(moduleFolderPrefix)); + return moduleFolderPrefix; +} + + +static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index, + PROPID propId, CLSID &clsId, bool &isAssigned) +{ + NCOM::CPropVariant prop; + isAssigned = false; + RINOK(getMethodProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + { + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; + isAssigned = true; + clsId = *(const GUID *)(const void *)prop.bstrVal; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func); +// #define MY_GET_FUNC(dest, type, func) dest = (type)(func); + +HRESULT CCodecs::LoadCodecs() +{ + CCodecLib &lib = Libs.Back(); + + MY_GET_FUNC (lib.CreateDecoder, Func_CreateDecoder, lib.Lib.GetProc("CreateDecoder")); + MY_GET_FUNC (lib.CreateEncoder, Func_CreateEncoder, lib.Lib.GetProc("CreateEncoder")); + MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib.GetProc("GetMethodProperty")); + + if (lib.GetMethodProperty) + { + UInt32 numMethods = 1; + Func_GetNumberOfMethods getNumberOfMethods; + MY_GET_FUNC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods")); + if (getNumberOfMethods) + { + RINOK(getNumberOfMethods(&numMethods)); + } + for (UInt32 i = 0; i < numMethods; i++) + { + CDllCodecInfo info; + info.LibIndex = Libs.Size() - 1; + info.CodecIndex = i; + RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); + RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); + Codecs.Add(info); + } + } + + Func_GetHashers getHashers; + MY_GET_FUNC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers")); + if (getHashers) + { + RINOK(getHashers(&lib.ComHashers)); + if (lib.ComHashers) + { + UInt32 numMethods = lib.ComHashers->GetNumHashers(); + for (UInt32 i = 0; i < numMethods; i++) + { + CDllHasherInfo info; + info.LibIndex = Libs.Size() - 1; + info.HasherIndex = i; + Hashers.Add(info); + } + } + } + + return S_OK; +} + +static HRESULT GetProp( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, NCOM::CPropVariant &prop) +{ + if (getProp2) + return getProp2(index, propID, &prop);; + return getProp(propID, &prop); +} + +static HRESULT GetProp_Bool( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, bool &res) +{ + res = false; + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BOOL) + res = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static HRESULT GetProp_UInt32( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UInt32 &res, bool &defined) +{ + res = 0; + defined = false; + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_UI4) + { + res = prop.ulVal; + defined = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static HRESULT GetProp_String( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, UString &res) +{ + res.Empty(); + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) + res.SetFromBstr(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static HRESULT GetProp_RawData( + Func_GetHandlerProperty getProp, + Func_GetHandlerProperty2 getProp2, + UInt32 index, PROPID propID, CByteBuffer &bb) +{ + bb.Free(); + NCOM::CPropVariant prop; + RINOK(GetProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) + { + UINT len = ::SysStringByteLen(prop.bstrVal); + bb.CopyFrom((const Byte *)prop.bstrVal, len); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static const UInt32 kArcFlagsPars[] = +{ + NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName, + NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams, + NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure +}; + +HRESULT CCodecs::LoadFormats() +{ + const NDLL::CLibrary &lib = Libs.Back().Lib; + + Func_GetHandlerProperty getProp = NULL; + Func_GetHandlerProperty2 getProp2; + MY_GET_FUNC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2")); + Func_GetIsArc getIsArc; + MY_GET_FUNC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc")); + + UInt32 numFormats = 1; + + if (getProp2) + { + Func_GetNumberOfFormats getNumberOfFormats; + MY_GET_FUNC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats")); + if (getNumberOfFormats) + { + RINOK(getNumberOfFormats(&numFormats)); + } + } + else + { + MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib.GetProc("GetHandlerProperty")); + if (!getProp) + return S_OK; + } + + for (UInt32 i = 0; i < numFormats; i++) + { + CArcInfoEx item; + item.LibIndex = (int)(Libs.Size() - 1); + item.FormatIndex = i; + + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name)); + + { + NCOM::CPropVariant prop; + if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK) + continue; + if (prop.vt != VT_BSTR) + continue; + if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID)) + return E_FAIL; + item.ClassID = *(const GUID *)(const void *)prop.bstrVal; + prop.Clear(); + } + + UString ext, addExt; + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext)); + RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt)); + item.AddExts(ext, addExt); + + GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled); + bool flags_Defined = false; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined)); + item.NewInterface = flags_Defined; + if (!flags_Defined) // && item.UpdateEnabled + { + // support for DLL version before 9.31: + for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2) + { + bool val = false; + GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val); + if (val) + item.Flags |= kArcFlagsPars[j + 1]; + } + } + + CByteBuffer sig; + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig)); + if (sig.Size() != 0) + item.Signatures.Add(sig); + else + { + RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig)); + ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures); + } + + bool signatureOffset_Defined; + RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined)); + + // bool version_Defined; + // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined)); + + if (getIsArc) + getIsArc(i, &item.IsArcFunc); + + Formats.Add(item); + } + return S_OK; +} + +#ifdef _7ZIP_LARGE_PAGES +extern "C" +{ + extern SIZE_T g_LargePageSize; +} +#endif + + +void CCodecs::AddLastError(const FString &path) +{ + HRESULT res = GetLastError_noZero_HRESULT(); + CCodecError &error = Errors.AddNew(); + error.Path = path; + error.ErrorCode = res; +} + +HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK) +{ + if (loadedOK) + *loadedOK = false; + + // needCheckDll = 1; + + #ifdef _WIN32 + if (needCheckDll) + { + NDLL::CLibrary lib; + if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) + { + /* if is not win32 + // %1 is not a valid Win32 application. + // #define ERROR_BAD_EXE_FORMAT 193L + */ + // return GetLastError_noZero_HRESULT(); + DWORD lastError = GetLastError(); + if (lastError != ERROR_BAD_EXE_FORMAT) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.Message = "cannot load file as datafile library"; + error.ErrorCode = HRESULT_FROM_WIN32(lastError); + } + return S_OK; + } + } + #else + UNUSED_VAR(needCheckDll) + #endif + + Libs.AddNew(); + CCodecLib &lib = Libs.Back(); + lib.Path = dllPath; + bool used = false; + // HRESULT res = S_OK; + + if (lib.Lib.Load(dllPath)) + { + if (loadedOK) + *loadedOK = true; + #ifdef NEW_FOLDER_INTERFACE + lib.LoadIcons(); + #endif + + /* + { + Func_LibStartup _LibStartup; + MY_GET_FUNC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup")); + if (_LibStartup) + { + HRESULT res = _LibStartup(); + if (res != 0) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.ErrorCode = res; + } + } + } + */ + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0) + { + Func_SetLargePageMode setLargePageMode; + MY_GET_FUNC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode")); + if (setLargePageMode) + setLargePageMode(); + } + #endif + + if (CaseSensitiveChange) + { + Func_SetCaseSensitive setCaseSensitive; + MY_GET_FUNC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive")); + if (setCaseSensitive) + setCaseSensitive(CaseSensitive ? 1 : 0); + } + + MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib.GetProc("CreateObject")); + { + unsigned startSize = Codecs.Size() + Hashers.Size(); + HRESULT res = LoadCodecs(); + if (startSize != Codecs.Size() + Hashers.Size()) + used = true; + if (res == S_OK && lib.CreateObject) + { + startSize = Formats.Size(); + res = LoadFormats(); + if (startSize != Formats.Size()) + used = true; + } + if (res != S_OK) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.ErrorCode = res; + } + } + // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs + /* + if (!used) + { + CCodecError &error = Errors.AddNew(); + error.Path = dllPath; + error.Message = "no 7-Zip code"; + } + */ + } + else + { + AddLastError(dllPath); + } + + if (!used) + Libs.DeleteBack(); + + return S_OK; +} + +HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath) +{ + if (!NFile::NFind::DoesDirExist_FollowLink(folderPath)) + // if (!NFile::NFind::DoesDirExist(folderPath)) + { + // AddLastError(folderPath); + return S_OK; + } + + FString folderPrefix = folderPath; + folderPrefix.Add_PathSepar(); + + NFile::NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(folderPrefix); + NFile::NFind::CDirEntry fi; + for (;;) + { + bool found; + if (!enumerator.Next(fi, found)) + { + // it can be wrong Symbolic link to folder here + AddLastError(folderPath); + break; + // return GetLastError_noZero_HRESULT(); + } + if (!found) + break; + if (fi.IsDir()) + continue; + RINOK(LoadDll(folderPrefix + fi.Name, true)); + } + return S_OK; +} + +void CCodecs::CloseLibs() +{ + // OutputDebugStringA("~CloseLibs start"); + /* + WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected, + if it's called from another FreeLibrary() call. + So we need to call FreeLibrary() before global destructors. + + Also we free global links from DLLs to object of this module before CLibrary::Free() call. + */ + + FOR_VECTOR(i, Libs) + { + const CCodecLib &lib = Libs[i]; + if (lib.SetCodecs) + lib.SetCodecs(NULL); + } + + // OutputDebugStringA("~CloseLibs after SetCodecs"); + Libs.Clear(); + // OutputDebugStringA("~CloseLibs end"); +} + +#endif // EXTERNAL_CODECS + + +HRESULT CCodecs::Load() +{ + #ifdef NEW_FOLDER_INTERFACE + InternalIcons.LoadIcons(g_hInstance); + #endif + + Formats.Clear(); + + #ifdef EXTERNAL_CODECS + Errors.Clear(); + MainDll_ErrorPath.Empty(); + Codecs.Clear(); + Hashers.Clear(); + #endif + + for (UInt32 i = 0; i < g_NumArcs; i++) + { + const CArcInfo &arc = *g_Arcs[i]; + CArcInfoEx item; + + item.Name = arc.Name; + item.CreateInArchive = arc.CreateInArchive; + item.IsArcFunc = arc.IsArc; + item.Flags = arc.Flags; + + { + UString e, ae; + if (arc.Ext) + e = arc.Ext; + if (arc.AddExt) + ae = arc.AddExt; + item.AddExts(e, ae); + } + + #ifndef _SFX + + item.CreateOutArchive = arc.CreateOutArchive; + item.UpdateEnabled = (arc.CreateOutArchive != NULL); + item.SignatureOffset = arc.SignatureOffset; + // item.Version = MY_VER_MIX; + item.NewInterface = true; + + if (arc.IsMultiSignature()) + ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures); + else + item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize); + + #endif + + Formats.Add(item); + } + + // printf("\nLoad codecs \n"); + + #ifdef EXTERNAL_CODECS + const FString baseFolder = GetBaseFolderPrefixFromRegistry(); + { + bool loadedOK; + RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK)); + if (!loadedOK) + MainDll_ErrorPath = kMainDll; + } + RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName)); + RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName)); + + NeedSetLibCodecs = true; + + if (Libs.Size() == 0) + NeedSetLibCodecs = false; + else if (Libs.Size() == 1) + { + // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module. + #ifndef EXPORT_CODECS + if (g_NumArcs == 0) + NeedSetLibCodecs = false; + #endif + } + + if (NeedSetLibCodecs) + { + /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c) + old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */ + + FOR_VECTOR(i, Libs) + { + CCodecLib &lib = Libs[i]; + MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib.GetProc("SetCodecs")); + if (lib.SetCodecs) + { + RINOK(lib.SetCodecs(this)); + } + } + } + + #endif + + return S_OK; +} + +#ifndef _SFX + +int CCodecs::FindFormatForArchiveName(const UString &arcPath) const +{ + int dotPos = arcPath.ReverseFind_Dot(); + if (dotPos <= arcPath.ReverseFind_PathSepar()) + return -1; + const UString ext = arcPath.Ptr((unsigned)(dotPos + 1)); + if (ext.IsEmpty()) + return -1; + if (ext.IsEqualTo_Ascii_NoCase("exe")) + return -1; + FOR_VECTOR (i, Formats) + { + const CArcInfoEx &arc = Formats[i]; + /* + if (!arc.UpdateEnabled) + continue; + */ + if (arc.FindExtension(ext) >= 0) + return (int)i; + } + return -1; +} + +int CCodecs::FindFormatForExtension(const UString &ext) const +{ + if (ext.IsEmpty()) + return -1; + FOR_VECTOR (i, Formats) + if (Formats[i].FindExtension(ext) >= 0) + return (int)i; + return -1; +} + +int CCodecs::FindFormatForArchiveType(const UString &arcType) const +{ + FOR_VECTOR (i, Formats) + if (Formats[i].Name.IsEqualTo_NoCase(arcType)) + return (int)i; + return -1; +} + +bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const +{ + formatIndices.Clear(); + for (unsigned pos = 0; pos < arcType.Len();) + { + int pos2 = arcType.Find(L'.', pos); + if (pos2 < 0) + pos2 = (int)arcType.Len(); + const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); + if (name.IsEmpty()) + return false; + int index = FindFormatForArchiveType(name); + if (index < 0 && name != L"*") + { + formatIndices.Clear(); + return false; + } + formatIndices.Add(index); + pos = (unsigned)pos2 + 1; + } + return true; +} + +#endif // _SFX + + +#ifdef NEW_FOLDER_INTERFACE + +void CCodecIcons::LoadIcons(HMODULE m) +{ + UString iconTypes; + MyLoadString(m, kIconTypesResId, iconTypes); + UStringVector pairs; + SplitString(iconTypes, pairs); + FOR_VECTOR (i, pairs) + { + const UString &s = pairs[i]; + int pos = s.Find(L':'); + CIconPair iconPair; + iconPair.IconIndex = -1; + if (pos < 0) + pos = (int)s.Len(); + else + { + const UString num = s.Ptr((unsigned)pos + 1); + if (!num.IsEmpty()) + { + const wchar_t *end; + iconPair.IconIndex = (int)ConvertStringToUInt32(num, &end); + if (*end != 0) + continue; + } + } + iconPair.Ext = s.Left((unsigned)pos); + IconPairs.Add(iconPair); + } +} + +bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const +{ + iconIndex = -1; + FOR_VECTOR (i, IconPairs) + { + const CIconPair &pair = IconPairs[i]; + if (ext.IsEqualTo_NoCase(pair.Ext)) + { + iconIndex = pair.IconIndex; + return true; + } + } + return false; +} + +#endif // NEW_FOLDER_INTERFACE + + +#ifdef EXTERNAL_CODECS + +// #define EXPORT_CODECS + +#ifdef EXPORT_CODECS + +extern unsigned g_NumCodecs; +STDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject); +STDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject); +STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +#define NUM_EXPORT_CODECS g_NumCodecs + +extern unsigned g_NumHashers; +STDAPI CreateHasher(UInt32 index, IHasher **hasher); +STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); +#define NUM_EXPORT_HASHERS g_NumHashers + +#else // EXPORT_CODECS + +#define NUM_EXPORT_CODECS 0 +#define NUM_EXPORT_HASHERS 0 + +#endif // EXPORT_CODECS + +STDMETHODIMP CCodecs::GetNumMethods(UInt32 *numMethods) +{ + *numMethods = NUM_EXPORT_CODECS + #ifdef EXTERNAL_CODECS + + Codecs.Size() + #endif + ; + return S_OK; +} + +STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return GetMethodProperty(index, propID, value); + #endif + + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + + if (propID == NMethodPropID::kDecoderIsAssigned || + propID == NMethodPropID::kEncoderIsAssigned) + { + NCOM::CPropVariant prop; + prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ? + ci.DecoderIsAssigned : + ci.EncoderIsAssigned); + prop.Detach(value); + return S_OK; + } + const CCodecLib &lib = Libs[ci.LibIndex]; + return lib.GetMethodProperty(ci.CodecIndex, propID, value); + #else + return E_FAIL; + #endif +} + +STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return CreateDecoder(index, iid, coder); + #endif + + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + if (ci.DecoderIsAssigned) + { + const CCodecLib &lib = Libs[ci.LibIndex]; + if (lib.CreateDecoder) + return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder); + if (lib.CreateObject) + return lib.CreateObject(&ci.Decoder, iid, (void **)coder); + } + return S_OK; + #else + return E_FAIL; + #endif +} + +STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return CreateEncoder(index, iid, coder); + #endif + + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + if (ci.EncoderIsAssigned) + { + const CCodecLib &lib = Libs[ci.LibIndex]; + if (lib.CreateEncoder) + return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder); + if (lib.CreateObject) + return lib.CreateObject(&ci.Encoder, iid, (void **)coder); + } + return S_OK; + #else + return E_FAIL; + #endif +} + + +STDMETHODIMP_(UInt32) CCodecs::GetNumHashers() +{ + return NUM_EXPORT_HASHERS + #ifdef EXTERNAL_CODECS + + Hashers.Size() + #endif + ; +} + +STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return ::GetHasherProp(index, propID, value); + #endif + + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value); + #else + return E_FAIL; + #endif +} + +STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return CreateHasher(index, hasher); + #endif + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher); + #else + return E_FAIL; + #endif +} + +int CCodecs::GetCodec_LibIndex(UInt32 index) const +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + return -1; + #endif + + #ifdef EXTERNAL_CODECS + const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS]; + return (int)ci.LibIndex; + #else + return -1; + #endif +} + +int CCodecs::GetHasherLibIndex(UInt32 index) +{ + #ifdef EXPORT_CODECS + if (index < g_NumHashers) + return -1; + #endif + + #ifdef EXTERNAL_CODECS + const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS]; + return (int)ci.LibIndex; + #else + return -1; + #endif +} + +bool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + { + NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK) + { + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + } + return false; + } + #endif + + #ifdef EXTERNAL_CODECS + return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned; + #else + return false; + #endif +} + +bool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const +{ + #ifdef EXPORT_CODECS + if (index < g_NumCodecs) + { + NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK) + { + if (prop.vt == VT_BOOL) + return VARIANT_BOOLToBool(prop.boolVal); + } + return false; + } + #endif + + #ifdef EXTERNAL_CODECS + return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned; + #else + return false; + #endif +} + +UInt32 CCodecs::GetCodec_NumStreams(UInt32 index) +{ + NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK) + return 0; + if (prop.vt == VT_UI4) + return (UInt32)prop.ulVal; + if (prop.vt == VT_EMPTY) + return 1; + return 0; +} + +HRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id) +{ + NCOM::CPropVariant prop; + RINOK(GetProperty(index, NMethodPropID::kID, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + id = prop.uhVal.QuadPart; + return S_OK; +} + +AString CCodecs::GetCodec_Name(UInt32 index) +{ + AString s; + NCOM::CPropVariant prop; + if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + s.SetFromWStr_if_Ascii(prop.bstrVal); + return s; +} + +UInt64 CCodecs::GetHasherId(UInt32 index) +{ + NCOM::CPropVariant prop; + if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK) + return 0; + if (prop.vt != VT_UI8) + return 0; + return prop.uhVal.QuadPart; +} + +AString CCodecs::GetHasherName(UInt32 index) +{ + AString s; + NCOM::CPropVariant prop; + if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK) + if (prop.vt == VT_BSTR) + s.SetFromWStr_if_Ascii(prop.bstrVal); + return s; +} + +UInt32 CCodecs::GetHasherDigestSize(UInt32 index) +{ + NCOM::CPropVariant prop; + if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK) + return 0; + if (prop.vt != VT_UI4) + return 0; + return prop.ulVal; +} + +void CCodecs::GetCodecsErrorMessage(UString &s) +{ + s.Empty(); + FOR_VECTOR (i, Errors) + { + const CCodecError &ce = Errors[i]; + s += "Codec Load Error: "; + s += fs2us(ce.Path); + if (ce.ErrorCode != 0) + { + s += " : "; + s += NWindows::NError::MyFormatMessage(ce.ErrorCode); + } + if (!ce.Message.IsEmpty()) + { + s += " : "; + s += ce.Message; + } + s.Add_LF(); + } +} + +#endif // EXTERNAL_CODECS diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.h new file mode 100644 index 0000000..660ddee --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/LoadCodecs.h @@ -0,0 +1,436 @@ +// LoadCodecs.h + +#ifndef __LOAD_CODECS_H +#define __LOAD_CODECS_H + +/* +Client application uses LoadCodecs.* to load plugins to +CCodecs object, that contains 3 lists of plugins: + 1) Formats - internal and external archive handlers + 2) Codecs - external codecs + 3) Hashers - external hashers + +EXTERNAL_CODECS +--------------- + + if EXTERNAL_CODECS is defined, then the code tries to load external + plugins from DLL files (shared libraries). + + There are two types of executables in 7-Zip: + + 1) Executable that uses external plugins must be compiled + with EXTERNAL_CODECS defined: + - 7z.exe, 7zG.exe, 7zFM.exe + + Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h + that code is used in plugin module (7z.dll). + + 2) Standalone modules are compiled without EXTERNAL_CODECS: + - SFX modules: 7z.sfx, 7zCon.sfx + - standalone versions of console 7-Zip: 7za.exe, 7zr.exe + + if EXTERNAL_CODECS is defined, CCodecs class implements interfaces: + - ICompressCodecsInfo : for Codecs + - IHashers : for Hashers + + The client application can send CCodecs object to each plugin module. + And plugin module can use ICompressCodecsInfo or IHashers interface to access + another plugins. + + There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin + 1) for old versions: + a) request ISetCompressCodecsInfo from created archive handler. + b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo) + 2) for new versions: + a) request "SetCodecs" function from DLL file + b) call SetCodecs(compressCodecsInfo) function from DLL file +*/ + +#include "../../../Common/MyBuffer.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" +#include "../../../Common/ComTry.h" + +#ifdef EXTERNAL_CODECS +#include "../../../Windows/DLL.h" +#endif + +#include "../../ICoder.h" + +#include "../../Archive/IArchive.h" + + +#ifdef EXTERNAL_CODECS + +struct CDllCodecInfo +{ + unsigned LibIndex; + UInt32 CodecIndex; + bool EncoderIsAssigned; + bool DecoderIsAssigned; + CLSID Encoder; + CLSID Decoder; +}; + +struct CDllHasherInfo +{ + unsigned LibIndex; + UInt32 HasherIndex; +}; + +#endif + +struct CArcExtInfo +{ + UString Ext; + UString AddExt; + + CArcExtInfo() {} + CArcExtInfo(const UString &ext): Ext(ext) {} + CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} +}; + + +struct CArcInfoEx +{ + UInt32 Flags; + + Func_CreateInArchive CreateInArchive; + Func_IsArc IsArcFunc; + + UString Name; + CObjectVector Exts; + + #ifndef _SFX + Func_CreateOutArchive CreateOutArchive; + bool UpdateEnabled; + bool NewInterface; + // UInt32 Version; + UInt32 SignatureOffset; + CObjectVector Signatures; + #ifdef NEW_FOLDER_INTERFACE + UStringVector AssociateExts; + #endif + #endif + + #ifdef EXTERNAL_CODECS + int LibIndex; + UInt32 FormatIndex; + CLSID ClassID; + #endif + + bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; } + bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; } + + bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; } + bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; } + bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; } + bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; } + + bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; } + bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; } + bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; } + bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; } + bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; } + bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; } + + UString GetMainExt() const + { + if (Exts.IsEmpty()) + return UString(); + return Exts[0].Ext; + } + int FindExtension(const UString &ext) const; + + /* + UString GetAllExtensions() const + { + UString s; + for (int i = 0; i < Exts.Size(); i++) + { + if (i > 0) + s += ' '; + s += Exts[i].Ext; + } + return s; + } + */ + + void AddExts(const UString &ext, const UString &addExt); + + bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); } + // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); } + + CArcInfoEx(): + Flags(0), + CreateInArchive(NULL), + IsArcFunc(NULL) + #ifndef _SFX + , CreateOutArchive(NULL) + , UpdateEnabled(false) + , NewInterface(false) + // , Version(0) + , SignatureOffset(0) + #endif + #ifdef EXTERNAL_CODECS + , LibIndex(-1) + #endif + {} +}; + +#ifdef NEW_FOLDER_INTERFACE + +struct CCodecIcons +{ + struct CIconPair + { + UString Ext; + int IconIndex; + }; + CObjectVector IconPairs; + + void LoadIcons(HMODULE m); + bool FindIconIndex(const UString &ext, int &iconIndex) const; +}; + +#endif + +#ifdef EXTERNAL_CODECS + +struct CCodecLib + #ifdef NEW_FOLDER_INTERFACE + : public CCodecIcons + #endif +{ + NWindows::NDLL::CLibrary Lib; + FString Path; + + Func_CreateObject CreateObject; + Func_GetMethodProperty GetMethodProperty; + Func_CreateDecoder CreateDecoder; + Func_CreateEncoder CreateEncoder; + Func_SetCodecs SetCodecs; + + CMyComPtr ComHashers; + + #ifdef NEW_FOLDER_INTERFACE + void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); } + #endif + + CCodecLib(): + CreateObject(NULL), + GetMethodProperty(NULL), + CreateDecoder(NULL), + CreateEncoder(NULL), + SetCodecs(NULL) + {} +}; + +#endif + +struct CCodecError +{ + FString Path; + HRESULT ErrorCode; + AString Message; + CCodecError(): ErrorCode(0) {} +}; + +class CCodecs: + #ifdef EXTERNAL_CODECS + public ICompressCodecsInfo, + public IHashers, + #else + public IUnknown, + #endif + public CMyUnknownImp +{ + CLASS_NO_COPY(CCodecs); +public: + #ifdef EXTERNAL_CODECS + + CObjectVector Libs; + FString MainDll_ErrorPath; + CObjectVector Errors; + + void AddLastError(const FString &path); + void CloseLibs(); + + class CReleaser + { + CLASS_NO_COPY(CReleaser); + + /* CCodecsReleaser object releases CCodecs links. + 1) CCodecs is COM object that is deleted when all links to that object will be released/ + 2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself. + To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */ + + CCodecs *_codecs; + + public: + CReleaser(): _codecs(NULL) {} + void Set(CCodecs *codecs) { _codecs = codecs; } + ~CReleaser() { if (_codecs) _codecs->CloseLibs(); } + }; + + bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo + + HRESULT LoadCodecs(); + HRESULT LoadFormats(); + HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL); + HRESULT LoadDllsFromFolder(const FString &folderPrefix); + + HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const + { + return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); + } + + #endif + + #ifdef NEW_FOLDER_INTERFACE + CCodecIcons InternalIcons; + #endif + + CObjectVector Formats; + + #ifdef EXTERNAL_CODECS + CRecordVector Codecs; + CRecordVector Hashers; + #endif + + bool CaseSensitiveChange; + bool CaseSensitive; + + CCodecs(): + #ifdef EXTERNAL_CODECS + NeedSetLibCodecs(true), + #endif + CaseSensitiveChange(false), + CaseSensitive(false) + {} + + ~CCodecs() + { + // OutputDebugStringA("~CCodecs"); + } + + const wchar_t *GetFormatNamePtr(int formatIndex) const + { + return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name; + } + + HRESULT Load(); + + #ifndef _SFX + int FindFormatForArchiveName(const UString &arcPath) const; + int FindFormatForExtension(const UString &ext) const; + int FindFormatForArchiveType(const UString &arcType) const; + bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; + #endif + + #ifdef EXTERNAL_CODECS + + MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers) + + STDMETHOD(GetNumMethods)(UInt32 *numMethods); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder); + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder); + + STDMETHOD_(UInt32, GetNumHashers)(); + STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher); + + #else + + MY_UNKNOWN_IMP + + #endif // EXTERNAL_CODECS + + + #ifdef EXTERNAL_CODECS + + int GetCodec_LibIndex(UInt32 index) const; + bool GetCodec_DecoderIsAssigned(UInt32 index) const; + bool GetCodec_EncoderIsAssigned(UInt32 index) const; + UInt32 GetCodec_NumStreams(UInt32 index); + HRESULT GetCodec_Id(UInt32 index, UInt64 &id); + AString GetCodec_Name(UInt32 index); + + int GetHasherLibIndex(UInt32 index); + UInt64 GetHasherId(UInt32 index); + AString GetHasherName(UInt32 index); + UInt32 GetHasherDigestSize(UInt32 index); + + void GetCodecsErrorMessage(UString &s); + + #endif + + HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr &archive) const + { + const CArcInfoEx &ai = Formats[formatIndex]; + #ifdef EXTERNAL_CODECS + if (ai.LibIndex < 0) + #endif + { + COM_TRY_BEGIN + archive = ai.CreateInArchive(); + return S_OK; + COM_TRY_END + } + #ifdef EXTERNAL_CODECS + return CreateArchiveHandler(ai, false, (void **)&archive); + #endif + } + + #ifndef _SFX + + HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr &archive) const + { + const CArcInfoEx &ai = Formats[formatIndex]; + #ifdef EXTERNAL_CODECS + if (ai.LibIndex < 0) + #endif + { + COM_TRY_BEGIN + archive = ai.CreateOutArchive(); + return S_OK; + COM_TRY_END + } + + #ifdef EXTERNAL_CODECS + return CreateArchiveHandler(ai, true, (void **)&archive); + #endif + } + + int FindOutFormatFromName(const UString &name) const + { + FOR_VECTOR (i, Formats) + { + const CArcInfoEx &arc = Formats[i]; + if (!arc.UpdateEnabled) + continue; + if (arc.Name.IsEqualTo_NoCase(name)) + return (int)i; + } + return -1; + } + + #endif // _SFX +}; + +#ifdef EXTERNAL_CODECS + #define CREATE_CODECS_OBJECT \ + CCodecs *codecs = new CCodecs; \ + CExternalCodecs __externalCodecs; \ + __externalCodecs.GetCodecs = codecs; \ + __externalCodecs.GetHashers = codecs; \ + CCodecs::CReleaser codecsReleaser; \ + codecsReleaser.Set(codecs); +#else + #define CREATE_CODECS_OBJECT \ + CCodecs *codecs = new CCodecs; \ + CMyComPtr __codecsRef = codecs; +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.cpp new file mode 100644 index 0000000..7bec9d5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.cpp @@ -0,0 +1,3626 @@ +// OpenArchive.cpp + +#include "StdAfx.h" + +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" + +#include "../../Compress/CopyCoder.h" + +#include "DefaultName.h" +#include "OpenArchive.h" + +#ifndef _SFX +#include "SetProperties.h" +#endif + +#ifndef _SFX +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif +#endif + +// increase it, if you need to support larger SFX stubs +static const UInt64 kMaxCheckStartPosition = 1 << 23; + +/* +Open: + - formatIndex >= 0 (exact Format) + 1) Open with main type. Archive handler is allowed to use archive start finder. + Warning, if there is tail. + + - formatIndex = -1 (Parser:0) (default) + - same as #1 but doesn't return Parser + + - formatIndex = -2 (#1) + - file has supported extension (like a.7z) + Open with that main type (only starting from start of file). + - open OK: + - if there is no tail - return OK + - if there is tail: + - archive is not "Self Exe" - return OK with Warning, that there is tail + - archive is "Self Exe" + ignore "Self Exe" stub, and tries to open tail + - tail can be open as archive - shows that archive and stub size property. + - tail can't be open as archive - shows Parser ??? + - open FAIL: + Try to open with all other types from offset 0 only. + If some open type is OK and physical archive size is uequal or larger + than file size, then return that archive with warning that cannot be open as [extension type]. + If extension was EXE, it will try to open as unknown_extension case + - file has unknown extension (like a.hhh) + It tries to open via parser code. + - if there is full archive or tail archive and unknown block or "Self Exe" + at front, it shows tail archive and stub size property. + - in another cases, if there is some archive inside file, it returns parser/ + - in another cases, it retuens S_FALSE + + + - formatIndex = -3 (#2) + - same as #1, but + - stub (EXE) + archive is open in Parser + + - formatIndex = -4 (#3) + - returns only Parser. skip full file archive. And show other sub-archives + + - formatIndex = -5 (#4) + - returns only Parser. skip full file archive. And show other sub-archives for each byte pos + +*/ + + + + +using namespace NWindows; + +/* +#ifdef _SFX +#define OPEN_PROPS_PARAM +#else +#define OPEN_PROPS_PARAM , props +#endif +*/ + +/* +CArc::~CArc() +{ + GetRawProps.Release(); + Archive.Release(); + printf("\nCArc::~CArc()\n"); +} +*/ + +#ifndef _SFX + +namespace NArchive { +namespace NParser { + +struct CParseItem +{ + UInt64 Offset; + UInt64 Size; + // UInt64 OkSize; + UString Name; + UString Extension; + FILETIME FileTime; + UString Comment; + UString ArcType; + + bool FileTime_Defined; + bool UnpackSize_Defined; + bool NumSubDirs_Defined; + bool NumSubFiles_Defined; + + bool IsSelfExe; + bool IsNotArcType; + + UInt64 UnpackSize; + UInt64 NumSubDirs; + UInt64 NumSubFiles; + + int FormatIndex; + + bool LenIsUnknown; + + CParseItem(): + // OkSize(0), + FileTime_Defined(false), + UnpackSize_Defined(false), + NumSubDirs_Defined(false), + NumSubFiles_Defined(false), + IsSelfExe(false), + IsNotArcType(false), + LenIsUnknown(false) + {} + + /* + bool IsEqualTo(const CParseItem &item) const + { + return Offset == item.Offset && Size == item.Size; + } + */ + + void NormalizeOffset() + { + if ((Int64)Offset < 0) + { + Size += Offset; + // OkSize += Offset; + Offset = 0; + } + } +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ +public: + CObjectVector _items; + UInt64 _maxEndOffset; + CMyComPtr _stream; + + MY_UNKNOWN_IMP2( + IInArchive, + IInArchiveGetStream) + + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); + + UInt64 GetLastEnd() const + { + if (_items.IsEmpty()) + return 0; + const CParseItem &back = _items.Back(); + return back.Offset + back.Size; + } + + void AddUnknownItem(UInt64 next); + int FindInsertPos(const CParseItem &item) const; + void AddItem(const CParseItem &item); + + CHandler(): _maxEndOffset(0) {} +}; + +int CHandler::FindInsertPos(const CParseItem &item) const +{ + unsigned left = 0, right = _items.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const CParseItem & midItem = _items[mid]; + if (item.Offset < midItem.Offset) + right = mid; + else if (item.Offset > midItem.Offset) + left = mid + 1; + else if (item.Size < midItem.Size) + right = mid; + /* + else if (item.Size > midItem.Size) + left = mid + 1; + */ + else + { + left = mid + 1; + // return -1; + } + } + return (int)left; +} + +void CHandler::AddUnknownItem(UInt64 next) +{ + /* + UInt64 prevEnd = 0; + if (!_items.IsEmpty()) + { + const CParseItem &back = _items.Back(); + prevEnd = back.Offset + back.Size; + } + */ + if (_maxEndOffset < next) + { + CParseItem item2; + item2.Offset = _maxEndOffset; + item2.Size = next - _maxEndOffset; + _maxEndOffset = next; + _items.Add(item2); + } + else if (_maxEndOffset > next && !_items.IsEmpty()) + { + CParseItem &back = _items.Back(); + if (back.LenIsUnknown) + { + back.Size = next - back.Offset; + _maxEndOffset = next; + } + } +} + +void CHandler::AddItem(const CParseItem &item) +{ + AddUnknownItem(item.Offset); + int pos = FindInsertPos(item); + if (pos >= 0) + { + _items.Insert((unsigned)pos, item); + UInt64 next = item.Offset + item.Size; + if (_maxEndOffset < next) + _maxEndOffset = next; + } +} + +/* +static const CStatProp kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidType, VT_BSTR}, + { NULL, kpidComment, VT_BSTR}, + { NULL, kpidOffset, VT_UI8}, + { NULL, kpidUnpackSize, VT_UI8}, +// { NULL, kpidNumSubDirs, VT_UI8}, +}; +*/ + +static const Byte kProps[] = +{ + kpidPath, + kpidSize, + kpidMTime, + kpidType, + kpidComment, + kpidOffset, + kpidUnpackSize +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */) +{ + COM_TRY_BEGIN + { + Close(); + _stream = stream; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _stream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NCOM::CPropVariant prop; + + const CParseItem &item = _items[index]; + + switch (propID) + { + case kpidPath: + { + char sz[32]; + ConvertUInt32ToString(index + 1, sz); + UString s(sz); + if (!item.Name.IsEmpty()) + { + s += '.'; + s += item.Name; + } + if (!item.Extension.IsEmpty()) + { + s += '.'; + s += item.Extension; + } + prop = s; break; + } + case kpidSize: + case kpidPackSize: prop = item.Size; break; + case kpidOffset: prop = item.Offset; break; + case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break; + case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break; + case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break; + case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break; + case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break; + case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + + bool allFilesMode = (numItems == (UInt32)(Int32)-1); + if (allFilesMode) + numItems = _items.Size(); + if (_stream && numItems == 0) + return S_OK; + UInt64 totalSize = 0; + UInt32 i; + for (i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + totalSize = 0; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr progress = lps; + lps->Init(extractCallback, false); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_stream); + + CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream; + CMyComPtr outStream(outStreamSpec); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); + CMyComPtr copyCoder = copyCoderSpec; + + for (i = 0; i < numItems; i++) + { + lps->InSize = totalSize; + lps->OutSize = totalSize; + RINOK(lps->SetCur()); + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + UInt32 index = allFilesMode ? i : indices[i]; + const CParseItem &item = _items[index]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + UInt64 unpackSize = item.Size; + totalSize += unpackSize; + bool skipMode = false; + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + + outStreamSpec->SetStream(realOutStream); + realOutStream.Release(); + outStreamSpec->Init(skipMode ? 0 : unpackSize, true); + + Int32 opRes = NExtract::NOperationResult::kOK; + RINOK(_stream->Seek((Int64)item.Offset, STREAM_SEEK_SET, NULL)); + streamSpec->Init(unpackSize); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + + if (outStreamSpec->GetRem() != 0) + opRes = NExtract::NOperationResult::kDataError; + outStreamSpec->ReleaseStream(); + RINOK(extractCallback->SetOperationResult(opRes)); + } + + return S_OK; + + COM_TRY_END +} + + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + const CParseItem &item = _items[index]; + return CreateLimitedInStream(_stream, item.Offset, item.Size, stream); + COM_TRY_END +} + +}} + +#endif + +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw() +{ + NCOM::CPropVariant prop; + result = false; + RINOK(arc->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDir, result); +} + +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAux, result); +} + +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result); +} + +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw() +{ + return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result); +} + +static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw() +{ + NCOM::CPropVariant prop; + result = false; + RINOK(arc->GetArchiveProperty(propid, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined) +{ + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; break; + case VT_I4: result = (UInt64)(Int64)prop.lVal; break; + case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; break; + case VT_I8: result = (UInt64)prop.hVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined) +{ + defined = false; + NCOM::CPropVariant prop; + RINOK(arc->GetArchiveProperty(propid, &prop)); + switch (prop.vt) + { + case VT_UI4: result = prop.ulVal; break; + case VT_I4: result = prop.lVal; break; + case VT_UI8: result = (Int64)prop.uhVal.QuadPart; break; + case VT_I8: result = (Int64)prop.hVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +#ifndef _SFX + +HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const +{ + if (!GetRawProps) + return E_FAIL; + if (index == parent) + return S_OK; + UInt32 curIndex = index; + + UString s; + + bool prevWasAltStream = false; + + for (;;) + { + #ifdef MY_CPU_LE + const void *p; + UInt32 size; + UInt32 propType; + RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType)); + if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) + s = (const wchar_t *)p; + else + #endif + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(curIndex, kpidName, &prop)); + if (prop.vt == VT_BSTR && prop.bstrVal) + s.SetFromBstr(prop.bstrVal); + else if (prop.vt == VT_EMPTY) + s.Empty(); + else + return E_FAIL; + } + + UInt32 curParent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)); + + // 18.06: fixed : we don't want to split name to parts + /* + if (parentType != NParentType::kAltStream) + { + for (;;) + { + int pos = s.ReverseFind_PathSepar(); + if (pos < 0) + { + break; + } + parts.Insert(0, s.Ptr(pos + 1)); + s.DeleteFrom(pos); + } + } + */ + + parts.Insert(0, s); + + if (prevWasAltStream) + { + { + UString &s2 = parts[parts.Size() - 2]; + s2 += ':'; + s2 += parts.Back(); + } + parts.DeleteBack(); + } + + if (parent == curParent) + return S_OK; + + prevWasAltStream = false; + if (parentType == NParentType::kAltStream) + prevWasAltStream = true; + + if (curParent == (UInt32)(Int32)-1) + return E_FAIL; + curIndex = curParent; + } +} + +#endif + + + +HRESULT CArc::GetItemPath(UInt32 index, UString &result) const +{ + #ifdef MY_CPU_LE + if (GetRawProps) + { + const void *p; + UInt32 size; + UInt32 propType; + if (!IsTree) + { + if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK && + propType == NPropDataType::kUtf16z) + { + unsigned len = size / 2 - 1; + // (len) doesn't include null terminator + + /* + #if WCHAR_MAX > 0xffff + len = (unsigned)Utf16LE__Get_Num_WCHARs(p, len); + + wchar_t *s = result.GetBuf(len); + wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, len, s); + if (s + len != sEnd) return E_FAIL; + *sEnd = 0; + + #else + */ + + wchar_t *s = result.GetBuf(len); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + else if (c == L'\\') + c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme + #endif + + *s++ = c; + } + *s = 0; + + // #endif + + result.ReleaseBuf_SetLen(len); + + Convert_UnicodeEsc16_To_UnicodeEscHigh(result); + if (len != 0) + return S_OK; + } + } + /* + else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK && + p && propType == NPropDataType::kUtf16z) + { + size -= 2; + UInt32 totalSize = size; + bool isOK = false; + + { + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + { + if (parentType != 0) + totalSize += 2; + isOK = true; + break; + } + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK && + p2 && propType == NPropDataType::kUtf16z) + break; + totalSize += size2; + } + } + + if (isOK) + { + wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2); + UInt32 pos = totalSize - size; + memcpy((Byte *)sz + pos, p, size); + UInt32 index2 = index; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK) + break; + if (parent == (UInt32)(Int32)-1) + { + if (parentType != 0) + sz[pos / 2 - 1] = L':'; + break; + } + index2 = parent; + UInt32 size2; + const void *p2; + if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK) + break; + pos -= size2; + memcpy((Byte *)sz + pos, p2, size2); + sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':'; + } + #ifdef _WIN32 + // result.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + return S_OK; + } + } + */ + } + #endif + + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_BSTR && prop.bstrVal) + result.SetFromBstr(prop.bstrVal); + else if (prop.vt == VT_EMPTY) + result.Empty(); + else + return E_FAIL; + } + + if (result.IsEmpty()) + return GetDefaultItemPath(index, result); + + Convert_UnicodeEsc16_To_UnicodeEscHigh(result); + return S_OK; +} + +HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const +{ + result.Empty(); + bool isDir; + RINOK(Archive_IsItem_Dir(Archive, index, isDir)); + if (!isDir) + { + result = DefaultName; + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidExtension, &prop)); + if (prop.vt == VT_BSTR) + { + result += '.'; + result += prop.bstrVal; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + } + return S_OK; +} + +HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const +{ + RINOK(GetItemPath(index, result)); + if (Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted)); + if (isDeleted) + result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); + } + return S_OK; +} + +#ifdef SUPPORT_ALT_STREAMS + +int FindAltStreamColon_in_Path(const wchar_t *path) +{ + unsigned i = 0; + int colonPos = -1; + for (;; i++) + { + wchar_t c = path[i]; + if (c == 0) + return colonPos; + if (c == ':') + { + if (colonPos < 0) + colonPos = (int)i; + continue; + } + if (c == WCHAR_PATH_SEPARATOR) + colonPos = -1; + } +} + +#endif + +HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const +{ + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream = false; + item.AltStreamName.Empty(); + item.MainPath.Empty(); + #endif + + item.IsDir = false; + item.Path.Empty(); + item.ParentIndex = (UInt32)(Int32)-1; + + item.PathParts.Clear(); + + RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir)); + item.MainIsDir = item.IsDir; + + RINOK(GetItemPath2(index, item.Path)); + + #ifndef _SFX + UInt32 mainIndex = index; + #endif + + #ifdef SUPPORT_ALT_STREAMS + + item.MainPath = item.Path; + if (Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream)); + } + + bool needFindAltStream = false; + + if (item.IsAltStream) + { + needFindAltStream = true; + if (GetRawProps) + { + UInt32 parentType = 0; + UInt32 parentIndex; + RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType)); + if (parentType == NParentType::kAltStream) + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidName, &prop)); + if (prop.vt == VT_BSTR && prop.bstrVal) + item.AltStreamName.SetFromBstr(prop.bstrVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + else + { + // item.IsAltStream = false; + } + /* + if (item.AltStreamName.IsEmpty()) + item.IsAltStream = false; + */ + + needFindAltStream = false; + item.ParentIndex = parentIndex; + mainIndex = parentIndex; + + if (parentIndex == (UInt32)(Int32)-1) + { + item.MainPath.Empty(); + item.MainIsDir = true; + } + else + { + RINOK(GetItemPath2(parentIndex, item.MainPath)); + RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir)); + } + } + } + } + + if (item.WriteToAltStreamIfColon || needFindAltStream) + { + /* Good handler must support GetRawProps::GetParent for alt streams. + So the following code currently is not used */ + int colon = FindAltStreamColon_in_Path(item.Path); + if (colon >= 0) + { + item.MainPath.DeleteFrom((unsigned)colon); + item.AltStreamName = item.Path.Ptr((unsigned)(colon + 1)); + item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1])); + item.IsAltStream = true; + } + } + + #endif + + #ifndef _SFX + if (item._use_baseParentFolder_mode) + { + RINOK(GetItemPathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts)); + + #ifdef SUPPORT_ALT_STREAMS + if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty()) + { + int colon; + { + UString &s = item.PathParts.Back(); + colon = FindAltStreamColon_in_Path(s); + if (colon >= 0) + { + item.AltStreamName = s.Ptr((unsigned)(colon + 1)); + item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1])); + item.IsAltStream = true; + s.DeleteFrom((unsigned)colon); + } + } + if (colon == 0) + item.PathParts.DeleteBack(); + } + #endif + + } + else + #endif + SplitPathToParts( + #ifdef SUPPORT_ALT_STREAMS + item.MainPath + #else + item.Path + #endif + , item.PathParts); + + return S_OK; +} + +#ifndef _SFX + +static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined) +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +#endif + +HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const +{ + NCOM::CPropVariant prop; + defined = false; + size = 0; + RINOK(Archive->GetProperty(index, kpidSize, &prop)); + switch (prop.vt) + { + case VT_UI1: size = prop.bVal; break; + case VT_UI2: size = prop.uiVal; break; + case VT_UI4: size = prop.ulVal; break; + case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break; + case VT_EMPTY: return S_OK; + default: return E_FAIL; + } + defined = true; + return S_OK; +} + +HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const +{ + NCOM::CPropVariant prop; + defined = false; + ft.dwHighDateTime = ft.dwLowDateTime = 0; + RINOK(Archive->GetProperty(index, kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime; + defined = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + else if (MTimeDefined) + { + ft = MTime; + defined = true; + } + return S_OK; +} + +#ifndef _SFX + +static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) +{ + for (size_t i = 0; i < size; i++) + if (p1[i] != p2[i]) + return false; + return true; +} + +static void MakeCheckOrder(CCodecs *codecs, + CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2, + const Byte *data, size_t dataSize) +{ + for (unsigned i = 0; i < numTypes; i++) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = codecs->Formats[(unsigned)index]; + if (ai.SignatureOffset != 0) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + continue; + } + + const CObjectVector &sigs = ai.Signatures; + FOR_VECTOR (k, sigs) + { + const CByteBuffer &sig = sigs[k]; + if ((sig.Size() == 0 && dataSize == 0) + || (sig.Size() != 0 && sig.Size() <= dataSize + && TestSignature(data, sig, sig.Size()))) + { + orderIndices2.Add(index); + orderIndices[i] = -1; + break; + } + } + } +} + +#ifdef UNDER_CE + static const unsigned kNumHashBytes = 1; + #define HASH_VAL(buf) ((buf)[0]) +#else + static const unsigned kNumHashBytes = 2; + // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8)) + #define HASH_VAL(buf) GetUi16(buf) +#endif + +static bool IsExeExt(const UString &ext) +{ + return ext.IsEqualTo_Ascii_NoCase("exe"); +} + +static const char * const k_PreArcFormats[] = +{ + "pe" + , "elf" + , "macho" + , "mub" + , "te" +}; + +static bool IsNameFromList(const UString &s, const char * const names[], size_t num) +{ + for (unsigned i = 0; i < num; i++) + if (StringsAreEqualNoCase_Ascii(s, names[i])) + return true; + return false; +} + + +static bool IsPreArcFormat(const CArcInfoEx &ai) +{ + if (ai.Flags_PreArc()) + return true; + return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats)); +} + +static const char * const k_Formats_with_simple_signuature[] = +{ + "7z" + , "xz" + , "rar" + , "bzip2" + , "gzip" + , "cab" + , "wim" + , "rpm" + , "vhd" + , "xar" +}; + +static bool IsNewStyleSignature(const CArcInfoEx &ai) +{ + // if (ai.Version >= 0x91F) + if (ai.NewInterface) + return true; + return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature)); +} + +class CArchiveOpenCallback_Offset: + public IArchiveOpenCallback, + public IArchiveOpenVolumeCallback, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + CMyComPtr OpenVolumeCallback; + UInt64 Files; + UInt64 Offset; + + #ifndef _NO_CRYPTO + CMyComPtr GetTextPassword; + #endif + + MY_QUERYINTERFACE_BEGIN2(IArchiveOpenCallback) + MY_QUERYINTERFACE_ENTRY(IArchiveOpenVolumeCallback) + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IArchiveOpenCallback(;) + INTERFACE_IArchiveOpenVolumeCallback(;) + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif +}; + +#ifndef _NO_CRYPTO +STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + if (GetTextPassword) + return GetTextPassword->CryptoGetTextPassword(password); + return E_NOTIMPL; + COM_TRY_END +} +#endif + +STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *) +{ + return S_OK; +} + +STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes) +{ + if (!Callback) + return S_OK; + UInt64 value = Offset; + if (bytes) + value += *bytes; + return Callback->SetCompleted(&Files, &value); +} + +STDMETHODIMP CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value) +{ + if (OpenVolumeCallback) + return OpenVolumeCallback->GetProperty(propID, value); + NCOM::PropVariant_Clear(value); + return S_OK; + // return E_NOTIMPL; +} + +STDMETHODIMP CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream) +{ + if (OpenVolumeCallback) + return OpenVolumeCallback->GetStream(name, inStream); + return S_FALSE; +} + +#endif + + +UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp) +{ + if (isDefinedProp != NULL) + *isDefinedProp = false; + + switch (prop.vt) + { + case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart; + case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal; + case VT_EMPTY: return 0; + default: throw 151199; + } +} + +void CArcErrorInfo::ClearErrors() +{ + // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!! + + ThereIsTail = false; + UnexpecedEnd = false; + IgnoreTail = false; + // NonZerosTail = false; + ErrorFlags_Defined = false; + ErrorFlags = 0; + WarningFlags = 0; + TailSize = 0; + + ErrorMessage.Empty(); + WarningMessage.Empty(); +} + +HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes) +{ + // OkPhySize_Defined = false; + PhySizeDefined = false; + PhySize = 0; + Offset = 0; + AvailPhySize = FileSize - startPos; + + ErrorInfo.ClearErrors(); + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop)); + ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined); + } + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop)); + ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop); + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidError, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown error"); + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidWarning, &prop)); + if (prop.vt != VT_EMPTY) + ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L"Unknown warning"); + } + + if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen()) + { + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined)); + /* + RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined)); + if (!OkPhySize_Defined) + { + OkPhySize_Defined = PhySizeDefined; + OkPhySize = PhySize; + } + */ + + bool offsetDefined; + RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined)); + + Int64 globalOffset = (Int64)startPos + Offset; + AvailPhySize = (UInt64)((Int64)FileSize - globalOffset); + if (PhySizeDefined) + { + UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize); + if (endPos < FileSize) + { + AvailPhySize = PhySize; + ErrorInfo.ThereIsTail = true; + ErrorInfo.TailSize = FileSize - endPos; + } + else if (endPos > FileSize) + ErrorInfo.UnexpecedEnd = true; + } + } + + return S_OK; +} + +/* +static void PrintNumber(const char *s, int n) +{ + char temp[100]; + sprintf(temp, "%s %d", s, n); + // OutputDebugStringA(temp); + printf(temp); +} +*/ + +HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive) +{ + // OutputDebugStringA("a1"); + // PrintNumber("formatIndex", formatIndex); + + RINOK(op.codecs->CreateInArchive(formatIndex, archive)); + // OutputDebugStringA("a2"); + if (!archive) + return S_OK; + + #ifdef EXTERNAL_CODECS + if (op.codecs->NeedSetLibCodecs) + { + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + if (ai.LibIndex >= 0 ? + !op.codecs->Libs[(unsigned)ai.LibIndex].SetCodecs : + !op.codecs->Libs.IsEmpty()) + { + CMyComPtr setCompressCodecsInfo; + archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs)); + } + } + } + #endif + + + #ifndef _SFX + + const CArcInfoEx &ai = op.codecs->Formats[formatIndex]; + + // OutputDebugStringW(ai.Name); + // OutputDebugStringA("a3"); + + if (ai.Flags_PreArc()) + { + /* we notify parsers that extract executables, that they don't need + to open archive, if there is tail after executable (for SFX cases) */ + CMyComPtr allowTail; + archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail); + if (allowTail) + allowTail->AllowTail(BoolToInt(true)); + } + + if (op.props) + { + /* + FOR_VECTOR (y, op.props) + { + const COptionalOpenProperties &optProps = (*op.props)[y]; + if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0) + { + RINOK(SetProperties(archive, optProps.Props)); + break; + } + } + */ + RINOK(SetProperties(archive, *op.props)); + } + + #endif + return S_OK; +} + +#ifndef _SFX + +static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi) +{ + pi.Extension = ai.GetMainExt(); + pi.FileTime_Defined = false; + pi.ArcType = ai.Name; + + RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType)); + + // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe)); + pi.IsSelfExe = ai.Flags_PreArc(); + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + if (!pi.FileTime_Defined) + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidCTime, &prop)); + if (prop.vt == VT_FILETIME) + { + pi.FileTime_Defined = true; + pi.FileTime = prop.filetime; + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidName, &prop)); + if (prop.vt == VT_BSTR) + { + pi.Name.SetFromBstr(prop.bstrVal); + pi.Extension.Empty(); + } + else + { + RINOK(archive->GetArchiveProperty(kpidExtension, &prop)); + if (prop.vt == VT_BSTR) + pi.Extension.SetFromBstr(prop.bstrVal); + } + } + + { + NCOM::CPropVariant prop; + RINOK(archive->GetArchiveProperty(kpidShortComment, &prop)); + if (prop.vt == VT_BSTR) + pi.Comment.SetFromBstr(prop.bstrVal); + } + + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + // pi.NumSubFiles = numItems; + // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined)); + // if (!pi.UnpackSize_Defined) + { + pi.NumSubFiles = 0; + pi.NumSubDirs = 0; + pi.UnpackSize = 0; + for (UInt32 i = 0; i < numItems; i++) + { + UInt64 size = 0; + bool defined = false; + Archive_GetItem_Size(archive, i, size, defined); + if (defined) + { + pi.UnpackSize_Defined = true; + pi.UnpackSize += size; + } + + bool isDir = false; + Archive_IsItem_Dir(archive, i, isDir); + if (isDir) + pi.NumSubDirs++; + else + pi.NumSubFiles++; + } + if (pi.NumSubDirs != 0) + pi.NumSubDirs_Defined = true; + pi.NumSubFiles_Defined = true; + } + + return S_OK; +} + +#endif + +HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset) +{ + if (!op.stream) + return S_OK; + RINOK(op.stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL)); + const UInt32 kBufSize = 1 << 11; + Byte buf[kBufSize]; + + for (;;) + { + UInt32 processed = 0; + RINOK(op.stream->Read(buf, kBufSize, &processed)); + if (processed == 0) + { + // ErrorInfo.NonZerosTail = false; + ErrorInfo.IgnoreTail = true; + return S_OK; + } + for (size_t i = 0; i < processed; i++) + { + if (buf[i] != 0) + { + // ErrorInfo.IgnoreTail = false; + // ErrorInfo.NonZerosTail = true; + return S_OK; + } + } + } +} + + + +#ifndef _SFX + +class CExtractCallback_To_OpenCallback: + public IArchiveExtractCallback, + public ICompressProgressInfo, + public CMyUnknownImp +{ +public: + CMyComPtr Callback; + UInt64 Files; + UInt64 Offset; + + MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo) + INTERFACE_IArchiveExtractCallback(;) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) + { + Callback = callback; + Files = 0; + Offset = 0; + } +}; + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 value = Offset; + if (inSize) + value += *inSize; + return Callback->SetCompleted(&Files, &value); + } + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */) +{ + *outStream = NULL; + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */) +{ + return S_OK; +} + +STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */) +{ + return S_OK; +} + + +static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize, + IInStream *stream, const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openCallback, + IArchiveExtractCallback *extractCallback) +{ + /* + if (needPhySize) + { + CMyComPtr open2; + archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2); + if (open2) + return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback); + } + */ + RINOK(archive->Open(stream, maxCheckStartPosition, openCallback)); + if (needPhySize) + { + bool phySize_Defined = false; + UInt64 phySize = 0; + RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined)); + if (phySize_Defined) + return S_OK; + + bool phySizeCantBeDetected = false; + RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected)); + + if (!phySizeCantBeDetected) + { + PRF(printf("\n-- !phySize_Defined after Open, call archive->Extract()")); + // It's for bzip2/gz and some xz archives, where Open operation doesn't know phySize. + // But the Handler will know phySize after full archive testing. + RINOK(archive->Extract(NULL, (UInt32)(Int32)-1, BoolToInt(true), extractCallback)); + PRF(printf("\n-- OK")); + } + } + return S_OK; +} + + + +static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name) +{ + FOR_VECTOR (i, orderIndices) + { + int oi = orderIndices[i]; + if (oi >= 0) + if (StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)oi].Name, name)) + return (int)i; + } + return -1; +} + +#endif + +HRESULT CArc::OpenStream2(const COpenOptions &op) +{ + // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout); + + Archive.Release(); + GetRawProps.Release(); + GetRootProps.Release(); + + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + IsParseArc = false; + ArcStreamOffset = 0; + + // OutputDebugStringA("1"); + // OutputDebugStringW(Path); + + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; + { + int dotPos = fileName.ReverseFind_Dot(); + if (dotPos >= 0) + extension = fileName.Ptr((unsigned)(dotPos + 1)); + } + + CIntVector orderIndices; + + bool searchMarkerInHandler = false; + #ifdef _SFX + searchMarkerInHandler = true; + #endif + + CBoolArr isMainFormatArr(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + isMainFormatArr[i] = false; + } + + UInt64 maxStartOffset = + op.openType.MaxStartOffset_Defined ? + op.openType.MaxStartOffset : + kMaxCheckStartPosition; + + #ifndef _SFX + bool isUnknownExt = false; + #endif + + #ifndef _SFX + bool isForced = false; + #endif + + unsigned numMainTypes = 0; + int formatIndex = op.openType.FormatIndex; + + if (formatIndex >= 0) + { + #ifndef _SFX + isForced = true; + #endif + orderIndices.Add(formatIndex); + numMainTypes = 1; + isMainFormatArr[(unsigned)formatIndex] = true; + + searchMarkerInHandler = true; + } + else + { + unsigned numFinded = 0; + #ifndef _SFX + bool isPrearcExt = false; + #endif + + { + #ifndef _SFX + + bool isZip = false; + bool isRar = false; + + const wchar_t c = extension[0]; + if (c == 'z' || c == 'Z' || c == 'r' || c == 'R') + { + bool isNumber = false; + for (unsigned k = 1;; k++) + { + const wchar_t d = extension[k]; + if (d == 0) + break; + if (d < '0' || d > '9') + { + isNumber = false; + break; + } + isNumber = true; + } + if (isNumber) + { + if (c == 'z' || c == 'Z') + isZip = true; + else + isRar = true; + } + } + + #endif + + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + + if (IgnoreSplit || !op.openType.CanReturnArc) + if (ai.IsSplit()) + continue; + if (op.excludedFormats->FindInSorted((int)i) >= 0) + continue; + + #ifndef _SFX + if (IsPreArcFormat(ai)) + isPrearcExt = true; + #endif + + if (ai.FindExtension(extension) >= 0 + #ifndef _SFX + || (isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip")) + || (isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar")) + #endif + ) + { + // PrintNumber("orderIndices.Insert", i); + orderIndices.Insert(numFinded++, (int)i); + isMainFormatArr[i] = true; + } + else + orderIndices.Add((int)i); + } + } + + if (!op.stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + // PrintNumber("numFinded", numFinded ); + + /* + if (op.openOnlySpecifiedByExtension) + { + if (numFinded != 0 && !IsExeExt(extension)) + orderIndices.DeleteFrom(numFinded); + } + */ + + #ifndef _SFX + + if (op.stream && orderIndices.Size() >= 2) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + CByteBuffer byteBuffer; + CIntVector orderIndices2; + if (numFinded == 0 || IsExeExt(extension)) + { + // signature search was here + } + else if (extension.IsEqualTo("000") || extension.IsEqualTo("001")) + { + int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar"); + if (i >= 0) + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize >= 16) + { + const Byte *buf = byteBuffer; + const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }; + if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0) + { + orderIndices2.Add(orderIndices[(unsigned)i]); + orderIndices[(unsigned)i] = -1; + if (i >= (int)numFinded) + numFinded++; + } + } + } + } + else + { + const size_t kBufSize = (1 << 10); + byteBuffer.Alloc(kBufSize); + size_t processedSize = kBufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + + /* + check type order: + 1) matched extension, no signuature + 2) matched extension, matched signuature + // 3) no signuature + // 4) matched signuature + */ + + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0); + MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0); + // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize); + } + + FOR_VECTOR (i, orderIndices) + { + int val = orderIndices[i]; + if (val != -1) + orderIndices2.Add(val); + } + orderIndices = orderIndices2; + } + + if (orderIndices.Size() >= 2) + { + int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso"); + int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf"); + if (iUdf > iIso && iIso >= 0) + { + int isoIndex = orderIndices[(unsigned)iIso]; + int udfIndex = orderIndices[(unsigned)iUdf]; + orderIndices[(unsigned)iUdf] = isoIndex; + orderIndices[(unsigned)iIso] = udfIndex; + } + } + + numMainTypes = numFinded; + isUnknownExt = (numMainTypes == 0) || isPrearcExt; + + #else // _SFX + + numMainTypes = orderIndices.Size(); + + // we need correct numMainTypes for mutlivolume SFX (if some volume is missing) + if (numFinded != 0) + numMainTypes = numFinded; + + #endif + } + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + + #ifndef _SFX + + CBoolArr skipFrontalFormat(op.codecs->Formats.Size()); + { + FOR_VECTOR(i, op.codecs->Formats) + skipFrontalFormat[i] = false; + } + + #endif + + const COpenType &mode = op.openType; + + + + + + if (mode.CanReturnArc) + { + // ---------- OPEN main type by extenssion ---------- + + unsigned numCheckTypes = orderIndices.Size(); + if (formatIndex >= 0) + numCheckTypes = numMainTypes; + + for (unsigned i = 0; i < numCheckTypes; i++) + { + FormatIndex = orderIndices[i]; + + // orderIndices[] item cannot be negative here + + bool exactOnly = false; + + #ifndef _SFX + + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; + // OutputDebugStringW(ai.Name); + if (i >= numMainTypes) + { + if (!ai.Flags_BackwardOpen() + // && !ai.Flags_PureStartOpen() + ) + continue; + exactOnly = true; + } + + #endif + + // Some handlers do not set total bytes. So we set it here + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + + CMyComPtr archive; + + RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)); + if (!archive) + continue; + + HRESULT result; + if (op.stream) + { + UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0; + result = archive->Open(op.stream, &searchLimit, op.callback); + } + else + { + CMyComPtr openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(op.seqStream); + } + + RINOK(ReadBasicProps(archive, 0, result)); + + if (result == S_FALSE) + { + bool isArc = ErrorInfo.IsArc_After_NonOpen(); + + #ifndef _SFX + // if it's archive, we allow another open attempt for parser + if (!mode.CanReturnParser || !isArc) + skipFrontalFormat[(unsigned)FormatIndex] = true; + #endif + + if (exactOnly) + continue; + + if (i == 0 && numMainTypes == 1) + { + // we set NonOpenErrorInfo, only if there is only one main format (defined by extension). + ErrorInfo.ErrorFormatIndex = FormatIndex; + NonOpen_ErrorInfo = ErrorInfo; + + if (!mode.CanReturnParser && isArc) + { + // if (formatIndex < 0 && !searchMarkerInHandler) + { + // if bad archive was detected, we don't need additional open attempts + #ifndef _SFX + if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */) + #endif + return S_FALSE; + } + } + } + + /* + #ifndef _SFX + if (IsExeExt(extension) || ai.Flags_PreArc()) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + // limitSignatureSearch = true; + } + #endif + */ + + continue; + } + + RINOK(result); + + #ifndef _SFX + + bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } + + if (Offset > 0) + { + if (exactOnly + || !searchMarkerInHandler + || !specFlags.CanReturn_NonStart() + || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset)) + continue; + } + if (thereIsTail) + { + if (Offset > 0) + { + if (!specFlags.CanReturnMid) + continue; + } + else if (!specFlags.CanReturnFrontal) + continue; + } + + if (Offset > 0 || thereIsTail) + { + if (formatIndex < 0) + { + if (IsPreArcFormat(ai)) + { + // openOnlyFullArc = false; + // canReturnTailArc = true; + /* + if (mode.SkipSfxStub) + limitSignatureSearch = true; + */ + // if (mode.SkipSfxStub) + { + // skipFrontalFormat[FormatIndex] = true; + continue; + } + } + } + } + + #endif + + Archive = archive; + return S_OK; + } + } + + + + #ifndef _SFX + + if (!op.stream) + return S_FALSE; + + if (formatIndex >= 0 && !mode.CanReturnParser) + { + if (mode.MaxStartOffset_Defined) + { + if (mode.MaxStartOffset == 0) + return S_FALSE; + } + else + { + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)formatIndex]; + if (ai.FindExtension(extension) >= 0) + { + if (ai.Flags_FindSignature() && searchMarkerInHandler) + return S_FALSE; + } + } + } + + NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler; + CMyComPtr handler = handlerSpec; + + CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback; + CMyComPtr extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec; + extractCallback_To_OpenCallback_Spec->Init(op.callback); + + { + // ---------- Check all possible START archives ---------- + // this code is better for full file archives than Parser's code. + + CByteBuffer byteBuffer; + bool endOfFile = false; + size_t processedSize; + { + size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF) + if (bufSize > fileSize) + { + bufSize = (size_t)fileSize; + endOfFile = true; + } + byteBuffer.Alloc(bufSize); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + processedSize = bufSize; + RINOK(ReadStream(op.stream, byteBuffer, &processedSize)); + if (processedSize == 0) + return S_FALSE; + if (processedSize < bufSize) + endOfFile = true; + } + CUIntVector sortedFormats; + + unsigned i; + + int splitIndex = -1; + + for (i = 0; i < orderIndices.Size(); i++) + { + // orderIndices[] item cannot be negative here + unsigned form = (unsigned)orderIndices[i]; + if (skipFrontalFormat[form]) + continue; + + const CArcInfoEx &ai = op.codecs->Formats[form]; + + if (ai.IsSplit()) + { + splitIndex = (int)form; + continue; + } + + if (ai.Flags_ByExtOnlyOpen()) + continue; + + if (ai.IsArcFunc) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue; + sortedFormats.Insert(0, form); + continue; + } + + bool isNewStyleSignature = IsNewStyleSignature(ai); + bool needCheck = !isNewStyleSignature + || ai.Signatures.IsEmpty() + || ai.Flags_PureStartOpen() + || ai.Flags_StartOpen() + || ai.Flags_BackwardOpen(); + + if (isNewStyleSignature && !ai.Signatures.IsEmpty()) + { + unsigned k; + for (k = 0; k < ai.Signatures.Size(); k++) + { + const CByteBuffer &sig = ai.Signatures[k]; + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (processedSize < signatureEnd) + { + if (!endOfFile) + needCheck = true; + } + else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0) + break; + } + if (k != ai.Signatures.Size()) + { + sortedFormats.Insert(0, form); + continue; + } + } + if (needCheck) + sortedFormats.Add(form); + } + + if (splitIndex >= 0) + sortedFormats.Insert(0, (unsigned)splitIndex); + + for (i = 0; i < sortedFormats.Size(); i++) + { + FormatIndex = (int)sortedFormats[i]; + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; + + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive)); + if (!archive) + continue; + + PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name)); + HRESULT result; + { + UInt64 searchLimit = 0; + /* + if (mode.CanReturnArc) + result = archive->Open(op.stream, &searchLimit, op.callback); + else + */ + // if (!CanReturnArc), it's ParserMode, and we need phy size + result = OpenArchiveSpec(archive, + !mode.CanReturnArc, // needPhySize + op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback); + } + + if (result == S_FALSE) + { + skipFrontalFormat[(unsigned)FormatIndex] = true; + // FIXME: maybe we must use LenIsUnknown. + // printf(" OpenForSize Error"); + continue; + } + RINOK(result); + + RINOK(ReadBasicProps(archive, 0, result)); + + if (Offset > 0) + { + continue; // good handler doesn't return such Offset > 0 + // but there are some cases like false prefixed PK00 archive, when + // we can support it? + } + + NArchive::NParser::CParseItem pi; + pi.Offset = (UInt64)Offset; + pi.Size = AvailPhySize; + + // bool needScan = false; + + if (!PhySizeDefined) + { + // it's for Z format + pi.LenIsUnknown = true; + // needScan = true; + // phySize = arcRem; + // nextNeedCheckStartOpen = false; + } + + /* + if (OkPhySize_Defined) + pi.OkSize = pi.OkPhySize; + else + pi.OkSize = pi.Size; + */ + + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + + if (mode.CanReturnArc) + { + bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + bool openCur = false; + + if (!ErrorInfo.ThereIsTail) + openCur = true; + else + { + if (mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize))); + if (ErrorInfo.IgnoreTail) + openCur = true; + } + if (!openCur) + { + openCur = specFlags.CanReturnFrontal; + if (formatIndex < 0) // format is not forced + { + if (IsPreArcFormat(ai)) + { + // if (mode.SkipSfxStub) + { + openCur = false; + } + } + } + } + } + + if (openCur) + { + InStream = op.stream; + Archive = archive; + return S_OK; + } + } + + skipFrontalFormat[(unsigned)FormatIndex] = true; + + + // if (!mode.CanReturnArc) + /* + if (!ErrorInfo.ThereIsTail) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + continue; + + // printf("\nAdd offset = %d", (int)pi.Offset); + RINOK(ReadParseItemProps(archive, ai, pi)); + handlerSpec->AddItem(pi); + } + } + + + + + + // ---------- PARSER ---------- + + CUIntVector arc2sig; // formatIndex to signatureIndex + CUIntVector sig2arc; // signatureIndex to formatIndex; + { + unsigned sum = 0; + FOR_VECTOR (i, op.codecs->Formats) + { + arc2sig.Add(sum); + const CObjectVector &sigs = op.codecs->Formats[i].Signatures; + sum += sigs.Size(); + FOR_VECTOR (k, sigs) + sig2arc.Add(i); + } + } + + { + const size_t kBeforeSize = 1 << 16; + const size_t kAfterSize = 1 << 20; + const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize + + const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8); + CByteArr hashBuffer(kNumVals); + Byte *hash = hashBuffer; + memset(hash, 0xFF, kNumVals); + Byte prevs[256]; + memset(prevs, 0xFF, sizeof(prevs)); + if (sig2arc.Size() >= 0xFF) + return S_FALSE; + + CUIntVector difficultFormats; + CBoolArr difficultBools(256); + { + for (unsigned i = 0; i < 256; i++) + difficultBools[i] = false; + } + + bool thereAreHandlersForSearch = false; + + // UInt32 maxSignatureEnd = 0; + + FOR_VECTOR (i, orderIndices) + { + int index = orderIndices[i]; + if (index < 0) + continue; + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index]; + if (ai.Flags_ByExtOnlyOpen()) + continue; + bool isDifficult = false; + // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31) + if (!ai.NewInterface) + isDifficult = true; + else + { + if (ai.Flags_StartOpen()) + isDifficult = true; + FOR_VECTOR (k, ai.Signatures) + { + const CByteBuffer &sig = ai.Signatures[k]; + /* + UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size(); + if (maxSignatureEnd < signatureEnd) + maxSignatureEnd = signatureEnd; + */ + if (sig.Size() < kNumHashBytes) + { + isDifficult = true; + continue; + } + thereAreHandlersForSearch = true; + UInt32 v = HASH_VAL(sig); + unsigned sigIndex = arc2sig[(unsigned)index] + k; + prevs[sigIndex] = hash[v]; + hash[v] = (Byte)sigIndex; + } + } + if (isDifficult) + { + difficultFormats.Add((unsigned)index); + difficultBools[(unsigned)index] = true; + } + } + + if (!thereAreHandlersForSearch) + { + // openOnlyFullArc = true; + // canReturnTailArc = true; + } + + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + + CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream; + CMyComPtr limitedStream = limitedStreamSpec; + limitedStreamSpec->SetStream(op.stream); + + CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL; + CMyComPtr openCallback_Offset; + if (op.callback) + { + openCallback_Offset_Spec = new CArchiveOpenCallback_Offset; + openCallback_Offset = openCallback_Offset_Spec; + openCallback_Offset_Spec->Callback = op.callback; + openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback); + #ifndef _NO_CRYPTO + openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword); + #endif + } + + if (op.callback) + RINOK(op.callback->SetTotal(NULL, &fileSize)); + + CByteBuffer &byteBuffer = limitedStreamSpec->Buffer; + byteBuffer.Alloc(kBufSize); + + UInt64 callbackPrev = 0; + bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos. + + bool endOfFile = false; + UInt64 bufPhyPos = 0; + size_t bytesInBuf = 0; + // UInt64 prevPos = 0; + + // ---------- Main Scan Loop ---------- + + UInt64 pos = 0; + + if (!mode.EachPos && handlerSpec->_items.Size() == 1) + { + NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (!pi.LenIsUnknown && pi.Offset == 0) + pos = pi.Size; + } + + for (;;) + { + // printf("\nPos = %d", (int)pos); + UInt64 posInBuf = pos - bufPhyPos; + + // if (pos > ((UInt64)1 << 35)) break; + + if (!endOfFile) + { + if (bytesInBuf < kBufSize) + { + size_t processedSize = kBufSize - bytesInBuf; + // printf("\nRead ask = %d", (unsigned)processedSize); + UInt64 seekPos = bufPhyPos + bytesInBuf; + RINOK(op.stream->Seek((Int64)(bufPhyPos + bytesInBuf), STREAM_SEEK_SET, NULL)); + RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize)); + // printf(" processed = %d", (unsigned)processedSize); + if (processedSize == 0) + { + fileSize = seekPos; + endOfFile = true; + } + else + { + bytesInBuf += processedSize; + limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos); + } + continue; + } + + if (bytesInBuf < posInBuf) + { + UInt64 skipSize = posInBuf - bytesInBuf; + if (skipSize <= kBeforeSize) + { + size_t keepSize = (size_t)(kBeforeSize - skipSize); + // printf("\nmemmove skip = %d", (int)keepSize); + memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize); + bytesInBuf = keepSize; + bufPhyPos = pos - keepSize; + continue; + } + // printf("\nSkip %d", (int)(skipSize - kBeforeSize)); + // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL)); + bytesInBuf = 0; + bufPhyPos = pos - kBeforeSize; + continue; + } + + if (bytesInBuf - posInBuf < kAfterSize) + { + size_t beg = (size_t)posInBuf - kBeforeSize; + // printf("\nmemmove for after beg = %d", (int)beg); + memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg); + bufPhyPos += beg; + bytesInBuf -= beg; + continue; + } + } + + if (bytesInBuf <= (size_t)posInBuf) + break; + + bool useOffsetCallback = false; + if (openCallback_Offset) + { + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = pos; + + useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1); + + if (pos >= callbackPrev + (1 << 23)) + { + RINOK(openCallback_Offset_Spec->SetCompleted(NULL, NULL)); + callbackPrev = pos; + } + } + + { + UInt64 endPos = bufPhyPos + bytesInBuf; + if (fileSize < endPos) + { + FileSize = fileSize; // why ???? + fileSize = endPos; + } + } + + const size_t availSize = bytesInBuf - (size_t)posInBuf; + if (availSize < kNumHashBytes) + break; + size_t scanSize = availSize - + ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes); + + { + /* + UInt64 scanLimit = openOnlyFullArc ? + maxSignatureEnd : + op.openType.ScanSize + maxSignatureEnd; + */ + if (!mode.CanReturnParser) + { + if (pos > maxStartOffset) + break; + UInt64 remScan = maxStartOffset - pos; + if (scanSize > remScan) + scanSize = (size_t)remScan; + } + } + + scanSize++; + + const Byte *buf = byteBuffer + (size_t)posInBuf; + const Byte *bufLimit = buf + scanSize; + size_t ppp = 0; + + if (!needCheckStartOpen) + { + for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++); + ppp = (size_t)(buf - (byteBuffer + (size_t)posInBuf)); + pos += ppp; + if (buf == bufLimit) + continue; + } + + UInt32 v = HASH_VAL(buf); + bool nextNeedCheckStartOpen = true; + unsigned i = hash[v]; + unsigned indexOfDifficult = 0; + + // ---------- Open Loop for Current Pos ---------- + bool wasOpen = false; + + for (;;) + { + unsigned index; + bool isDifficult; + if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size()) + { + index = difficultFormats[indexOfDifficult++]; + isDifficult = true; + } + else + { + if (i == 0xFF) + break; + index = sig2arc[i]; + unsigned sigIndex = i - arc2sig[index]; + i = prevs[i]; + if (needCheckStartOpen && difficultBools[index]) + continue; + const CArcInfoEx &ai = op.codecs->Formats[index]; + + if (pos < ai.SignatureOffset) + continue; + + /* + if (openOnlyFullArc) + if (pos != ai.SignatureOffset) + continue; + */ + + const CByteBuffer &sig = ai.Signatures[sigIndex]; + + if (ppp + sig.Size() > availSize + || !TestSignature(buf, sig, sig.Size())) + continue; + // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos)); + // prevPos = pos; + isDifficult = false; + } + + const CArcInfoEx &ai = op.codecs->Formats[index]; + + + if ((isDifficult && pos == 0) || ai.SignatureOffset == pos) + { + // we don't check same archive second time */ + if (skipFrontalFormat[index]) + continue; + } + + UInt64 startArcPos = pos; + if (!isDifficult) + { + if (pos < ai.SignatureOffset) + continue; + startArcPos = pos - ai.SignatureOffset; + /* + // we don't need the check for Z files + if (startArcPos < handlerSpec->GetLastEnd()) + continue; + */ + } + + if (ai.IsArcFunc && startArcPos >= bufPhyPos) + { + size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos); + if (offsetInBuf < bytesInBuf) + { + UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf); + if (isArcRes == k_IsArc_Res_NO) + continue; + if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile) + continue; + /* + if (isArcRes == k_IsArc_Res_YES_LOW_PROB) + { + // if (pos != ai.SignatureOffset) + continue; + } + */ + } + // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name); + } + + PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name)); + + const bool isMainFormat = isMainFormatArr[index]; + const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt); + + CMyComPtr archive; + RINOK(PrepareToOpen(op, index, archive)); + if (!archive) + return E_FAIL; + + // OutputDebugStringW(ai.Name); + + const UInt64 rem = fileSize - startArcPos; + + UInt64 arcStreamOffset = 0; + + if (ai.Flags_UseGlobalOffset()) + { + limitedStreamSpec->InitAndSeek(0, fileSize); + limitedStream->Seek((Int64)startArcPos, STREAM_SEEK_SET, NULL); + } + else + { + limitedStreamSpec->InitAndSeek(startArcPos, rem); + arcStreamOffset = startArcPos; + } + + UInt64 maxCheckStartPosition = 0; + + if (openCallback_Offset) + { + openCallback_Offset_Spec->Files = handlerSpec->_items.Size(); + openCallback_Offset_Spec->Offset = startArcPos; + } + + // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset); + extractCallback_To_OpenCallback_Spec->Files = 0; + extractCallback_To_OpenCallback_Spec->Offset = startArcPos; + + HRESULT result = OpenArchiveSpec(archive, + true, // needPhySize + limitedStream, &maxCheckStartPosition, + useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback, + extractCallback_To_OpenCallback); + + RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result)); + + bool isOpen = false; + + if (result == S_FALSE) + { + if (!mode.CanReturnParser) + { + if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen()) + { + ErrorInfo.ErrorFormatIndex = (int)index; + NonOpen_ErrorInfo = ErrorInfo; + // if archive was detected, we don't need additional open attempts + return S_FALSE; + } + continue; + } + if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0) + continue; + } + else + { + if (PhySizeDefined && PhySize == 0) + { + PRF(printf(" phySizeDefined && PhySize == 0 ")); + // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function. + continue; + } + isOpen = true; + RINOK(result); + PRF(printf(" OK ")); + } + + // fprintf(stderr, "\n %8X %S", startArcPos, Path); + // printf("\nOpen OK: %S", ai.Name); + + + NArchive::NParser::CParseItem pi; + pi.Offset = startArcPos; + + if (ai.Flags_UseGlobalOffset()) + pi.Offset = (UInt64)Offset; + else if (Offset != 0) + return E_FAIL; + + UInt64 arcRem = FileSize - pi.Offset; + UInt64 phySize = arcRem; + bool phySizeDefined = PhySizeDefined; + if (phySizeDefined) + { + if (pi.Offset + PhySize > FileSize) + { + // ErrorInfo.ThereIsTail = true; + PhySize = FileSize - pi.Offset; + } + phySize = PhySize; + } + if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63)) + return E_FAIL; + + /* + if (!ai.UseGlobalOffset) + { + if (phySize > arcRem) + { + ThereIsTail = true; + phySize = arcRem; + } + } + */ + + bool needScan = false; + + + if (isOpen && !phySizeDefined) + { + // it's for Z format, or bzip2,gz,xz with phySize that was not detected + pi.LenIsUnknown = true; + needScan = true; + phySize = arcRem; + nextNeedCheckStartOpen = false; + } + + pi.Size = phySize; + /* + if (OkPhySize_Defined) + pi.OkSize = OkPhySize; + */ + pi.NormalizeOffset(); + // printf(" phySize = %8d", (unsigned)phySize); + + /* + if (needSkipFullArc) + if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize) + continue; + */ + if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize) + { + // it's possible for dmg archives + if (!mode.CanReturnArc) + continue; + } + + if (mode.EachPos) + pos++; + else if (needScan) + { + pos++; + /* + if (!OkPhySize_Defined) + pos++; + else + pos = pi.Offset + pi.OkSize; + */ + } + else + pos = pi.Offset + pi.Size; + + + RINOK(ReadParseItemProps(archive, ai, pi)); + + if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */) + { + /* It's for DMG format. + This code deletes all previous items that are included to current item */ + + while (!handlerSpec->_items.IsEmpty()) + { + { + const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back(); + if (back.Offset < pi.Offset) + break; + if (back.Offset + back.Size > pi.Offset + pi.Size) + break; + } + handlerSpec->_items.DeleteBack(); + } + } + + + if (isOpen && mode.CanReturnArc && phySizeDefined) + { + // if (pi.Offset + pi.Size >= fileSize) + bool openCur = false; + + bool thereIsTail = ErrorInfo.ThereIsTail; + if (thereIsTail && mode.ZerosTailIsAllowed) + { + RINOK(CheckZerosTail(op, (UInt64)((Int64)arcStreamOffset + Offset + (Int64)PhySize))); + if (ErrorInfo.IgnoreTail) + thereIsTail = false; + } + + if (pi.Offset != 0) + { + if (!pi.IsNotArcType) + { + if (thereIsTail) + openCur = specFlags.CanReturnMid; + else + openCur = specFlags.CanReturnTail; + } + } + else + { + if (!thereIsTail) + openCur = true; + else + openCur = specFlags.CanReturnFrontal; + + if (formatIndex >= -2) + openCur = true; + } + + if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */) + openCur = false; + + // We open file as SFX, if there is front archive or first archive is "Self Executable" + if (!openCur && !pi.IsSelfExe && !thereIsTail && + (!pi.IsNotArcType || pi.Offset == 0)) + { + if (handlerSpec->_items.IsEmpty()) + { + if (specFlags.CanReturnTail) + openCur = true; + } + else if (handlerSpec->_items.Size() == 1) + { + if (handlerSpec->_items[0].IsSelfExe) + { + if (mode.SpecUnknownExt.CanReturnTail) + openCur = true; + } + } + } + + if (openCur) + { + InStream = op.stream; + Archive = archive; + FormatIndex = (int)index; + ArcStreamOffset = arcStreamOffset; + return S_OK; + } + } + + /* + if (openOnlyFullArc) + { + ErrorInfo.ClearErrors(); + return S_FALSE; + } + */ + + pi.FormatIndex = (int)index; + + // printf("\nAdd offset = %d", (int)pi.Offset); + handlerSpec->AddItem(pi); + wasOpen = true; + break; + } + // ---------- End of Open Loop for Current Pos ---------- + + if (!wasOpen) + pos++; + needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen); + } + // ---------- End of Main Scan Loop ---------- + + /* + if (handlerSpec->_items.Size() == 1) + { + const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0]; + if (pi.Size == fileSize && pi.Offset == 0) + { + Archive = archive; + FormatIndex2 = pi.FormatIndex; + return S_OK; + } + } + */ + + if (mode.CanReturnParser) + { + bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing + handlerSpec->AddUnknownItem(fileSize); + if (handlerSpec->_items.Size() == 0) + return S_FALSE; + if (returnParser || handlerSpec->_items.Size() != 1) + { + // return S_FALSE; + handlerSpec->_stream = op.stream; + Archive = handler; + ErrorInfo.ClearErrors(); + IsParseArc = true; + FormatIndex = -1; // It's parser + Offset = 0; + return S_OK; + } + } + } + + #endif + + if (!Archive) + return S_FALSE; + return S_OK; +} + + + + +HRESULT CArc::OpenStream(const COpenOptions &op) +{ + RINOK(OpenStream2(op)); + // PrintNumber("op.formatIndex 3", op.formatIndex); + + if (Archive) + { + GetRawProps.Release(); + GetRootProps.Release(); + Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps); + Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps); + + RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream)); + RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux)); + RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode)); + RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly)); + + const UString fileName = ExtractFileNameFromPath(Path); + UString extension; + { + int dotPos = fileName.ReverseFind_Dot(); + if (dotPos >= 0) + extension = fileName.Ptr((unsigned)(dotPos + 1)); + } + + DefaultName.Empty(); + if (FormatIndex >= 0) + { + const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex]; + if (ai.Exts.Size() == 0) + DefaultName = GetDefaultName2(fileName, UString(), UString()); + else + { + int subExtIndex = ai.FindExtension(extension); + if (subExtIndex < 0) + subExtIndex = 0; + const CArcExtInfo &extInfo = ai.Exts[(unsigned)subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); + } + } + } + + return S_OK; +} + +#ifdef _SFX + +#ifdef _WIN32 + #define k_ExeExt ".exe" + static const unsigned k_ExeExt_Len = 4; +#else + #define k_ExeExt "" + static const unsigned k_ExeExt_Len = 0; +#endif + +#endif + +HRESULT CArc::OpenStreamOrFile(COpenOptions &op) +{ + CMyComPtr fileStream; + CMyComPtr seqStream; + CInFileStream *fileStreamSpec = NULL; + + if (op.stdInMode) + { + seqStream = new CStdInFileStream; + op.seqStream = seqStream; + } + else if (!op.stream) + { + fileStreamSpec = new CInFileStream; + fileStream = fileStreamSpec; + Path = filePath; + if (!fileStreamSpec->Open(us2fs(Path))) + return GetLastError_noZero_HRESULT(); + op.stream = fileStream; + #ifdef _SFX + IgnoreSplit = true; + #endif + } + + /* + if (callback) + { + UInt64 fileSize; + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.callback->SetTotal(NULL, &fileSize)) + } + */ + + HRESULT res = OpenStream(op); + IgnoreSplit = false; + + #ifdef _SFX + + if (res != S_FALSE + || !fileStreamSpec + || !op.callbackSpec + || NonOpen_ErrorInfo.IsArc_After_NonOpen()) + return res; + + { + if (filePath.Len() > k_ExeExt_Len + && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt)) + { + const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len); + FOR_VECTOR (i, op.codecs->Formats) + { + const CArcInfoEx &ai = op.codecs->Formats[i]; + if (ai.IsSplit()) + continue; + UString path3 = path2; + path3 += '.'; + path3 += ai.GetMainExt(); // "7z" for SFX. + Path = path3; + Path += ".001"; + bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + if (!isOk) + { + Path = path3; + isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path)); + } + if (isOk) + { + if (fileStreamSpec->Open(us2fs(Path))) + { + op.stream = fileStream; + NonOpen_ErrorInfo.ClearErrors_Full(); + if (OpenStream(op) == S_OK) + return S_OK; + } + } + } + } + } + + #endif + + return res; +} + +void CArchiveLink::KeepModeForNextOpen() +{ + for (unsigned i = Arcs.Size(); i != 0;) + { + i--; + CMyComPtr keep; + Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep); + if (keep) + keep->KeepModeForNextOpen(); + } +} + +HRESULT CArchiveLink::Close() +{ + for (unsigned i = Arcs.Size(); i != 0;) + { + i--; + RINOK(Arcs[i].Close()); + } + IsOpen = false; + // ErrorsText.Empty(); + return S_OK; +} + +void CArchiveLink::Release() +{ + // NonOpenErrorFormatIndex = -1; + NonOpen_ErrorInfo.ClearErrors(); + NonOpen_ArcPath.Empty(); + while (!Arcs.IsEmpty()) + Arcs.DeleteBack(); +} + +/* +void CArchiveLink::Set_ErrorsText() +{ + FOR_VECTOR(i, Arcs) + { + const CArc &arc = Arcs[i]; + if (!arc.ErrorFlagsText.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText.Add_LF(); + ErrorsText += GetUnicodeString(arc.ErrorFlagsText); + } + if (!arc.ErrorMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText.Add_LF(); + ErrorsText += arc.ErrorMessage; + } + + if (!arc.WarningMessage.IsEmpty()) + { + if (!ErrorsText.IsEmpty()) + ErrorsText.Add_LF(); + ErrorsText += arc.WarningMessage; + } + } +} +*/ + +HRESULT CArchiveLink::Open(COpenOptions &op) +{ + Release(); + if (op.types->Size() >= 32) + return E_NOTIMPL; + + HRESULT resSpec; + + for (;;) + { + resSpec = S_OK; + + op.openType = COpenType(); + if (op.types->Size() >= 1) + { + COpenType latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (!latest.Recursive) + break; + } + op.openType = latest; + } + else if (Arcs.Size() >= 32) + break; + + /* + op.formatIndex = -1; + if (op.types->Size() >= 1) + { + int latest; + if (Arcs.Size() < op.types->Size()) + latest = (*op.types)[op.types->Size() - Arcs.Size() - 1]; + else + { + latest = (*op.types)[0]; + if (latest != -2 && latest != -3) + break; + } + if (latest >= 0) + op.formatIndex = latest; + else if (latest == -1 || latest == -2) + { + // default + } + else if (latest == -3) + op.formatIndex = -2; + else + op.formatIndex = latest + 2; + } + else if (Arcs.Size() >= 32) + break; + */ + + if (Arcs.IsEmpty()) + { + CArc arc; + arc.filePath = op.filePath; + arc.Path = op.filePath; + arc.SubfileIndex = (UInt32)(Int32)-1; + HRESULT result = arc.OpenStreamOrFile(op); + if (result != S_OK) + { + if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo; + // NonOpenErrorFormatIndex = arc.ErrorFormatIndex; + NonOpen_ArcPath = arc.Path; + } + return result; + } + Arcs.Add(arc); + continue; + } + + // PrintNumber("op.formatIndex 11", op.formatIndex); + + const CArc &arc = Arcs.Back(); + + if (op.types->Size() > Arcs.Size()) + resSpec = E_NOTIMPL; + + UInt32 mainSubfile; + { + NCOM::CPropVariant prop; + RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop)); + if (prop.vt == VT_UI4) + mainSubfile = prop.ulVal; + else + break; + UInt32 numItems; + RINOK(arc.Archive->GetNumberOfItems(&numItems)); + if (mainSubfile >= numItems) + break; + } + + + CMyComPtr getStream; + if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) + break; + + CMyComPtr subSeqStream; + if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) + break; + + CMyComPtr subStream; + if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) + break; + + CArc arc2; + RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); + + bool zerosTailIsAllowed; + RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed)); + + + if (op.callback) + { + CMyComPtr setSubArchiveName; + op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + if (setSubArchiveName) + setSubArchiveName->SetSubArchiveName(arc2.Path); + } + + arc2.SubfileIndex = mainSubfile; + + // CIntVector incl; + CIntVector excl; + + COpenOptions op2; + #ifndef _SFX + op2.props = op.props; + #endif + op2.codecs = op.codecs; + // op2.types = &incl; + op2.openType = op.openType; + op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed; + op2.excludedFormats = ! + op2.stdInMode = false; + op2.stream = subStream; + op2.filePath = arc2.Path; + op2.callback = op.callback; + op2.callbackSpec = op.callbackSpec; + + + HRESULT result = arc2.OpenStream(op2); + resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE); + if (result == S_FALSE) + { + NonOpen_ErrorInfo = arc2.ErrorInfo; + NonOpen_ArcPath = arc2.Path; + break; + } + RINOK(result); + RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); + Arcs.Add(arc2); + } + IsOpen = !Arcs.IsEmpty(); + return resSpec; +} + +HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) +{ + VolumesSize = 0; + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + CMyComPtr callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; + + FString prefix, name; + + if (!op.stream && !op.stdInMode) + { + NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name); + RINOK(openCallbackSpec->Init2(prefix, name)); + } + else + { + openCallbackSpec->SetSubArchiveName(op.filePath); + } + + op.callback = callback; + op.callbackSpec = openCallbackSpec; + + HRESULT res = Open(op); + + PasswordWasAsked = openCallbackSpec->PasswordWasAsked; + // Password = openCallbackSpec->Password; + + RINOK(res); + // VolumePaths.Add(fs2us(prefix + name)); + + FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed) + { + if (openCallbackSpec->FileNames_WasUsed[i]) + { + VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]); + VolumesSize += openCallbackSpec->FileSizes[i]; + } + } + // VolumesSize = openCallbackSpec->TotalSize; + return S_OK; +} + +HRESULT CArc::ReOpen(const COpenOptions &op) +{ + ErrorInfo.ClearErrors(); + ErrorInfo.ErrorFormatIndex = -1; + + UInt64 fileSize = 0; + if (op.stream) + { + RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize)); + RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL)); + } + FileSize = fileSize; + + CMyComPtr stream2; + Int64 globalOffset = GetGlobalOffset(); + if (globalOffset <= 0) + stream2 = op.stream; + else + { + CTailInStream *tailStreamSpec = new CTailInStream; + stream2 = tailStreamSpec; + tailStreamSpec->Stream = op.stream; + tailStreamSpec->Offset = (UInt64)globalOffset; + tailStreamSpec->Init(); + RINOK(tailStreamSpec->SeekToStart()); + } + + // There are archives with embedded STUBs (like ZIP), so we must support signature scanning + // But for another archives we can use 0 here. So the code can be fixed !!! + UInt64 maxStartPosition = kMaxCheckStartPosition; + HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback); + + if (res == S_OK) + { + RINOK(ReadBasicProps(Archive, (UInt64)globalOffset, res)); + ArcStreamOffset = (UInt64)globalOffset; + if (ArcStreamOffset != 0) + InStream = op.stream; + } + return res; +} + +HRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI) +{ + HRESULT res = Open2(op, callbackUI); + if (callbackUI) + { + RINOK(callbackUI->Open_Finished()); + } + return res; +} + +HRESULT CArchiveLink::ReOpen(COpenOptions &op) +{ + if (Arcs.Size() > 1) + return E_NOTIMPL; + + CObjectVector inc; + CIntVector excl; + + op.types = &inc; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + if (Arcs.Size() == 0) // ??? + return Open2(op, NULL); + + COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; + CMyComPtr openCallbackNew = openCallbackSpec; + + openCallbackSpec->Callback = NULL; + openCallbackSpec->ReOpenCallback = op.callback; + { + FString dirPrefix, fileName; + NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName); + RINOK(openCallbackSpec->Init2(dirPrefix, fileName)); + } + + + CInFileStream *fileStreamSpec = new CInFileStream; + CMyComPtr stream(fileStreamSpec); + if (!fileStreamSpec->Open(us2fs(op.filePath))) + return GetLastError_noZero_HRESULT(); + op.stream = stream; + + CArc &arc = Arcs[0]; + HRESULT res = arc.ReOpen(op); + + PasswordWasAsked = openCallbackSpec->PasswordWasAsked; + // Password = openCallbackSpec->Password; + + IsOpen = (res == S_OK); + return res; +} + +#ifndef _SFX + +bool ParseComplexSize(const wchar_t *s, UInt64 &result); +bool ParseComplexSize(const wchar_t *s, UInt64 &result) +{ + result = 0; + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (end == s) + return false; + if (*end == 0) + { + result = number; + return true; + } + if (end[1] != 0) + return false; + unsigned numBits; + switch (MyCharLower_Ascii(*end)) + { + case 'b': result = number; return true; + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + result = number << numBits; + return true; +} + +static bool ParseTypeParams(const UString &s, COpenType &type) +{ + if (s[0] == 0) + return true; + if (s[1] == 0) + { + switch ((unsigned)(Byte)s[0]) + { + case 'e': type.EachPos = true; return true; + case 'a': type.CanReturnArc = true; return true; + case 'r': type.Recursive = true; return true; + } + return false; + } + if (s[0] == 's') + { + UInt64 result; + if (!ParseComplexSize(s.Ptr(1), result)) + return false; + type.MaxStartOffset = result; + type.MaxStartOffset_Defined = true; + return true; + } + + return false; +} + +static bool ParseType(CCodecs &codecs, const UString &s, COpenType &type) +{ + int pos2 = s.Find(L':'); + + { + UString name; + if (pos2 < 0) + { + name = s; + pos2 = (int)s.Len(); + } + else + { + name = s.Left((unsigned)pos2); + pos2++; + } + + int index = codecs.FindFormatForArchiveType(name); + type.Recursive = false; + + if (index < 0) + { + if (name[0] == '*') + { + if (name[1] != 0) + return false; + } + else if (name[0] == '#') + { + if (name[1] != 0) + return false; + type.CanReturnArc = false; + type.CanReturnParser = true; + } + else + return false; + } + + type.FormatIndex = index; + + } + + for (unsigned i = (unsigned)pos2; i < s.Len();) + { + int next = s.Find(L':', i); + if (next < 0) + next = (int)s.Len(); + const UString name = s.Mid(i, (unsigned)next - i); + if (name.IsEmpty()) + return false; + if (!ParseTypeParams(name, type)) + return false; + i = (unsigned)next + 1; + } + + return true; +} + +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types) +{ + types.Clear(); + for (unsigned pos = 0; pos < s.Len();) + { + int pos2 = s.Find(L'.', pos); + if (pos2 < 0) + pos2 = (int)s.Len(); + UString name = s.Mid(pos, (unsigned)pos2 - pos); + if (name.IsEmpty()) + return false; + COpenType type; + if (!ParseType(codecs, name, type)) + return false; + types.Add(type); + pos = (unsigned)pos2 + 1; + } + return true; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.h new file mode 100644 index 0000000..ebeb91d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/OpenArchive.h @@ -0,0 +1,443 @@ +// OpenArchive.h + +#ifndef __OPEN_ARCHIVE_H +#define __OPEN_ARCHIVE_H + +#include "../../../Windows/PropVariant.h" + +#include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" +#include "Property.h" + +#ifndef _SFX + +#define SUPPORT_ALT_STREAMS + +#endif + +HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); +HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); +HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); + +#ifdef SUPPORT_ALT_STREAMS +int FindAltStreamColon_in_Path(const wchar_t *path); +#endif + +/* +struct COptionalOpenProperties +{ + UString FormatName; + CObjectVector Props; +}; +*/ + +#ifdef _SFX +#define OPEN_PROPS_DECL +#else +#define OPEN_PROPS_DECL const CObjectVector *props; +// #define OPEN_PROPS_DECL , const CObjectVector *props +#endif + +struct COpenSpecFlags +{ + // bool CanReturnFull; + bool CanReturnFrontal; + bool CanReturnTail; + bool CanReturnMid; + + bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; } + + COpenSpecFlags(): + // CanReturnFull(true), + CanReturnFrontal(false), + CanReturnTail(false), + CanReturnMid(false) + {} +}; + +struct COpenType +{ + int FormatIndex; + + COpenSpecFlags SpecForcedType; + COpenSpecFlags SpecMainType; + COpenSpecFlags SpecWrongExt; + COpenSpecFlags SpecUnknownExt; + + bool Recursive; + + bool CanReturnArc; + bool CanReturnParser; + bool EachPos; + + // bool SkipSfxStub; + // bool ExeAsUnknown; + + bool ZerosTailIsAllowed; + + bool MaxStartOffset_Defined; + UInt64 MaxStartOffset; + + const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const + { + return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); + } + + COpenType(): + FormatIndex(-1), + Recursive(true), + CanReturnArc(true), + CanReturnParser(false), + EachPos(false), + // SkipSfxStub(true), + // ExeAsUnknown(true), + ZerosTailIsAllowed(false), + MaxStartOffset_Defined(false), + MaxStartOffset(0) + { + SpecForcedType.CanReturnFrontal = true; + SpecForcedType.CanReturnTail = true; + SpecForcedType.CanReturnMid = true; + + SpecMainType.CanReturnFrontal = true; + + SpecUnknownExt.CanReturnTail = true; // for sfx + SpecUnknownExt.CanReturnMid = true; + SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad + + // ZerosTailIsAllowed = true; + } +}; + +struct COpenOptions +{ + CCodecs *codecs; + COpenType openType; + const CObjectVector *types; + const CIntVector *excludedFormats; + + IInStream *stream; + ISequentialInStream *seqStream; + IArchiveOpenCallback *callback; + COpenCallbackImp *callbackSpec; // it's used for SFX only + OPEN_PROPS_DECL + // bool openOnlySpecifiedByExtension, + + bool stdInMode; + UString filePath; + + COpenOptions(): + codecs(NULL), + types(NULL), + excludedFormats(NULL), + stream(NULL), + seqStream(NULL), + callback(NULL), + callbackSpec(NULL), + stdInMode(false) + {} + +}; + +UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); + +struct CArcErrorInfo +{ + bool ThereIsTail; + bool UnexpecedEnd; + bool IgnoreTail; // all are zeros + // bool NonZerosTail; + bool ErrorFlags_Defined; + UInt32 ErrorFlags; + UInt32 WarningFlags; + int ErrorFormatIndex; // - 1 means no Error. + // if FormatIndex == ErrorFormatIndex, the archive is open with offset + UInt64 TailSize; + + /* if CArc is Open OK with some format: + - ErrorFormatIndex shows error format index, if extension is incorrect + - other variables show message and warnings of archive that is open */ + + UString ErrorMessage; + UString WarningMessage; + + // call IsArc_After_NonOpen only if Open returns S_FALSE + bool IsArc_After_NonOpen() const + { + return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); + } + + + CArcErrorInfo(): + ThereIsTail(false), + UnexpecedEnd(false), + IgnoreTail(false), + // NonZerosTail(false), + ErrorFlags_Defined(false), + ErrorFlags(0), + WarningFlags(0), + ErrorFormatIndex(-1), + TailSize(0) + {} + + void ClearErrors(); + + void ClearErrors_Full() + { + ErrorFormatIndex = -1; + ClearErrors(); + } + + bool IsThereErrorOrWarning() const + { + return ErrorFlags != 0 + || WarningFlags != 0 + || NeedTailWarning() + || UnexpecedEnd + || !ErrorMessage.IsEmpty() + || !WarningMessage.IsEmpty(); + } + + bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } + bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } + + bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } + + UInt32 GetWarningFlags() const + { + UInt32 a = WarningFlags; + if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) + a |= kpv_ErrorFlags_DataAfterEnd; + return a; + } + + UInt32 GetErrorFlags() const + { + UInt32 a = ErrorFlags; + if (UnexpecedEnd) + a |= kpv_ErrorFlags_UnexpectedEnd; + return a; + } +}; + +struct CReadArcItem +{ + UString Path; // Path from root (including alt stream name, if alt stream) + UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode + + #ifdef SUPPORT_ALT_STREAMS + UString MainPath; + /* MainPath = Path for non-AltStream, + MainPath = Path of parent, if there is parent for AltStream. */ + UString AltStreamName; + bool IsAltStream; + bool WriteToAltStreamIfColon; + #endif + + bool IsDir; + bool MainIsDir; + UInt32 ParentIndex; // use it, if IsAltStream + + #ifndef _SFX + bool _use_baseParentFolder_mode; + int _baseParentFolder; + #endif + + CReadArcItem() + { + #ifdef SUPPORT_ALT_STREAMS + WriteToAltStreamIfColon = false; + #endif + + #ifndef _SFX + _use_baseParentFolder_mode = false; + _baseParentFolder = -1; + #endif + } +}; + +class CArc +{ + HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr &archive); + HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); + HRESULT OpenStream2(const COpenOptions &options); + + #ifndef _SFX + // parts.Back() can contain alt stream name "nams:AltName" + HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; + #endif + +public: + CMyComPtr Archive; + CMyComPtr InStream; + // we use InStream in 2 cases (ArcStreamOffset != 0): + // 1) if we use additional cache stream + // 2) we reopen sfx archive with CTailInStream + + CMyComPtr GetRawProps; + CMyComPtr GetRootProps; + + CArcErrorInfo ErrorInfo; // for OK archives + CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) + + UString Path; + UString filePath; + UString DefaultName; + int FormatIndex; // - 1 means Parser. + UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile + FILETIME MTime; + bool MTimeDefined; + + Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler + UInt64 PhySize; + // UInt64 OkPhySize; + bool PhySizeDefined; + // bool OkPhySize_Defined; + UInt64 FileSize; + UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file + // bool offsetDefined; + + UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; } + + UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler + Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive + + // AString ErrorFlagsText; + + bool IsParseArc; + + bool IsTree; + bool IsReadOnly; + + bool Ask_Deleted; + bool Ask_AltStream; + bool Ask_Aux; + bool Ask_INode; + + bool IgnoreSplit; // don't try split handler + + // void Set_ErrorFlagsText(); + + CArc(): + MTimeDefined(false), + IsTree(false), + IsReadOnly(false), + Ask_Deleted(false), + Ask_AltStream(false), + Ask_Aux(false), + Ask_INode(false), + IgnoreSplit(false) + {} + + HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); + + // ~CArc(); + + HRESULT Close() + { + InStream.Release(); + return Archive->Close(); + } + + HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetDefaultItemPath(UInt32 index, UString &result) const; + + // GetItemPath2 adds [DELETED] dir prefix for deleted items. + HRESULT GetItemPath2(UInt32 index, UString &result) const; + + HRESULT GetItem(UInt32 index, CReadArcItem &item) const; + + HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; + HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; + HRESULT IsItemAnti(UInt32 index, bool &result) const + { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } + + + HRESULT OpenStream(const COpenOptions &options); + HRESULT OpenStreamOrFile(COpenOptions &options); + + HRESULT ReOpen(const COpenOptions &options); + + HRESULT CreateNewTailStream(CMyComPtr &stream); +}; + +struct CArchiveLink +{ + CObjectVector Arcs; + UStringVector VolumePaths; + UInt64 VolumesSize; + bool IsOpen; + + bool PasswordWasAsked; + // UString Password; + + // int NonOpenErrorFormatIndex; // - 1 means no Error. + UString NonOpen_ArcPath; + + CArcErrorInfo NonOpen_ErrorInfo; + + // UString ErrorsText; + // void Set_ErrorsText(); + + CArchiveLink(): + VolumesSize(0), + IsOpen(false), + PasswordWasAsked(false) + {} + + void KeepModeForNextOpen(); + HRESULT Close(); + void Release(); + ~CArchiveLink() { Release(); } + + const CArc *GetArc() const { return &Arcs.Back(); } + IInArchive *GetArchive() const { return Arcs.Back().Archive; } + IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } + IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } + + /* + Open() opens archive and COpenOptions::callback + Open2() uses COpenCallbackImp that implements Volumes and password callback + Open3() calls Open2() and callbackUI->Open_Finished(); + Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive. + */ + + HRESULT Open(COpenOptions &options); + HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); + HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); + + HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI) + { + HRESULT result = Open3(options, callbackUI); + if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + result = S_FALSE; + return result; + } + + HRESULT ReOpen(COpenOptions &options); +}; + +bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector &types); + + +struct CDirPathSortPair +{ + unsigned Len; + unsigned Index; + + void SetNumSlashes(const FChar *s); + + int Compare(const CDirPathSortPair &a) const + { + // We need sorting order where parent items will be after child items + if (Len < a.Len) return 1; + if (Len > a.Len) return -1; + if (Index < a.Index) return -1; + if (Index > a.Index) return 1; + return 0; + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.cpp new file mode 100644 index 0000000..30efd53 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -0,0 +1,696 @@ +// PropIDUtils.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileIO.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../../PropID.h" + +#include "PropIDUtils.h" + +#ifndef _SFX +#define Get16(x) GetUi16(x) +#define Get32(x) GetUi32(x) +#endif + +using namespace NWindows; + +static const unsigned kNumWinAtrribFlags = 21; +static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU"; + +/* +FILE_ATTRIBUTE_ + +0 READONLY +1 HIDDEN +2 SYSTEM +3 (Volume label - obsolete) +4 DIRECTORY +5 ARCHIVE +6 DEVICE +7 NORMAL +8 TEMPORARY +9 SPARSE_FILE +10 REPARSE_POINT +11 COMPRESSED +12 OFFLINE +13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer) +14 ENCRYPTED +15 INTEGRITY_STREAM (V - ReFS Win8/Win2012) +16 VIRTUAL (reserved) +17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib) +18 RECALL_ON_OPEN or EA +19 PINNED +20 UNPINNED +21 STRICTLY_SEQUENTIAL +22 RECALL_ON_DATA_ACCESS +*/ + + +static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; +#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-'; + +static void ConvertPosixAttribToString(char *s, UInt32 a) throw() +{ + s[0] = kPosixTypes[(a >> 12) & 0xF]; + for (int i = 6; i >= 0; i -= 3) + { + s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); + s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); + s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); + } + if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID + if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID + if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX + s[10] = 0; + + a &= ~(UInt32)0xFFFF; + if (a != 0) + { + s[10] = ' '; + ConvertUInt32ToHex8Digits(a, s + 11); + } +} + + +void ConvertWinAttribToString(char *s, UInt32 wa) throw() +{ + /* + some programs store posix attributes in high 16 bits. + p7zip - stores additional 0x8000 flag marker. + macos - stores additional 0x4000 flag marker. + info-zip - no additional marker. + */ + + bool isPosix = ((wa & 0xF0000000) != 0); + + UInt32 posix = 0; + if (isPosix) + { + posix = wa >> 16; + wa &= (UInt32)0x3FFF; + } + + for (unsigned i = 0; i < kNumWinAtrribFlags; i++) + { + UInt32 flag = (1 << i); + if ((wa & flag) != 0) + { + char c = g_WinAttribChars[i]; + if (c != '.') + { + wa &= ~flag; + // if (i != 7) // we can disable N (NORMAL) printing + *s++ = c; + } + } + } + + if (wa != 0) + { + *s++ = ' '; + ConvertUInt32ToHex8Digits(wa, s); + s += strlen(s); + } + + *s = 0; + + if (isPosix) + { + *s++ = ' '; + ConvertPosixAttribToString(s, posix); + } +} + + +void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw() +{ + *dest = 0; + + if (prop.vt == VT_FILETIME) + { + const FILETIME &ft = prop.filetime; + if ((ft.dwHighDateTime == 0 && + ft.dwLowDateTime == 0)) + return; + ConvertUtcFileTimeToString(prop.filetime, dest, level); + return; + } + + switch (propID) + { + case kpidCRC: + { + if (prop.vt != VT_UI4) + break; + ConvertUInt32ToHex8Digits(prop.ulVal, dest); + return; + } + case kpidAttrib: + { + if (prop.vt != VT_UI4) + break; + UInt32 a = prop.ulVal; + + /* + if ((a & 0x8000) && (a & 0x7FFF) == 0) + ConvertPosixAttribToString(dest, a >> 16); + else + */ + ConvertWinAttribToString(dest, a); + return; + } + case kpidPosixAttrib: + { + if (prop.vt != VT_UI4) + break; + ConvertPosixAttribToString(dest, prop.ulVal); + return; + } + case kpidINode: + { + if (prop.vt != VT_UI8) + break; + ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest); + dest += strlen(dest); + *dest++ = '-'; + UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1); + ConvertUInt64ToString(low, dest); + return; + } + case kpidVa: + { + UInt64 v = 0; + if (prop.vt == VT_UI4) + v = prop.ulVal; + else if (prop.vt == VT_UI8) + v = (UInt64)prop.uhVal.QuadPart; + else + break; + dest[0] = '0'; + dest[1] = 'x'; + ConvertUInt64ToHex(v, dest + 2); + return; + } + } + + ConvertPropVariantToShortString(prop, dest); +} + +void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level) +{ + if (prop.vt == VT_BSTR) + { + dest.SetFromBstr(prop.bstrVal); + return; + } + char temp[64]; + ConvertPropertyToShortString2(temp, prop, propID, level); + dest = temp; +} + +#ifndef _SFX + +static inline unsigned GetHex(unsigned v) +{ + return (v < 10) ? ('0' + v) : ('A' + (v - 10)); +} + +static inline void AddHexToString(AString &res, unsigned v) +{ + res += (char)GetHex(v >> 4); + res += (char)GetHex(v & 0xF); +} + +/* +static AString Data_To_Hex(const Byte *data, size_t size) +{ + AString s; + for (size_t i = 0; i < size; i++) + AddHexToString(s, data[i]); + return s; +} +*/ + +static const char * const sidNames[] = +{ + "0" + , "Dialup" + , "Network" + , "Batch" + , "Interactive" + , "Logon" // S-1-5-5-X-Y + , "Service" + , "Anonymous" + , "Proxy" + , "EnterpriseDC" + , "Self" + , "AuthenticatedUsers" + , "RestrictedCode" + , "TerminalServer" + , "RemoteInteractiveLogon" + , "ThisOrganization" + , "16" + , "IUserIIS" + , "LocalSystem" + , "LocalService" + , "NetworkService" + , "Domains" +}; + +struct CSecID2Name +{ + UInt32 n; + const char *sz; +}; + +static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id) +{ + for (unsigned i = 0; i < num; i++) + if (pairs[i].n == id) + return (int)i; + return -1; +} + +static const CSecID2Name sid_32_Names[] = +{ + { 544, "Administrators" }, + { 545, "Users" }, + { 546, "Guests" }, + { 547, "PowerUsers" }, + { 548, "AccountOperators" }, + { 549, "ServerOperators" }, + { 550, "PrintOperators" }, + { 551, "BackupOperators" }, + { 552, "Replicators" }, + { 553, "Backup Operators" }, + { 554, "PreWindows2000CompatibleAccess" }, + { 555, "RemoteDesktopUsers" }, + { 556, "NetworkConfigurationOperators" }, + { 557, "IncomingForestTrustBuilders" }, + { 558, "PerformanceMonitorUsers" }, + { 559, "PerformanceLogUsers" }, + { 560, "WindowsAuthorizationAccessGroup" }, + { 561, "TerminalServerLicenseServers" }, + { 562, "DistributedCOMUsers" }, + { 569, "CryptographicOperators" }, + { 573, "EventLogReaders" }, + { 574, "CertificateServiceDCOMAccess" } +}; + +static const CSecID2Name sid_21_Names[] = +{ + { 500, "Administrator" }, + { 501, "Guest" }, + { 502, "KRBTGT" }, + { 512, "DomainAdmins" }, + { 513, "DomainUsers" }, + { 515, "DomainComputers" }, + { 516, "DomainControllers" }, + { 517, "CertPublishers" }, + { 518, "SchemaAdmins" }, + { 519, "EnterpriseAdmins" }, + { 520, "GroupPolicyCreatorOwners" }, + { 553, "RASandIASServers" }, + { 553, "RASandIASServers" }, + { 571, "AllowedRODCPasswordReplicationGroup" }, + { 572, "DeniedRODCPasswordReplicationGroup" } +}; + +struct CServicesToName +{ + UInt32 n[5]; + const char *sz; +}; + +static const CServicesToName services_to_name[] = +{ + { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" } +}; + +static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize) +{ + sidSize = 0; + if (lim < 8) + { + s += "ERROR"; + return; + } + UInt32 rev = p[0]; + if (rev != 1) + { + s += "UNSUPPORTED"; + return; + } + UInt32 num = p[1]; + if (8 + num * 4 > lim) + { + s += "ERROR"; + return; + } + sidSize = 8 + num * 4; + UInt32 authority = GetBe32(p + 4); + + if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1) + { + UInt32 v0 = Get32(p + 8); + if (v0 < ARRAY_SIZE(sidNames)) + { + s += sidNames[v0]; + return; + } + if (v0 == 32 && num == 2) + { + UInt32 v1 = Get32(p + 12); + int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1); + if (index >= 0) + { + s += sid_32_Names[(unsigned)index].sz; + return; + } + } + if (v0 == 21 && num == 5) + { + UInt32 v4 = Get32(p + 8 + 4 * 4); + int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4); + if (index >= 0) + { + s += sid_21_Names[(unsigned)index].sz; + return; + } + } + if (v0 == 80 && num == 6) + { + for (unsigned i = 0; i < ARRAY_SIZE(services_to_name); i++) + { + const CServicesToName &sn = services_to_name[i]; + int j; + for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++); + if (j == 5) + { + s += sn.sz; + return; + } + } + } + } + + s += "S-1-"; + if (p[2] == 0 && p[3] == 0) + s.Add_UInt32(authority); + else + { + s += "0x"; + for (int i = 2; i < 8; i++) + AddHexToString(s, p[i]); + } + for (UInt32 i = 0; i < num; i++) + { + s += '-'; + s.Add_UInt32(Get32(p + 8 + i * 4)); + } +} + +static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos) +{ + if (pos > size) + { + s += "ERROR"; + return; + } + UInt32 sidSize = 0; + ParseSid(s, p + pos, size - pos, sidSize); +} + +static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset) +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return; + UInt32 pos = Get32(p + offset); + s.Add_Space(); + s += strName; + if (pos >= size) + return; + p += pos; + size -= pos; + if (size < 8) + return; + if (Get16(p) != 2) // revision + return; + UInt32 num = Get32(p + 4); + s.Add_UInt32(num); + + /* + UInt32 aclSize = Get16(p + 2); + if (num >= (1 << 16)) + return; + if (aclSize > size) + return; + size = aclSize; + size -= 8; + p += 8; + for (UInt32 i = 0 ; i < num; i++) + { + if (size <= 8) + return; + // Byte type = p[0]; + // Byte flags = p[1]; + // UInt32 aceSize = Get16(p + 2); + // UInt32 mask = Get32(p + 4); + p += 8; + size -= 8; + + UInt32 sidSize = 0; + s.Add_Space(); + ParseSid(s, p, size, sidSize); + if (sidSize == 0) + return; + p += sidSize; + size -= sidSize; + } + + // the tail can contain zeros. So (size != 0) is not ERROR + // if (size != 0) s += " ERROR"; + */ +} + +/* +#define MY_SE_OWNER_DEFAULTED (0x0001) +#define MY_SE_GROUP_DEFAULTED (0x0002) +*/ +#define MY_SE_DACL_PRESENT (0x0004) +/* +#define MY_SE_DACL_DEFAULTED (0x0008) +*/ +#define MY_SE_SACL_PRESENT (0x0010) +/* +#define MY_SE_SACL_DEFAULTED (0x0020) +#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100) +#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200) +#define MY_SE_DACL_AUTO_INHERITED (0x0400) +#define MY_SE_SACL_AUTO_INHERITED (0x0800) +#define MY_SE_DACL_PROTECTED (0x1000) +#define MY_SE_SACL_PROTECTED (0x2000) +#define MY_SE_RM_CONTROL_VALID (0x4000) +#define MY_SE_SELF_RELATIVE (0x8000) +*/ + +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s) +{ + s.Empty(); + if (size < 20 || size > (1 << 18)) + { + s += "ERROR"; + return; + } + if (Get16(data) != 1) // revision + { + s += "UNSUPPORTED"; + return; + } + ParseOwner(s, data, size, Get32(data + 4)); + s.Add_Space(); + ParseOwner(s, data, size, Get32(data + 8)); + ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12); + ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16); + s.Add_Space(); + s.Add_UInt32(size); + // s += '\n'; + // s += Data_To_Hex(data, size); +} + +#ifdef _WIN32 + +static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw() +{ + if (pos >= size) + return false; + size -= pos; + if (size < 8) + return false; + UInt32 rev = data[pos]; + if (rev != 1) + return false; + UInt32 num = data[pos + 1]; + return (8 + num * 4 <= size); +} + +static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset) throw() +{ + UInt32 control = Get16(p + 2); + if ((flags & control) == 0) + return true; + UInt32 pos = Get32(p + offset); + if (pos >= size) + return false; + p += pos; + size -= pos; + if (size < 8) + return false; + UInt32 aclSize = Get16(p + 2); + return (aclSize <= size); +} + +bool CheckNtSecure(const Byte *data, UInt32 size) throw() +{ + if (size < 20) + return false; + if (Get16(data) != 1) // revision + return true; // windows function can handle such error, so we allow it + if (size > (1 << 18)) + return false; + if (!CheckSid(data, size, Get32(data + 4))) return false; + if (!CheckSid(data, size, Get32(data + 8))) return false; + if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false; + if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false; + return true; +} + +#endif + + + +// IO_REPARSE_TAG_* + +static const CSecID2Name k_ReparseTags[] = +{ + { 0xA0000003, "MOUNT_POINT" }, + { 0xC0000004, "HSM" }, + { 0x80000005, "DRIVE_EXTENDER" }, + { 0x80000006, "HSM2" }, + { 0x80000007, "SIS" }, + { 0x80000008, "WIM" }, + { 0x80000009, "CSV" }, + { 0x8000000A, "DFS" }, + { 0x8000000B, "FILTER_MANAGER" }, + { 0xA000000C, "SYMLINK" }, + { 0xA0000010, "IIS_CACHE" }, + { 0x80000012, "DFSR" }, + { 0x80000013, "DEDUP" }, + { 0xC0000014, "APPXSTRM" }, + { 0x80000014, "NFS" }, + { 0x80000015, "FILE_PLACEHOLDER" }, + { 0x80000016, "DFM" }, + { 0x80000017, "WOF" }, + { 0x80000018, "WCI" }, + { 0x8000001B, "APPEXECLINK" }, + { 0xA000001D, "LX_SYMLINK" }, + { 0x80000023, "AF_UNIX" }, + { 0x80000024, "LX_FIFO" }, + { 0x80000025, "LX_CHR" }, + { 0x80000026, "LX_BLK" } +}; + +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s) +{ + s.Empty(); + NFile::CReparseAttr attr; + + if (attr.Parse(data, size)) + { + if (attr.IsSymLink_WSL()) + { + s += "WSL: "; + s += attr.GetPath(); + } + else + { + if (!attr.IsSymLink_Win()) + s += "Junction: "; + s += attr.GetPath(); + if (s.IsEmpty()) + s += "Link: "; + if (!attr.IsOkNamePair()) + { + s += " : "; + s += attr.PrintName; + } + } + if (attr.MinorError) + s += " : MINOR_ERROR"; + return true; + // s += " "; // for debug + } + + if (size < 8) + return false; + UInt32 tag = Get32(data); + UInt32 len = Get16(data + 4); + if (len + 8 > size) + return false; + if (Get16(data + 6) != 0) // padding + return false; + + /* + #define _my_IO_REPARSE_TAG_DEDUP (0x80000013L) + if (tag == _my_IO_REPARSE_TAG_DEDUP) + { + } + */ + + { + int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag); + if (index >= 0) + s += k_ReparseTags[(unsigned)index].sz; + else + { + s += "REPARSE:"; + char hex[16]; + ConvertUInt32ToHex8Digits(tag, hex); + s += hex; + } + } + + s += ":"; + s.Add_UInt32(len); + + if (len != 0) + { + s.Add_Space(); + + data += 8; + + for (UInt32 i = 0; i < len; i++) + { + if (i >= 16) + { + s += "..."; + break; + } + unsigned b = data[i]; + s += (char)GetHex((b >> 4) & 0xF); + s += (char)GetHex(b & 0xF); + } + } + + return true; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.h new file mode 100644 index 0000000..915bfc2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/PropIDUtils.h @@ -0,0 +1,18 @@ +// PropIDUtils.h + +#ifndef __PROPID_UTILS_H +#define __PROPID_UTILS_H + +#include "../../../Common/MyString.h" + +// provide at least 64 bytes for buffer including zero-end +void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw(); +void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0); + +bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s); +void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s); +bool CheckNtSecure(const Byte *data, UInt32 size) throw();; + +void ConvertWinAttribToString(char *s, UInt32 wa) throw(); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Property.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Property.h new file mode 100644 index 0000000..8b57a2a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Property.h @@ -0,0 +1,14 @@ +// Property.h + +#ifndef __7Z_PROPERTY_H +#define __7Z_PROPERTY_H + +#include "../../../Common/MyString.h" + +struct CProperty +{ + UString Name; + UString Value; +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.cpp new file mode 100644 index 0000000..4b3037a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.cpp @@ -0,0 +1,87 @@ +// SetProperties.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyCom.h" +#include "../../../Common/MyString.h" +#include "../../../Common/StringToInt.h" + +#include "../../../Windows/PropVariant.h" + +#include "../../Archive/IArchive.h" + +#include "SetProperties.h" + +using namespace NWindows; +using namespace NCOM; + +static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) +{ + const wchar_t *end; + UInt64 result = ConvertStringToUInt64(s, &end); + if (*end != 0 || s.IsEmpty()) + prop = s; + else if (result <= (UInt32)0xFFFFFFFF) + prop = (UInt32)result; + else + prop = result; +} + + +struct CPropPropetiesVector +{ + CPropVariant *values; + CPropPropetiesVector(unsigned num) + { + values = new CPropVariant[num]; + } + ~CPropPropetiesVector() + { + delete []values; + } +}; + + +HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties) +{ + if (properties.IsEmpty()) + return S_OK; + CMyComPtr setProperties; + unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); + if (!setProperties) + return S_OK; + + UStringVector realNames; + CPropPropetiesVector values(properties.Size()); + { + unsigned i; + for (i = 0; i < properties.Size(); i++) + { + const CProperty &property = properties[i]; + NCOM::CPropVariant propVariant; + UString name = property.Name; + if (property.Value.IsEmpty()) + { + if (!name.IsEmpty()) + { + wchar_t c = name.Back(); + if (c == L'-') + propVariant = false; + else if (c == L'+') + propVariant = true; + if (propVariant.vt != VT_EMPTY) + name.DeleteBack(); + } + } + else + ParseNumberString(property.Value, propVariant); + realNames.Add(name); + values.values[i] = propVariant; + } + CRecordVector names; + for (i = 0; i < realNames.Size(); i++) + names.Add((const wchar_t *)realNames[i]); + + return setProperties->SetProperties(&names.Front(), values.values, names.Size()); + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.h new file mode 100644 index 0000000..892f1a2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SetProperties.h @@ -0,0 +1,10 @@ +// SetProperties.h + +#ifndef __SETPROPERTIES_H +#define __SETPROPERTIES_H + +#include "Property.h" + +HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.cpp new file mode 100644 index 0000000..5f29249 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.cpp @@ -0,0 +1,25 @@ +// SortUtils.cpp + +#include "StdAfx.h" + +#include "../../../Common/Wildcard.h" + +#include "SortUtils.h" + +static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param) +{ + const UStringVector &strings = *(const UStringVector *)param; + return CompareFileNames(strings[*p1], strings[*p2]); +} + +void SortFileNames(const UStringVector &strings, CUIntVector &indices) +{ + const unsigned numItems = strings.Size(); + indices.ClearAndSetSize(numItems); + if (numItems == 0) + return; + unsigned *vals = &indices[0]; + for (unsigned i = 0; i < numItems; i++) + vals[i] = i; + indices.Sort(CompareStrings, (void *)&strings); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.h new file mode 100644 index 0000000..8e42e06 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/SortUtils.h @@ -0,0 +1,10 @@ +// SortUtils.h + +#ifndef __SORT_UTLS_H +#define __SORT_UTLS_H + +#include "../../../Common/MyString.h" + +void SortFileNames(const UStringVector &strings, CUIntVector &indices); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.cpp new file mode 100644 index 0000000..2f86838 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.cpp @@ -0,0 +1,19 @@ +// TempFiles.cpp + +#include "StdAfx.h" + +#include "../../../Windows/FileDir.h" + +#include "TempFiles.h" + +using namespace NWindows; +using namespace NFile; + +void CTempFiles::Clear() +{ + while (!Paths.IsEmpty()) + { + NDir::DeleteFileAlways(Paths.Back()); + Paths.DeleteBack(); + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.h new file mode 100644 index 0000000..4099e65 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/TempFiles.h @@ -0,0 +1,16 @@ +// TempFiles.h + +#ifndef __TEMP_FILES_H +#define __TEMP_FILES_H + +#include "../../../Common/MyString.h" + +class CTempFiles +{ + void Clear(); +public: + FStringVector Paths; + ~CTempFiles() { Clear(); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.cpp new file mode 100644 index 0000000..fc922a7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.cpp @@ -0,0 +1,1705 @@ +// Update.cpp + +#include "StdAfx.h" + +#include "Update.h" + +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/DLL.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" +#include "../../../Windows/TimeUtils.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/LimitedStreams.h" + +#include "../../Compress/CopyCoder.h" + +#include "../Common/DirItem.h" +#include "../Common/EnumDirItems.h" +#include "../Common/OpenArchive.h" +#include "../Common/UpdateProduce.h" + +#include "EnumDirItems.h" +#include "SetProperties.h" +#include "TempFiles.h" +#include "UpdateCallback.h" + +static const char * const kUpdateIsNotSupoorted = + "update operations are not supported for this archive"; + +static const char * const kUpdateIsNotSupported_MultiVol = + "Updating for multivolume archives is not implemented"; + +using namespace NWindows; +using namespace NCOM; +using namespace NFile; +using namespace NDir; +using namespace NName; + +#ifdef _WIN32 +static CFSTR const kTempFolderPrefix = FTEXT("7zE"); +#endif + +void CUpdateErrorInfo::SetFromLastError(const char *message) +{ + SystemError = ::GetLastError(); + Message = message; +} + +HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &fileName) +{ + SetFromLastError(message); + FileNames.Add(fileName); + return Get_HRESULT_Error(); +} + +HRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error) +{ + Message = message; + FileNames.Add(fileName); + SystemError = error; + return Get_HRESULT_Error(); +} + + +using namespace NUpdateArchive; + +class COutMultiVolStream: + public IOutStream, + public CMyUnknownImp +{ + unsigned _streamIndex; // required stream + UInt64 _offsetPos; // offset from start of _streamIndex index + UInt64 _absPos; + UInt64 _length; + + struct CAltStreamInfo + { + COutFileStream *StreamSpec; + CMyComPtr Stream; + FString Name; + UInt64 Pos; + UInt64 RealSize; + }; + CObjectVector Streams; +public: + // CMyComPtr VolumeCallback; + CRecordVector Sizes; + FString Prefix; + CTempFiles *TempFiles; + + void Init() + { + _streamIndex = 0; + _offsetPos = 0; + _absPos = 0; + _length = 0; + } + + bool SetMTime(const FILETIME *mTime); + HRESULT Close(); + + UInt64 GetSize() const { return _length; } + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(UInt64 newSize); +}; + +// static NSynchronization::CCriticalSection g_TempPathsCS; + +HRESULT COutMultiVolStream::Close() +{ + HRESULT res = S_OK; + FOR_VECTOR (i, Streams) + { + COutFileStream *s = Streams[i].StreamSpec; + if (s) + { + HRESULT res2 = s->Close(); + if (res2 != S_OK) + res = res2; + } + } + return res; +} + +bool COutMultiVolStream::SetMTime(const FILETIME *mTime) +{ + bool res = true; + FOR_VECTOR (i, Streams) + { + COutFileStream *s = Streams[i].StreamSpec; + if (s) + if (!s->SetMTime(mTime)) + res = false; + } + return res; +} + +STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + while (size > 0) + { + if (_streamIndex >= Streams.Size()) + { + CAltStreamInfo altStream; + + FString name; + name.Add_UInt32(_streamIndex + 1); + while (name.Len() < 3) + name.InsertAtFront(FTEXT('0')); + name.Insert(0, Prefix); + altStream.StreamSpec = new COutFileStream; + altStream.Stream = altStream.StreamSpec; + if (!altStream.StreamSpec->Create(name, false)) + return GetLastError_noZero_HRESULT(); + { + // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); + TempFiles->Paths.Add(name); + } + + altStream.Pos = 0; + altStream.RealSize = 0; + altStream.Name = name; + Streams.Add(altStream); + continue; + } + CAltStreamInfo &altStream = Streams[_streamIndex]; + + unsigned index = _streamIndex; + if (index >= Sizes.Size()) + index = Sizes.Size() - 1; + UInt64 volSize = Sizes[index]; + + if (_offsetPos >= volSize) + { + _offsetPos -= volSize; + _streamIndex++; + continue; + } + if (_offsetPos != altStream.Pos) + { + // CMyComPtr outStream; + // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream)); + RINOK(altStream.Stream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL)); + altStream.Pos = _offsetPos; + } + + UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos); + UInt32 realProcessed; + RINOK(altStream.Stream->Write(data, curSize, &realProcessed)); + data = (const void *)((const Byte *)data + realProcessed); + size -= realProcessed; + altStream.Pos += realProcessed; + _offsetPos += realProcessed; + _absPos += realProcessed; + if (_absPos > _length) + _length = _absPos; + if (_offsetPos > altStream.RealSize) + altStream.RealSize = _offsetPos; + if (processedSize) + *processedSize += realProcessed; + if (altStream.Pos == volSize) + { + _streamIndex++; + _offsetPos = 0; + } + if (realProcessed == 0 && curSize != 0) + return E_FAIL; + break; + } + return S_OK; +} + +STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) +{ + if (seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + switch (seekOrigin) + { + case STREAM_SEEK_SET: _absPos = (UInt64)offset; break; + case STREAM_SEEK_CUR: _absPos = (UInt64)((Int64)_absPos + offset); break; + case STREAM_SEEK_END: _absPos = (UInt64)((Int64)_length + offset); break; + } + _offsetPos = _absPos; + if (newPosition) + *newPosition = _absPos; + _streamIndex = 0; + return S_OK; +} + +STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize) +{ + unsigned i = 0; + while (i < Streams.Size()) + { + CAltStreamInfo &altStream = Streams[i++]; + if ((UInt64)newSize < altStream.RealSize) + { + RINOK(altStream.Stream->SetSize(newSize)); + altStream.RealSize = newSize; + break; + } + newSize -= altStream.RealSize; + } + while (i < Streams.Size()) + { + { + CAltStreamInfo &altStream = Streams.Back(); + altStream.Stream.Release(); + DeleteFileAlways(altStream.Name); + } + Streams.DeleteBack(); + } + _offsetPos = _absPos; + _streamIndex = 0; + _length = newSize; + return S_OK; +} + +void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode) +{ + OriginalPath = path; + + SplitPathToParts_2(path, Prefix, Name); + + if (mode == k_ArcNameMode_Add) + return; + + if (mode != k_ArcNameMode_Exact) + { + int dotPos = Name.ReverseFind_Dot(); + if (dotPos < 0) + return; + if ((unsigned)dotPos == Name.Len() - 1) + Name.DeleteBack(); + else + { + const UString ext = Name.Ptr((unsigned)(dotPos + 1)); + if (BaseExtension.IsEqualTo_NoCase(ext)) + { + BaseExtension = ext; + Name.DeleteFrom((unsigned)dotPos); + return; + } + } + } + + BaseExtension.Empty(); +} + +UString CArchivePath::GetFinalPath() const +{ + UString path = GetPathWithoutExt(); + if (!BaseExtension.IsEmpty()) + { + path += '.'; + path += BaseExtension; + } + return path; +} + +UString CArchivePath::GetFinalVolPath() const +{ + UString path = GetPathWithoutExt(); + // if BaseExtension is empty, we must ignore VolExtension also. + if (!BaseExtension.IsEmpty()) + { + path += '.'; + path += VolExtension; + } + return path; +} + +FString CArchivePath::GetTempPath() const +{ + FString path = TempPrefix; + path += us2fs(Name); + if (!BaseExtension.IsEmpty()) + { + path += '.'; + path += us2fs(BaseExtension); + } + path += ".tmp"; + path += TempPostfix; + return path; +} + +static const char * const kDefaultArcType = "7z"; +static const char * const kDefaultArcExt = "7z"; +static const char * const kSFXExtension = + #ifdef _WIN32 + "exe"; + #else + ""; + #endif + +bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs, + const CObjectVector &types, const UString &arcPath) +{ + if (types.Size() > 1) + return false; + // int arcTypeIndex = -1; + if (types.Size() != 0) + { + MethodMode.Type = types[0]; + MethodMode.Type_Defined = true; + } + if (MethodMode.Type.FormatIndex < 0) + { + // MethodMode.Type = -1; + MethodMode.Type = COpenType(); + if (ArcNameMode != k_ArcNameMode_Add) + { + MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + if (MethodMode.Type.FormatIndex >= 0) + MethodMode.Type_Defined = true; + } + } + return true; +} + +bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath) +{ + UString typeExt; + int formatIndex = MethodMode.Type.FormatIndex; + if (formatIndex < 0) + { + typeExt = kDefaultArcExt; + } + else + { + const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; + if (!arcInfo.UpdateEnabled) + return false; + typeExt = arcInfo.GetMainExt(); + } + UString ext = typeExt; + if (SfxMode) + ext = kSFXExtension; + ArchivePath.BaseExtension = ext; + ArchivePath.VolExtension = typeExt; + ArchivePath.ParseFromPath(arcPath, ArcNameMode); + FOR_VECTOR (i, Commands) + { + CUpdateArchiveCommand &uc = Commands[i]; + uc.ArchivePath.BaseExtension = ext; + uc.ArchivePath.VolExtension = typeExt; + uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode); + } + return true; +} + + +struct CUpdateProduceCallbackImp: public IUpdateProduceCallback +{ + const CObjectVector *_arcItems; + CDirItemsStat *_stat; + IUpdateCallbackUI *_callback; + + CUpdateProduceCallbackImp( + const CObjectVector *a, + CDirItemsStat *stat, + IUpdateCallbackUI *callback): + _arcItems(a), + _stat(stat), + _callback(callback) {} + + virtual HRESULT ShowDeleteFile(unsigned arcIndex); +}; + + +HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex) +{ + const CArcItem &ai = (*_arcItems)[arcIndex]; + { + CDirItemsStat &stat = *_stat; + if (ai.IsDir) + stat.NumDirs++; + else if (ai.IsAltStream) + { + stat.NumAltStreams++; + stat.AltStreamsSize += ai.Size; + } + else + { + stat.NumFiles++; + stat.FilesSize += ai.Size; + } + } + return _callback->ShowDeleteFile(ai.Name, ai.IsDir); +} + +bool CRenamePair::Prepare() +{ + if (RecursedType != NRecursedType::kNonRecursed) + return false; + if (!WildcardParsing) + return true; + return !DoesNameContainWildcard(OldName); +} + +extern bool g_CaseSensitive; + +static unsigned CompareTwoNames(const wchar_t *s1, const wchar_t *s2) +{ + for (unsigned i = 0;; i++) + { + wchar_t c1 = s1[i]; + wchar_t c2 = s2[i]; + if (c1 == 0 || c2 == 0) + return i; + if (c1 == c2) + continue; + if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2))) + continue; + if (IsPathSepar(c1) && IsPathSepar(c2)) + continue; + return i; + } +} + +bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const +{ + unsigned num = CompareTwoNames(OldName, src); + if (OldName[num] == 0) + { + if (src[num] != 0 && !IsPathSepar(src[num]) && num != 0 && !IsPathSepar(src[num - 1])) + return false; + } + else + { + // OldName[num] != 0 + // OldName = "1\1a.txt" + // src = "1" + + if (!isFolder + || src[num] != 0 + || !IsPathSepar(OldName[num]) + || OldName[num + 1] != 0) + return false; + } + dest = NewName + src.Ptr(num); + return true; +} + +#ifdef SUPPORT_ALT_STREAMS +int FindAltStreamColon_in_Path(const wchar_t *path); +#endif + +static HRESULT Compress( + const CUpdateOptions &options, + bool isUpdatingItself, + CCodecs *codecs, + const CActionSet &actionSet, + const CArc *arc, + CArchivePath &archivePath, + const CObjectVector &arcItems, + Byte *processedItemsStatuses, + const CDirItems &dirItems, + const CDirItem *parentDirItem, + CTempFiles &tempFiles, + CUpdateErrorInfo &errorInfo, + IUpdateCallbackUI *callback, + CFinishArchiveStat &st) +{ + CMyComPtr outArchive; + int formatIndex = options.MethodMode.Type.FormatIndex; + + if (arc) + { + formatIndex = arc->FormatIndex; + if (formatIndex < 0) + return E_NOTIMPL; + CMyComPtr archive2 = arc->Archive; + HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); + if (result != S_OK) + throw kUpdateIsNotSupoorted; + } + else + { + RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive)); + + #ifdef EXTERNAL_CODECS + { + CMyComPtr setCompressCodecsInfo; + outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); + if (setCompressCodecsInfo) + { + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); + } + } + #endif + } + + if (outArchive == 0) + throw kUpdateIsNotSupoorted; + + NFileTimeType::EEnum fileTimeType; + { + UInt32 value; + RINOK(outArchive->GetFileTimeType(&value)); + + switch (value) + { + case NFileTimeType::kWindows: + case NFileTimeType::kUnix: + case NFileTimeType::kDOS: + fileTimeType = (NFileTimeType::EEnum)value; + break; + default: + return E_FAIL; + } + } + + { + const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex]; + if (options.AltStreams.Val && !arcInfo.Flags_AltStreams()) + return E_NOTIMPL; + if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure()) + return E_NOTIMPL; + } + + CRecordVector updatePairs2; + + UStringVector newNames; + + CArcToDoStat stat2; + + if (options.RenamePairs.Size() != 0) + { + FOR_VECTOR (i, arcItems) + { + const CArcItem &ai = arcItems[i]; + bool needRename = false; + UString dest; + + if (ai.Censored) + { + FOR_VECTOR (j, options.RenamePairs) + { + const CRenamePair &rp = options.RenamePairs[j]; + if (rp.GetNewPath(ai.IsDir, ai.Name, dest)) + { + needRename = true; + break; + } + + #ifdef SUPPORT_ALT_STREAMS + if (ai.IsAltStream) + { + int colonPos = FindAltStreamColon_in_Path(ai.Name); + if (colonPos >= 0) + { + UString mainName = ai.Name.Left((unsigned)colonPos); + /* + actually we must improve that code to support cases + with folder renaming like: rn arc dir1\ dir2\ + */ + if (rp.GetNewPath(false, mainName, dest)) + { + needRename = true; + dest += ':'; + dest += ai.Name.Ptr((unsigned)(colonPos + 1)); + break; + } + } + } + #endif + } + } + + CUpdatePair2 up2; + up2.SetAs_NoChangeArcItem(ai.IndexInServer); + if (needRename) + { + up2.NewProps = true; + RINOK(arc->IsItemAnti(i, up2.IsAnti)); + up2.NewNameIndex = (int)newNames.Add(dest); + } + updatePairs2.Add(up2); + } + } + else + { + CRecordVector updatePairs; + GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! + CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback); + + UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL); + } + + { + FOR_VECTOR (i, updatePairs2) + { + const CUpdatePair2 &up = updatePairs2[i]; + + // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases)) + + if (up.NewData && !up.UseArcProps) + { + if (up.ExistOnDisk()) + { + CDirItemsStat2 &stat = stat2.NewData; + const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex]; + if (di.IsDir()) + { + if (up.IsAnti) + stat.Anti_NumDirs++; + else + stat.NumDirs++; + } + else if (di.IsAltStream) + { + if (up.IsAnti) + stat.Anti_NumAltStreams++; + else + { + stat.NumAltStreams++; + stat.AltStreamsSize += di.Size; + } + } + else + { + if (up.IsAnti) + stat.Anti_NumFiles++; + else + { + stat.NumFiles++; + stat.FilesSize += di.Size; + } + } + } + } + else if (up.ArcIndex >= 0) + { + CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData); + const CArcItem &ai = arcItems[(unsigned)up.ArcIndex]; + if (ai.IsDir) + { + if (up.IsAnti) + stat.Anti_NumDirs++; + else + stat.NumDirs++; + } + else if (ai.IsAltStream) + { + if (up.IsAnti) + stat.Anti_NumAltStreams++; + else + { + stat.NumAltStreams++; + stat.AltStreamsSize += ai.Size; + } + } + else + { + if (up.IsAnti) + stat.Anti_NumFiles++; + else + { + stat.NumFiles++; + stat.FilesSize += ai.Size; + } + } + } + } + RINOK(callback->SetNumItems(stat2)); + } + + CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; + CMyComPtr updateCallback(updateCallbackSpec); + + updateCallbackSpec->PreserveATime = options.PreserveATime; + updateCallbackSpec->ShareForWrite = options.OpenShareForWrite; + updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError; + updateCallbackSpec->StdInMode = options.StdInMode; + updateCallbackSpec->Callback = callback; + + if (arc) + { + // we set Archive to allow to transfer GetProperty requests back to DLL. + updateCallbackSpec->Archive = arc->Archive; + } + + updateCallbackSpec->DirItems = &dirItems; + updateCallbackSpec->ParentDirItem = parentDirItem; + + updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val; + updateCallbackSpec->StoreHardLinks = options.HardLinks.Val; + updateCallbackSpec->StoreSymLinks = options.SymLinks.Val; + + updateCallbackSpec->Arc = arc; + updateCallbackSpec->ArcItems = &arcItems; + updateCallbackSpec->UpdatePairs = &updatePairs2; + + updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses; + + if (options.RenamePairs.Size() != 0) + updateCallbackSpec->NewNames = &newNames; + + CMyComPtr outSeekStream; + CMyComPtr outStream; + + if (!options.StdOutMode) + { + FString dirPrefix; + if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix)) + throw 1417161; + CreateComplexDir(dirPrefix); + } + + COutFileStream *outStreamSpec = NULL; + CStdOutFileStream *stdOutFileStreamSpec = NULL; + COutMultiVolStream *volStreamSpec = NULL; + + if (options.VolumesSizes.Size() == 0) + { + if (options.StdOutMode) + { + stdOutFileStreamSpec = new CStdOutFileStream; + outStream = stdOutFileStreamSpec; + } + else + { + outStreamSpec = new COutFileStream; + outSeekStream = outStreamSpec; + outStream = outSeekStream; + bool isOK = false; + FString realPath; + + for (unsigned i = 0; i < (1 << 16); i++) + { + if (archivePath.Temp) + { + if (i > 0) + { + archivePath.TempPostfix.Empty(); + archivePath.TempPostfix.Add_UInt32(i); + } + realPath = archivePath.GetTempPath(); + } + else + realPath = us2fs(archivePath.GetFinalPath()); + if (outStreamSpec->Create(realPath, false)) + { + tempFiles.Paths.Add(realPath); + isOK = true; + break; + } + if (::GetLastError() != ERROR_FILE_EXISTS) + break; + if (!archivePath.Temp) + break; + } + + if (!isOK) + return errorInfo.SetFromLastError("cannot open file", realPath); + } + } + else + { + if (options.StdOutMode) + return E_FAIL; + if (arc && arc->GetGlobalOffset() > 0) + return E_NOTIMPL; + + volStreamSpec = new COutMultiVolStream; + outSeekStream = volStreamSpec; + outStream = outSeekStream; + volStreamSpec->Sizes = options.VolumesSizes; + volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath()); + volStreamSpec->Prefix += '.'; + volStreamSpec->TempFiles = &tempFiles; + volStreamSpec->Init(); + + /* + updateCallbackSpec->VolumesSizes = volumesSizes; + updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; + if (!archivePath.VolExtension.IsEmpty()) + updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension; + */ + } + + RINOK(SetProperties(outArchive, options.MethodMode.Properties)); + + if (options.SfxMode) + { + CInFileStream *sfxStreamSpec = new CInFileStream; + CMyComPtr sfxStream(sfxStreamSpec); + if (!sfxStreamSpec->Open(options.SfxModule)) + return errorInfo.SetFromLastError("cannot open SFX module", options.SfxModule); + + CMyComPtr sfxOutStream; + COutFileStream *outStreamSpec2 = NULL; + if (options.VolumesSizes.Size() == 0) + sfxOutStream = outStream; + else + { + outStreamSpec2 = new COutFileStream; + sfxOutStream = outStreamSpec2; + FString realPath = us2fs(archivePath.GetFinalPath()); + if (!outStreamSpec2->Create(realPath, false)) + return errorInfo.SetFromLastError("cannot open file", realPath); + } + + { + UInt64 sfxSize; + RINOK(sfxStreamSpec->GetSize(&sfxSize)); + RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize)); + } + + RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)); + + if (outStreamSpec2) + { + RINOK(outStreamSpec2->Close()); + } + } + + CMyComPtr tailStream; + + if (options.SfxMode || !arc || arc->ArcStreamOffset == 0) + tailStream = outStream; + else + { + // Int64 globalOffset = arc->GetGlobalOffset(); + RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL)); + if (options.StdOutMode) + tailStream = outStream; + else + { + CTailOutStream *tailStreamSpec = new CTailOutStream; + tailStream = tailStreamSpec; + tailStreamSpec->Stream = outSeekStream; + tailStreamSpec->Offset = arc->ArcStreamOffset; + tailStreamSpec->Init(); + } + } + + + HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback); + // callback->Finalize(); + RINOK(result); + + if (!updateCallbackSpec->AreAllFilesClosed()) + { + errorInfo.Message = "There are unclosed input file:"; + errorInfo.FileNames = updateCallbackSpec->_openFiles_Paths; + return E_FAIL; + } + + if (options.SetArcMTime) + { + FILETIME ft; + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + FOR_VECTOR (i, updatePairs2) + { + CUpdatePair2 &pair2 = updatePairs2[i]; + const FILETIME *ft2 = NULL; + if (pair2.NewProps && pair2.DirIndex >= 0) + ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime; + else if (pair2.UseArcProps && pair2.ArcIndex >= 0) + ft2 = &arcItems[(unsigned)pair2.ArcIndex].MTime; + if (ft2) + { + if (::CompareFileTime(&ft, ft2) < 0) + ft = *ft2; + } + } + if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0) + { + if (outStreamSpec) + outStreamSpec->SetMTime(&ft); + else if (volStreamSpec) + volStreamSpec->SetMTime(&ft); + } + } + + if (callback) + { + UInt64 size = 0; + if (outStreamSpec) + outStreamSpec->GetSize(&size); + else if (stdOutFileStreamSpec) + size = stdOutFileStreamSpec->GetSize(); + else + size = volStreamSpec->GetSize(); + + st.OutArcFileSize = size; + } + + if (outStreamSpec) + result = outStreamSpec->Close(); + else if (volStreamSpec) + result = volStreamSpec->Close(); + return result; +} + +bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); + +static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item) +{ + bool finded = false; + FOR_VECTOR (i, censor.Pairs) + { + bool include; + if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} + +static HRESULT EnumerateInArchiveItems( + // bool storeStreamsMode, + const NWildcard::CCensor &censor, + const CArc &arc, + CObjectVector &arcItems) +{ + arcItems.Clear(); + UInt32 numItems; + IInArchive *archive = arc.Archive; + RINOK(archive->GetNumberOfItems(&numItems)); + arcItems.ClearAndReserve(numItems); + + CReadArcItem item; + + for (UInt32 i = 0; i < numItems; i++) + { + CArcItem ai; + + RINOK(arc.GetItem(i, item)); + ai.Name = item.Path; + ai.IsDir = item.IsDir; + ai.IsAltStream = + #ifdef SUPPORT_ALT_STREAMS + item.IsAltStream; + #else + false; + #endif + + /* + if (!storeStreamsMode && ai.IsAltStream) + continue; + */ + ai.Censored = Censor_CheckPath(censor, item); + + RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); + RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined)); + + { + CPropVariant prop; + RINOK(archive->GetProperty(i, kpidTimeType, &prop)); + if (prop.vt == VT_UI4) + { + ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; + switch (ai.TimeType) + { + case NFileTimeType::kWindows: + case NFileTimeType::kUnix: + case NFileTimeType::kDOS: + break; + default: + return E_FAIL; + } + } + } + + ai.IndexInServer = i; + arcItems.AddInReserved(ai); + } + return S_OK; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +#include + +#endif + +HRESULT UpdateArchive( + CCodecs *codecs, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, + CUpdateOptions &options, + CUpdateErrorInfo &errorInfo, + IOpenCallbackUI *openCallback, + IUpdateCallbackUI2 *callback, + bool needSetPath) +{ + if (options.StdOutMode && options.EMailMode) + return E_FAIL; + + if (types.Size() > 1) + return E_NOTIMPL; + + bool renameMode = !options.RenamePairs.IsEmpty(); + if (renameMode) + { + if (options.Commands.Size() != 1) + return E_FAIL; + } + + if (options.DeleteAfterCompressing) + { + if (options.Commands.Size() != 1) + return E_NOTIMPL; + const CActionSet &as = options.Commands[0].ActionSet; + for (unsigned i = 2; i < NPairState::kNumValues; i++) + if (as.StateActions[i] != NPairAction::kCompress) + return E_NOTIMPL; + } + + censor.AddPathsToCensor(options.PathMode); + #ifdef _WIN32 + ConvertToLongNames(censor); + #endif + censor.ExtendExclude(); + + + if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */)) + return E_NOTIMPL; + + if (options.SfxMode) + { + CProperty property; + property.Name = "rsfx"; + options.MethodMode.Properties.Add(property); + if (options.SfxModule.IsEmpty()) + { + errorInfo.Message = "SFX file is not specified"; + return E_FAIL; + } + bool found = false; + if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0) + { + const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule; + if (NFind::DoesFileExist_FollowLink(fullName)) + { + options.SfxModule = fullName; + found = true; + } + } + if (!found) + { + if (!NFind::DoesFileExist_FollowLink(options.SfxModule)) + return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule); + } + } + + CArchiveLink arcLink; + + + if (needSetPath) + { + if (!options.InitFormatIndex(codecs, types, cmdArcPath2) || + !options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + + UString arcPath = options.ArchivePath.GetFinalPath(); + + if (!options.VolumesSizes.IsEmpty()) + { + arcPath = options.ArchivePath.GetFinalVolPath(); + arcPath += '.'; + arcPath += "001"; + } + + if (cmdArcPath2.IsEmpty()) + { + if (options.MethodMode.Type.FormatIndex < 0) + throw "type of archive is not specified"; + } + else + { + NFind::CFileInfo fi; + if (!fi.Find_FollowLink(us2fs(arcPath))) + { + if (renameMode) + throw "can't find archive";; + if (options.MethodMode.Type.FormatIndex < 0) + { + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + } + else + { + if (fi.IsDir()) + return errorInfo.SetFromError_DWORD("There is a folder with the name of archive", + us2fs(arcPath), + #ifdef _WIN32 + ERROR_ACCESS_DENIED + #else + EISDIR + #endif + ); + if (fi.IsDevice) + return E_NOTIMPL; + + if (!options.StdOutMode && options.UpdateArchiveItself) + if (fi.IsReadOnly()) + { + return errorInfo.SetFromError_DWORD("The file is read-only", + us2fs(arcPath), + #ifdef _WIN32 + ERROR_ACCESS_DENIED + #else + EACCES + #endif + ); + } + + if (options.VolumesSizes.Size() > 0) + { + errorInfo.FileNames.Add(us2fs(arcPath)); + // errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = kUpdateIsNotSupported_MultiVol; + return E_NOTIMPL; + } + CObjectVector types2; + // change it. + if (options.MethodMode.Type_Defined) + types2.Add(options.MethodMode.Type); + // We need to set Properties to open archive only in some cases (WIM archives). + + CIntVector excl; + COpenOptions op; + #ifndef _SFX + op.props = &options.MethodMode.Properties; + #endif + op.codecs = codecs; + op.types = &types2; + op.excludedFormats = ! + op.stdInMode = false; + op.stream = NULL; + op.filePath = arcPath; + + RINOK(callback->StartOpenArchive(arcPath)); + + HRESULT result = arcLink.Open_Strict(op, openCallback); + + if (result == E_ABORT) + return result; + + HRESULT res2 = callback->OpenResult(codecs, arcLink, arcPath, result); + /* + if (result == S_FALSE) + return E_FAIL; + */ + RINOK(res2); + RINOK(result); + + if (arcLink.VolumePaths.Size() > 1) + { + // errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = kUpdateIsNotSupported_MultiVol; + return E_NOTIMPL; + } + + CArc &arc = arcLink.Arcs.Back(); + arc.MTimeDefined = !fi.IsDevice; + arc.MTime = fi.MTime; + + if (arc.ErrorInfo.ThereIsTail) + { + // errorInfo.SystemError = (DWORD)E_NOTIMPL; + errorInfo.Message = "There is some data block after the end of the archive"; + return E_NOTIMPL; + } + if (options.MethodMode.Type.FormatIndex < 0) + { + options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex; + if (!options.SetArcPath(codecs, cmdArcPath2)) + return E_NOTIMPL; + } + } + } + + if (options.MethodMode.Type.FormatIndex < 0) + { + options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType); + if (options.MethodMode.Type.FormatIndex < 0) + return E_NOTIMPL; + } + + bool thereIsInArchive = arcLink.IsOpen; + if (!thereIsInArchive && renameMode) + return E_FAIL; + + CDirItems dirItems; + dirItems.Callback = callback; + + CDirItem parentDirItem; + CDirItem *parentDirItem_Ptr = NULL; + + /* + FStringVector requestedPaths; + FStringVector *requestedPaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + requestedPaths_Ptr = &requestedPaths; + */ + + if (options.StdInMode) + { + CDirItem di; + di.Name = options.StdInFileName; + di.Size = (UInt64)(Int64)-1; + di.Attrib = 0; + NTime::GetCurUtcFileTime(di.MTime); + di.CTime = di.ATime = di.MTime; + dirItems.Items.Add(di); + } + else + { + bool needScanning = false; + + if (!renameMode) + FOR_VECTOR (i, options.Commands) + if (options.Commands[i].ActionSet.NeedScanning()) + needScanning = true; + + if (needScanning) + { + RINOK(callback->StartScanning()); + + dirItems.SymLinks = options.SymLinks.Val; + + #if defined(_WIN32) && !defined(UNDER_CE) + dirItems.ReadSecure = options.NtSecurity.Val; + #endif + + dirItems.ScanAltStreams = options.AltStreams.Val; + + HRESULT res = EnumerateItems(censor, + options.PathMode, + UString(), // options.AddPathPrefix, + dirItems); + + if (res != S_OK) + { + if (res != E_ABORT) + errorInfo.Message = "Scanning error"; + return res; + } + + RINOK(callback->FinishScanning(dirItems.Stat)); + + if (censor.Pairs.Size() == 1) + { + NFind::CFileInfo fi; + FString prefix = us2fs(censor.Pairs[0].Prefix); + prefix += '.'; + // UString prefix = censor.Pairs[0].Prefix; + /* + if (prefix.Back() == WCHAR_PATH_SEPARATOR) + { + prefix.DeleteBack(); + } + */ + if (fi.Find(prefix)) + if (fi.IsDir()) + { + parentDirItem.Size = fi.Size; + parentDirItem.CTime = fi.CTime; + parentDirItem.ATime = fi.ATime; + parentDirItem.MTime = fi.MTime; + parentDirItem.Attrib = fi.Attrib; + parentDirItem_Ptr = &parentDirItem; + + int secureIndex = -1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (options.NtSecurity.Val) + dirItems.AddSecurityItem(prefix, secureIndex); + #endif + parentDirItem.SecureIndex = secureIndex; + } + } + } + } + + FString tempDirPrefix; + bool usesTempDir = false; + + #ifdef _WIN32 + CTempDir tempDirectory; + if (options.EMailMode && options.EMailRemoveAfter) + { + tempDirectory.Create(kTempFolderPrefix); + tempDirPrefix = tempDirectory.GetPath(); + NormalizeDirPathPrefix(tempDirPrefix); + usesTempDir = true; + } + #endif + + CTempFiles tempFiles; + + bool createTempFile = false; + + if (!options.StdOutMode && options.UpdateArchiveItself) + { + CArchivePath &ap = options.Commands[0].ArchivePath; + ap = options.ArchivePath; + // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) + if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) + { + createTempFile = true; + ap.Temp = true; + if (!options.WorkingDir.IsEmpty()) + ap.TempPrefix = options.WorkingDir; + else + ap.TempPrefix = us2fs(ap.Prefix); + NormalizeDirPathPrefix(ap.TempPrefix); + } + } + + unsigned ci; + + + // self including protection + if (options.DeleteAfterCompressing) + { + for (ci = 0; ci < options.Commands.Size(); ci++) + { + CArchivePath &ap = options.Commands[ci].ArchivePath; + const FString path = us2fs(ap.GetFinalPath()); + // maybe we must compare absolute paths path here + FOR_VECTOR (i, dirItems.Items) + { + const FString phyPath = dirItems.GetPhyPath(i); + if (phyPath == path) + { + UString s; + s = "It is not allowed to include archive to itself"; + s.Add_LF(); + s += path; + throw s; + } + } + } + } + + + for (ci = 0; ci < options.Commands.Size(); ci++) + { + CArchivePath &ap = options.Commands[ci].ArchivePath; + if (usesTempDir) + { + // Check it + ap.Prefix = fs2us(tempDirPrefix); + // ap.Temp = true; + // ap.TempPrefix = tempDirPrefix; + } + if (!options.StdOutMode && + (ci > 0 || !createTempFile)) + { + const FString path = us2fs(ap.GetFinalPath()); + if (NFind::DoesFileOrDirExist(path)) + { + errorInfo.SystemError = ERROR_FILE_EXISTS; + errorInfo.Message = "The file already exists"; + errorInfo.FileNames.Add(path); + return errorInfo.Get_HRESULT_Error(); + } + } + } + + CObjectVector arcItems; + if (thereIsInArchive) + { + RINOK(EnumerateInArchiveItems( + // options.StoreAltStreams, + censor, arcLink.Arcs.Back(), arcItems)); + } + + /* + FStringVector processedFilePaths; + FStringVector *processedFilePaths_Ptr = NULL; + if (options.DeleteAfterCompressing) + processedFilePaths_Ptr = &processedFilePaths; + */ + + CByteBuffer processedItems; + if (options.DeleteAfterCompressing) + { + unsigned num = dirItems.Items.Size(); + processedItems.Alloc(num); + for (unsigned i = 0; i < num; i++) + processedItems[i] = 0; + } + + /* + #ifndef _NO_CRYPTO + if (arcLink.PasswordWasAsked) + { + // We set password, if open have requested password + RINOK(callback->SetPassword(arcLink.Password)); + } + #endif + */ + + for (ci = 0; ci < options.Commands.Size(); ci++) + { + const CArc *arc = thereIsInArchive ? arcLink.GetArc() : NULL; + CUpdateArchiveCommand &command = options.Commands[ci]; + UString name; + bool isUpdating; + + if (options.StdOutMode) + { + name = "stdout"; + isUpdating = thereIsInArchive; + } + else + { + name = command.ArchivePath.GetFinalPath(); + isUpdating = (ci == 0 && options.UpdateArchiveItself && thereIsInArchive); + } + + RINOK(callback->StartArchive(name, isUpdating)) + + CFinishArchiveStat st; + + RINOK(Compress(options, + isUpdating, + codecs, + command.ActionSet, + arc, + command.ArchivePath, + arcItems, + options.DeleteAfterCompressing ? (Byte *)processedItems : NULL, + + dirItems, + parentDirItem_Ptr, + + tempFiles, + errorInfo, callback, st)); + + RINOK(callback->FinishArchive(st)); + } + + + if (thereIsInArchive) + { + RINOK(arcLink.Close()); + arcLink.Release(); + } + + tempFiles.Paths.Clear(); + if (createTempFile) + { + try + { + CArchivePath &ap = options.Commands[0].ArchivePath; + const FString &tempPath = ap.GetTempPath(); + + // DWORD attrib = 0; + if (thereIsInArchive) + { + // attrib = NFind::GetFileAttrib(us2fs(arcPath)); + if (!DeleteFileAlways(us2fs(arcPath))) + return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); + } + + if (!MyMoveFile(tempPath, us2fs(arcPath))) + { + errorInfo.SetFromLastError("cannot move the file", tempPath); + errorInfo.FileNames.Add(us2fs(arcPath)); + return errorInfo.Get_HRESULT_Error(); + } + + /* + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) + { + DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath)); + if (attrib2 != INVALID_FILE_ATTRIBUTES) + NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY); + } + */ + } + catch(...) + { + throw; + } + } + + + #if defined(_WIN32) && !defined(UNDER_CE) + + if (options.EMailMode) + { + NDLL::CLibrary mapiLib; + if (!mapiLib.Load(FTEXT("Mapi32.dll"))) + { + errorInfo.SetFromLastError("cannot load Mapi32.dll"); + return errorInfo.Get_HRESULT_Error(); + } + + /* + LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments"); + if (fnSend == 0) + { + errorInfo.SetFromLastError)("7-Zip cannot find MAPISendDocuments function"); + return errorInfo.Get_HRESULT_Error(); + } + */ + + LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)(void *)mapiLib.GetProc("MAPISendMail"); + if (sendMail == 0) + { + errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function"); + return errorInfo.Get_HRESULT_Error();; + } + + FStringVector fullPaths; + unsigned i; + + for (i = 0; i < options.Commands.Size(); i++) + { + CArchivePath &ap = options.Commands[i].ArchivePath; + FString finalPath = us2fs(ap.GetFinalPath()); + FString arcPath2; + if (!MyGetFullPathName(finalPath, arcPath2)) + return errorInfo.SetFromLastError("GetFullPathName error", finalPath); + fullPaths.Add(arcPath2); + } + + CCurrentDirRestorer curDirRestorer; + + AStringVector paths; + AStringVector names; + + for (i = 0; i < fullPaths.Size(); i++) + { + const UString arcPath2 = fs2us(fullPaths[i]); + const UString fileName = ExtractFileNameFromPath(arcPath2); + paths.Add(GetAnsiString(arcPath2)); + names.Add(GetAnsiString(fileName)); + // const AString path (GetAnsiString(arcPath2)); + // const AString name (GetAnsiString(fileName)); + // Warning!!! MAPISendDocuments function changes Current directory + // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); + } + + CRecordVector files; + files.ClearAndSetSize(paths.Size()); + + for (i = 0; i < paths.Size(); i++) + { + MapiFileDesc &f = files[i]; + memset(&f, 0, sizeof(f)); + f.nPosition = 0xFFFFFFFF; + f.lpszPathName = paths[i].Ptr_non_const(); + f.lpszFileName = names[i].Ptr_non_const(); + } + + { + MapiMessage m; + memset(&m, 0, sizeof(m)); + m.nFileCount = files.Size(); + m.lpFiles = &files.Front(); + + const AString addr (GetAnsiString(options.EMailAddress)); + MapiRecipDesc rec; + if (!addr.IsEmpty()) + { + memset(&rec, 0, sizeof(rec)); + rec.ulRecipClass = MAPI_TO; + rec.lpszAddress = addr.Ptr_non_const(); + m.nRecipCount = 1; + m.lpRecips = &rec; + } + + sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0); + } + } + + #endif + + if (options.DeleteAfterCompressing) + { + CRecordVector pairs; + FStringVector foldersNames; + + unsigned i; + + for (i = 0; i < dirItems.Items.Size(); i++) + { + const CDirItem &dirItem = dirItems.Items[i]; + const FString phyPath = dirItems.GetPhyPath(i); + if (dirItem.IsDir()) + { + CDirPathSortPair pair; + pair.Index = i; + pair.SetNumSlashes(phyPath); + pairs.Add(pair); + } + else + { + if (processedItems[i] != 0 || dirItem.Size == 0) + { + NFind::CFileInfo fileInfo; + /* here we compare Raw FileInfo that can be link with actual file info that was processed. + we can fix it. */ + if (fileInfo.Find(phyPath)) + { + // FIXME: here we can check Find_FollowLink() also; + + // maybe we must exclude also files with archive name: "a a.7z * -sdel" + if (fileInfo.Size == dirItem.Size + && CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0 + && CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0) + { + RINOK(callback->DeletingAfterArchiving(phyPath, false)); + DeleteFileAlways(phyPath); + } + } + } + else + { + // file was skipped + /* + errorInfo.SystemError = 0; + errorInfo.Message = "file was not processed"; + errorInfo.FileName = phyPath; + return E_FAIL; + */ + } + } + } + + pairs.Sort2(); + + for (i = 0; i < pairs.Size(); i++) + { + const FString phyPath = dirItems.GetPhyPath(pairs[i].Index); + if (NFind::DoesDirExist(phyPath)) + { + RINOK(callback->DeletingAfterArchiving(phyPath, true)); + RemoveDir(phyPath); + } + } + + RINOK(callback->FinishDeletingAfterArchiving()); + } + + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.h new file mode 100644 index 0000000..06d1387 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/Update.h @@ -0,0 +1,208 @@ +// Update.h + +#ifndef __COMMON_UPDATE_H +#define __COMMON_UPDATE_H + +#include "../../../Common/Wildcard.h" + +#include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" +#include "OpenArchive.h" +#include "Property.h" +#include "UpdateAction.h" +#include "UpdateCallback.h" + +#include "DirItem.h" + +enum EArcNameMode +{ + k_ArcNameMode_Smart, + k_ArcNameMode_Exact, + k_ArcNameMode_Add +}; + +struct CArchivePath +{ + UString OriginalPath; + + UString Prefix; // path(folder) prefix including slash + UString Name; // base name + UString BaseExtension; // archive type extension or "exe" extension + UString VolExtension; // archive type extension for volumes + + bool Temp; + FString TempPrefix; // path(folder) for temp location + FString TempPostfix; + + CArchivePath(): Temp(false) {}; + + void ParseFromPath(const UString &path, EArcNameMode mode); + UString GetPathWithoutExt() const { return Prefix + Name; } + UString GetFinalPath() const; + UString GetFinalVolPath() const; + FString GetTempPath() const; +}; + +struct CUpdateArchiveCommand +{ + UString UserArchivePath; + CArchivePath ArchivePath; + NUpdateArchive::CActionSet ActionSet; +}; + +struct CCompressionMethodMode +{ + bool Type_Defined; + COpenType Type; + CObjectVector Properties; + + CCompressionMethodMode(): Type_Defined(false) {} +}; + +namespace NRecursedType { enum EEnum +{ + kRecursed, + kWildcardOnlyRecursed, + kNonRecursed +};} + +struct CRenamePair +{ + UString OldName; + UString NewName; + bool WildcardParsing; + NRecursedType::EEnum RecursedType; + + CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {} + + bool Prepare(); + bool GetNewPath(bool isFolder, const UString &src, UString &dest) const; +}; + +struct CUpdateOptions +{ + CCompressionMethodMode MethodMode; + + CObjectVector Commands; + bool UpdateArchiveItself; + CArchivePath ArchivePath; + EArcNameMode ArcNameMode; + + bool SfxMode; + FString SfxModule; + + bool PreserveATime; + bool OpenShareForWrite; + bool StopAfterOpenError; + + bool StdInMode; + UString StdInFileName; + bool StdOutMode; + + bool EMailMode; + bool EMailRemoveAfter; + UString EMailAddress; + + FString WorkingDir; + NWildcard::ECensorPathMode PathMode; + // UString AddPathPrefix; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + bool DeleteAfterCompressing; + + bool SetArcMTime; + + CObjectVector RenamePairs; + + bool InitFormatIndex(const CCodecs *codecs, const CObjectVector &types, const UString &arcPath); + bool SetArcPath(const CCodecs *codecs, const UString &arcPath); + + CUpdateOptions(): + UpdateArchiveItself(true), + ArcNameMode(k_ArcNameMode_Smart), + + SfxMode(false), + + PreserveATime(false), + OpenShareForWrite(false), + StopAfterOpenError(false), + + StdInMode(false), + StdOutMode(false), + + EMailMode(false), + EMailRemoveAfter(false), + + PathMode(NWildcard::k_RelatPath), + + DeleteAfterCompressing(false), + SetArcMTime(false) + + {}; + + void SetActionCommand_Add() + { + Commands.Clear(); + CUpdateArchiveCommand c; + c.ActionSet = NUpdateArchive::k_ActionSet_Add; + Commands.Add(c); + } + + CRecordVector VolumesSizes; +}; + +struct CUpdateErrorInfo +{ + DWORD SystemError; // it's DWORD (WRes) only; + AString Message; + FStringVector FileNames; + + bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); } + HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); } + void SetFromLastError(const char *message); + HRESULT SetFromLastError(const char *message, const FString &fileName); + HRESULT SetFromError_DWORD(const char *message, const FString &fileName, DWORD error); + + CUpdateErrorInfo(): SystemError(0) {}; +}; + +struct CFinishArchiveStat +{ + UInt64 OutArcFileSize; + + CFinishArchiveStat(): OutArcFileSize(0) {} +}; + +#define INTERFACE_IUpdateCallbackUI2(x) \ + INTERFACE_IUpdateCallbackUI(x) \ + INTERFACE_IDirItemsCallback(x) \ + virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \ + virtual HRESULT StartScanning() x; \ + virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \ + virtual HRESULT StartOpenArchive(const wchar_t *name) x; \ + virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ + virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \ + virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \ + virtual HRESULT FinishDeletingAfterArchiving() x; \ + +struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback +{ + INTERFACE_IUpdateCallbackUI2(=0) +}; + +HRESULT UpdateArchive( + CCodecs *codecs, + const CObjectVector &types, + const UString &cmdArcPath2, + NWildcard::CCensor &censor, + CUpdateOptions &options, + CUpdateErrorInfo &errorInfo, + IOpenCallbackUI *openCallback, + IUpdateCallbackUI2 *callback, + bool needSetPath); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.cpp new file mode 100644 index 0000000..a80db72 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.cpp @@ -0,0 +1,64 @@ +// UpdateAction.cpp + +#include "StdAfx.h" + +#include "UpdateAction.h" + +namespace NUpdateArchive { + +const CActionSet k_ActionSet_Add = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress, + NPairAction::kCompress +}}; + +const CActionSet k_ActionSet_Update = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress +}}; + +const CActionSet k_ActionSet_Fresh = +{{ + NPairAction::kCopy, + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress +}}; + +const CActionSet k_ActionSet_Sync = +{{ + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, + NPairAction::kCopy, + NPairAction::kCompress, +}}; + +const CActionSet k_ActionSet_Delete = +{{ + NPairAction::kCopy, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore, + NPairAction::kIgnore +}}; + +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.h new file mode 100644 index 0000000..bc53fcd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateAction.h @@ -0,0 +1,66 @@ +// UpdateAction.h + +#ifndef __UPDATE_ACTION_H +#define __UPDATE_ACTION_H + +namespace NUpdateArchive { + + namespace NPairState + { + const unsigned kNumValues = 7; + enum EEnum + { + kNotMasked = 0, + kOnlyInArchive, + kOnlyOnDisk, + kNewInArchive, + kOldInArchive, + kSameFiles, + kUnknowNewerFiles + }; + } + + namespace NPairAction + { + enum EEnum + { + kIgnore = 0, + kCopy, + kCompress, + kCompressAsAnti + }; + } + + struct CActionSet + { + NPairAction::EEnum StateActions[NPairState::kNumValues]; + + bool IsEqualTo(const CActionSet &a) const + { + for (unsigned i = 0; i < NPairState::kNumValues; i++) + if (StateActions[i] != a.StateActions[i]) + return false; + return true; + } + + bool NeedScanning() const + { + unsigned i; + for (i = 0; i < NPairState::kNumValues; i++) + if (StateActions[i] == NPairAction::kCompress) + return true; + for (i = 1; i < NPairState::kNumValues; i++) + if (StateActions[i] != NPairAction::kIgnore) + return true; + return false; + } + }; + + extern const CActionSet k_ActionSet_Add; + extern const CActionSet k_ActionSet_Update; + extern const CActionSet k_ActionSet_Fresh; + extern const CActionSet k_ActionSet_Sync; + extern const CActionSet k_ActionSet_Delete; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.cpp new file mode 100644 index 0000000..69cde09 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -0,0 +1,834 @@ +// UpdateCallback.cpp + +#include "StdAfx.h" + +// #include + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" +#include "../../../Common/UTFConvert.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/PropVariant.h" + +#include "../../Common/StreamObjects.h" + +#include "UpdateCallback.h" + +#if defined(_WIN32) && !defined(UNDER_CE) +#define _USE_SECURITY_CODE +#include "../../../Windows/SecurityUtils.h" +#endif + +using namespace NWindows; +using namespace NFile; + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + + +#ifdef _USE_SECURITY_CODE +bool InitLocalPrivileges(); +#endif + +CArchiveUpdateCallback::CArchiveUpdateCallback(): + _hardIndex_From((UInt32)(Int32)-1), + + Callback(NULL), + + DirItems(NULL), + ParentDirItem(NULL), + + Arc(NULL), + ArcItems(NULL), + UpdatePairs(NULL), + NewNames(NULL), + CommentIndex(-1), + Comment(NULL), + + PreserveATime(false), + ShareForWrite(false), + StopAfterOpenError(false), + StdInMode(false), + + KeepOriginalItemNames(false), + StoreNtSecurity(false), + StoreHardLinks(false), + StoreSymLinks(false), + + ProcessedItemsStatuses(NULL) +{ + #ifdef _USE_SECURITY_CODE + _saclEnabled = InitLocalPrivileges(); + #endif +} + + +STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) +{ + COM_TRY_BEGIN + return Callback->SetTotal(size); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) +{ + COM_TRY_BEGIN + return Callback->SetCompleted(completeValue); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + COM_TRY_BEGIN + return Callback->SetRatioInfo(inSize, outSize); + COM_TRY_END +} + + +/* +static const CStatProp kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidAttrib, VT_UI4}, + { NULL, kpidIsAnti, VT_BOOL} +}; + +STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) +{ + return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator); +} +*/ + +STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, + Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) +{ + COM_TRY_BEGIN + RINOK(Callback->CheckBreak()); + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (newData) *newData = BoolToInt(up.NewData); + if (newProps) *newProps = BoolToInt(up.NewProps); + if (indexInArchive) + { + *indexInArchive = (UInt32)(Int32)-1; + if (up.ExistInArchive()) + *indexInArchive = ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex; + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch (propID) + { + case kpidIsDir: prop = true; break; + case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break; + case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break; + case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break; + case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType) +{ + *parentType = NParentType::kDir; + *parent = (UInt32)(Int32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps) +{ + *numProps = 0; + if (StoreNtSecurity) + *numProps = 1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID) +{ + *name = NULL; + *propID = kpidNtSecure; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID + #ifdef _USE_SECURITY_CODE + propID + #endif + , const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + if (!StoreNtSecurity) + return S_OK; + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) + { + if (StdInMode) + return S_OK; + + if (ParentDirItem) + { + if (ParentDirItem->SecureIndex < 0) + return S_OK; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)ParentDirItem->SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + return S_OK; + } + + if (Arc && Arc->GetRootProps) + return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType); + } + #endif + return S_OK; +} + +// #ifdef _USE_SECURITY_CODE +// #endif + +STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) +{ + *data = 0; + *dataSize = 0; + *propType = 0; + + if (propID == kpidNtSecure || + propID == kpidNtReparse) + { + if (StdInMode) + return S_OK; + + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps) + return Arc->GetRawProps->GetRawProp( + ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, + propID, data, dataSize, propType); + { + /* + if (!up.NewData) + return E_FAIL; + */ + if (up.IsAnti) + return S_OK; + + #if defined(_WIN32) && !defined(UNDER_CE) + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + #endif + + #ifdef _USE_SECURITY_CODE + if (propID == kpidNtSecure) + { + if (!StoreNtSecurity) + return S_OK; + if (di.SecureIndex < 0) + return S_OK; + const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[(unsigned)di.SecureIndex]; + *data = buf; + *dataSize = (UInt32)buf.Size(); + *propType = NPropDataType::kRaw; + } + else + #endif + if (propID == kpidNtReparse) + { + if (!StoreSymLinks) + return S_OK; + #if defined(_WIN32) && !defined(UNDER_CE) + // we use ReparseData2 instead of ReparseData for WIM format + const CByteBuffer *buf = &di.ReparseData2; + if (buf->Size() == 0) + buf = &di.ReparseData; + if (buf->Size() != 0) + { + *data = *buf; + *dataSize = (UInt32)buf->Size(); + *propType = NPropDataType::kRaw; + } + #endif + } + + return S_OK; + } + } + + return S_OK; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +static UString GetRelativePath(const UString &to, const UString &from) +{ + UStringVector partsTo, partsFrom; + SplitPathToParts(to, partsTo); + SplitPathToParts(from, partsFrom); + + unsigned i; + for (i = 0;; i++) + { + if (i + 1 >= partsFrom.Size() || + i + 1 >= partsTo.Size()) + break; + if (CompareFileNames(partsFrom[i], partsTo[i]) != 0) + break; + } + + if (i == 0) + { + #ifdef _WIN32 + if (NName::IsDrivePath(to) || + NName::IsDrivePath(from)) + return to; + #endif + } + + UString s; + unsigned k; + + for (k = i + 1; k < partsFrom.Size(); k++) + s += ".." STRING_PATH_SEPARATOR; + + for (k = i; k < partsTo.Size(); k++) + { + if (k != i) + s.Add_PathSepar(); + s += partsTo[k]; + } + + return s; +} + +#endif + +STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + const CUpdatePair2 &up = (*UpdatePairs)[index]; + NCOM::CPropVariant prop; + + if (up.NewData) + { + /* + if (propID == kpidIsHardLink) + { + prop = _isHardLink; + prop.Detach(value); + return S_OK; + } + */ + if (propID == kpidSymLink) + { + if (index == _hardIndex_From) + { + prop.Detach(value); + return S_OK; + } + + #if !defined(UNDER_CE) + + if (up.DirIndex >= 0) + { + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + + #ifdef _WIN32 + // if (di.IsDir()) + { + CReparseAttr attr; + if (attr.Parse(di.ReparseData, di.ReparseData.Size())) + { + UString simpleName = attr.GetPath(); + if (!attr.IsSymLink_WSL() && attr.IsRelative_Win()) + prop = simpleName; + else + { + const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); + FString fullPath; + if (NDir::MyGetFullPathName(phyPath, fullPath)) + { + prop = GetRelativePath(simpleName, fs2us(fullPath)); + } + } + prop.Detach(value); + return S_OK; + } + } + + #else // _WIN32 + + if (di.ReparseData.Size() != 0) + { + AString utf; + utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); + + UString us; + if (ConvertUTF8ToUnicode(utf, us)) + { + prop = us; + prop.Detach(value); + return S_OK; + } + } + + #endif // _WIN32 + } + #endif // !defined(UNDER_CE) + } + else if (propID == kpidHardLink) + { + if (index == _hardIndex_From) + { + const CKeyKeyValPair &pair = _map[_hardIndex_To]; + const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; + prop = DirItems->GetLogPath((unsigned)up2.DirIndex); + prop.Detach(value); + return S_OK; + } + if (up.DirIndex >= 0) + { + prop.Detach(value); + return S_OK; + } + } + } + + if (up.IsAnti + && propID != kpidIsDir + && propID != kpidPath + && propID != kpidIsAltStream) + { + switch (propID) + { + case kpidSize: prop = (UInt64)0; break; + case kpidIsAnti: prop = true; break; + } + } + else if (propID == kpidPath && up.NewNameIndex >= 0) + prop = (*NewNames)[(unsigned)up.NewNameIndex]; + else if (propID == kpidComment + && CommentIndex >= 0 + && (unsigned)CommentIndex == index + && Comment) + prop = *Comment; + else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) + { + // we can generate new ShortName here; + } + else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) + && up.ExistInArchive() && Archive) + return Archive->GetProperty(ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, value); + else if (up.ExistOnDisk()) + { + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + switch (propID) + { + case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break; + case kpidIsDir: prop = di.IsDir(); break; + case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; + case kpidAttrib: prop = di.Attrib; break; + case kpidCTime: prop = di.CTime; break; + case kpidATime: prop = di.ATime; break; + case kpidMTime: prop = di.MTime; break; + case kpidIsAltStream: prop = di.IsAltStream; break; + #if defined(_WIN32) && !defined(UNDER_CE) + // case kpidShortName: prop = di.ShortName; break; + #endif + case kpidPosixAttrib: + { + #ifdef _WIN32 + prop = di.GetPosixAttrib(); + #else + if (di.Attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) + prop = (UInt32)(di.Attrib >> 16); + #endif + break; + } + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection CS; +#endif + +STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode) +{ + COM_TRY_BEGIN + *inStream = NULL; + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (!up.NewData) + return E_FAIL; + + RINOK(Callback->CheckBreak()); + // RINOK(Callback->Finalize()); + + bool isDir = IsDir(up); + + if (up.IsAnti) + { + UString name; + if (up.ArcIndex >= 0) + name = (*ArcItems)[(unsigned)up.ArcIndex].Name; + else if (up.DirIndex >= 0) + name = DirItems->GetLogPath((unsigned)up.DirIndex); + RINOK(Callback->GetStream(name, isDir, true, mode)); + + /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. + so we return empty stream */ + + if (!isDir) + { + CBufInStream *inStreamSpec = new CBufInStream(); + CMyComPtr inStreamLoc = inStreamSpec; + inStreamSpec->Init(NULL, 0); + *inStream = inStreamLoc.Detach(); + } + return S_OK; + } + + RINOK(Callback->GetStream(DirItems->GetLogPath((unsigned)up.DirIndex), isDir, false, mode)); + + if (isDir) + return S_OK; + + if (StdInMode) + { + if (mode != NUpdateNotifyOp::kAdd && + mode != NUpdateNotifyOp::kUpdate) + return S_OK; + + CStdInFileStream *inStreamSpec = new CStdInFileStream; + CMyComPtr inStreamLoc(inStreamSpec); + *inStream = inStreamLoc.Detach(); + } + else + { + #if !defined(UNDER_CE) + const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; + if (di.AreReparseData()) + { + /* + // we still need DeviceIoControlOut() instead of Read + if (!inStreamSpec->File.OpenReparse(path)) + { + return Callback->OpenFileError(path, ::GetLastError()); + } + */ + // 20.03: we use Reparse Data instead of real data + + CBufInStream *inStreamSpec = new CBufInStream(); + CMyComPtr inStreamLoc = inStreamSpec; + inStreamSpec->Init(di.ReparseData, di.ReparseData.Size()); + *inStream = inStreamLoc.Detach(); + return S_OK; + } + #endif // !defined(UNDER_CE) + + CInFileStream *inStreamSpec = new CInFileStream; + CMyComPtr inStreamLoc(inStreamSpec); + + inStreamSpec->SupportHardLinks = StoreHardLinks; + inStreamSpec->File.PreserveATime = PreserveATime; + + const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex); + _openFiles_Indexes.Add(index); + _openFiles_Paths.Add(path); + + /* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding + for correct working if exception was raised in GetPhyPath */ + inStreamSpec->Callback = this; + inStreamSpec->CallbackRef = index; + + if (!inStreamSpec->OpenShared(path, ShareForWrite)) + { + DWORD error = ::GetLastError(); + HRESULT hres = Callback->OpenFileError(path, error); + if (StopAfterOpenError) + if (hres == S_OK || hres == S_FALSE) + return HRESULT_FROM_WIN32(error); + return hres; + } + + // #if defined(USE_WIN_FILE) || !defined(_WIN32) + if (StoreHardLinks) + { + CStreamFileProps props; + if (inStreamSpec->GetProps2(&props) == S_OK) + { + if (props.NumLinks > 1) + { + CKeyKeyValPair pair; + pair.Key1 = props.VolID; + pair.Key2 = props.FileID_Low; + pair.Value = index; + unsigned numItems = _map.Size(); + unsigned pairIndex = _map.AddToUniqueSorted2(pair); + if (numItems == _map.Size()) + { + // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex]; + _hardIndex_From = index; + _hardIndex_To = pairIndex; + // we could return NULL as stream, but it's better to return real stream + // return S_OK; + } + } + } + } + // #endif + + if (ProcessedItemsStatuses) + { + #ifndef _7ZIP_ST + NSynchronization::CCriticalSectionLock lock(CS); + #endif + ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1; + } + *inStream = inStreamLoc.Detach(); + } + + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes) +{ + COM_TRY_BEGIN + return Callback->SetOperationResult(opRes); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) +{ + COM_TRY_BEGIN + return GetStream2(index, inStream, + (*UpdatePairs)[index].ArcIndex < 0 ? + NUpdateNotifyOp::kAdd : + NUpdateNotifyOp::kUpdate); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op) +{ + COM_TRY_BEGIN + + bool isDir = false; + + if (indexType == NArchive::NEventIndexType::kOutArcIndex) + { + UString name; + if (index != (UInt32)(Int32)-1) + { + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.ExistOnDisk()) + { + name = DirItems->GetLogPath((unsigned)up.DirIndex); + isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir(); + } + } + return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir); + } + + wchar_t temp[16]; + UString s2; + const wchar_t *s = NULL; + + if (indexType == NArchive::NEventIndexType::kInArcIndex) + { + if (index != (UInt32)(Int32)-1) + { + if (ArcItems) + { + const CArcItem &ai = (*ArcItems)[index]; + s = ai.Name; + isDir = ai.IsDir; + } + else if (Arc) + { + RINOK(Arc->GetItemPath(index, s2)); + s = s2; + RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir)); + } + } + } + else if (indexType == NArchive::NEventIndexType::kBlockIndex) + { + temp[0] = '#'; + ConvertUInt32ToString(index, temp + 1); + s = temp; + } + + if (!s) + s = L""; + + return Callback->ReportUpdateOpeartion(op, s, isDir); + + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes) +{ + COM_TRY_BEGIN + + bool isEncrypted = false; + wchar_t temp[16]; + UString s2; + const wchar_t *s = NULL; + + if (indexType == NArchive::NEventIndexType::kOutArcIndex) + { + /* + UString name; + if (index != (UInt32)(Int32)-1) + { + const CUpdatePair2 &up = (*UpdatePairs)[index]; + if (up.ExistOnDisk()) + { + s2 = DirItems->GetLogPath(up.DirIndex); + s = s2; + } + } + */ + return E_FAIL; + } + + if (indexType == NArchive::NEventIndexType::kInArcIndex) + { + if (index != (UInt32)(Int32)-1) + { + if (ArcItems) + s = (*ArcItems)[index].Name; + else if (Arc) + { + RINOK(Arc->GetItemPath(index, s2)); + s = s2; + } + if (Archive) + { + RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted)); + } + } + } + else if (indexType == NArchive::NEventIndexType::kBlockIndex) + { + temp[0] = '#'; + ConvertUInt32ToString(index, temp + 1); + s = temp; + } + + return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s); + + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) +{ + if (VolumesSizes.Size() == 0) + return S_FALSE; + if (index >= (UInt32)VolumesSizes.Size()) + index = VolumesSizes.Size() - 1; + *size = VolumesSizes[index]; + return S_OK; +} + +STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) +{ + COM_TRY_BEGIN + char temp[16]; + ConvertUInt32ToString(index + 1, temp); + FString res (temp); + while (res.Len() < 2) + res.InsertAtFront(FTEXT('0')); + FString fileName = VolName; + fileName += '.'; + fileName += res; + fileName += VolExt; + COutFileStream *streamSpec = new COutFileStream; + CMyComPtr streamLoc(streamSpec); + if (!streamSpec->Create(fileName, false)) + return GetLastError_noZero_HRESULT(); + *volumeStream = streamLoc.Detach(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + COM_TRY_BEGIN + return Callback->CryptoGetTextPassword2(passwordIsDefined, password); + COM_TRY_END +} + +STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + return Callback->CryptoGetTextPassword(password); + COM_TRY_END +} + +HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error) +{ + #ifdef _WIN32 // FIX IT !!! + // why did we check only for ERROR_LOCK_VIOLATION ? + // if (error == ERROR_LOCK_VIOLATION) + #endif + { + MT_LOCK + UInt32 index = (UInt32)val; + FOR_VECTOR(i, _openFiles_Indexes) + { + if (_openFiles_Indexes[i] == index) + { + RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error)); + break; + } + } + } + return HRESULT_FROM_WIN32(error); +} + +void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val) +{ + { + MT_LOCK + UInt32 index = (UInt32)val; + FOR_VECTOR(i, _openFiles_Indexes) + { + if (_openFiles_Indexes[i] == index) + { + _openFiles_Indexes.Delete(i); + _openFiles_Paths.Delete(i); + return; + } + } + } + /* 21.02 : this function can be called in destructor. + And destructor can be called after some exception. + If we don't want to throw exception in desctructors or after another exceptions, + we must disable the code below that raises new exception. + */ + // throw 20141125; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.h new file mode 100644 index 0000000..3fe0a64 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateCallback.h @@ -0,0 +1,163 @@ +// UpdateCallback.h + +#ifndef __UPDATE_CALLBACK_H +#define __UPDATE_CALLBACK_H + +#include "../../../Common/MyCom.h" + +#include "../../Common/FileStreams.h" + +#include "../../IPassword.h" +#include "../../ICoder.h" + +#include "../Common/UpdatePair.h" +#include "../Common/UpdateProduce.h" + +#include "OpenArchive.h" + +struct CArcToDoStat +{ + CDirItemsStat2 NewData; + CDirItemsStat2 OldData; + CDirItemsStat2 DeleteData; + + UInt64 Get_NumDataItems_Total() const + { + return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2(); + } +}; + +#define INTERFACE_IUpdateCallbackUI(x) \ + virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \ + virtual HRESULT SetTotal(UInt64 size) x; \ + virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ + virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ + virtual HRESULT CheckBreak() x; \ + /* virtual HRESULT Finalize() x; */ \ + virtual HRESULT SetNumItems(const CArcToDoStat &stat) x; \ + virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \ + virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \ + virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \ + virtual HRESULT SetOperationResult(Int32 opRes) x; \ + virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \ + virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \ + /* virtual HRESULT SetPassword(const UString &password) x; */ \ + virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ + virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ + virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \ + /* virtual HRESULT CloseProgress() { return S_OK; } */ + +struct IUpdateCallbackUI +{ + INTERFACE_IUpdateCallbackUI(=0) +}; + +struct CKeyKeyValPair +{ + UInt64 Key1; + UInt64 Key2; + unsigned Value; + + int Compare(const CKeyKeyValPair &a) const + { + if (Key1 < a.Key1) return -1; + if (Key1 > a.Key1) return 1; + return MyCompare(Key2, a.Key2); + } +}; + + +class CArchiveUpdateCallback: + public IArchiveUpdateCallback2, + public IArchiveUpdateCallbackFile, + public IArchiveExtractCallbackMessage, + public IArchiveGetRawProps, + public IArchiveGetRootProps, + public ICryptoGetTextPassword2, + public ICryptoGetTextPassword, + public ICompressProgressInfo, + public IInFileStream_Callback, + public CMyUnknownImp +{ + #if defined(_WIN32) && !defined(UNDER_CE) + bool _saclEnabled; + #endif + CRecordVector _map; + + UInt32 _hardIndex_From; + UInt32 _hardIndex_To; + +public: + MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2) + MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile) + MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) + MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps) + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2) + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + INTERFACE_IArchiveUpdateCallback2(;) + INTERFACE_IArchiveUpdateCallbackFile(;) + INTERFACE_IArchiveExtractCallbackMessage(;) + INTERFACE_IArchiveGetRawProps(;) + INTERFACE_IArchiveGetRootProps(;) + + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + CRecordVector _openFiles_Indexes; + FStringVector _openFiles_Paths; + + bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); } + virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error); + virtual void InFileStream_On_Destroy(UINT_PTR val); + + CRecordVector VolumesSizes; + FString VolName; + FString VolExt; + + IUpdateCallbackUI *Callback; + + const CDirItems *DirItems; + const CDirItem *ParentDirItem; + + const CArc *Arc; + CMyComPtr Archive; + const CObjectVector *ArcItems; + const CRecordVector *UpdatePairs; + const UStringVector *NewNames; + int CommentIndex; + const UString *Comment; + + bool PreserveATime; + bool ShareForWrite; + bool StopAfterOpenError; + bool StdInMode; + + bool KeepOriginalItemNames; + bool StoreNtSecurity; + bool StoreHardLinks; + bool StoreSymLinks; + + Byte *ProcessedItemsStatuses; + + + CArchiveUpdateCallback(); + + bool IsDir(const CUpdatePair2 &up) const + { + if (up.DirIndex >= 0) + return DirItems->Items[(unsigned)up.DirIndex].IsDir(); + else if (up.ArcIndex >= 0) + return (*ArcItems)[(unsigned)up.ArcIndex].IsDir; + return false; + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.cpp new file mode 100644 index 0000000..31d73f9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.cpp @@ -0,0 +1,235 @@ +// UpdatePair.cpp + +#include "StdAfx.h" + +#include + +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/TimeUtils.h" + +#include "SortUtils.h" +#include "UpdatePair.h" + +using namespace NWindows; +using namespace NTime; + +static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) +{ + switch (fileTimeType) + { + case NFileTimeType::kWindows: + return ::CompareFileTime(&time1, &time2); + case NFileTimeType::kUnix: + { + UInt32 unixTime1, unixTime2; + FileTimeToUnixTime(time1, unixTime1); + FileTimeToUnixTime(time2, unixTime2); + return MyCompare(unixTime1, unixTime2); + } + case NFileTimeType::kDOS: + { + UInt32 dosTime1, dosTime2; + FileTimeToDosTime(time1, dosTime1); + FileTimeToDosTime(time2, dosTime2); + return MyCompare(dosTime1, dosTime2); + } + } + throw 4191618; +} + +static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:"; +static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:"; +static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):"; + +MY_ATTR_NORETURN +static +void ThrowError(const char *message, const UString &s1, const UString &s2) +{ + UString m (message); + m.Add_LF(); m += s1; + m.Add_LF(); m += s2; + throw m; +} + +static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2) +{ + int res = CompareFileNames(ai1.Name, ai2.Name); + if (res != 0) + return res; + if (ai1.IsDir != ai2.IsDir) + return ai1.IsDir ? -1 : 1; + return 0; +} + +static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param) +{ + unsigned i1 = *p1; + unsigned i2 = *p2; + const CObjectVector &arcItems = *(const CObjectVector *)param; + int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]); + if (res != 0) + return res; + return MyCompare(i1, i2); +} + +void GetUpdatePairInfoList( + const CDirItems &dirItems, + const CObjectVector &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &updatePairs) +{ + CUIntVector dirIndices, arcIndices; + + unsigned numDirItems = dirItems.Items.Size(); + unsigned numArcItems = arcItems.Size(); + + CIntArr duplicatedArcItem(numArcItems); + { + int *vals = &duplicatedArcItem[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = 0; + } + + { + arcIndices.ClearAndSetSize(numArcItems); + if (numArcItems != 0) + { + unsigned *vals = &arcIndices[0]; + for (unsigned i = 0; i < numArcItems; i++) + vals[i] = i; + } + arcIndices.Sort(CompareArcItems, (void *)&arcItems); + for (unsigned i = 0; i + 1 < numArcItems; i++) + if (CompareArcItemsBase( + arcItems[arcIndices[i]], + arcItems[arcIndices[i + 1]]) == 0) + { + duplicatedArcItem[i] = 1; + duplicatedArcItem[i + 1] = -1; + } + } + + UStringVector dirNames; + { + dirNames.ClearAndReserve(numDirItems); + unsigned i; + for (i = 0; i < numDirItems; i++) + dirNames.AddInReserved(dirItems.GetLogPath(i)); + SortFileNames(dirNames, dirIndices); + for (i = 0; i + 1 < numDirItems; i++) + { + const UString &s1 = dirNames[dirIndices[i]]; + const UString &s2 = dirNames[dirIndices[i + 1]]; + if (CompareFileNames(s1, s2) == 0) + ThrowError(k_Duplicate_inDir_Message, s1, s2); + } + } + + unsigned dirIndex = 0; + unsigned arcIndex = 0; + + int prevHostFile = -1; + const UString *prevHostName = NULL; + + while (dirIndex < numDirItems || arcIndex < numArcItems) + { + CUpdatePair pair; + + int dirIndex2 = -1; + int arcIndex2 = -1; + const CDirItem *di = NULL; + const CArcItem *ai = NULL; + + int compareResult = -1; + const UString *name = NULL; + + if (dirIndex < numDirItems) + { + dirIndex2 = (int)dirIndices[dirIndex]; + di = &dirItems.Items[(unsigned)dirIndex2]; + } + + if (arcIndex < numArcItems) + { + arcIndex2 = (int)arcIndices[arcIndex]; + ai = &arcItems[(unsigned)arcIndex2]; + compareResult = 1; + if (dirIndex < numDirItems) + { + compareResult = CompareFileNames(dirNames[(unsigned)dirIndex2], ai->Name); + if (compareResult == 0) + { + if (di->IsDir() != ai->IsDir) + compareResult = (ai->IsDir ? 1 : -1); + } + } + } + + if (compareResult < 0) + { + name = &dirNames[(unsigned)dirIndex2]; + pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; + pair.DirIndex = dirIndex2; + dirIndex++; + } + else if (compareResult > 0) + { + name = &ai->Name; + pair.State = ai->Censored ? + NUpdateArchive::NPairState::kOnlyInArchive: + NUpdateArchive::NPairState::kNotMasked; + pair.ArcIndex = arcIndex2; + arcIndex++; + } + else + { + int dupl = duplicatedArcItem[arcIndex]; + if (dupl != 0) + ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name); + + name = &dirNames[(unsigned)dirIndex2]; + if (!ai->Censored) + ThrowError(k_NotCensoredCollision_Message, *name, ai->Name); + + pair.DirIndex = dirIndex2; + pair.ArcIndex = arcIndex2; + + switch (ai->MTimeDefined ? MyCompareTime( + ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType, + di->MTime, ai->MTime): 0) + { + case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; + case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; + default: + pair.State = (ai->SizeDefined && di->Size == ai->Size) ? + NUpdateArchive::NPairState::kSameFiles : + NUpdateArchive::NPairState::kUnknowNewerFiles; + } + + dirIndex++; + arcIndex++; + } + + if ((di && di->IsAltStream) || + (ai && ai->IsAltStream)) + { + if (prevHostName) + { + unsigned hostLen = prevHostName->Len(); + if (name->Len() > hostLen) + if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0) + pair.HostIndex = prevHostFile; + } + } + else + { + prevHostFile = (int)updatePairs.Size(); + prevHostName = name; + } + + updatePairs.Add(pair); + } + + updatePairs.ReserveDown(); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.h new file mode 100644 index 0000000..296d3b0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdatePair.h @@ -0,0 +1,27 @@ +// UpdatePair.h + +#ifndef __UPDATE_PAIR_H +#define __UPDATE_PAIR_H + +#include "DirItem.h" +#include "UpdateAction.h" + +#include "../../Archive/IArchive.h" + +struct CUpdatePair +{ + NUpdateArchive::NPairState::EEnum State; + int ArcIndex; + int DirIndex; + int HostIndex; // >= 0 for alt streams only, contains index of host pair + + CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {} +}; + +void GetUpdatePairInfoList( + const CDirItems &dirItems, + const CObjectVector &arcItems, + NFileTimeType::EEnum fileTimeType, + CRecordVector &updatePairs); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.cpp new file mode 100644 index 0000000..fa4bd69 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -0,0 +1,70 @@ +// UpdateProduce.cpp + +#include "StdAfx.h" + +#include "UpdateProduce.h" + +using namespace NUpdateArchive; + +static const char * const kUpdateActionSetCollision = "Internal collision in update action set"; + +void UpdateProduce( + const CRecordVector &updatePairs, + const CActionSet &actionSet, + CRecordVector &operationChain, + IUpdateProduceCallback *callback) +{ + FOR_VECTOR (i, updatePairs) + { + const CUpdatePair &pair = updatePairs[i]; + + CUpdatePair2 up2; + up2.DirIndex = pair.DirIndex; + up2.ArcIndex = pair.ArcIndex; + up2.NewData = up2.NewProps = true; + up2.UseArcProps = false; + + switch (actionSet.StateActions[(unsigned)pair.State]) + { + case NPairAction::kIgnore: + if (pair.ArcIndex >= 0 && callback) + callback->ShowDeleteFile((unsigned)pair.ArcIndex); + continue; + + case NPairAction::kCopy: + if (pair.State == NPairState::kOnlyOnDisk) + throw kUpdateActionSetCollision; + if (pair.State == NPairState::kOnlyInArchive) + { + if (pair.HostIndex >= 0) + { + /* + ignore alt stream if + 1) no such alt stream in Disk + 2) there is Host file in disk + */ + if (updatePairs[(unsigned)pair.HostIndex].DirIndex >= 0) + continue; + } + } + up2.NewData = up2.NewProps = false; + up2.UseArcProps = true; + break; + + case NPairAction::kCompress: + if (pair.State == NPairState::kOnlyInArchive || + pair.State == NPairState::kNotMasked) + throw kUpdateActionSetCollision; + break; + + case NPairAction::kCompressAsAnti: + up2.IsAnti = true; + up2.UseArcProps = (pair.ArcIndex >= 0); + break; + } + + operationChain.Add(up2); + } + + operationChain.ReserveDown(); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.h new file mode 100644 index 0000000..595370f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/UpdateProduce.h @@ -0,0 +1,55 @@ +// UpdateProduce.h + +#ifndef __UPDATE_PRODUCE_H +#define __UPDATE_PRODUCE_H + +#include "UpdatePair.h" + +struct CUpdatePair2 +{ + bool NewData; + bool NewProps; + bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties. + bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status + + int DirIndex; + int ArcIndex; + int NewNameIndex; + + bool IsMainRenameItem; + + void SetAs_NoChangeArcItem(unsigned arcIndex) // int + { + NewData = NewProps = false; + UseArcProps = true; + IsAnti = false; + ArcIndex = (int)arcIndex; + } + + bool ExistOnDisk() const { return DirIndex != -1; } + bool ExistInArchive() const { return ArcIndex != -1; } + + CUpdatePair2(): + NewData(false), + NewProps(false), + UseArcProps(false), + IsAnti(false), + DirIndex(-1), + ArcIndex(-1), + NewNameIndex(-1), + IsMainRenameItem(false) + {} +}; + +struct IUpdateProduceCallback +{ + virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0; +}; + +void UpdateProduce( + const CRecordVector &updatePairs, + const NUpdateArchive::CActionSet &actionSet, + CRecordVector &operationChain, + IUpdateProduceCallback *callback); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.cpp new file mode 100644 index 0000000..1307cee --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.cpp @@ -0,0 +1,93 @@ +// WorkDir.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" + +#include "WorkDir.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName) +{ + NWorkDir::NMode::EEnum mode = workDirInfo.Mode; + + #if defined(_WIN32) && !defined(UNDER_CE) + if (workDirInfo.ForRemovableOnly) + { + mode = NWorkDir::NMode::kCurrent; + FString prefix = path.Left(3); + if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\')) + { + UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP)); + if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) + mode = workDirInfo.Mode; + } + /* + CParsedPath parsedPath; + parsedPath.ParsePath(archiveName); + UINT driveType = GetDriveType(parsedPath.Prefix); + if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) + mode = NZipSettings::NWorkDir::NMode::kCurrent; + */ + } + #endif + + int pos = path.ReverseFind_PathSepar() + 1; + fileName = path.Ptr((unsigned)pos); + + switch (mode) + { + case NWorkDir::NMode::kCurrent: + { + return path.Left((unsigned)pos); + } + case NWorkDir::NMode::kSpecified: + { + FString tempDir = workDirInfo.Path; + NName::NormalizeDirPathPrefix(tempDir); + return tempDir; + } + default: + { + FString tempDir; + if (!MyGetTempPath(tempDir)) + throw 141717; + return tempDir; + } + } +} + +HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) +{ + NWorkDir::CInfo workDirInfo; + workDirInfo.Load(); + FString namePart; + FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); + CreateComplexDir(workDir); + CTempFile tempFile; + _outStreamSpec = new COutFileStream; + OutStream = _outStreamSpec; + if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) + { + return GetLastError_noZero_HRESULT(); + } + _originalPath = originalPath; + return S_OK; +} + +HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) +{ + OutStream.Release(); + if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) + { + return GetLastError_noZero_HRESULT(); + } + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.h new file mode 100644 index 0000000..75850a9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/WorkDir.h @@ -0,0 +1,26 @@ +// WorkDir.h + +#ifndef __WORK_DIR_H +#define __WORK_DIR_H + +#include "../../../Windows/FileDir.h" + +#include "../../Common/FileStreams.h" + +#include "ZipRegistry.h" + +FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); + +class CWorkDirTempFile +{ + FString _originalPath; + NWindows::NFile::NDir::CTempFile _tempFile; + COutFileStream *_outStreamSpec; +public: + CMyComPtr OutStream; + + HRESULT CreateTempFile(const FString &originalPath); + HRESULT MoveToOriginal(bool deleteOriginal); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ZipRegistry.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ZipRegistry.h new file mode 100644 index 0000000..76a9844 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Common/ZipRegistry.h @@ -0,0 +1,130 @@ +// ZipRegistry.h + +#ifndef __ZIP_REGISTRY_H +#define __ZIP_REGISTRY_H + +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.h" + +#include "ExtractMode.h" + +namespace NExtract +{ + struct CInfo + { + NPathMode::EEnum PathMode; + NOverwriteMode::EEnum OverwriteMode; + bool PathMode_Force; + bool OverwriteMode_Force; + + CBoolPair SplitDest; + CBoolPair ElimDup; + // CBoolPair AltStreams; + CBoolPair NtSecurity; + CBoolPair ShowPassword; + + UStringVector Paths; + + void Save() const; + void Load(); + }; + + void Save_ShowPassword(bool showPassword); + bool Read_ShowPassword(); +} + +namespace NCompression +{ + struct CFormatOptions + { + UInt32 Level; + UInt32 Dictionary; + UInt32 Order; + UInt32 BlockLogSize; + UInt32 NumThreads; + + CSysString FormatID; + UString Method; + UString Options; + UString EncryptionMethod; + + void Reset_BlockLogSize() + { + BlockLogSize = (UInt32)(Int32)-1; + } + + void ResetForLevelChange() + { + BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1; + Method.Empty(); + // Options.Empty(); + // EncryptionMethod.Empty(); + } + CFormatOptions() { ResetForLevelChange(); } + }; + + struct CInfo + { + UInt32 Level; + bool ShowPassword; + bool EncryptHeaders; + UString ArcType; + UStringVector ArcPaths; + + CObjectVector Formats; + + CBoolPair NtSecurity; + CBoolPair AltStreams; + CBoolPair HardLinks; + CBoolPair SymLinks; + + void Save() const; + void Load(); + }; +} + +namespace NWorkDir +{ + namespace NMode + { + enum EEnum + { + kSystem, + kCurrent, + kSpecified + }; + } + struct CInfo + { + NMode::EEnum Mode; + FString Path; + bool ForRemovableOnly; + + void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } + void SetDefault() + { + Mode = NMode::kSystem; + Path.Empty(); + SetForRemovableOnlyDefault(); + } + + void Save() const; + void Load(); + }; +} + + +struct CContextMenuInfo +{ + CBoolPair Cascaded; + CBoolPair MenuIcons; + CBoolPair ElimDup; + + bool Flags_Def; + UInt32 Flags; + + void Save() const; + void Load(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.cpp new file mode 100644 index 0000000..a7c9e67 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.cpp @@ -0,0 +1,41 @@ +// BenchCon.cpp + +#include "StdAfx.h" + +#include "../Common/Bench.h" + +#include "BenchCon.h" +#include "ConsoleClose.h" + +struct CPrintBenchCallback: public IBenchPrintCallback +{ + FILE *_file; + + void Print(const char *s); + void NewLine(); + HRESULT CheckBreak(); +}; + +void CPrintBenchCallback::Print(const char *s) +{ + fputs(s, _file); +} + +void CPrintBenchCallback::NewLine() +{ + fputc('\n', _file); +} + +HRESULT CPrintBenchCallback::CheckBreak() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK; +} + +HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector &props, UInt32 numIterations, FILE *f) +{ + CPrintBenchCallback callback; + callback._file = f; + return Bench(EXTERNAL_CODECS_LOC_VARS + &callback, NULL, props, numIterations, true); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.h new file mode 100644 index 0000000..c9da1de --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/BenchCon.h @@ -0,0 +1,14 @@ +// BenchCon.h + +#ifndef __BENCH_CON_H +#define __BENCH_CON_H + +#include + +#include "../../Common/CreateCoder.h" +#include "../../UI/Common/Property.h" + +HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS + const CObjectVector &props, UInt32 numIterations, FILE *f); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.mak b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.mak new file mode 100644 index 0000000..bd4c1da --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.mak @@ -0,0 +1,43 @@ +MY_CONSOLE = 1 + +!IFNDEF UNDER_CE +CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE +!ENDIF + +CONSOLE_OBJS = \ + $O\BenchCon.obj \ + $O\ConsoleClose.obj \ + $O\ExtractCallbackConsole.obj \ + $O\HashCon.obj \ + $O\List.obj \ + $O\Main.obj \ + $O\MainAr.obj \ + $O\OpenCallbackConsole.obj \ + $O\PercentPrinter.obj \ + $O\UpdateCallbackConsole.obj \ + $O\UserInputUtils.obj \ + +UI_COMMON_OBJS = \ + $O\ArchiveCommandLine.obj \ + $O\ArchiveExtractCallback.obj \ + $O\ArchiveOpenCallback.obj \ + $O\Bench.obj \ + $O\DefaultName.obj \ + $O\EnumDirItems.obj \ + $O\Extract.obj \ + $O\ExtractingFilePath.obj \ + $O\HashCalc.obj \ + $O\LoadCodecs.obj \ + $O\OpenArchive.obj \ + $O\PropIDUtils.obj \ + $O\SetProperties.obj \ + $O\SortUtils.obj \ + $O\TempFiles.obj \ + $O\Update.obj \ + $O\UpdateAction.obj \ + $O\UpdateCallback.obj \ + $O\UpdatePair.obj \ + $O\UpdateProduce.obj \ + +C_OBJS = $(C_OBJS) \ + $O\DllSecur.obj \ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.manifest b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.manifest new file mode 100644 index 0000000..58b68ce --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Console.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.cpp new file mode 100644 index 0000000..9e4c040 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.cpp @@ -0,0 +1,100 @@ +// ConsoleClose.cpp + +#include "StdAfx.h" + +#include "ConsoleClose.h" + +#ifndef UNDER_CE + +#ifdef _WIN32 +#include "../../../Common/MyWindows.h" +#else +#include +#include +#endif + +namespace NConsoleClose { + +unsigned g_BreakCounter = 0; +static const unsigned kBreakAbortThreshold = 2; + +#ifdef _WIN32 + +static BOOL WINAPI HandlerRoutine(DWORD ctrlType) +{ + if (ctrlType == CTRL_LOGOFF_EVENT) + { + // printf("\nCTRL_LOGOFF_EVENT\n"); + return TRUE; + } + + g_BreakCounter++; + if (g_BreakCounter < kBreakAbortThreshold) + return TRUE; + return FALSE; + /* + switch (ctrlType) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + if (g_BreakCounter < kBreakAbortThreshold) + return TRUE; + } + return FALSE; + */ +} + +CCtrlHandlerSetter::CCtrlHandlerSetter() +{ + if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) + throw "SetConsoleCtrlHandler fails"; +} + +CCtrlHandlerSetter::~CCtrlHandlerSetter() +{ + if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) + { + // warning for throw in destructor. + // throw "SetConsoleCtrlHandler fails"; + } +} + +#else // _WIN32 + +static void HandlerRoutine(int) +{ + g_BreakCounter++; + if (g_BreakCounter < kBreakAbortThreshold) + return; + exit(EXIT_FAILURE); +} + +CCtrlHandlerSetter::CCtrlHandlerSetter() +{ + memo_sig_int = signal(SIGINT, HandlerRoutine); // CTRL-C + if (memo_sig_int == SIG_ERR) + throw "SetConsoleCtrlHandler fails (SIGINT)"; + memo_sig_term = signal(SIGTERM, HandlerRoutine); // for kill -15 (before "kill -9") + if (memo_sig_term == SIG_ERR) + throw "SetConsoleCtrlHandler fails (SIGTERM)"; +} + +CCtrlHandlerSetter::~CCtrlHandlerSetter() +{ + signal(SIGINT, memo_sig_int); // CTRL-C + signal(SIGTERM, memo_sig_term); // kill {pid} +} + +#endif // _WIN32 + +/* +void CheckCtrlBreak() +{ + if (TestBreakSignal()) + throw CCtrlBreakException(); +} +*/ + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.h new file mode 100644 index 0000000..9c9e035 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ConsoleClose.h @@ -0,0 +1,39 @@ +// ConsoleClose.h + +#ifndef __CONSOLE_CLOSE_H +#define __CONSOLE_CLOSE_H + +namespace NConsoleClose { + +class CCtrlBreakException {}; + +#ifdef UNDER_CE + +inline bool TestBreakSignal() { return false; } +struct CCtrlHandlerSetter {}; + +#else + +extern unsigned g_BreakCounter; + +inline bool TestBreakSignal() +{ + return (g_BreakCounter != 0); +} + +class CCtrlHandlerSetter +{ + #ifndef _WIN32 + void (*memo_sig_int)(int); + void (*memo_sig_term)(int); + #endif +public: + CCtrlHandlerSetter(); + virtual ~CCtrlHandlerSetter(); +}; + +#endif + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp new file mode 100644 index 0000000..23eab61 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp @@ -0,0 +1,834 @@ +// ExtractCallbackConsole.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/TimeUtils.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/PropVariantConv.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + +#include "../../Common/FilePathAutoRename.h" + +#include "../Common/ExtractingFilePath.h" + +#include "ConsoleClose.h" +#include "ExtractCallbackConsole.h" +#include "UserInputUtils.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +static const char * const kError = "ERROR: "; + + +void CExtractScanConsole::StartScanning() +{ + if (NeedPercents()) + _percent.Command = "Scan"; +} + +HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) +{ + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + + return CheckBreak2(); +} + +HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError) +{ + ClosePercentsAndFlush(); + + if (_se) + { + *_se << endl << kError << NError::MyFormatMessage(systemError) << endl; + _se->NormalizePrint_UString(fs2us(path)); + *_se << endl << endl; + _se->Flush(); + } + return HRESULT_FROM_WIN32(systemError); +} + + +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name) +{ + char temp[32]; + ConvertUInt64ToString(val, temp); + s += temp; + s.Add_Space(); + s += name; +} + +void PrintSize_bytes_Smart(AString &s, UInt64 val); +void PrintSize_bytes_Smart(AString &s, UInt64 val) +{ + Print_UInt64_and_String(s, val, "bytes"); + + if (val == 0) + return; + + unsigned numBits = 10; + char c = 'K'; + char temp[4] = { 'K', 'i', 'B', 0 }; + if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; } + else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; } + temp[0] = c; + s += " ("; + Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp); + s += ')'; +} + +static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val) +{ + if (val == (UInt64)(Int64)-1) + return; + s += ", "; + PrintSize_bytes_Smart(s, val); +} + + + +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); +void Print_DirItemsStat(AString &s, const CDirItemsStat &st) +{ + if (st.NumDirs != 0) + { + Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders"); + s += ", "; + } + Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files"); + PrintSize_bytes_Smart_comma(s, st.FilesSize); + if (st.NumAltStreams != 0) + { + s.Add_LF(); + Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams"); + PrintSize_bytes_Smart_comma(s, st.AltStreamsSize); + } +} + + +void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); +void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st) +{ + Print_DirItemsStat(s, (CDirItemsStat &)st); + bool needLF = true; + if (st.Anti_NumDirs != 0) + { + if (needLF) + s.Add_LF(); + needLF = false; + Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders"); + } + if (st.Anti_NumFiles != 0) + { + if (needLF) + s.Add_LF(); + else + s += ", "; + needLF = false; + Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files"); + } + if (st.Anti_NumAltStreams != 0) + { + if (needLF) + s.Add_LF(); + else + s += ", "; + needLF = false; + Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams"); + } +} + + +void CExtractScanConsole::PrintStat(const CDirItemsStat &st) +{ + if (_so) + { + AString s; + Print_DirItemsStat(s, st); + *_so << s << endl; + } +} + + + + + + + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + + +static const char * const kTestString = "T"; +static const char * const kExtractString = "-"; +static const char * const kSkipString = "."; + +// static const char * const kCantAutoRename = "cannot create file with auto name\n"; +// static const char * const kCantRenameFile = "cannot rename existing file\n"; +// static const char * const kCantDeleteOutputFile = "cannot delete output file "; + +static const char * const kMemoryExceptionMessage = "Can't allocate required memory!"; + +static const char * const kExtracting = "Extracting archive: "; +static const char * const kTesting = "Testing archive: "; + +static const char * const kEverythingIsOk = "Everything is Ok"; +static const char * const kNoFiles = "No files to process"; + +static const char * const kUnsupportedMethod = "Unsupported Method"; +static const char * const kCrcFailed = "CRC Failed"; +static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; +static const char * const kDataError = "Data Error"; +static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; +static const char * const kUnavailableData = "Unavailable data"; +static const char * const kUnexpectedEnd = "Unexpected end of data"; +static const char * const kDataAfterEnd = "There are some data after the end of the payload data"; +static const char * const kIsNotArc = "Is not archive"; +static const char * const kHeadersError = "Headers Error"; +static const char * const kWrongPassword = "Wrong password"; + +static const char * const k_ErrorFlagsMessages[] = +{ + "Is not archive" + , "Headers Error" + , "Headers Error in encrypted archive. Wrong password?" + , "Unavailable start of archive" + , "Unconfirmed start of archive" + , "Unexpected end of archive" + , "There are data after the end of archive" + , "Unsupported method" + , "Unsupported feature" + , "Data Error" + , "CRC Error" +}; + +STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size) +{ + MT_LOCK + + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } + return CheckBreak2(); +} + +STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + MT_LOCK + + if (NeedPercents()) + { + if (completeValue) + _percent.Completed = *completeValue; + _percent.Print(); + } + return CheckBreak2(); +} + +static const char * const kTab = " "; + +static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size) +{ + *_so << kTab << "Path: "; + _so->NormalizePrint_wstr(path); + *_so << endl; + if (size && *size != (UInt64)(Int64)-1) + { + AString s; + PrintSize_bytes_Smart(s, *size); + *_so << kTab << "Size: " << s << endl; + } + if (ft) + { + char temp[64]; + if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC)) + *_so << kTab << "Modified: " << temp << endl; + } +} + +STDMETHODIMP CExtractCallbackConsole::AskOverwrite( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *answer) +{ + MT_LOCK + + RINOK(CheckBreak2()); + + ClosePercentsAndFlush(); + + if (_so) + { + *_so << endl << "Would you like to replace the existing file:\n"; + PrintFileInfo(_so, existName, existTime, existSize); + *_so << "with the file from archive:\n"; + PrintFileInfo(_so, newName, newTime, newSize); + } + + NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so); + + switch (overwriteAnswer) + { + case NUserAnswerMode::kQuit: return E_ABORT; + case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; + case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; + case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; + case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; + case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; + case NUserAnswerMode::kEof: return E_ABORT; + case NUserAnswerMode::kError: return E_FAIL; + default: return E_FAIL; + } + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + + return CheckBreak2(); +} + +STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position) +{ + MT_LOCK + + _currentName = name; + + const char *s; + unsigned requiredLevel = 1; + + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break; + case NArchive::NExtract::NAskMode::kTest: s = kTestString; break; + case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break; + default: s = "???"; requiredLevel = 2; + }; + + bool show2 = (LogLevel >= requiredLevel && _so); + + if (show2) + { + ClosePercents_for_so(); + + _tempA = s; + if (name) + _tempA.Add_Space(); + *_so << _tempA; + + _tempU.Empty(); + if (name) + { + _tempU = name; + _so->Normalize_UString(_tempU); + } + _so->PrintUString(_tempU, _tempA); + if (position) + *_so << " <" << *position << ">"; + *_so << endl; + + if (NeedFlush) + _so->Flush(); + } + + if (NeedPercents()) + { + if (PercentsNameLevel >= 1) + { + _percent.FileName.Empty(); + _percent.Command.Empty(); + if (PercentsNameLevel > 1 || !show2) + { + _percent.Command = s; + if (name) + _percent.FileName = name; + } + } + _percent.Print(); + } + + return CheckBreak2(); +} + +STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) +{ + MT_LOCK + + RINOK(CheckBreak2()); + + NumFileErrors_in_Current++; + NumFileErrors++; + + ClosePercentsAndFlush(); + if (_se) + { + *_se << kError << message << endl; + _se->Flush(); + } + + return CheckBreak2(); +} + +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest) +{ + dest.Empty(); + const char *s = NULL; + + switch (opRes) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + s = kUnsupportedMethod; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + s = (encrypted ? kCrcFailedEncrypted : kCrcFailed); + break; + case NArchive::NExtract::NOperationResult::kDataError: + s = (encrypted ? kDataErrorEncrypted : kDataError); + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + s = kUnavailableData; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + s = kUnexpectedEnd; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + s = kDataAfterEnd; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + s = kIsNotArc; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + s = kHeadersError; + break; + case NArchive::NExtract::NOperationResult::kWrongPassword: + s = kWrongPassword; + break; + } + + dest += kError; + if (s) + dest += s; + else + { + dest += "Error #"; + dest.Add_UInt32((UInt32)opRes); + } +} + +STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + MT_LOCK + + if (opRes == NArchive::NExtract::NOperationResult::kOK) + { + if (NeedPercents()) + { + _percent.Command.Empty(); + _percent.FileName.Empty(); + _percent.Files++; + } + } + else + { + NumFileErrors_in_Current++; + NumFileErrors++; + + if (_se) + { + ClosePercentsAndFlush(); + + AString s; + SetExtractErrorMessage(opRes, encrypted, s); + + *_se << s; + if (!_currentName.IsEmpty()) + { + *_se << " : "; + _se->NormalizePrint_UString(_currentName); + } + *_se << endl; + _se->Flush(); + } + } + + return CheckBreak2(); +} + +STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + _currentName = name; + return SetOperationResult(opRes, encrypted); + } + + return CheckBreak2(); +} + + + +#ifndef _NO_CRYPTO + +HRESULT CExtractCallbackConsole::SetPassword(const UString &password) +{ + PasswordIsDefined = true; + Password = password; + return S_OK; +} + +STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + MT_LOCK + return Open_CryptoGetTextPassword(password); + COM_TRY_END +} + +#endif + +HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode) +{ + RINOK(CheckBreak2()); + + NumTryArcs++; + ThereIsError_in_Current = false; + ThereIsWarning_in_Current = false; + NumFileErrors_in_Current = 0; + + ClosePercents_for_so(); + if (_so) + { + *_so << endl << (testMode ? kTesting : kExtracting); + _so->NormalizePrint_wstr(name); + *_so << endl; + } + + if (NeedPercents()) + _percent.Command = "Open"; + return S_OK; +} + +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); + +static AString GetOpenArcErrorMessage(UInt32 errorFlags) +{ + AString s; + + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++) + { + UInt32 f = (1 << i); + if ((errorFlags & f) == 0) + continue; + const char *m = k_ErrorFlagsMessages[i]; + if (!s.IsEmpty()) + s.Add_LF(); + s += m; + errorFlags &= ~f; + } + + if (errorFlags != 0) + { + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(errorFlags, sz + 2); + if (!s.IsEmpty()) + s.Add_LF(); + s += sz; + } + + return s; +} + +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags) +{ + if (errorFlags == 0) + return; + so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl; +} + +static void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType) +{ + s.Add_LF(); + s += pre; + s += " as ["; + s += arcType; + s += "] archive"; +} + +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc) +{ + const CArcErrorInfo &er = arc.ErrorInfo; + + *_so << "WARNING:\n"; + _so->NormalizePrint_UString(arc.Path); + UString s; + if (arc.FormatIndex == er.ErrorFormatIndex) + { + s.Add_LF(); + s += "The archive is open with offset"; + } + else + { + Add_Messsage_Pre_ArcType(s, "Cannot open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex)); + Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex)); + } + + *_so << s << endl << endl; +} + + +HRESULT CExtractCallbackConsole::OpenResult( + const CCodecs *codecs, const CArchiveLink &arcLink, + const wchar_t *name, HRESULT result) +{ + ClosePercents(); + + if (NeedPercents()) + { + _percent.Files = 0; + _percent.Command.Empty(); + _percent.FileName.Empty(); + } + + + ClosePercentsAndFlush(); + + FOR_VECTOR (level, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; + + UInt32 errorFlags = er.GetErrorFlags(); + + if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) + { + if (_se) + { + *_se << endl; + if (level != 0) + { + _se->NormalizePrint_UString(arc.Path); + *_se << endl; + } + } + + if (errorFlags != 0) + { + if (_se) + PrintErrorFlags(*_se, "ERRORS:", errorFlags); + NumOpenArcErrors++; + ThereIsError_in_Current = true; + } + + if (!er.ErrorMessage.IsEmpty()) + { + if (_se) + *_se << "ERRORS:" << endl << er.ErrorMessage << endl; + NumOpenArcErrors++; + ThereIsError_in_Current = true; + } + + if (_se) + { + *_se << endl; + _se->Flush(); + } + } + + UInt32 warningFlags = er.GetWarningFlags(); + + if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) + { + if (_so) + { + *_so << endl; + if (level != 0) + { + _so->NormalizePrint_UString(arc.Path); + *_so << endl; + } + } + + if (warningFlags != 0) + { + if (_so) + PrintErrorFlags(*_so, "WARNINGS:", warningFlags); + NumOpenArcWarnings++; + ThereIsWarning_in_Current = true; + } + + if (!er.WarningMessage.IsEmpty()) + { + if (_so) + *_so << "WARNINGS:" << endl << er.WarningMessage << endl; + NumOpenArcWarnings++; + ThereIsWarning_in_Current = true; + } + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + } + + + if (er.ErrorFormatIndex >= 0) + { + if (_so) + { + Print_ErrorFormatIndex_Warning(_so, codecs, arc); + if (NeedFlush) + _so->Flush(); + } + ThereIsWarning_in_Current = true; + } + } + + if (result == S_OK) + { + if (_so) + { + RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)); + *_so << endl; + } + } + else + { + NumCantOpenArcs++; + if (_so) + _so->Flush(); + if (_se) + { + *_se << kError; + _se->NormalizePrint_wstr(name); + *_se << endl; + HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); + RINOK(res); + if (result == S_FALSE) + { + } + else + { + if (result == E_OUTOFMEMORY) + *_se << "Can't allocate required memory"; + else + *_se << NError::MyFormatMessage(result); + *_se << endl; + } + _se->Flush(); + } + } + + + return CheckBreak2(); +} + +HRESULT CExtractCallbackConsole::ThereAreNoFiles() +{ + ClosePercents_for_so(); + + if (_so) + { + *_so << endl << kNoFiles << endl; + if (NeedFlush) + _so->Flush(); + } + return CheckBreak2(); +} + +HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) +{ + MT_LOCK + + if (NeedPercents()) + { + _percent.ClosePrint(true); + _percent.Command.Empty(); + _percent.FileName.Empty(); + } + + if (_so) + _so->Flush(); + + if (result == S_OK) + { + if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current) + { + if (ThereIsWarning_in_Current) + NumArcsWithWarnings++; + else + NumOkArcs++; + if (_so) + *_so << kEverythingIsOk << endl; + } + else + { + NumArcsWithError++; + if (_so) + { + *_so << endl; + if (NumFileErrors_in_Current != 0) + *_so << "Sub items Errors: " << NumFileErrors_in_Current << endl; + } + } + if (_so && NeedFlush) + _so->Flush(); + } + else + { + NumArcsWithError++; + if (result == E_ABORT + || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) + ) + return result; + + if (_se) + { + *_se << endl << kError; + if (result == E_OUTOFMEMORY) + *_se << kMemoryExceptionMessage; + else + *_se << NError::MyFormatMessage(result); + *_se << endl; + _se->Flush(); + } + } + + return CheckBreak2(); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.h new file mode 100644 index 0000000..5ac1d0b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/ExtractCallbackConsole.h @@ -0,0 +1,167 @@ +// ExtractCallbackConsole.h + +#ifndef __EXTRACT_CALLBACK_CONSOLE_H +#define __EXTRACT_CALLBACK_CONSOLE_H + +#include "../../../Common/StdOutStream.h" + +#include "../../IPassword.h" + +#include "../../Archive/IArchive.h" + +#include "../Common/ArchiveExtractCallback.h" + +#include "PercentPrinter.h" + +#include "OpenCallbackConsole.h" + +class CExtractScanConsole: public IDirItemsCallback +{ + CStdOutStream *_so; + CStdOutStream *_se; + CPercentPrinter _percent; + + bool NeedPercents() const { return _percent._so != NULL; } + + void ClosePercentsAndFlush() + { + if (NeedPercents()) + _percent.ClosePrint(true); + if (_so) + _so->Flush(); + } + +public: + + virtual ~CExtractScanConsole() {} + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + _so = outStream; + _se = errorStream; + _percent._so = percentStream; + } + + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void StartScanning(); + + INTERFACE_IDirItemsCallback(;) + + void CloseScanning() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + void PrintStat(const CDirItemsStat &st); +}; + + + + +class CExtractCallbackConsole: + public IExtractCallbackUI, + // public IArchiveExtractCallbackMessage, + public IFolderArchiveExtractCallback2, + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public COpenCallbackConsole, + public CMyUnknownImp +{ + AString _tempA; + UString _tempU; + + UString _currentName; + + void ClosePercents_for_so() + { + if (NeedPercents() && _so == _percent._so) + _percent.ClosePrint(false); + } + + void ClosePercentsAndFlush() + { + if (NeedPercents()) + _percent.ClosePrint(true); + if (_so) + _so->Flush(); + } + +public: + MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) + // MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage) + MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2) + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(SetTotal)(UInt64 total); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + INTERFACE_IFolderArchiveExtractCallback(;) + + INTERFACE_IExtractCallbackUI(;) + // INTERFACE_IArchiveExtractCallbackMessage(;) + INTERFACE_IFolderArchiveExtractCallback2(;) + + #ifndef _NO_CRYPTO + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + + #endif + + UInt64 NumTryArcs; + + bool ThereIsError_in_Current; + bool ThereIsWarning_in_Current; + + UInt64 NumOkArcs; + UInt64 NumCantOpenArcs; + UInt64 NumArcsWithError; + UInt64 NumArcsWithWarnings; + + UInt64 NumOpenArcErrors; + UInt64 NumOpenArcWarnings; + + UInt64 NumFileErrors; + UInt64 NumFileErrors_in_Current; + + bool NeedFlush; + unsigned PercentsNameLevel; + unsigned LogLevel; + + CExtractCallbackConsole(): + NeedFlush(false), + PercentsNameLevel(1), + LogLevel(0) + {} + + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + COpenCallbackConsole::Init(outStream, errorStream, percentStream); + + NumTryArcs = 0; + + ThereIsError_in_Current = false; + ThereIsWarning_in_Current = false; + + NumOkArcs = 0; + NumCantOpenArcs = 0; + NumArcsWithError = 0; + NumArcsWithWarnings = 0; + + NumOpenArcErrors = 0; + NumOpenArcWarnings = 0; + + NumFileErrors = 0; + NumFileErrors_in_Current = 0; + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.cpp new file mode 100644 index 0000000..a70f5f8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.cpp @@ -0,0 +1,363 @@ +// HashCon.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "ConsoleClose.h" +#include "HashCon.h" + +static const char * const kEmptyFileAlias = "[Content]"; + +static const char * const kScanningMessage = "Scanning"; + +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT CHashCallbackConsole::CheckBreak() +{ + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::StartScanning() +{ + if (PrintHeaders && _so) + *_so << kScanningMessage << endl; + if (NeedPercents()) + { + _percent.ClearCurState(); + _percent.Command = "Scan"; + } + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) +{ + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError) +{ + return ScanError_Base(path, systemError); +} + +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); + +HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st) +{ + if (NeedPercents()) + { + _percent.ClosePrint(true); + _percent.ClearCurState(); + } + if (PrintHeaders && _so) + { + Print_DirItemsStat(_s, st); + *_so << _s << endl << endl; + } + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */) +{ + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::SetTotal(UInt64 size) +{ + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + if (completeValue && NeedPercents()) + { + _percent.Completed = *completeValue; + _percent.Print(); + } + return CheckBreak2(); +} + +static void AddMinuses(AString &s, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + s += '-'; +} + +static void AddSpaces_if_Positive(AString &s, int num) +{ + for (int i = 0; i < num; i++) + s.Add_Space(); +} + +static void SetSpacesAndNul(char *s, unsigned num) +{ + for (unsigned i = 0; i < num; i++) + s[i] = ' '; + s[num] = 0; +} + +static const unsigned kSizeField_Len = 13; +static const unsigned kNameField_Len = 12; + +static const unsigned kHashColumnWidth_Min = 4 * 2; + +static unsigned GetColumnWidth(unsigned digestSize) +{ + unsigned width = digestSize * 2; + return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width; +} + +void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector &hashers) +{ + _s.Empty(); + + for (unsigned i = 0; i < hashers.Size(); i++) + { + if (i != 0) + _s.Add_Space(); + const CHasherState &h = hashers[i]; + AddMinuses(_s, GetColumnWidth(h.DigestSize)); + } + + if (PrintSize) + { + _s.Add_Space(); + AddMinuses(_s, kSizeField_Len); + } + + if (PrintName) + { + AddSpacesBeforeName(); + AddMinuses(_s, kNameField_Len); + } + + *_so << _s << endl; +} + +HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb) +{ + if (PrintHeaders && _so) + { + _s.Empty(); + ClosePercents_for_so(); + + FOR_VECTOR (i, hb.Hashers) + { + if (i != 0) + _s.Add_Space(); + const CHasherState &h = hb.Hashers[i]; + _s += h.Name; + AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len()); + } + + if (PrintSize) + { + _s.Add_Space(); + const AString s2 ("Size"); + AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len()); + _s += s2; + } + + if (PrintName) + { + AddSpacesBeforeName(); + _s += "Name"; + } + + *_so << _s << endl; + PrintSeparatorLine(hb.Hashers); + } + + return CheckBreak2(); +} + +HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError) +{ + return OpenFileError_Base(path, systemError); +} + +HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */) +{ + _fileName = name; + + if (NeedPercents()) + { + if (PrintNameInPercents) + { + _percent.FileName.Empty(); + if (name) + _percent.FileName = name; + } + _percent.Print(); + } + return CheckBreak2(); +} + +void CHashCallbackConsole::PrintResultLine(UInt64 fileSize, + const CObjectVector &hashers, unsigned digestIndex, bool showHash) +{ + ClosePercents_for_so(); + + _s.Empty(); + + FOR_VECTOR (i, hashers) + { + const CHasherState &h = hashers[i]; + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + s[0] = 0; + if (showHash) + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + const unsigned pos = (unsigned)strlen(s); + SetSpacesAndNul(s + pos, GetColumnWidth(h.DigestSize) - pos); + if (i != 0) + _s.Add_Space(); + _s += s; + } + + if (PrintSize) + { + _s.Add_Space(); + + char s[kSizeField_Len + 32]; + char *p = s; + + SetSpacesAndNul(s, kSizeField_Len); + if (showHash) + { + p = s + kSizeField_Len; + ConvertUInt64ToString(fileSize, p); + int numSpaces = (int)kSizeField_Len - (int)strlen(p); + if (numSpaces > 0) + p -= (unsigned)numSpaces; + } + + _s += p; + } + + if (PrintName) + AddSpacesBeforeName(); + + *_so << _s; +} + +HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) +{ + if (_so) + { + PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash); + if (PrintName) + { + if (_fileName.IsEmpty()) + *_so << kEmptyFileAlias; + else + _so->NormalizePrint_UString(_fileName); + } + *_so << endl; + } + + if (NeedPercents()) + { + _percent.Files++; + _percent.Print(); + } + + return CheckBreak2(); +} + +static const char * const k_DigestTitles[] = +{ + " : " + , " for data: " + , " for data and names: " + , " for streams and names: " +}; + +static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex) +{ + so << h.Name; + + { + AString temp; + AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len()); + so << temp; + } + + so << k_DigestTitles[digestIndex]; + + char s[k_HashCalc_DigestSize_Max * 2 + 64]; + s[0] = 0; + AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize); + so << s << endl; +} + +void PrintHashStat(CStdOutStream &so, const CHashBundle &hb) +{ + FOR_VECTOR (i, hb.Hashers) + { + const CHasherState &h = hb.Hashers[i]; + PrintSum(so, h, k_HashCalc_Index_DataSum); + if (hb.NumFiles != 1 || hb.NumDirs != 0) + PrintSum(so, h, k_HashCalc_Index_NamesSum); + if (hb.NumAltStreams != 0) + PrintSum(so, h, k_HashCalc_Index_StreamsSum); + so << endl; + } +} + +void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value) +{ + char s[32]; + s[0] = ':'; + s[1] = ' '; + ConvertUInt64ToString(value, s + 2); + *_so << name << s << endl; +} + +HRESULT CHashCallbackConsole::AfterLastFile(CHashBundle &hb) +{ + ClosePercents2(); + + if (PrintHeaders && _so) + { + PrintSeparatorLine(hb.Hashers); + + PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true); + + *_so << endl << endl; + + if (hb.NumFiles != 1 || hb.NumDirs != 0) + { + if (hb.NumDirs != 0) + PrintProperty("Folders", hb.NumDirs); + PrintProperty("Files", hb.NumFiles); + } + + PrintProperty("Size", hb.FilesSize); + + if (hb.NumAltStreams != 0) + { + PrintProperty("Alternate streams", hb.NumAltStreams); + PrintProperty("Alternate streams size", hb.AltStreamsSize); + } + + *_so << endl; + PrintHashStat(*_so, hb); + } + + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.h new file mode 100644 index 0000000..0731bd1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/HashCon.h @@ -0,0 +1,48 @@ +// HashCon.h + +#ifndef __HASH_CON_H +#define __HASH_CON_H + +#include "../Common/HashCalc.h" + +#include "UpdateCallbackConsole.h" + +class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase +{ + UString _fileName; + AString _s; + + void AddSpacesBeforeName() + { + _s.Add_Space(); + _s.Add_Space(); + } + + void PrintSeparatorLine(const CObjectVector &hashers); + void PrintResultLine(UInt64 fileSize, + const CObjectVector &hashers, unsigned digestIndex, bool showHash); + void PrintProperty(const char *name, UInt64 value); + +public: + bool PrintNameInPercents; + + bool PrintHeaders; + + bool PrintSize; + bool PrintName; + + CHashCallbackConsole(): + PrintNameInPercents(true), + PrintHeaders(false), + PrintSize(true), + PrintName(true) + {} + + virtual ~CHashCallbackConsole() {} + + INTERFACE_IHashCallbackUI(;) +}; + +void PrintHashStat(CStdOutStream &so, const CHashBundle &hb); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.cpp new file mode 100644 index 0000000..d6cb982 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.cpp @@ -0,0 +1,1361 @@ +// List.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/StdOutStream.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/UTFConvert.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../Common/OpenArchive.h" +#include "../Common/PropIDUtils.h" + +#include "ConsoleClose.h" +#include "List.h" +#include "OpenCallbackConsole.h" + +using namespace NWindows; +using namespace NCOM; + +extern CStdOutStream *g_StdStream; +extern CStdOutStream *g_ErrStream; + +static const char * const kPropIdToName[] = +{ + "0" + , "1" + , "2" + , "Path" + , "Name" + , "Extension" + , "Folder" + , "Size" + , "Packed Size" + , "Attributes" + , "Created" + , "Accessed" + , "Modified" + , "Solid" + , "Commented" + , "Encrypted" + , "Split Before" + , "Split After" + , "Dictionary Size" + , "CRC" + , "Type" + , "Anti" + , "Method" + , "Host OS" + , "File System" + , "User" + , "Group" + , "Block" + , "Comment" + , "Position" + , "Path Prefix" + , "Folders" + , "Files" + , "Version" + , "Volume" + , "Multivolume" + , "Offset" + , "Links" + , "Blocks" + , "Volumes" + , "Time Type" + , "64-bit" + , "Big-endian" + , "CPU" + , "Physical Size" + , "Headers Size" + , "Checksum" + , "Characteristics" + , "Virtual Address" + , "ID" + , "Short Name" + , "Creator Application" + , "Sector Size" + , "Mode" + , "Symbolic Link" + , "Error" + , "Total Size" + , "Free Space" + , "Cluster Size" + , "Label" + , "Local Name" + , "Provider" + , "NT Security" + , "Alternate Stream" + , "Aux" + , "Deleted" + , "Tree" + , "SHA-1" + , "SHA-256" + , "Error Type" + , "Errors" + , "Errors" + , "Warnings" + , "Warning" + , "Streams" + , "Alternate Streams" + , "Alternate Streams Size" + , "Virtual Size" + , "Unpack Size" + , "Total Physical Size" + , "Volume Index" + , "SubType" + , "Short Comment" + , "Code Page" + , "Is not archive type" + , "Physical Size can't be detected" + , "Zeros Tail Is Allowed" + , "Tail Size" + , "Embedded Stub Size" + , "Link" + , "Hard Link" + , "iNode" + , "Stream ID" + , "Read-only" + , "Out Name" + , "Copy Link" +}; + +static const char kEmptyAttribChar = '.'; + +static const char * const kListing = "Listing archive: "; + +static const char * const kString_Files = "files"; +static const char * const kString_Dirs = "folders"; +static const char * const kString_AltStreams = "alternate streams"; +static const char * const kString_Streams = "streams"; + +static const char * const kError = "ERROR: "; + +static void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s) +{ + if (isDir) + wa |= FILE_ATTRIBUTE_DIRECTORY; + if (allAttribs) + { + ConvertWinAttribToString(s, wa); + return; + } + s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar; + s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; + s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; + s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; + s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; + s[5] = 0; +} + +enum EAdjustment +{ + kLeft, + kCenter, + kRight +}; + +struct CFieldInfo +{ + PROPID PropID; + bool IsRawProp; + UString NameU; + AString NameA; + EAdjustment TitleAdjustment; + EAdjustment TextAdjustment; + unsigned PrefixSpacesWidth; + unsigned Width; +}; + +struct CFieldInfoInit +{ + PROPID PropID; + const char *Name; + EAdjustment TitleAdjustment; + EAdjustment TextAdjustment; + unsigned PrefixSpacesWidth; + unsigned Width; +}; + +static const CFieldInfoInit kStandardFieldTable[] = +{ + { kpidMTime, " Date Time", kLeft, kLeft, 0, 19 }, + { kpidAttrib, "Attr", kRight, kCenter, 1, 5 }, + { kpidSize, "Size", kRight, kRight, 1, 12 }, + { kpidPackSize, "Compressed", kRight, kRight, 1, 12 }, + { kpidPath, "Name", kLeft, kLeft, 2, 24 } +}; + +const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width +static const char *g_Spaces = +" " ; + +static void PrintSpaces(unsigned numSpaces) +{ + if (numSpaces > 0 && numSpaces <= kNumSpacesMax) + g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces); +} + +static void PrintSpacesToString(char *dest, unsigned numSpaces) +{ + unsigned i; + for (i = 0; i < numSpaces; i++) + dest[i] = ' '; + dest[i] = 0; +} + +// extern int g_CodePage; + +static void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp) +{ + /* + // we don't need multibyte align. + int codePage = g_CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(s, temp); + else + UnicodeStringToMultiByte2(temp, s, (UINT)codePage); + */ + + unsigned numSpaces = 0; + + if (width > s.Len()) + { + numSpaces = width - s.Len(); + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpaces(numLeftSpaces); + numSpaces -= numLeftSpaces; + } + + g_StdOut.PrintUString(s, temp); + PrintSpaces(numSpaces); +} + +static void PrintString(EAdjustment adj, unsigned width, const char *s) +{ + unsigned numSpaces = 0; + unsigned len = (unsigned)strlen(s); + + if (width > len) + { + numSpaces = width - len; + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpaces(numLeftSpaces); + numSpaces -= numLeftSpaces; + } + + g_StdOut << s; + PrintSpaces(numSpaces); +} + +static void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString) +{ + unsigned numSpaces = 0; + unsigned len = (unsigned)strlen(textString); + + if (width > len) + { + numSpaces = width - len; + unsigned numLeftSpaces = 0; + switch (adj) + { + case kLeft: numLeftSpaces = 0; break; + case kCenter: numLeftSpaces = numSpaces / 2; break; + case kRight: numLeftSpaces = numSpaces; break; + } + PrintSpacesToString(dest, numLeftSpaces); + dest += numLeftSpaces; + numSpaces -= numLeftSpaces; + } + + memcpy(dest, textString, len); + dest += len; + PrintSpacesToString(dest, numSpaces); +} + +struct CListUInt64Def +{ + UInt64 Val; + bool Def; + + CListUInt64Def(): Val(0), Def(false) {} + void Add(UInt64 v) { Val += v; Def = true; } + void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); } +}; + +struct CListFileTimeDef +{ + FILETIME Val; + bool Def; + + CListFileTimeDef(): Def(false) { Val.dwLowDateTime = 0; Val.dwHighDateTime = 0; } + void Update(const CListFileTimeDef &t) + { + if (t.Def && (!Def || CompareFileTime(&Val, &t.Val) < 0)) + { + Val = t.Val; + Def = true; + } + } +}; + +struct CListStat +{ + CListUInt64Def Size; + CListUInt64Def PackSize; + CListFileTimeDef MTime; + UInt64 NumFiles; + + CListStat(): NumFiles(0) {} + void Update(const CListStat &st) + { + Size.Add(st.Size); + PackSize.Add(st.PackSize); + MTime.Update(st.MTime); + NumFiles += st.NumFiles; + } + void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; } +}; + +struct CListStat2 +{ + CListStat MainFiles; + CListStat AltStreams; + UInt64 NumDirs; + + CListStat2(): NumDirs(0) {} + + void Update(const CListStat2 &st) + { + MainFiles.Update(st.MainFiles); + AltStreams.Update(st.AltStreams); + NumDirs += st.NumDirs; + } + UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; } + CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; } +}; + +class CFieldPrinter +{ + CObjectVector _fields; + + void AddProp(const wchar_t *name, PROPID propID, bool isRawProp); +public: + const CArc *Arc; + bool TechMode; + UString FilePath; + AString TempAString; + UString TempWString; + bool IsDir; + + AString LinesString; + + void Clear() { _fields.Clear(); LinesString.Empty(); } + void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems); + + HRESULT AddMainProps(IInArchive *archive); + HRESULT AddRawProps(IArchiveGetRawProps *getRawProps); + + void PrintTitle(); + void PrintTitleLines(); + HRESULT PrintItemInfo(UInt32 index, const CListStat &st); + void PrintSum(const CListStat &st, UInt64 numDirs, const char *str); + void PrintSum(const CListStat2 &stat2); +}; + +void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems) +{ + Clear(); + for (unsigned i = 0; i < numItems; i++) + { + CFieldInfo &f = _fields.AddNew(); + const CFieldInfoInit &fii = standardFieldTable[i]; + f.PropID = fii.PropID; + f.IsRawProp = false; + f.NameA = fii.Name; + f.TitleAdjustment = fii.TitleAdjustment; + f.TextAdjustment = fii.TextAdjustment; + f.PrefixSpacesWidth = fii.PrefixSpacesWidth; + f.Width = fii.Width; + + unsigned k; + for (k = 0; k < fii.PrefixSpacesWidth; k++) + LinesString.Add_Space(); + for (k = 0; k < fii.Width; k++) + LinesString += '-'; + } +} + +static void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU) +{ + if (propID < ARRAY_SIZE(kPropIdToName)) + { + nameA = kPropIdToName[propID]; + return; + } + if (name) + nameU = name; + else + { + nameA.Empty(); + nameA.Add_UInt32(propID); + } +} + +void CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp) +{ + CFieldInfo f; + f.PropID = propID; + f.IsRawProp = isRawProp; + GetPropName(propID, name, f.NameA, f.NameU); + f.NameU += " = "; + if (!f.NameA.IsEmpty()) + f.NameA += " = "; + else + { + const UString &s = f.NameU; + AString sA; + unsigned i; + for (i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (c >= 0x80) + break; + sA += (char)c; + } + if (i == s.Len()) + f.NameA = sA; + } + _fields.Add(f); +} + +HRESULT CFieldPrinter::AddMainProps(IInArchive *archive) +{ + UInt32 numProps; + RINOK(archive->GetNumberOfProperties(&numProps)); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); + AddProp(name, propID, false); + } + return S_OK; +} + +HRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps) +{ + UInt32 numProps; + RINOK(getRawProps->GetNumRawProps(&numProps)); + for (UInt32 i = 0; i < numProps; i++) + { + CMyComBSTR name; + PROPID propID; + RINOK(getRawProps->GetRawPropInfo(i, &name, &propID)); + AddProp(name, propID, true); + } + return S_OK; +} + +void CFieldPrinter::PrintTitle() +{ + FOR_VECTOR (i, _fields) + { + const CFieldInfo &f = _fields[i]; + PrintSpaces(f.PrefixSpacesWidth); + PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA); + } +} + +void CFieldPrinter::PrintTitleLines() +{ + g_StdOut << LinesString; +} + +static void PrintTime(char *dest, const FILETIME *ft) +{ + *dest = 0; + if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0) + return; + ConvertUtcFileTimeToString(*ft, dest, kTimestampPrintLevel_SEC); +} + +#ifndef _SFX + +static inline char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +static void HexToString(char *dest, const Byte *data, UInt32 size) +{ + for (UInt32 i = 0; i < size; i++) + { + Byte b = data[i]; + dest[0] = GetHex((Byte)((b >> 4) & 0xF)); + dest[1] = GetHex((Byte)(b & 0xF)); + dest += 2; + } + *dest = 0; +} + +#endif + +#define MY_ENDL endl + +HRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st) +{ + char temp[128]; + size_t tempPos = 0; + + bool techMode = this->TechMode; + /* + if (techMode) + { + g_StdOut << "Index = "; + g_StdOut << (UInt64)index; + g_StdOut << endl; + } + */ + FOR_VECTOR (i, _fields) + { + const CFieldInfo &f = _fields[i]; + + if (!techMode) + { + PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth); + tempPos += f.PrefixSpacesWidth; + } + + if (techMode) + { + if (!f.NameA.IsEmpty()) + g_StdOut << f.NameA; + else + g_StdOut << f.NameU; + } + + if (f.PropID == kpidPath) + { + if (!techMode) + g_StdOut << temp; + g_StdOut.NormalizePrint_UString(FilePath, TempWString, TempAString); + if (techMode) + g_StdOut << MY_ENDL; + continue; + } + + const unsigned width = f.Width; + + if (f.IsRawProp) + { + #ifndef _SFX + + const void *data; + UInt32 dataSize; + UInt32 propType; + RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType)); + + if (dataSize != 0) + { + bool needPrint = true; + + if (f.PropID == kpidNtSecure) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + #ifndef _SFX + ConvertNtSecureToString((const Byte *)data, dataSize, TempAString); + g_StdOut << TempAString; + needPrint = false; + #endif + } + else if (f.PropID == kpidNtReparse) + { + UString s; + if (ConvertNtReparseToString((const Byte *)data, dataSize, s)) + { + needPrint = false; + g_StdOut.PrintUString(s, TempAString); + } + } + + if (needPrint) + { + if (propType != NPropDataType::kRaw) + return E_FAIL; + + const UInt32 kMaxDataSize = 64; + + if (dataSize > kMaxDataSize) + { + g_StdOut << "data:"; + g_StdOut << dataSize; + } + else + { + char hexStr[kMaxDataSize * 2 + 4]; + HexToString(hexStr, (const Byte *)data, dataSize); + g_StdOut << hexStr; + } + } + } + + #endif + } + else + { + CPropVariant prop; + switch (f.PropID) + { + case kpidSize: if (st.Size.Def) prop = st.Size.Val; break; + case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break; + case kpidMTime: if (st.MTime.Def) prop = st.MTime.Val; break; + default: + RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop)); + } + if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4)) + { + GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos); + if (techMode) + g_StdOut << temp + tempPos; + else + tempPos += strlen(temp + tempPos); + } + else if (prop.vt == VT_EMPTY) + { + if (!techMode) + { + PrintSpacesToString(temp + tempPos, width); + tempPos += width; + } + } + else if (prop.vt == VT_FILETIME) + { + PrintTime(temp + tempPos, &prop.filetime); + if (techMode) + g_StdOut << temp + tempPos; + else + { + size_t len = strlen(temp + tempPos); + tempPos += len; + if (len < (unsigned)f.Width) + { + len = f.Width - len; + PrintSpacesToString(temp + tempPos, (unsigned)len); + tempPos += len; + } + } + } + else if (prop.vt == VT_BSTR) + { + TempWString.SetFromBstr(prop.bstrVal); + // do we need multi-line support here ? + g_StdOut.Normalize_UString(TempWString); + if (techMode) + { + g_StdOut.PrintUString(TempWString, TempAString); + } + else + PrintUString(f.TextAdjustment, width, TempWString, TempAString); + } + else + { + char s[64]; + ConvertPropertyToShortString2(s, prop, f.PropID); + if (techMode) + g_StdOut << s; + else + { + PrintStringToString(temp + tempPos, f.TextAdjustment, width, s); + tempPos += strlen(temp + tempPos); + } + } + } + if (techMode) + g_StdOut << MY_ENDL; + } + g_StdOut << MY_ENDL; + return S_OK; +} + +static void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value) +{ + char s[32]; + s[0] = 0; + if (value.Def) + ConvertUInt64ToString(value.Val, s); + PrintString(adj, width, s); +} + +void Print_UInt64_and_String(AString &s, UInt64 val, const char *name); + +void CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str) +{ + FOR_VECTOR (i, _fields) + { + const CFieldInfo &f = _fields[i]; + PrintSpaces(f.PrefixSpacesWidth); + if (f.PropID == kpidSize) + PrintNumber(f.TextAdjustment, f.Width, st.Size); + else if (f.PropID == kpidPackSize) + PrintNumber(f.TextAdjustment, f.Width, st.PackSize); + else if (f.PropID == kpidMTime) + { + char s[64]; + s[0] = 0; + if (st.MTime.Def) + PrintTime(s, &st.MTime.Val); + PrintString(f.TextAdjustment, f.Width, s); + } + else if (f.PropID == kpidPath) + { + AString s; + Print_UInt64_and_String(s, st.NumFiles, str); + if (numDirs != 0) + { + s += ", "; + Print_UInt64_and_String(s, numDirs, kString_Dirs); + } + PrintString(f.TextAdjustment, 0, s); + } + else + PrintString(f.TextAdjustment, f.Width, ""); + } + g_StdOut << endl; +} + +void CFieldPrinter::PrintSum(const CListStat2 &stat2) +{ + PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files); + if (stat2.AltStreams.NumFiles != 0) + { + PrintSum(stat2.AltStreams, 0, kString_AltStreams); + CListStat st = stat2.MainFiles; + st.Update(stat2.AltStreams); + PrintSum(st, 0, kString_Streams); + } +} + +static HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value) +{ + value.Val = 0; + value.Def = false; + CPropVariant prop; + RINOK(archive->GetProperty(index, propID, &prop)); + value.Def = ConvertPropVariantToUInt64(prop, value.Val); + return S_OK; +} + +static HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t) +{ + t.Val.dwLowDateTime = 0; + t.Val.dwHighDateTime = 0; + t.Def = false; + CPropVariant prop; + RINOK(archive->GetProperty(index, kpidMTime, &prop)); + if (prop.vt == VT_FILETIME) + { + t.Val = prop.filetime; + t.Def = true; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +static void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val) +{ + so << name << ": " << val << endl; +} + +static void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID) +{ + const char *s; + char temp[16]; + if (propID < ARRAY_SIZE(kPropIdToName)) + s = kPropIdToName[propID]; + else + { + ConvertUInt32ToString(propID, temp); + s = temp; + } + so << s << " = "; +} + +static void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val) +{ + PrintPropName_and_Eq(so, propID); + so << val << endl; +} + +static void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val) +{ + PrintPropName_and_Eq(so, propID); + so << val << endl; +} + + +static void UString_Replace_CRLF_to_LF(UString &s) +{ + // s.Replace(L"\r\n", L"\n"); + wchar_t *src = s.GetBuf(); + wchar_t *dest = src; + for (;;) + { + wchar_t c = *src++; + if (c == 0) + break; + if (c == '\r' && *src == '\n') + { + src++; + c = '\n'; + } + *dest++ = c; + } + s.ReleaseBuf_SetEnd((unsigned)(dest - s.GetBuf())); +} + + +static void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val) +{ + UString s = val; + if (s.Find(L'\n') >= 0) + { + so << endl; + so << "{"; + so << endl; + UString_Replace_CRLF_to_LF(s); + so.Normalize_UString__LF_Allowed(s); + so << s; + so << endl; + so << "}"; + } + else + { + so.Normalize_UString(s); + so << s; + } + so << endl; +} + + +static void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine) +{ + so << name << " = "; + if (multiLine) + { + PrintPropVal_MultiLine(so, val); + return; + } + UString s = val; + so.Normalize_UString(s); + so << s; + so << endl; +} + + +static void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop) +{ + UString s; + ConvertPropertyToString2(s, prop, propID); + if (!s.IsEmpty()) + { + AString nameA; + UString nameU; + GetPropName(propID, name, nameA, nameU); + if (!nameA.IsEmpty()) + so << nameA; + else + so << nameU; + so << " = "; + PrintPropVal_MultiLine(so, s); + } +} + +static HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name) +{ + CPropVariant prop; + RINOK(archive->GetArchiveProperty(propID, &prop)); + PrintPropertyPair2(so, propID, name, prop); + return S_OK; +} + +static void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning) +{ + so << "Open " << (isWarning ? "WARNING" : "ERROR") + << ": Cannot open the file as [" + << type + << "] archive" + << endl; +} + +int Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name); + +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); + +static void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er) +{ + PrintErrorFlags(so, "ERRORS:", er.GetErrorFlags()); + if (!er.ErrorMessage.IsEmpty()) + PrintPropPair(so, "ERROR", er.ErrorMessage, true); + + PrintErrorFlags(so, "WARNINGS:", er.GetWarningFlags()); + if (!er.WarningMessage.IsEmpty()) + PrintPropPair(so, "WARNING", er.WarningMessage, true); +} + +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) +{ + FOR_VECTOR (r, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[r]; + const CArcErrorInfo &er = arc.ErrorInfo; + + so << "--\n"; + PrintPropPair(so, "Path", arc.Path, false); + if (er.ErrorFormatIndex >= 0) + { + if (er.ErrorFormatIndex == arc.FormatIndex) + so << "Warning: The archive is open with offset" << endl; + else + PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true); + } + PrintPropPair(so, "Type", codecs->GetFormatNamePtr(arc.FormatIndex), false); + + ErrorInfo_Print(so, er); + + Int64 offset = arc.GetGlobalOffset(); + if (offset != 0) + PrintPropNameAndNumber_Signed(so, kpidOffset, offset); + IInArchive *archive = arc.Archive; + RINOK(PrintArcProp(so, archive, kpidPhySize, NULL)); + if (er.TailSize != 0) + PrintPropNameAndNumber(so, kpidTailSize, er.TailSize); + { + UInt32 numProps; + RINOK(archive->GetNumberOfArchiveProperties(&numProps)); + + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); + RINOK(PrintArcProp(so, archive, propID, name)); + } + } + + if (r != arcLink.Arcs.Size() - 1) + { + UInt32 numProps; + so << "----\n"; + if (archive->GetNumberOfProperties(&numProps) == S_OK) + { + UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex; + for (UInt32 j = 0; j < numProps; j++) + { + CMyComBSTR name; + PROPID propID; + VARTYPE vt; + RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); + CPropVariant prop; + RINOK(archive->GetProperty(mainIndex, propID, &prop)); + PrintPropertyPair2(so, propID, name, prop); + } + } + } + } + return S_OK; +} + +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink) +{ + #ifndef _NO_CRYPTO + if (arcLink.PasswordWasAsked) + so << "Cannot open encrypted archive. Wrong password?"; + else + #endif + { + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + so.NormalizePrint_UString(arcLink.NonOpen_ArcPath); + so << endl; + PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + } + else + so << "Cannot open the file as archive"; + } + + so << endl; + so << endl; + ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo); + + return S_OK; +} + +bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); + +HRESULT ListArchives(CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, + bool stdInMode, + UStringVector &arcPaths, UStringVector &arcPathsFull, + bool processAltStreams, bool showAltStreams, + const NWildcard::CCensorNode &wildcardCensor, + bool enableHeaders, bool techMode, + #ifndef _NO_CRYPTO + bool &passwordEnabled, UString &password, + #endif + #ifndef _SFX + const CObjectVector *props, + #endif + UInt64 &numErrors, + UInt64 &numWarnings) +{ + bool allFilesAreAllowed = wildcardCensor.AreAllAllowed(); + + numErrors = 0; + numWarnings = 0; + + CFieldPrinter fp; + if (!techMode) + fp.Init(kStandardFieldTable, ARRAY_SIZE(kStandardFieldTable)); + + CListStat2 stat2total; + + CBoolArr skipArcs(arcPaths.Size()); + unsigned arcIndex; + for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) + skipArcs[arcIndex] = false; + UInt64 numVolumes = 0; + UInt64 numArcs = 0; + UInt64 totalArcSizes = 0; + + HRESULT lastError = 0; + + for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++) + { + if (skipArcs[arcIndex]) + continue; + const UString &arcPath = arcPaths[arcIndex]; + UInt64 arcPackSize = 0; + + if (!stdInMode) + { + NFile::NFind::CFileInfo fi; + if (!fi.Find_FollowLink(us2fs(arcPath))) + { + DWORD errorCode = GetLastError(); + if (errorCode == 0) + errorCode = ERROR_FILE_NOT_FOUND; + lastError = HRESULT_FROM_WIN32(errorCode); + g_StdOut.Flush(); + if (g_ErrStream) + { + *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl; + g_ErrStream->NormalizePrint_UString(arcPath); + *g_ErrStream << endl << endl; + } + numErrors++; + continue; + } + if (fi.IsDir()) + { + g_StdOut.Flush(); + if (g_ErrStream) + { + *g_ErrStream << endl << kError; + g_ErrStream->NormalizePrint_UString(arcPath); + *g_ErrStream << " is not a file" << endl << endl; + } + numErrors++; + continue; + } + arcPackSize = fi.Size; + totalArcSizes += arcPackSize; + } + + CArchiveLink arcLink; + + COpenCallbackConsole openCallback; + openCallback.Init(&g_StdOut, g_ErrStream, NULL); + + #ifndef _NO_CRYPTO + + openCallback.PasswordIsDefined = passwordEnabled; + openCallback.Password = password; + + #endif + + /* + CObjectVector optPropsVector; + COptionalOpenProperties &optProps = optPropsVector.AddNew(); + optProps.Props = *props; + */ + + COpenOptions options; + #ifndef _SFX + options.props = props; + #endif + options.codecs = codecs; + options.types = &types; + options.excludedFormats = &excludedFormats; + options.stdInMode = stdInMode; + options.stream = NULL; + options.filePath = arcPath; + + if (enableHeaders) + { + g_StdOut << endl << kListing; + g_StdOut.NormalizePrint_UString(arcPath); + g_StdOut << endl << endl; + } + + HRESULT result = arcLink.Open_Strict(options, &openCallback); + + if (result != S_OK) + { + if (result == E_ABORT) + return result; + if (result != S_FALSE) + lastError = result; + g_StdOut.Flush(); + if (g_ErrStream) + { + *g_ErrStream << endl << kError; + g_ErrStream->NormalizePrint_UString(arcPath); + *g_ErrStream << " : "; + if (result == S_FALSE) + { + Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink); + } + else + { + *g_ErrStream << "opening : "; + if (result == E_OUTOFMEMORY) + *g_ErrStream << "Can't allocate required memory"; + else + *g_ErrStream << NError::MyFormatMessage(result); + } + *g_ErrStream << endl; + } + numErrors++; + continue; + } + + { + FOR_VECTOR (r, arcLink.Arcs) + { + const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo; + if (!arc.WarningMessage.IsEmpty()) + numWarnings++; + if (arc.AreThereWarnings()) + numWarnings++; + if (arc.ErrorFormatIndex >= 0) + numWarnings++; + if (arc.AreThereErrors()) + { + numErrors++; + // break; + } + if (!arc.ErrorMessage.IsEmpty()) + numErrors++; + } + } + + numArcs++; + numVolumes++; + + if (!stdInMode) + { + numVolumes += arcLink.VolumePaths.Size(); + totalArcSizes += arcLink.VolumesSize; + FOR_VECTOR (v, arcLink.VolumePaths) + { + int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]); + if (index >= 0 && (unsigned)index > arcIndex) + skipArcs[(unsigned)index] = true; + } + } + + + if (enableHeaders) + { + RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink)); + + g_StdOut << endl; + if (techMode) + g_StdOut << "----------\n"; + } + + if (enableHeaders && !techMode) + { + fp.PrintTitle(); + g_StdOut << endl; + fp.PrintTitleLines(); + g_StdOut << endl; + } + + const CArc &arc = arcLink.Arcs.Back(); + fp.Arc = &arc; + fp.TechMode = techMode; + IInArchive *archive = arc.Archive; + if (techMode) + { + fp.Clear(); + RINOK(fp.AddMainProps(archive)); + if (arc.GetRawProps) + { + RINOK(fp.AddRawProps(arc.GetRawProps)); + } + } + + CListStat2 stat2; + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + CReadArcItem item; + UStringVector pathParts; + + for (UInt32 i = 0; i < numItems; i++) + { + if (NConsoleClose::TestBreakSignal()) + return E_ABORT; + + HRESULT res = arc.GetItemPath2(i, fp.FilePath); + + if (stdInMode && res == E_INVALIDARG) + break; + RINOK(res); + + if (arc.Ask_Aux) + { + bool isAux; + RINOK(Archive_IsItem_Aux(archive, i, isAux)); + if (isAux) + continue; + } + + bool isAltStream = false; + if (arc.Ask_AltStream) + { + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (isAltStream && !processAltStreams) + continue; + } + + RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir)); + + if (!allFilesAreAllowed) + { + if (isAltStream) + { + RINOK(arc.GetItem(i, item)); + if (!CensorNode_CheckPath(wildcardCensor, item)) + continue; + } + else + { + SplitPathToParts(fp.FilePath, pathParts); + bool include; + if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include)) + continue; + if (!include) + continue; + } + } + + CListStat st; + + RINOK(GetUInt64Value(archive, i, kpidSize, st.Size)); + RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize)); + RINOK(GetItemMTime(archive, i, st.MTime)); + + if (fp.IsDir) + stat2.NumDirs++; + else + st.NumFiles = 1; + stat2.GetStat(isAltStream).Update(st); + + if (isAltStream && !showAltStreams) + continue; + RINOK(fp.PrintItemInfo(i, st)); + } + + UInt64 numStreams = stat2.GetNumStreams(); + if (!stdInMode + && !stat2.MainFiles.PackSize.Def + && !stat2.AltStreams.PackSize.Def) + { + if (arcLink.VolumePaths.Size() != 0) + arcPackSize += arcLink.VolumesSize; + stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize); + } + + stat2.MainFiles.SetSizeDefIfNoFiles(); + stat2.AltStreams.SetSizeDefIfNoFiles(); + + if (enableHeaders && !techMode) + { + fp.PrintTitleLines(); + g_StdOut << endl; + fp.PrintSum(stat2); + } + + if (enableHeaders) + { + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + g_StdOut << "----------\n"; + PrintPropPair(g_StdOut, "Path", arcLink.NonOpen_ArcPath, false); + PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false); + } + } + + stat2total.Update(stat2); + + g_StdOut.Flush(); + } + + if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1)) + { + g_StdOut << endl; + fp.PrintTitleLines(); + g_StdOut << endl; + fp.PrintSum(stat2total); + g_StdOut << endl; + PrintPropNameAndNumber(g_StdOut, "Archives", numArcs); + PrintPropNameAndNumber(g_StdOut, "Volumes", numVolumes); + PrintPropNameAndNumber(g_StdOut, "Total archives size", totalArcSizes); + } + + if (numErrors == 1 && lastError != 0) + return lastError; + + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.h new file mode 100644 index 0000000..462c471 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/List.h @@ -0,0 +1,27 @@ +// List.h + +#ifndef __LIST_H +#define __LIST_H + +#include "../../../Common/Wildcard.h" + +#include "../Common/LoadCodecs.h" + +HRESULT ListArchives(CCodecs *codecs, + const CObjectVector &types, + const CIntVector &excludedFormats, + bool stdInMode, + UStringVector &archivePaths, UStringVector &archivePathsFull, + bool processAltStreams, bool showAltStreams, + const NWildcard::CCensorNode &wildcardCensor, + bool enableHeaders, bool techMode, + #ifndef _NO_CRYPTO + bool &passwordEnabled, UString &password, + #endif + #ifndef _SFX + const CObjectVector *props, + #endif + UInt64 &errors, + UInt64 &numWarnings); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Main.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Main.cpp new file mode 100644 index 0000000..e7d9fd1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/Main.cpp @@ -0,0 +1,1457 @@ +// Main.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyWindows.h" + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#endif + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/MyInitGuid.h" + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/MyException.h" +#include "../../../Common/StdInStream.h" +#include "../../../Common/StdOutStream.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" +#include "../../../Common/UTFConvert.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/TimeUtils.h" + +#include "../Common/ArchiveCommandLine.h" +#include "../Common/Bench.h" +#include "../Common/ExitCode.h" +#include "../Common/Extract.h" + +#ifdef EXTERNAL_CODECS +#include "../Common/LoadCodecs.h" +#endif + +#include "../../Common/RegisterCodec.h" + +#include "BenchCon.h" +#include "ConsoleClose.h" +#include "ExtractCallbackConsole.h" +#include "HashCon.h" +#include "List.h" +#include "OpenCallbackConsole.h" +#include "UpdateCallbackConsole.h" + +#ifdef PROG_VARIANT_R +#include "../../../../C/7zVersion.h" +#else +#include "../../MyVersion.h" +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NCommandLineParser; + +#ifdef _WIN32 +HINSTANCE g_hInstance = 0; +#endif + +extern CStdOutStream *g_StdStream; +extern CStdOutStream *g_ErrStream; + +extern unsigned g_NumCodecs; +extern const CCodecInfo *g_Codecs[]; + +extern unsigned g_NumHashers; +extern const CHasherInfo *g_Hashers[]; + + +#if defined(PROG_VARIANT_Z) + #define PROG_POSTFIX "z" + #define PROG_POSTFIX_2 " (z)" +#elif defined(PROG_VARIANT_R) + #define PROG_POSTFIX "r" + #define PROG_POSTFIX_2 " (r)" +#elif !defined(EXTERNAL_CODECS) + #define PROG_POSTFIX "a" + #define PROG_POSTFIX_2 " (a)" +#else + #define PROG_POSTFIX "" + #define PROG_POSTFIX_2 "" +#endif + + +static const char * const kCopyrightString = "\n7-Zip" + PROG_POSTFIX_2 + " " MY_VERSION_CPU + " : " MY_COPYRIGHT_DATE "\n"; + +static const char * const kHelpString = + "Usage: 7z" + PROG_POSTFIX + " [...] [...] [@listfile]\n" + "\n" + "\n" + " a : Add files to archive\n" + " b : Benchmark\n" + " d : Delete files from archive\n" + " e : Extract files from archive (without using directory names)\n" + " h : Calculate hash values for files\n" + " i : Show information about supported formats\n" + " l : List contents of archive\n" + " rn : Rename files in archive\n" + " t : Test integrity of archive\n" + " u : Update files to archive\n" + " x : eXtract files with full paths\n" + "\n" + "\n" + " -- : Stop switches and @listfile parsing\n" + " -ai[r[-|0]]{@listfile|!wildcard} : Include archives\n" + " -ax[r[-|0]]{@listfile|!wildcard} : eXclude archives\n" + " -ao{a|s|t|u} : set Overwrite mode\n" + " -an : disable archive_name field\n" + " -bb[0-3] : set output log level\n" + " -bd : disable progress indicator\n" + " -bs{o|e|p}{0|1|2} : set output stream for output/error/progress line\n" + " -bt : show execution time statistics\n" + " -i[r[-|0]]{@listfile|!wildcard} : Include filenames\n" + " -m{Parameters} : set compression Method\n" + " -mmt[N] : set number of CPU threads\n" + " -mx[N] : set compression level: -mx1 (fastest) ... -mx9 (ultra)\n" + " -o{Directory} : set Output directory\n" + #ifndef _NO_CRYPTO + " -p{Password} : set Password\n" + #endif + " -r[-|0] : Recurse subdirectories for name search\n" + " -sa{a|e|s} : set Archive name mode\n" + " -scc{UTF-8|WIN|DOS} : set charset for for console input/output\n" + " -scs{UTF-8|UTF-16LE|UTF-16BE|WIN|DOS|{id}} : set charset for list files\n" + " -scrc[CRC32|CRC64|SHA1|SHA256|*] : set hash function for x, e, h commands\n" + " -sdel : delete files after compression\n" + " -seml[.] : send archive by email\n" + " -sfx[{name}] : Create SFX archive\n" + " -si[{name}] : read data from stdin\n" + " -slp : set Large Pages mode\n" + " -slt : show technical information for l (List) command\n" + " -snh : store hard links as links\n" + " -snl : store symbolic links as links\n" + " -sni : store NT security information\n" + " -sns[-] : store NTFS alternate streams\n" + " -so : write data to stdout\n" + " -spd : disable wildcard matching for file names\n" + " -spe : eliminate duplication of root folder for extract command\n" + " -spf : use fully qualified file paths\n" + " -ssc[-] : set sensitive case mode\n" + " -sse : stop archive creating, if it can't open some input file\n" + " -ssp : do not change Last Access Time of source files while archiving\n" + " -ssw : compress shared files\n" + " -stl : set archive timestamp from the most recently modified file\n" + " -stm{HexMask} : set CPU thread affinity mask (hexadecimal number)\n" + " -stx{Type} : exclude archive type\n" + " -t{Type} : Set type of archive\n" + " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName] : Update options\n" + " -v{Size}[b|k|m|g] : Create volumes\n" + " -w[{path}] : assign Work directory. Empty path means a temporary directory\n" + " -x[r[-|0]]{@listfile|!wildcard} : eXclude filenames\n" + " -y : assume Yes on all queries\n"; + +// --------------------------- +// exception messages + +static const char * const kEverythingIsOk = "Everything is Ok"; +static const char * const kUserErrorMessage = "Incorrect command line"; +static const char * const kNoFormats = "7-Zip cannot find the code that works with archives."; +static const char * const kUnsupportedArcTypeMessage = "Unsupported archive type"; +// static const char * const kUnsupportedUpdateArcType = "Can't create archive for that type"; + +#define kDefaultSfxModule "7zCon.sfx" + +MY_ATTR_NORETURN +static void ShowMessageAndThrowException(LPCSTR message, NExitCode::EEnum code) +{ + if (g_ErrStream) + *g_ErrStream << endl << "ERROR: " << message << endl; + throw code; +} + + +#ifdef _WIN32 +#define ShowProgInfo(so) +#else +static void ShowProgInfo(CStdOutStream *so) +{ + if (!so) + return; + + *so + + /* + #ifdef __DATE__ + << " " << __DATE__ + #endif + #ifdef __TIME__ + << " " << __TIME__ + #endif + */ + + << " " << (unsigned)(sizeof(void *)) * 8 << "-bit" + + #ifdef __ILP32__ + << " ILP32" + #endif + + #ifdef __ARM_ARCH + << " arm_v:" << __ARM_ARCH + #ifdef __ARM_ARCH_ISA_THUMB + << " thumb:" << __ARM_ARCH_ISA_THUMB + #endif + #endif + ; + + + + #ifdef ENV_HAVE_LOCALE + *so << " locale=" << GetLocale(); + #endif + #ifndef _WIN32 + { + const bool is_IsNativeUTF8 = IsNativeUTF8(); + if (!is_IsNativeUTF8) + *so << " UTF8=" << (is_IsNativeUTF8 ? "+" : "-"); + } + if (!g_ForceToUTF8) + *so << " use-UTF8=" << (g_ForceToUTF8 ? "+" : "-"); + { + const unsigned wchar_t_size = (unsigned)sizeof(wchar_t); + if (wchar_t_size != 4) + *so << " wchar_t=" << wchar_t_size * 8 << "-bit"; + } + { + const unsigned off_t_size = (unsigned)sizeof(off_t); + if (off_t_size != 8) + *so << " Files=" << off_t_size * 8 << "-bit"; + } + #endif + + { + const UInt32 numCpus = NWindows::NSystem::GetNumberOfProcessors(); + *so << " Threads:" << numCpus; + } + + #ifdef _7ZIP_ASM + *so << ", ASM"; + #endif + + /* + { + AString s; + GetCpuName(s); + s.Trim(); + *so << ", " << s; + } + + #ifdef __ARM_FEATURE_CRC32 + << " CRC32" + #endif + + + #if (defined MY_CPU_X86_OR_AMD64 || defined(MY_CPU_ARM_OR_ARM64)) + if (CPU_IsSupported_AES()) *so << ",AES"; + #endif + + #ifdef MY_CPU_ARM_OR_ARM64 + if (CPU_IsSupported_CRC32()) *so << ",CRC32"; + #if defined(_WIN32) + if (CPU_IsSupported_CRYPTO()) *so << ",CRYPTO"; + #else + if (CPU_IsSupported_SHA1()) *so << ",SHA1"; + if (CPU_IsSupported_SHA2()) *so << ",SHA2"; + #endif + #endif + */ + + *so << endl; +} +#endif + +static void ShowCopyrightAndHelp(CStdOutStream *so, bool needHelp) +{ + if (!so) + return; + *so << kCopyrightString; + // *so << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << endl; + ShowProgInfo(so); + *so << endl; + if (needHelp) + *so << kHelpString; +} + + +static void PrintStringRight(CStdOutStream &so, const char *s, unsigned size) +{ + unsigned len = MyStringLen(s); + for (unsigned i = len; i < size; i++) + so << ' '; + so << s; +} + +static void PrintUInt32(CStdOutStream &so, UInt32 val, unsigned size) +{ + char s[16]; + ConvertUInt32ToString(val, s); + PrintStringRight(so, s, size); +} + +static void PrintLibIndex(CStdOutStream &so, int libIndex) +{ + if (libIndex >= 0) + PrintUInt32(so, (UInt32)libIndex, 2); + else + so << " "; + so << ' '; +} + +static void PrintString(CStdOutStream &so, const UString &s, unsigned size) +{ + unsigned len = s.Len(); + so << s; + for (unsigned i = len; i < size; i++) + so << ' '; +} + +static inline char GetHex(unsigned val) +{ + return (char)((val < 10) ? ('0' + val) : ('A' + (val - 10))); +} + +static void PrintWarningsPaths(const CErrorPathCodes &pc, CStdOutStream &so) +{ + FOR_VECTOR(i, pc.Paths) + { + so.NormalizePrint_UString(fs2us(pc.Paths[i])); + so << " : "; + so << NError::MyFormatMessage(pc.Codes[i]) << endl; + } + so << "----------------" << endl; +} + +static int WarningsCheck(HRESULT result, const CCallbackConsoleBase &callback, + const CUpdateErrorInfo &errorInfo, + CStdOutStream *so, + CStdOutStream *se, + bool showHeaders) +{ + int exitCode = NExitCode::kSuccess; + + if (callback.ScanErrors.Paths.Size() != 0) + { + if (se) + { + *se << endl; + *se << "Scan WARNINGS for files and folders:" << endl << endl; + PrintWarningsPaths(callback.ScanErrors, *se); + *se << "Scan WARNINGS: " << callback.ScanErrors.Paths.Size(); + *se << endl; + } + exitCode = NExitCode::kWarning; + } + + if (result != S_OK || errorInfo.ThereIsError()) + { + if (se) + { + UString message; + if (!errorInfo.Message.IsEmpty()) + { + message += errorInfo.Message.Ptr(); + message.Add_LF(); + } + { + FOR_VECTOR(i, errorInfo.FileNames) + { + message += fs2us(errorInfo.FileNames[i]); + message.Add_LF(); + } + } + if (errorInfo.SystemError != 0) + { + message += NError::MyFormatMessage(errorInfo.SystemError); + message.Add_LF(); + } + if (!message.IsEmpty()) + *se << L"\nError:\n" << message; + } + + // we will work with (result) later + // throw CSystemException(result); + return NExitCode::kFatalError; + } + + unsigned numErrors = callback.FailedFiles.Paths.Size(); + if (numErrors == 0) + { + if (showHeaders) + if (callback.ScanErrors.Paths.Size() == 0) + if (so) + { + if (se) + se->Flush(); + *so << kEverythingIsOk << endl; + } + } + else + { + if (se) + { + *se << endl; + *se << "WARNINGS for files:" << endl << endl; + PrintWarningsPaths(callback.FailedFiles, *se); + *se << "WARNING: Cannot open " << numErrors << " file"; + if (numErrors > 1) + *se << 's'; + *se << endl; + } + exitCode = NExitCode::kWarning; + } + + return exitCode; +} + +static void ThrowException_if_Error(HRESULT res) +{ + if (res != S_OK) + throw CSystemException(res); +} + +static void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') +{ + char temp[64]; + char *p = temp + 32; + ConvertUInt64ToString(val, p); + unsigned len = MyStringLen(p); + for (; len < numDigits; len++) + *--p = c; + *g_StdStream << p; +} + +#ifdef _WIN32 + +static void PrintTime(const char *s, UInt64 val, UInt64 total) +{ + *g_StdStream << endl << s << " Time ="; + const UInt32 kFreq = 10000000; + UInt64 sec = val / kFreq; + PrintNum(sec, 6); + *g_StdStream << '.'; + UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); + PrintNum(ms, 3, '0'); + + while (val > ((UInt64)1 << 56)) + { + val >>= 1; + total >>= 1; + } + + UInt64 percent = 0; + if (total != 0) + percent = val * 100 / total; + *g_StdStream << " ="; + PrintNum(percent, 5); + *g_StdStream << '%'; +} + +#ifndef UNDER_CE + +#define SHIFT_SIZE_VALUE(x, num) (((x) + (1 << (num)) - 1) >> (num)) + +static void PrintMemUsage(const char *s, UInt64 val) +{ + *g_StdStream << " " << s << " Memory ="; + PrintNum(SHIFT_SIZE_VALUE(val, 20), 7); + *g_StdStream << " MB"; + + #ifdef _7ZIP_LARGE_PAGES + AString lp; + Add_LargePages_String(lp); + if (!lp.IsEmpty()) + *g_StdStream << lp; + #endif +} + +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_GetProcessMemoryInfo)(HANDLE Process, + PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); +typedef BOOL (WINAPI *Func_QueryProcessCycleTime)(HANDLE Process, PULONG64 CycleTime); +EXTERN_C_END + +#endif + +static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } + +static void PrintStat() +{ + FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; + if (! + #ifdef UNDER_CE + ::GetThreadTimes(::GetCurrentThread() + #else + // NT 3.5 + ::GetProcessTimes(::GetCurrentProcess() + #endif + , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT)) + return; + FILETIME curTimeFT; + NTime::GetCurUtcFileTime(curTimeFT); + + #ifndef UNDER_CE + + PROCESS_MEMORY_COUNTERS m; + memset(&m, 0, sizeof(m)); + BOOL memDefined = FALSE; + BOOL cycleDefined = FALSE; + ULONG64 cycleTime = 0; + { + /* NT 4.0: GetProcessMemoryInfo() in Psapi.dll + Win7: new function K32GetProcessMemoryInfo() in kernel32.dll + It's faster to call kernel32.dll code than Psapi.dll code + GetProcessMemoryInfo() requires Psapi.lib + Psapi.lib in SDK7+ can link to K32GetProcessMemoryInfo in kernel32.dll + The program with K32GetProcessMemoryInfo will not work on systems before Win7 + // memDefined = GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + */ + + HMODULE kern = ::GetModuleHandleW(L"kernel32.dll"); + Func_GetProcessMemoryInfo my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo) + (void *)::GetProcAddress(kern, "K32GetProcessMemoryInfo"); + if (!my_GetProcessMemoryInfo) + { + HMODULE lib = LoadLibraryW(L"Psapi.dll"); + if (lib) + my_GetProcessMemoryInfo = (Func_GetProcessMemoryInfo)(void *)::GetProcAddress(lib, "GetProcessMemoryInfo"); + } + if (my_GetProcessMemoryInfo) + memDefined = my_GetProcessMemoryInfo(GetCurrentProcess(), &m, sizeof(m)); + // FreeLibrary(lib); + + Func_QueryProcessCycleTime my_QueryProcessCycleTime = (Func_QueryProcessCycleTime) + (void *)::GetProcAddress(kern, "QueryProcessCycleTime"); + if (my_QueryProcessCycleTime) + cycleDefined = my_QueryProcessCycleTime(GetCurrentProcess(), &cycleTime); + } + + #endif + + UInt64 curTime = GetTime64(curTimeFT); + UInt64 creationTime = GetTime64(creationTimeFT); + UInt64 kernelTime = GetTime64(kernelTimeFT); + UInt64 userTime = GetTime64(userTimeFT); + + UInt64 totalTime = curTime - creationTime; + + PrintTime("Kernel ", kernelTime, totalTime); + + const UInt64 processTime = kernelTime + userTime; + + #ifndef UNDER_CE + if (cycleDefined) + { + *g_StdStream << " Cnt:"; + PrintNum(cycleTime / 1000000, 15); + *g_StdStream << " MCycles"; + } + #endif + + PrintTime("User ", userTime, totalTime); + + #ifndef UNDER_CE + if (cycleDefined) + { + *g_StdStream << " Freq (cnt/ptime):"; + UInt64 us = processTime / 10; + if (us == 0) + us = 1; + PrintNum(cycleTime / us, 6); + *g_StdStream << " MHz"; + } + #endif + + PrintTime("Process", processTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Virtual ", m.PeakPagefileUsage); + #endif + + PrintTime("Global ", totalTime, totalTime); + #ifndef UNDER_CE + if (memDefined) PrintMemUsage("Physical", m.PeakWorkingSetSize); + #endif +} + + +#else // ! _WIN32 + +static UInt64 Get_timeofday_us() +{ + struct timeval now; + if (gettimeofday(&now, 0 ) == 0) + return (UInt64)now.tv_sec * 1000000 + (UInt64)now.tv_usec; + return 0; +} + +static void PrintTime(const char *s, UInt64 val, UInt64 total_us, UInt64 kFreq) +{ + *g_StdStream << endl << s << " Time ="; + + { + UInt64 sec, ms; + + if (kFreq == 0) + { + sec = val / 1000000; + ms = val % 1000000 / 1000; + } + else + { + sec = val / kFreq; + ms = (UInt32)((val - (sec * kFreq)) * 1000 / kFreq); + } + + PrintNum(sec, 6); + *g_StdStream << '.'; + PrintNum(ms, 3, '0'); + } + + if (total_us == 0) + return; + + UInt64 percent = 0; + if (kFreq == 0) + percent = val * 100 / total_us; + else + { + const UInt64 kMaxVal = (UInt64)(Int64)-1; + UInt32 m = 100000000; + for (;;) + { + if (m == 0 || kFreq == 0) + break; + if (kMaxVal / m > val && + kMaxVal / kFreq > total_us) + break; + if (val > m) + val >>= 1; + else + m >>= 1; + if (kFreq > total_us) + kFreq >>= 1; + else + total_us >>= 1; + } + const UInt64 total = kFreq * total_us; + if (total != 0) + percent = val * m / total; + } + *g_StdStream << " ="; + PrintNum(percent, 5); + *g_StdStream << '%'; +} + +static void PrintStat(UInt64 startTime) +{ + tms t; + /* clock_t res = */ times(&t); + const UInt64 totalTime = Get_timeofday_us() - startTime; + const UInt64 kFreq = (UInt64)sysconf(_SC_CLK_TCK); + PrintTime("Kernel ", (UInt64)t.tms_stime, totalTime, kFreq); + PrintTime("User ", (UInt64)t.tms_utime, totalTime, kFreq); + PrintTime("Process", (UInt64)t.tms_utime + (UInt64)t.tms_stime, totalTime, kFreq); + PrintTime("Global ", totalTime, totalTime, 0); + *g_StdStream << endl; +} + +#endif // ! _WIN32 + + + + + +static void PrintHexId(CStdOutStream &so, UInt64 id) +{ + char s[32]; + ConvertUInt64ToHex(id, s); + PrintStringRight(so, s, 8); +} + +#ifndef _WIN32 +void Set_ModuleDirPrefix_From_ProgArg0(const char *s); +#endif + +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +); +int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +) +{ + #if defined(MY_CPU_SIZEOF_POINTER) + { unsigned k = sizeof(void *); if (k != MY_CPU_SIZEOF_POINTER) throw "incorrect MY_CPU_PTR_SIZE"; } + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + SetFileApisToOEM(); + #endif + + #ifdef ENV_HAVE_LOCALE + // printf("\nBefore SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); + MY_SetLocale(); + // printf("\nAfter SetLocale() : %s\n", IsNativeUtf8() ? "NATIVE UTF-8" : "IS NOT NATIVE UTF-8"); + #endif + + #ifndef _WIN32 + UInt64 startTime = Get_timeofday_us(); + #endif + + UStringVector commandStrings; + + #ifdef _WIN32 + NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); + #else + { + if (numArgs > 0) + Set_ModuleDirPrefix_From_ProgArg0(args[0]); + + for (int i = 0; i < numArgs; i++) + { + AString a (args[i]); + /* + printf("\n%d %s :", i, a.Ptr()); + for (unsigned k = 0; k < a.Len(); k++) + printf(" %2x", (unsigned)(Byte)a[k]); + */ + const UString s = MultiByteToUnicodeString(a); + commandStrings.Add(s); + } + // printf("\n"); + } + + #endif + + #ifndef UNDER_CE + if (commandStrings.Size() > 0) + commandStrings.Delete(0); + #endif + + if (commandStrings.Size() == 0) + { + ShowCopyrightAndHelp(g_StdStream, true); + return 0; + } + + CArcCmdLineOptions options; + + CArcCmdLineParser parser; + + parser.Parse1(commandStrings, options); + + g_StdOut.IsTerminalMode = options.IsStdOutTerminal; + g_StdErr.IsTerminalMode = options.IsStdErrTerminal; + + if (options.Number_for_Out != k_OutStream_stdout) + g_StdStream = (options.Number_for_Out == k_OutStream_stderr ? &g_StdErr : NULL); + + if (options.Number_for_Errors != k_OutStream_stderr) + g_ErrStream = (options.Number_for_Errors == k_OutStream_stdout ? &g_StdOut : NULL); + + CStdOutStream *percentsStream = NULL; + if (options.Number_for_Percents != k_OutStream_disabled) + percentsStream = (options.Number_for_Percents == k_OutStream_stderr) ? &g_StdErr : &g_StdOut;; + + if (options.HelpMode) + { + ShowCopyrightAndHelp(g_StdStream, true); + return 0; + } + + if (options.EnableHeaders) + { + ShowCopyrightAndHelp(g_StdStream, false); + if (!parser.Parse1Log.IsEmpty()) + *g_StdStream << parser.Parse1Log; + } + + parser.Parse2(options); + + { + int cp = options.ConsoleCodePage; + + int stdout_cp = cp; + int stderr_cp = cp; + int stdin_cp = cp; + + /* + // these cases are complicated. + // maybe we must use CRT functions instead of console WIN32. + // different Windows/CRT versions also can work different ways. + // so the following code was not enabled: + if (cp == -1) + { + // we set CodePage only if stream is attached to terminal + // maybe we should set CodePage even if is not terminal? + #ifdef _WIN32 + { + UINT ccp = GetConsoleOutputCP(); + if (ccp != 0) + { + if (options.IsStdOutTerminal) stdout_cp = ccp; + if (options.IsStdErrTerminal) stderr_cp = ccp; + } + } + if (options.IsInTerminal) + { + UINT ccp = GetConsoleCP(); + if (ccp != 0) stdin_cp = ccp; + } + #endif + } + */ + + if (stdout_cp != -1) g_StdOut.CodePage = stdout_cp; + if (stderr_cp != -1) g_StdErr.CodePage = stderr_cp; + if (stdin_cp != -1) g_StdIn.CodePage = stdin_cp; + } + + unsigned percentsNameLevel = 1; + if (options.LogLevel == 0 || options.Number_for_Percents != options.Number_for_Out) + percentsNameLevel = 2; + + unsigned consoleWidth = 80; + + if (percentsStream) + { + #ifdef _WIN32 + + #if !defined(UNDER_CE) + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo)) + consoleWidth = (unsigned)consoleInfo.dwSize.X; + #endif + + #else + + struct winsize w; + if (ioctl(0, TIOCGWINSZ, &w) == 0) + consoleWidth = w.ws_col; + + #endif + } + + CREATE_CODECS_OBJECT + + codecs->CaseSensitiveChange = options.CaseSensitiveChange; + codecs->CaseSensitive = options.CaseSensitive; + ThrowException_if_Error(codecs->Load()); + + #ifdef EXTERNAL_CODECS + { + UString s; + codecs->GetCodecsErrorMessage(s); + if (!s.IsEmpty()) + { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); + so << endl << s << endl; + } + } + #endif + + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + + if (codecs->Formats.Size() == 0 && + (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kList + || options.Command.IsFromUpdateGroup())) + { + #ifdef EXTERNAL_CODECS + if (!codecs->MainDll_ErrorPath.IsEmpty()) + { + UString s ("Can't load module: "); + s += fs2us(codecs->MainDll_ErrorPath); + throw s; + } + #endif + + throw kNoFormats; + } + + CObjectVector types; + if (!ParseOpenTypes(*codecs, options.ArcType, types)) + throw kUnsupportedArcTypeMessage; + + CIntVector excludedFormats; + FOR_VECTOR (k, options.ExcludedArcTypes) + { + CIntVector tempIndices; + if (!codecs->FindFormatForArchiveType(options.ExcludedArcTypes[k], tempIndices) + || tempIndices.Size() != 1) + throw kUnsupportedArcTypeMessage; + excludedFormats.AddToUniqueSorted(tempIndices[0]); + // excludedFormats.Sort(); + } + + + #ifdef EXTERNAL_CODECS + if (isExtractGroupCommand + || options.Command.CommandType == NCommandType::kHash + || options.Command.CommandType == NCommandType::kBenchmark) + ThrowException_if_Error(__externalCodecs.Load()); + #endif + + int retCode = NExitCode::kSuccess; + HRESULT hresultMain = S_OK; + + // bool showStat = options.ShowTime; + + /* + if (!options.EnableHeaders || + options.TechMode) + showStat = false; + */ + + + if (options.Command.CommandType == NCommandType::kInfo) + { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); + unsigned i; + + #ifdef EXTERNAL_CODECS + so << endl << "Libs:" << endl; + for (i = 0; i < codecs->Libs.Size(); i++) + { + PrintLibIndex(so, (int)i); + so << ' ' << codecs->Libs[i].Path << endl; + } + #endif + + so << endl << "Formats:" << endl; + + const char * const kArcFlags = "KSNFMGOPBELHX"; + const unsigned kNumArcFlags = (unsigned)strlen(kArcFlags); + + for (i = 0; i < codecs->Formats.Size(); i++) + { + const CArcInfoEx &arc = codecs->Formats[i]; + + #ifdef EXTERNAL_CODECS + PrintLibIndex(so, arc.LibIndex); + #else + so << " "; + #endif + + so << (char)(arc.UpdateEnabled ? 'C' : ' '); + + for (unsigned b = 0; b < kNumArcFlags; b++) + { + so << (char) + ((arc.Flags & ((UInt32)1 << b)) != 0 ? kArcFlags[b] : ' '); + } + + so << ' '; + PrintString(so, arc.Name, 8); + so << ' '; + UString s; + + FOR_VECTOR (t, arc.Exts) + { + if (t != 0) + s.Add_Space(); + const CArcExtInfo &ext = arc.Exts[t]; + s += ext.Ext; + if (!ext.AddExt.IsEmpty()) + { + s += " ("; + s += ext.AddExt; + s += ')'; + } + } + + PrintString(so, s, 13); + so << ' '; + + if (arc.SignatureOffset != 0) + so << "offset=" << arc.SignatureOffset << ' '; + + FOR_VECTOR(si, arc.Signatures) + { + if (si != 0) + so << " || "; + + const CByteBuffer &sig = arc.Signatures[si]; + + for (size_t j = 0; j < sig.Size(); j++) + { + if (j != 0) + so << ' '; + Byte b = sig[j]; + if (b > 0x20 && b < 0x80) + { + so << (char)b; + } + else + { + so << GetHex((b >> 4) & 0xF); + so << GetHex(b & 0xF); + } + } + } + so << endl; + } + + so << endl << "Codecs:" << endl; // << "Lib ID Name" << endl; + + for (i = 0; i < g_NumCodecs; i++) + { + const CCodecInfo &cod = *g_Codecs[i]; + + PrintLibIndex(so, -1); + + if (cod.NumStreams == 1) + so << ' '; + else + so << cod.NumStreams; + + so << (char)(cod.CreateEncoder ? 'E' : ' '); + so << (char)(cod.CreateDecoder ? 'D' : ' '); + + so << ' '; + PrintHexId(so, cod.Id); + so << ' ' << cod.Name << endl; + } + + + #ifdef EXTERNAL_CODECS + + UInt32 numMethods; + if (codecs->GetNumMethods(&numMethods) == S_OK) + for (UInt32 j = 0; j < numMethods; j++) + { + PrintLibIndex(so, codecs->GetCodec_LibIndex(j)); + + UInt32 numStreams = codecs->GetCodec_NumStreams(j); + if (numStreams == 1) + so << ' '; + else + so << numStreams; + + so << (char)(codecs->GetCodec_EncoderIsAssigned(j) ? 'E' : ' '); + so << (char)(codecs->GetCodec_DecoderIsAssigned(j) ? 'D' : ' '); + + so << ' '; + UInt64 id; + HRESULT res = codecs->GetCodec_Id(j, id); + if (res != S_OK) + id = (UInt64)(Int64)-1; + PrintHexId(so, id); + so << ' ' << codecs->GetCodec_Name(j) << endl; + } + + #endif + + + so << endl << "Hashers:" << endl; // << " L Size ID Name" << endl; + + for (i = 0; i < g_NumHashers; i++) + { + const CHasherInfo &codec = *g_Hashers[i]; + PrintLibIndex(so, -1); + PrintUInt32(so, codec.DigestSize, 4); + so << ' '; + PrintHexId(so, codec.Id); + so << ' ' << codec.Name << endl; + } + + #ifdef EXTERNAL_CODECS + + numMethods = codecs->GetNumHashers(); + for (UInt32 j = 0; j < numMethods; j++) + { + PrintLibIndex(so, codecs->GetHasherLibIndex(j)); + PrintUInt32(so, codecs->GetHasherDigestSize(j), 4); + so << ' '; + PrintHexId(so, codecs->GetHasherId(j)); + so << ' ' << codecs->GetHasherName(j) << endl; + } + + #endif + + } + else if (options.Command.CommandType == NCommandType::kBenchmark) + { + CStdOutStream &so = (g_StdStream ? *g_StdStream : g_StdOut); + hresultMain = BenchCon(EXTERNAL_CODECS_VARS_L + options.Properties, options.NumIterations, (FILE *)so); + if (hresultMain == S_FALSE) + { + so << endl; + if (g_ErrStream) + *g_ErrStream << "\nDecoding ERROR\n"; + retCode = NExitCode::kFatalError; + hresultMain = S_OK; + } + } + else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) + { + UStringVector ArchivePathsSorted; + UStringVector ArchivePathsFullSorted; + + if (options.StdInMode) + { + ArchivePathsSorted.Add(options.ArcName_for_StdInMode); + ArchivePathsFullSorted.Add(options.ArcName_for_StdInMode); + } + else + { + CExtractScanConsole scan; + + scan.Init(options.EnableHeaders ? g_StdStream : NULL, g_ErrStream, percentsStream); + scan.SetWindowWidth(consoleWidth); + + if (g_StdStream && options.EnableHeaders) + *g_StdStream << "Scanning the drive for archives:" << endl; + + CDirItemsStat st; + + scan.StartScanning(); + + hresultMain = EnumerateDirItemsAndSort( + options.arcCensor, + NWildcard::k_RelatPath, + UString(), // addPathPrefix + ArchivePathsSorted, + ArchivePathsFullSorted, + st, + &scan); + + scan.CloseScanning(); + + if (hresultMain == S_OK) + { + if (options.EnableHeaders) + scan.PrintStat(st); + } + else + { + /* + if (res != E_ABORT) + { + throw CSystemException(res); + // errorInfo.Message = "Scanning error"; + } + return res; + */ + } + } + + if (hresultMain == S_OK) { + if (isExtractGroupCommand) + { + CExtractCallbackConsole *ecs = new CExtractCallbackConsole; + CMyComPtr extractCallback = ecs; + + #ifndef _NO_CRYPTO + ecs->PasswordIsDefined = options.PasswordEnabled; + ecs->Password = options.Password; + #endif + + ecs->Init(g_StdStream, g_ErrStream, percentsStream); + ecs->MultiArcMode = (ArchivePathsSorted.Size() > 1); + + ecs->LogLevel = options.LogLevel; + ecs->PercentsNameLevel = percentsNameLevel; + + if (percentsStream) + ecs->SetWindowWidth(consoleWidth); + + /* + COpenCallbackConsole openCallback; + openCallback.Init(g_StdStream, g_ErrStream); + + #ifndef _NO_CRYPTO + openCallback.PasswordIsDefined = options.PasswordEnabled; + openCallback.Password = options.Password; + #endif + */ + + CExtractOptions eo; + (CExtractOptionsBase &)eo = options.ExtractOptions; + + eo.StdInMode = options.StdInMode; + eo.StdOutMode = options.StdOutMode; + eo.YesToAll = options.YesToAll; + eo.TestMode = options.Command.IsTestCommand(); + + #ifndef _SFX + eo.Properties = options.Properties; + #endif + + UString errorMessage; + CDecompressStat stat; + CHashBundle hb; + IHashCalc *hashCalc = NULL; + + if (!options.HashMethods.IsEmpty()) + { + hashCalc = &hb; + ThrowException_if_Error(hb.SetMethods(EXTERNAL_CODECS_VARS_L options.HashMethods)); + // hb.Init(); + } + + hresultMain = Extract( + codecs, + types, + excludedFormats, + ArchivePathsSorted, + ArchivePathsFullSorted, + options.Censor.Pairs.Front().Head, + eo, ecs, ecs, hashCalc, errorMessage, stat); + + ecs->ClosePercents(); + + if (!errorMessage.IsEmpty()) + { + if (g_ErrStream) + *g_ErrStream << endl << "ERROR:" << endl << errorMessage << endl; + if (hresultMain == S_OK) + hresultMain = E_FAIL; + } + + CStdOutStream *so = g_StdStream; + + bool isError = false; + + if (so) + { + *so << endl; + + if (ecs->NumTryArcs > 1) + { + *so << "Archives: " << ecs->NumTryArcs << endl; + *so << "OK archives: " << ecs->NumOkArcs << endl; + } + } + + if (ecs->NumCantOpenArcs != 0) + { + isError = true; + if (so) + *so << "Can't open as archive: " << ecs->NumCantOpenArcs << endl; + } + + if (ecs->NumArcsWithError != 0) + { + isError = true; + if (so) + *so << "Archives with Errors: " << ecs->NumArcsWithError << endl; + } + + if (so) + { + if (ecs->NumArcsWithWarnings != 0) + *so << "Archives with Warnings: " << ecs->NumArcsWithWarnings << endl; + + if (ecs->NumOpenArcWarnings != 0) + { + *so << endl; + if (ecs->NumOpenArcWarnings != 0) + *so << "Warnings: " << ecs->NumOpenArcWarnings << endl; + } + } + + if (ecs->NumOpenArcErrors != 0) + { + isError = true; + if (so) + { + *so << endl; + if (ecs->NumOpenArcErrors != 0) + *so << "Open Errors: " << ecs->NumOpenArcErrors << endl; + } + } + + if (isError) + retCode = NExitCode::kFatalError; + + if (so) { + if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) + { + // if (ecs->NumArchives > 1) + { + *so << endl; + if (ecs->NumFileErrors != 0) + *so << "Sub items Errors: " << ecs->NumFileErrors << endl; + } + } + else if (hresultMain == S_OK) + { + if (stat.NumFolders != 0) + *so << "Folders: " << stat.NumFolders << endl; + if (stat.NumFiles != 1 || stat.NumFolders != 0 || stat.NumAltStreams != 0) + *so << "Files: " << stat.NumFiles << endl; + if (stat.NumAltStreams != 0) + { + *so << "Alternate Streams: " << stat.NumAltStreams << endl; + *so << "Alternate Streams Size: " << stat.AltStreams_UnpackSize << endl; + } + + *so + << "Size: " << stat.UnpackSize << endl + << "Compressed: " << stat.PackSize << endl; + if (hashCalc) + { + *so << endl; + PrintHashStat(*so, hb); + } + } + } // if (so) + } + else // if_(!isExtractGroupCommand) + { + UInt64 numErrors = 0; + UInt64 numWarnings = 0; + + // options.ExtractNtOptions.StoreAltStreams = true, if -sns[-] is not definmed + + hresultMain = ListArchives( + codecs, + types, + excludedFormats, + options.StdInMode, + ArchivePathsSorted, + ArchivePathsFullSorted, + options.ExtractOptions.NtOptions.AltStreams.Val, + options.AltStreams.Val, // we don't want to show AltStreams by default + options.Censor.Pairs.Front().Head, + options.EnableHeaders, + options.TechMode, + #ifndef _NO_CRYPTO + options.PasswordEnabled, + options.Password, + #endif + &options.Properties, + numErrors, numWarnings); + + if (options.EnableHeaders) + if (numWarnings > 0) + g_StdOut << endl << "Warnings: " << numWarnings << endl; + + if (numErrors > 0) + { + if (options.EnableHeaders) + g_StdOut << endl << "Errors: " << numErrors << endl; + retCode = NExitCode::kFatalError; + } + } // if_(isExtractGroupCommand) + } // if_(hresultMain == S_OK) + } + else if (options.Command.IsFromUpdateGroup()) + { + CUpdateOptions &uo = options.UpdateOptions; + if (uo.SfxMode && uo.SfxModule.IsEmpty()) + uo.SfxModule = kDefaultSfxModule; + + COpenCallbackConsole openCallback; + openCallback.Init(g_StdStream, g_ErrStream, percentsStream); + + #ifndef _NO_CRYPTO + bool passwordIsDefined = + (options.PasswordEnabled && !options.Password.IsEmpty()); + openCallback.PasswordIsDefined = passwordIsDefined; + openCallback.Password = options.Password; + #endif + + CUpdateCallbackConsole callback; + callback.LogLevel = options.LogLevel; + callback.PercentsNameLevel = percentsNameLevel; + + if (percentsStream) + callback.SetWindowWidth(consoleWidth); + + #ifndef _NO_CRYPTO + callback.PasswordIsDefined = passwordIsDefined; + callback.AskPassword = (options.PasswordEnabled && options.Password.IsEmpty()); + callback.Password = options.Password; + #endif + + callback.StdOutMode = uo.StdOutMode; + callback.Init( + // NULL, + g_StdStream, g_ErrStream, percentsStream); + + CUpdateErrorInfo errorInfo; + + /* + if (!uo.Init(codecs, types, options.ArchiveName)) + throw kUnsupportedUpdateArcType; + */ + hresultMain = UpdateArchive(codecs, + types, + options.ArchiveName, + options.Censor, + uo, + errorInfo, &openCallback, &callback, true); + + callback.ClosePercents2(); + + CStdOutStream *se = g_StdStream; + if (!se) + se = g_ErrStream; + + retCode = WarningsCheck(hresultMain, callback, errorInfo, + g_StdStream, se, + true // options.EnableHeaders + ); + } + else if (options.Command.CommandType == NCommandType::kHash) + { + const CHashOptions &uo = options.HashOptions; + + CHashCallbackConsole callback; + if (percentsStream) + callback.SetWindowWidth(consoleWidth); + + callback.Init(g_StdStream, g_ErrStream, percentsStream); + callback.PrintHeaders = options.EnableHeaders; + + AString errorInfoString; + hresultMain = HashCalc(EXTERNAL_CODECS_VARS_L + options.Censor, uo, + errorInfoString, &callback); + CUpdateErrorInfo errorInfo; + errorInfo.Message = errorInfoString; + CStdOutStream *se = g_StdStream; + if (!se) + se = g_ErrStream; + retCode = WarningsCheck(hresultMain, callback, errorInfo, g_StdStream, se, options.EnableHeaders); + } + else + ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError); + + if (options.ShowTime && g_StdStream) + PrintStat( + #ifndef _WIN32 + startTime + #endif + ); + + ThrowException_if_Error(hresultMain); + + return retCode; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/MainAr.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/MainAr.cpp new file mode 100644 index 0000000..0e45312 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/MainAr.cpp @@ -0,0 +1,181 @@ +// MainAr.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include "../../../../C/DllSecur.h" +#endif + +#include "../../../Common/MyException.h" +#include "../../../Common/StdOutStream.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/NtCheck.h" + +#include "../Common/ArchiveCommandLine.h" +#include "../Common/ExitCode.h" + +#include "ConsoleClose.h" + +using namespace NWindows; + +extern +CStdOutStream *g_StdStream; +CStdOutStream *g_StdStream = NULL; +extern +CStdOutStream *g_ErrStream; +CStdOutStream *g_ErrStream = NULL; + +extern int Main2( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +); + +static const char * const kException_CmdLine_Error_Message = "Command Line Error:"; +static const char * const kExceptionErrorMessage = "ERROR:"; +static const char * const kUserBreakMessage = "Break signaled"; +static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!"; +static const char * const kUnknownExceptionMessage = "Unknown Error"; +static const char * const kInternalExceptionMessage = "\n\nInternal Error #"; + +static void FlushStreams() +{ + if (g_StdStream) + g_StdStream->Flush(); +} + +static void PrintError(const char *message) +{ + FlushStreams(); + if (g_ErrStream) + *g_ErrStream << "\n\n" << message << endl; +} + +#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) +#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError; +#endif + +int MY_CDECL main +( + #ifndef _WIN32 + int numArgs, char *args[] + #endif +) +{ + g_ErrStream = &g_StdErr; + g_StdStream = &g_StdOut; + + NT_CHECK + + NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; + int res = 0; + + try + { + #ifdef _WIN32 + My_SetDefaultDllDirectories(); + #endif + + res = Main2( + #ifndef _WIN32 + numArgs, args + #endif + ); + } + catch(const CNewException &) + { + PrintError(kMemoryExceptionMessage); + return (NExitCode::kMemoryError); + } + catch(const NConsoleClose::CCtrlBreakException &) + { + PrintError(kUserBreakMessage); + return (NExitCode::kUserBreak); + } + catch(const CMessagePathException &e) + { + PrintError(kException_CmdLine_Error_Message); + if (g_ErrStream) + *g_ErrStream << e << endl; + return (NExitCode::kUserError); + } + catch(const CSystemException &systemError) + { + if (systemError.ErrorCode == E_OUTOFMEMORY) + { + PrintError(kMemoryExceptionMessage); + return (NExitCode::kMemoryError); + } + if (systemError.ErrorCode == E_ABORT) + { + PrintError(kUserBreakMessage); + return (NExitCode::kUserBreak); + } + if (g_ErrStream) + { + PrintError("System ERROR:"); + *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl; + } + return (NExitCode::kFatalError); + } + catch(NExitCode::EEnum &exitCode) + { + FlushStreams(); + if (g_ErrStream) + *g_ErrStream << kInternalExceptionMessage << exitCode << endl; + return (exitCode); + } + catch(const UString &s) + { + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } + return (NExitCode::kFatalError); + } + catch(const AString &s) + { + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } + return (NExitCode::kFatalError); + } + catch(const char *s) + { + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } + return (NExitCode::kFatalError); + } + catch(const wchar_t *s) + { + if (g_ErrStream) + { + PrintError(kExceptionErrorMessage); + *g_ErrStream << s << endl; + } + return (NExitCode::kFatalError); + } + catch(int t) + { + if (g_ErrStream) + { + FlushStreams(); + *g_ErrStream << kInternalExceptionMessage << t << endl; + return (NExitCode::kFatalError); + } + } + catch(...) + { + PrintError(kUnknownExceptionMessage); + return (NExitCode::kFatalError); + } + + return res; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.cpp new file mode 100644 index 0000000..a074fa1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.cpp @@ -0,0 +1,115 @@ +// OpenCallbackConsole.cpp + +#include "StdAfx.h" + +#include "OpenCallbackConsole.h" + +#include "ConsoleClose.h" +#include "UserInputUtils.h" + +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT COpenCallbackConsole::Open_CheckBreak() +{ + return CheckBreak2(); +} + +HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes) +{ + if (!MultiArcMode && NeedPercents()) + { + if (files) + { + _totalFilesDefined = true; + // _totalFiles = *files; + _percent.Total = *files; + } + else + _totalFilesDefined = false; + + if (bytes) + { + // _totalBytesDefined = true; + _totalBytes = *bytes; + if (!files) + _percent.Total = *bytes; + } + else + { + // _totalBytesDefined = false; + if (!files) + _percent.Total = _totalBytes; + } + } + + return CheckBreak2(); +} + +HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) +{ + if (!MultiArcMode && NeedPercents()) + { + if (files) + { + _percent.Files = *files; + if (_totalFilesDefined) + _percent.Completed = *files; + } + + if (bytes) + { + if (!_totalFilesDefined) + _percent.Completed = *bytes; + } + _percent.Print(); + } + + return CheckBreak2(); +} + +HRESULT COpenCallbackConsole::Open_Finished() +{ + ClosePercents(); + return S_OK; +} + + +#ifndef _NO_CRYPTO + +HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) +{ + *password = NULL; + RINOK(CheckBreak2()); + + if (!PasswordIsDefined) + { + ClosePercents(); + RINOK(GetPassword_HRESULT(_so, Password)); + PasswordIsDefined = true; + } + return StringToBstr(Password, password); +} + +/* +HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) +{ + passwordIsDefined = PasswordIsDefined; + password = Password; + return S_OK; +} + +bool COpenCallbackConsole::Open_WasPasswordAsked() +{ + return PasswordWasAsked; +} + +void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag () +{ + PasswordWasAsked = false; +} +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.h new file mode 100644 index 0000000..075d374 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/OpenCallbackConsole.h @@ -0,0 +1,68 @@ +// OpenCallbackConsole.h + +#ifndef __OPEN_CALLBACK_CONSOLE_H +#define __OPEN_CALLBACK_CONSOLE_H + +#include "../../../Common/StdOutStream.h" + +#include "../Common/ArchiveOpenCallback.h" + +#include "PercentPrinter.h" + +class COpenCallbackConsole: public IOpenCallbackUI +{ +protected: + CPercentPrinter _percent; + + CStdOutStream *_so; + CStdOutStream *_se; + + bool _totalFilesDefined; + // bool _totalBytesDefined; + // UInt64 _totalFiles; + UInt64 _totalBytes; + + bool NeedPercents() const { return _percent._so != NULL; } + +public: + + bool MultiArcMode; + + void ClosePercents() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + COpenCallbackConsole(): + _totalFilesDefined(false), + // _totalBytesDefined(false), + _totalBytes(0), + MultiArcMode(false) + + #ifndef _NO_CRYPTO + , PasswordIsDefined(false) + // , PasswordWasAsked(false) + #endif + + {} + + virtual ~COpenCallbackConsole() {} + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + _so = outStream; + _se = errorStream; + _percent._so = percentStream; + } + + INTERFACE_IOpenCallbackUI(;) + + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + // bool PasswordWasAsked; + UString Password; + #endif +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.cpp new file mode 100644 index 0000000..4341fd9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.cpp @@ -0,0 +1,183 @@ +// PercentPrinter.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "PercentPrinter.h" + +static const unsigned kPercentsSize = 4; + +CPercentPrinter::~CPercentPrinter() +{ + ClosePrint(false); +} + +void CPercentPrinterState::ClearCurState() +{ + Completed = 0; + Total = ((UInt64)(Int64)-1); + Files = 0; + Command.Empty(); + FileName.Empty(); +} + +void CPercentPrinter::ClosePrint(bool needFlush) +{ + unsigned num = _printedString.Len(); + if (num != 0) + { + + unsigned i; + + /* '\r' in old MAC OS means "new line". + So we can't use '\r' in some systems */ + + #ifdef _WIN32 + char *start = _temp.GetBuf(num + 2); + char *p = start; + *p++ = '\r'; + for (i = 0; i < num; i++) *p++ = ' '; + *p++ = '\r'; + #else + char *start = _temp.GetBuf(num * 3); + char *p = start; + for (i = 0; i < num; i++) *p++ = '\b'; + for (i = 0; i < num; i++) *p++ = ' '; + for (i = 0; i < num; i++) *p++ = '\b'; + #endif + + *p = 0; + _temp.ReleaseBuf_SetLen((unsigned)(p - start)); + *_so << _temp; + } + if (needFlush) + _so->Flush(); + _printedString.Empty(); +} + +void CPercentPrinter::GetPercents() +{ + char s[32]; + unsigned size; + { + char c = '%'; + UInt64 val = 0; + if (Total == (UInt64)(Int64)-1) + { + val = Completed >> 20; + c = 'M'; + } + else if (Total != 0) + val = Completed * 100 / Total; + ConvertUInt64ToString(val, s); + size = (unsigned)strlen(s); + s[size++] = c; + s[size] = 0; + } + + while (size < kPercentsSize) + { + _s += ' '; + size++; + } + + _s += s; +} + +void CPercentPrinter::Print() +{ + DWORD tick = 0; + if (_tickStep != 0) + tick = GetTickCount(); + + bool onlyPercentsChanged = false; + + if (!_printedString.IsEmpty()) + { + if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep) + return; + + CPercentPrinterState &st = *this; + if (_printedState.Command == st.Command + && _printedState.FileName == st.FileName + && _printedState.Files == st.Files) + { + if (_printedState.Total == st.Total + && _printedState.Completed == st.Completed) + return; + onlyPercentsChanged = true; + } + } + + _s.Empty(); + + GetPercents(); + + if (onlyPercentsChanged && _s == _printedPercents) + return; + + _printedPercents = _s; + + if (Files != 0) + { + char s[32]; + ConvertUInt64ToString(Files, s); + // unsigned size = (unsigned)strlen(s); + // for (; size < 3; size++) _s += ' '; + _s += ' '; + _s += s; + // _s += "f"; + } + + + if (!Command.IsEmpty()) + { + _s += ' '; + _s += Command; + } + + if (!FileName.IsEmpty() && _s.Len() < MaxLen) + { + _s += ' '; + + _tempU = FileName; + _so->Normalize_UString(_tempU); + _so->Convert_UString_to_AString(_tempU, _temp); + if (_s.Len() + _temp.Len() > MaxLen) + { + unsigned len = FileName.Len(); + for (; len != 0;) + { + unsigned delta = len / 8; + if (delta == 0) + delta = 1; + len -= delta; + _tempU = FileName; + _tempU.Delete(len / 2, _tempU.Len() - len); + _tempU.Insert(len / 2, L" . "); + _so->Normalize_UString(_tempU); + _so->Convert_UString_to_AString(_tempU, _temp); + if (_s.Len() + _temp.Len() <= MaxLen) + break; + } + if (len == 0) + _temp.Empty(); + } + _s += _temp; + } + + if (_printedString != _s) + { + ClosePrint(false); + *_so << _s; + if (NeedFlush) + _so->Flush(); + _printedString = _s; + } + + _printedState = *this; + + if (_tickStep != 0) + _prevTick = tick; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.h new file mode 100644 index 0000000..95290b3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/PercentPrinter.h @@ -0,0 +1,62 @@ +// PercentPrinter.h + +#ifndef __PERCENT_PRINTER_H +#define __PERCENT_PRINTER_H + +#include "../../../Common/StdOutStream.h" + +struct CPercentPrinterState +{ + UInt64 Completed; + UInt64 Total; + + UInt64 Files; + + AString Command; + UString FileName; + + void ClearCurState(); + + CPercentPrinterState(): + Completed(0), + Total((UInt64)(Int64)-1), + Files(0) + {} +}; + +class CPercentPrinter: public CPercentPrinterState +{ + UInt32 _tickStep; + DWORD _prevTick; + + AString _s; + + AString _printedString; + AString _temp; + UString _tempU; + + CPercentPrinterState _printedState; + AString _printedPercents; + + void GetPercents(); + +public: + CStdOutStream *_so; + + bool NeedFlush; + unsigned MaxLen; + + CPercentPrinter(UInt32 tickStep = 200): + _tickStep(tickStep), + _prevTick(0), + NeedFlush(true), + MaxLen(80 - 1) + {} + + ~CPercentPrinter(); + + void ClosePrint(bool needFlush); + void Print(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.cpp new file mode 100644 index 0000000..d0feea8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.h new file mode 100644 index 0000000..2854ff3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp new file mode 100644 index 0000000..2405607 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp @@ -0,0 +1,709 @@ +// UpdateCallbackConsole.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "../../../Windows/ErrorMsg.h" + +#ifndef _7ZIP_ST +#include "../../../Windows/Synchronization.h" +#endif + +#include "ConsoleClose.h" +#include "UserInputUtils.h" +#include "UpdateCallbackConsole.h" + +using namespace NWindows; + +#ifndef _7ZIP_ST +static NSynchronization::CCriticalSection g_CriticalSection; +#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); +#else +#define MT_LOCK +#endif + +static const wchar_t * const kEmptyFileAlias = L"[Content]"; + +static const char * const kOpenArchiveMessage = "Open archive: "; +static const char * const kCreatingArchiveMessage = "Creating archive: "; +static const char * const kUpdatingArchiveMessage = "Updating archive: "; +static const char * const kScanningMessage = "Scanning the drive:"; + +static const char * const kError = "ERROR: "; +static const char * const kWarning = "WARNING: "; + +static HRESULT CheckBreak2() +{ + return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK; +} + +HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); +HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink); + +void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags); + +void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc); + +HRESULT CUpdateCallbackConsole::OpenResult( + const CCodecs *codecs, const CArchiveLink &arcLink, + const wchar_t *name, HRESULT result) +{ + ClosePercents2(); + + FOR_VECTOR (level, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; + + UInt32 errorFlags = er.GetErrorFlags(); + + if (errorFlags != 0 || !er.ErrorMessage.IsEmpty()) + { + if (_se) + { + *_se << endl; + if (level != 0) + *_se << arc.Path << endl; + } + + if (errorFlags != 0) + { + if (_se) + PrintErrorFlags(*_se, "ERRORS:", errorFlags); + } + + if (!er.ErrorMessage.IsEmpty()) + { + if (_se) + *_se << "ERRORS:" << endl << er.ErrorMessage << endl; + } + + if (_se) + { + *_se << endl; + _se->Flush(); + } + } + + UInt32 warningFlags = er.GetWarningFlags(); + + if (warningFlags != 0 || !er.WarningMessage.IsEmpty()) + { + if (_so) + { + *_so << endl; + if (level != 0) + *_so << arc.Path << endl; + } + + if (warningFlags != 0) + { + if (_so) + PrintErrorFlags(*_so, "WARNINGS:", warningFlags); + } + + if (!er.WarningMessage.IsEmpty()) + { + if (_so) + *_so << "WARNINGS:" << endl << er.WarningMessage << endl; + } + + if (_so) + { + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + } + + + if (er.ErrorFormatIndex >= 0) + { + if (_so) + { + Print_ErrorFormatIndex_Warning(_so, codecs, arc); + if (NeedFlush) + _so->Flush(); + } + } + } + + if (result == S_OK) + { + if (_so) + { + RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink)); + *_so << endl; + } + } + else + { + if (_so) + _so->Flush(); + if (_se) + { + *_se << kError; + _se->NormalizePrint_wstr(name); + *_se << endl; + HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink); + RINOK(res); + _se->Flush(); + } + } + + return S_OK; +} + +HRESULT CUpdateCallbackConsole::StartScanning() +{ + if (_so) + *_so << kScanningMessage << endl; + _percent.Command = "Scan "; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */) +{ + if (NeedPercents()) + { + _percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams; + _percent.Completed = st.GetTotalBytes(); + _percent.FileName = fs2us(path); + _percent.Print(); + } + + return CheckBreak(); +} + +void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning) +{ + ClosePercents2(); + + if (_se) + { + if (_so) + _so->Flush(); + + *_se << endl << (isWarning ? kWarning : kError) + << NError::MyFormatMessage(systemError) + << endl; + _se->NormalizePrint_UString(fs2us(path)); + *_se << endl << endl; + _se->Flush(); + } +} + + +HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + + ScanErrors.AddError(path, systemError); + CommonError(path, systemError, true); + + return S_OK; +} + +HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + FailedFiles.AddError(path, systemError); + NumNonOpenFiles++; + /* + if (systemError == ERROR_SHARING_VIOLATION) + { + */ + CommonError(path, systemError, true); + return S_FALSE; + /* + } + return systemError; + */ +} + +HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError) +{ + MT_LOCK + CommonError(path, systemError, false); + return HRESULT_FROM_WIN32(systemError); +} + +HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError) +{ + return ScanError_Base(path, systemError); +} + + +static void PrintPropPair(AString &s, const char *name, UInt64 val) +{ + char temp[32]; + ConvertUInt64ToString(val, temp); + s += name; + s += ": "; + s += temp; +} + +void PrintSize_bytes_Smart(AString &s, UInt64 val); +void Print_DirItemsStat(AString &s, const CDirItemsStat &st); +void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st); + +HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st) +{ + if (NeedPercents()) + { + _percent.ClosePrint(true); + _percent.ClearCurState(); + } + + if (_so) + { + AString s; + Print_DirItemsStat(s, st); + *_so << s << endl << endl; + } + return S_OK; +} + +static const char * const k_StdOut_ArcName = "StdOut"; + +HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name) +{ + if (_so) + { + *_so << kOpenArchiveMessage; + if (name) + *_so << name; + else + *_so << k_StdOut_ArcName; + *_so << endl; + } + return S_OK; +} + +HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) +{ + if (NeedPercents()) + _percent.ClosePrint(true); + + _percent.ClearCurState(); + NumNonOpenFiles = 0; + + if (_so) + { + *_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage); + if (name) + _so->NormalizePrint_wstr(name); + else + *_so << k_StdOut_ArcName; + *_so << endl << endl; + } + return S_OK; +} + +HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st) +{ + ClosePercents2(); + + if (_so) + { + AString s; + // Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files); + PrintPropPair(s, "Files read from disk", _percent.Files - NumNonOpenFiles); + s.Add_LF(); + s += "Archive size: "; + PrintSize_bytes_Smart(s, st.OutArcFileSize); + s.Add_LF(); + *_so << endl; + *_so << s; + // *_so << endl; + } + + return S_OK; +} + +HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size) +{ + if (_so) + { + *_so << "Write SFX: "; + *_so << name; + AString s (" : "); + PrintSize_bytes_Smart(s, size); + *_so << s << endl; + } + return S_OK; +} + + +HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */) +{ + if (LogLevel > 0 && _so) + { + ClosePercents_for_so(); + + if (!DeleteMessageWasShown) + { + if (_so) + *_so << endl << ": Removing files after including to archive" << endl; + } + + { + { + _tempA = "Removing"; + _tempA.Add_Space(); + *_so << _tempA; + _tempU = fs2us(path); + _so->Normalize_UString(_tempU); + _so->PrintUString(_tempU, _tempA); + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + } + } + + if (!DeleteMessageWasShown) + { + if (NeedPercents()) + { + _percent.ClearCurState(); + } + DeleteMessageWasShown = true; + } + else + { + _percent.Files++; + } + + if (NeedPercents()) + { + // if (!FullLog) + { + _percent.Command = "Removing"; + _percent.FileName = fs2us(path); + } + _percent.Print(); + } + + return S_OK; +} + + +HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving() +{ + ClosePercents2(); + if (_so && DeleteMessageWasShown) + *_so << endl; + return S_OK; +} + +HRESULT CUpdateCallbackConsole::CheckBreak() +{ + return CheckBreak2(); +} + +/* +HRESULT CUpdateCallbackConsole::Finalize() +{ + // MT_LOCK + return S_OK; +} +*/ + + +void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name) +{ + AString s; + Print_DirItemsStat2(s, stat); + *_so << name << ": " << s << endl; +} + +HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat) +{ + if (_so) + { + ClosePercents_for_so(); + if (!stat.DeleteData.IsEmpty()) + { + *_so << endl; + PrintToDoStat(_so, stat.DeleteData, "Delete data from archive"); + } + if (!stat.OldData.IsEmpty()) + PrintToDoStat(_so, stat.OldData, "Keep old data in archive"); + // if (!stat.NewData.IsEmpty()) + { + PrintToDoStat(_so, stat.NewData, "Add new data to archive"); + } + *_so << endl; + } + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) +{ + MT_LOCK + if (NeedPercents()) + { + _percent.Total = size; + _percent.Print(); + } + return S_OK; +} + +HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) +{ + MT_LOCK + if (completeValue) + { + if (NeedPercents()) + { + _percent.Completed = *completeValue; + _percent.Print(); + } + } + return CheckBreak2(); +} + +HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) +{ + return CheckBreak2(); +} + +HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog) +{ + MT_LOCK + + bool show2 = (showInLog && _so); + + if (show2) + { + ClosePercents_for_so(); + + _tempA = command; + if (name) + _tempA.Add_Space(); + *_so << _tempA; + + _tempU.Empty(); + if (name) + { + _tempU = name; + _so->Normalize_UString(_tempU); + } + _so->PrintUString(_tempU, _tempA); + *_so << endl; + if (NeedFlush) + _so->Flush(); + } + + if (NeedPercents()) + { + if (PercentsNameLevel >= 1) + { + _percent.FileName.Empty(); + _percent.Command.Empty(); + if (PercentsNameLevel > 1 || !show2) + { + _percent.Command = command; + if (name) + _percent.FileName = name; + } + } + _percent.Print(); + } + + return CheckBreak2(); +} + +HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode) +{ + if (StdOutMode) + return S_OK; + + if (!name || name[0] == 0) + name = kEmptyFileAlias; + + unsigned requiredLevel = 1; + + const char *s; + if (mode == NUpdateNotifyOp::kAdd || + mode == NUpdateNotifyOp::kUpdate) + { + if (isAnti) + s = "Anti"; + else if (mode == NUpdateNotifyOp::kAdd) + s = "+"; + else + s = "U"; + } + else + { + requiredLevel = 3; + if (mode == NUpdateNotifyOp::kAnalyze) + s = "A"; + else + s = "Reading"; + } + + return PrintProgress(name, s, LogLevel >= requiredLevel); +} + +HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError) +{ + return OpenFileError_Base(path, systemError); +} + +HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError) +{ + return ReadingFileError_Base(path, systemError); +} + +HRESULT CUpdateCallbackConsole::SetOperationResult(Int32) +{ + MT_LOCK + _percent.Files++; + return S_OK; +} + +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest); + +HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) +{ + // if (StdOutMode) return S_OK; + + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + ClosePercents2(); + + if (_se) + { + if (_so) + _so->Flush(); + + AString s; + SetExtractErrorMessage(opRes, isEncrypted, s); + *_se << s << " : " << endl; + _se->NormalizePrint_wstr(name); + *_se << endl << endl; + _se->Flush(); + } + return S_OK; + } + return S_OK; +} + + +HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */) +{ + // if (StdOutMode) return S_OK; + + char temp[16]; + const char *s; + + unsigned requiredLevel = 1; + + switch (op) + { + case NUpdateNotifyOp::kAdd: s = "+"; break; + case NUpdateNotifyOp::kUpdate: s = "U"; break; + case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break; + case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break; + case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break; + case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break; + case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break; + case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break; + default: + { + temp[0] = 'o'; + temp[1] = 'p'; + ConvertUInt64ToString(op, temp + 2); + s = temp; + } + } + + return PrintProgress(name, s, LogLevel >= requiredLevel); +} + +/* +HRESULT CUpdateCallbackConsole::SetPassword(const UString & + #ifndef _NO_CRYPTO + password + #endif + ) +{ + #ifndef _NO_CRYPTO + PasswordIsDefined = true; + Password = password; + #endif + return S_OK; +} +*/ + +HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + COM_TRY_BEGIN + + *password = NULL; + + #ifdef _NO_CRYPTO + + *passwordIsDefined = false; + return S_OK; + + #else + + if (!PasswordIsDefined) + { + if (AskPassword) + { + RINOK(GetPassword_HRESULT(_so, Password)); + PasswordIsDefined = true; + } + } + *passwordIsDefined = BoolToInt(PasswordIsDefined); + return StringToBstr(Password, password); + + #endif + + COM_TRY_END +} + +HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + + *password = NULL; + + #ifdef _NO_CRYPTO + + return E_NOTIMPL; + + #else + + if (!PasswordIsDefined) + { + { + RINOK(GetPassword_HRESULT(_so, Password)) + PasswordIsDefined = true; + } + } + return StringToBstr(Password, password); + + #endif + COM_TRY_END +} + +HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */) +{ + if (StdOutMode) + return S_OK; + + if (LogLevel > 7) + { + if (!name || name[0] == 0) + name = kEmptyFileAlias; + return PrintProgress(name, "D", true); + } + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.h new file mode 100644 index 0000000..5c205aa --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UpdateCallbackConsole.h @@ -0,0 +1,127 @@ +// UpdateCallbackConsole.h + +#ifndef __UPDATE_CALLBACK_CONSOLE_H +#define __UPDATE_CALLBACK_CONSOLE_H + +#include "../../../Common/StdOutStream.h" + +#include "../Common/Update.h" + +#include "PercentPrinter.h" + +struct CErrorPathCodes +{ + FStringVector Paths; + CRecordVector Codes; + + void AddError(const FString &path, DWORD systemError) + { + Paths.Add(path); + Codes.Add(systemError); + } + void Clear() + { + Paths.Clear(); + Codes.Clear(); + } +}; + +class CCallbackConsoleBase +{ +protected: + CPercentPrinter _percent; + + CStdOutStream *_so; + CStdOutStream *_se; + + void CommonError(const FString &path, DWORD systemError, bool isWarning); + + HRESULT ScanError_Base(const FString &path, DWORD systemError); + HRESULT OpenFileError_Base(const FString &name, DWORD systemError); + HRESULT ReadingFileError_Base(const FString &name, DWORD systemError); + +public: + bool NeedPercents() const { return _percent._so != NULL; }; + + bool StdOutMode; + + bool NeedFlush; + unsigned PercentsNameLevel; + unsigned LogLevel; + + AString _tempA; + UString _tempU; + + CCallbackConsoleBase(): + StdOutMode(false), + NeedFlush(false), + PercentsNameLevel(1), + LogLevel(0), + NumNonOpenFiles(0) + {} + + void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; } + + void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream) + { + FailedFiles.Clear(); + + _so = outStream; + _se = errorStream; + _percent._so = percentStream; + } + + void ClosePercents2() + { + if (NeedPercents()) + _percent.ClosePrint(true); + } + + void ClosePercents_for_so() + { + if (NeedPercents() && _so == _percent._so) + _percent.ClosePrint(false); + } + + CErrorPathCodes FailedFiles; + CErrorPathCodes ScanErrors; + UInt64 NumNonOpenFiles; + + HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog); + +}; + +class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase +{ + // void PrintPropPair(const char *name, const wchar_t *val); + +public: + bool DeleteMessageWasShown; + + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + UString Password; + bool AskPassword; + #endif + + CUpdateCallbackConsole(): + DeleteMessageWasShown(false) + #ifndef _NO_CRYPTO + , PasswordIsDefined(false) + , AskPassword(false) + #endif + {} + + virtual ~CUpdateCallbackConsole() {} + + /* + void Init(CStdOutStream *outStream) + { + CCallbackConsoleBase::Init(outStream); + } + */ + // ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); } + INTERFACE_IUpdateCallbackUI2(;) +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.cpp new file mode 100644 index 0000000..93f60eb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.cpp @@ -0,0 +1,110 @@ +// UserInputUtils.cpp + +#include "StdAfx.h" + +#include "../../../Common/StdInStream.h" +#include "../../../Common/StringConvert.h" + +#include "UserInputUtils.h" + +static const char kYes = 'y'; +static const char kNo = 'n'; +static const char kYesAll = 'a'; +static const char kNoAll = 's'; +static const char kAutoRenameAll = 'u'; +static const char kQuit = 'q'; + +static const char * const kFirstQuestionMessage = "? "; +static const char * const kHelpQuestionMessage = + "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; + +// return true if pressed Quite; + +NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) +{ + if (outStream) + *outStream << kFirstQuestionMessage; + for (;;) + { + if (outStream) + { + *outStream << kHelpQuestionMessage; + outStream->Flush(); + } + AString scannedString; + if (!g_StdIn.ScanAStringUntilNewLine(scannedString)) + return NUserAnswerMode::kError; + if (g_StdIn.Error()) + return NUserAnswerMode::kError; + scannedString.Trim(); + if (scannedString.IsEmpty() && g_StdIn.Eof()) + return NUserAnswerMode::kEof; + + if (scannedString.Len() == 1) + switch (::MyCharLower_Ascii(scannedString[0])) + { + case kYes: return NUserAnswerMode::kYes; + case kNo: return NUserAnswerMode::kNo; + case kYesAll: return NUserAnswerMode::kYesAll; + case kNoAll: return NUserAnswerMode::kNoAll; + case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; + case kQuit: return NUserAnswerMode::kQuit; + } + } +} + +#ifdef _WIN32 +#ifndef UNDER_CE +#define MY_DISABLE_ECHO +#endif +#endif + +static bool GetPassword(CStdOutStream *outStream, UString &psw) +{ + if (outStream) + { + *outStream << "\nEnter password" + #ifdef MY_DISABLE_ECHO + " (will not be echoed)" + #endif + ":"; + outStream->Flush(); + } + + #ifdef MY_DISABLE_ECHO + + HANDLE console = GetStdHandle(STD_INPUT_HANDLE); + bool wasChanged = false; + DWORD mode = 0; + if (console != INVALID_HANDLE_VALUE && console != 0) + if (GetConsoleMode(console, &mode)) + wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0); + bool res = g_StdIn.ScanUStringUntilNewLine(psw); + if (wasChanged) + SetConsoleMode(console, mode); + + #else + + bool res = g_StdIn.ScanUStringUntilNewLine(psw); + + #endif + + if (outStream) + { + *outStream << endl; + outStream->Flush(); + } + + return res; +} + +HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw) +{ + if (!GetPassword(outStream, psw)) + return E_INVALIDARG; + if (g_StdIn.Error()) + return E_FAIL; + if (g_StdIn.Eof() && psw.IsEmpty()) + return E_ABORT; + return S_OK; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.h new file mode 100644 index 0000000..256feaf --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/UserInputUtils.h @@ -0,0 +1,27 @@ +// UserInputUtils.h + +#ifndef __USER_INPUT_UTILS_H +#define __USER_INPUT_UTILS_H + +#include "../../../Common/StdOutStream.h" + +namespace NUserAnswerMode { + +enum EEnum +{ + kYes, + kNo, + kYesAll, + kNoAll, + kAutoRenameAll, + kQuit, + kEof, + kError +}; +} + +NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); +// bool GetPassword(CStdOutStream *outStream, UString &psw); +HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile new file mode 100644 index 0000000..ada782b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile @@ -0,0 +1,65 @@ +PROG = 7z.exe +CFLAGS = $(CFLAGS) \ + -DEXTERNAL_CODECS \ + +COMMON_OBJS = \ + $O\CommandLineParser.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\ListFileUtils.obj \ + $O\NewHandler.obj \ + $O\StdInStream.obj \ + $O\StdOutStream.obj \ + $O\MyString.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\UTFConvert.obj \ + $O\MyVector.obj \ + $O\Wildcard.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\ErrorMsg.obj \ + $O\FileDir.obj \ + $O\FileFind.obj \ + $O\FileIO.obj \ + $O\FileLink.obj \ + $O\FileName.obj \ + $O\FileSystem.obj \ + $O\MemoryLock.obj \ + $O\PropVariant.obj \ + $O\PropVariantConv.obj \ + $O\Registry.obj \ + $O\System.obj \ + $O\SystemInfo.obj \ + $O\TimeUtils.obj \ + +7ZIP_COMMON_OBJS = \ + $O\CreateCoder.obj \ + $O\FilePathAutoRename.obj \ + $O\FileStreams.obj \ + $O\FilterCoder.obj \ + $O\LimitedStreams.obj \ + $O\MethodProps.obj \ + $O\ProgressUtils.obj \ + $O\PropId.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + $O\UniqBlocks.obj \ + +AR_COMMON_OBJS = \ + $O\OutStreamWithCRC.obj \ + +COMPRESS_OBJS = \ + $O\CopyCoder.obj \ + +C_OBJS = $(C_OBJS) \ + $O\Alloc.obj \ + $O\CpuArch.obj \ + $O\Sort.obj \ + $O\Threads.obj \ + +!include "../../Crc.mak" +!include "Console.mak" + +!include "../../7zip.mak" diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile.gcc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile.gcc new file mode 100644 index 0000000..e0d996c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/makefile.gcc @@ -0,0 +1,171 @@ +PROG = 7z +IS_NOT_STANDALONE = 1 + +# IS_X64 = 1 +# USE_ASM = 1 +# ST_MODE = 1 + + +LOCAL_FLAGS_ST = +MT_OBJS = + +ifdef ST_MODE + +LOCAL_FLAGS_ST = -D_7ZIP_ST + +ifdef SystemDrive +MT_OBJS = \ + $O/Threads.o \ + +endif + +else + +MT_OBJS = \ + $O/Synchronization.o \ + $O/Threads.o \ + +endif + + + +LOCAL_FLAGS_WIN= + +ifdef SystemDrive + +LOCAL_FLAGS_WIN = \ + -D_7ZIP_LARGE_PAGES \ + -DWIN_LONG_PATH \ + -DSUPPORT_DEVICE_FILE \ + +SYS_OBJS = \ + $O/FileSystem.o \ + $O/Registry.o \ + $O/MemoryLock.o \ + $O/DllSecur.o \ + $O/resource.o \ + +else + +SYS_OBJS = \ + $O/MyWindows.o \ + +endif + + + +LOCAL_FLAGS = \ + $(LOCAL_FLAGS_WIN) \ + $(LOCAL_FLAGS_ST) \ + -DEXTERNAL_CODECS \ + + + +CONSOLE_OBJS = \ + $O/BenchCon.o \ + $O/ConsoleClose.o \ + $O/ExtractCallbackConsole.o \ + $O/HashCon.o \ + $O/List.o \ + $O/Main.o \ + $O/MainAr.o \ + $O/OpenCallbackConsole.o \ + $O/PercentPrinter.o \ + $O/UpdateCallbackConsole.o \ + $O/UserInputUtils.o \ + +UI_COMMON_OBJS = \ + $O/ArchiveCommandLine.o \ + $O/ArchiveExtractCallback.o \ + $O/ArchiveOpenCallback.o \ + $O/Bench.o \ + $O/DefaultName.o \ + $O/EnumDirItems.o \ + $O/Extract.o \ + $O/ExtractingFilePath.o \ + $O/HashCalc.o \ + $O/LoadCodecs.o \ + $O/OpenArchive.o \ + $O/PropIDUtils.o \ + $O/SetProperties.o \ + $O/SortUtils.o \ + $O/TempFiles.o \ + $O/Update.o \ + $O/UpdateAction.o \ + $O/UpdateCallback.o \ + $O/UpdatePair.o \ + $O/UpdateProduce.o \ + +COMMON_OBJS = \ + $O/CommandLineParser.o \ + $O/CRC.o \ + $O/CrcReg.o \ + $O/IntToString.o \ + $O/ListFileUtils.o \ + $O/NewHandler.o \ + $O/StdInStream.o \ + $O/StdOutStream.o \ + $O/MyString.o \ + $O/StringConvert.o \ + $O/StringToInt.o \ + $O/UTFConvert.o \ + $O/MyVector.o \ + $O/Wildcard.o \ + +WIN_OBJS = \ + $O/DLL.o \ + $O/ErrorMsg.o \ + $O/FileDir.o \ + $O/FileFind.o \ + $O/FileIO.o \ + $O/FileLink.o \ + $O/FileName.o \ + $O/PropVariant.o \ + $O/PropVariantConv.o \ + $O/System.o \ + $O/SystemInfo.o \ + $O/TimeUtils.o \ + +7ZIP_COMMON_OBJS = \ + $O/CreateCoder.o \ + $O/CWrappers.o \ + $O/FilePathAutoRename.o \ + $O/FileStreams.o \ + $O/InBuffer.o \ + $O/InOutTempBuffer.o \ + $O/FilterCoder.o \ + $O/LimitedStreams.o \ + $O/MethodId.o \ + $O/MethodProps.o \ + $O/OffsetStream.o \ + $O/OutBuffer.o \ + $O/ProgressUtils.o \ + $O/PropId.o \ + $O/StreamObjects.o \ + $O/StreamUtils.o \ + $O/UniqBlocks.o \ + +COMPRESS_OBJS = \ + $O/CopyCoder.o \ + +C_OBJS = \ + $O/Alloc.o \ + $O/CpuArch.o \ + $O/Sort.o \ + $O/7zCrc.o \ + $O/7zCrcOpt.o \ + + +OBJS = \ + $(C_OBJS) \ + $(MT_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(SYS_OBJS) \ + $(COMPRESS_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(UI_COMMON_OBJS) \ + $(CONSOLE_OBJS) \ + + +include ../../7zip_gcc.mak diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/resource.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/resource.rc new file mode 100644 index 0000000..414427f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Console/resource.rc @@ -0,0 +1,7 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_APP("7-Zip Console" , "7z") + +#ifndef UNDER_CE +1 24 MOVEABLE PURE "Console.manifest" +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.cpp new file mode 100644 index 0000000..c912504 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.cpp @@ -0,0 +1,37 @@ +// MyMessages.cpp + +#include "StdAfx.h" + +#include "MyMessages.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/ResourceString.h" + +#include "../FileManager/LangUtils.h" + +using namespace NWindows; + +void ShowErrorMessage(HWND window, LPCWSTR message) +{ + ::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP); +} + +void ShowErrorMessageHwndRes(HWND window, UINT resID) +{ + ShowErrorMessage(window, LangString(resID)); +} + +void ShowErrorMessageRes(UINT resID) +{ + ShowErrorMessageHwndRes(0, resID); +} + +static void ShowErrorMessageDWORD(HWND window, DWORD errorCode) +{ + ShowErrorMessage(window, NError::MyFormatMessage(errorCode)); +} + +void ShowLastErrorMessage(HWND window) +{ + ShowErrorMessageDWORD(window, ::GetLastError()); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.h new file mode 100644 index 0000000..d5822f4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/Explorer/MyMessages.h @@ -0,0 +1,16 @@ +// MyMessages.h + +#ifndef __MY_MESSAGES_H +#define __MY_MESSAGES_H + +#include "../../../Common/MyString.h" + +void ShowErrorMessage(HWND window, LPCWSTR message); +inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); } + +void ShowErrorMessageHwndRes(HWND window, UInt32 langID); +void ShowErrorMessageRes(UInt32 langID); + +void ShowLastErrorMessage(HWND window = 0); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.cpp new file mode 100644 index 0000000..6d2b6b5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -0,0 +1,1025 @@ +// BrowseDialog.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyWindows.h" + +#include + +#ifndef UNDER_CE +#include "../../../Windows/CommonDialog.h" +#include "../../../Windows/Shell.h" +#endif + +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileFind.h" + +#ifdef UNDER_CE +#include +#endif + +#include "BrowseDialog.h" + +#define USE_MY_BROWSE_DIALOG + +#ifdef USE_MY_BROWSE_DIALOG + +#include "../../../Common/Defs.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/Edit.h" +#include "../../../Windows/Control/ListView.h" + +#include "BrowseDialogRes.h" +#include "PropertyNameRes.h" +#include "SysIconUtils.h" + +#ifndef _SFX +#include "RegistryUtils.h" +#endif + +#endif + +#include "ComboDialog.h" +#include "LangUtils.h" + +#include "resource.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; +using namespace NFind; + +#ifdef USE_MY_BROWSE_DIALOG + +extern bool g_LVN_ITEMACTIVATE_Support; + +static const int kParentIndex = -1; +static const UINT k_Message_RefreshPathEdit = WM_APP + 1; + +static HRESULT GetNormalizedError() +{ + DWORD errorCode = GetLastError(); + return errorCode == 0 ? E_FAIL : errorCode; +} + +extern UString HResultToMessage(HRESULT errorCode); + +static void MessageBox_Error_Global(HWND wnd, const wchar_t *message) +{ + ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR); +} + +static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name) +{ + UString s = HResultToMessage(errorCode); + if (name) + { + s.Add_LF(); + s += name; + } + MessageBox_Error_Global(wnd, s); +} + +class CBrowseDialog: public NControl::CModalDialog +{ + NControl::CListView _list; + NControl::CEdit _pathEdit; + NControl::CComboBox _filterCombo; + + CObjectVector _files; + + CExtToIconMap _extToIconMap; + int _sortIndex; + bool _ascending; + bool _showDots; + UString _topDirPrefix; // we don't open parent of that folder + UString DirPrefix; + + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnNotify(UINT controlID, LPNMHDR header); + virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK(); + + void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); } + + bool GetParentPath(const UString &path, UString &parentPrefix, UString &name); + // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter + HRESULT Reload(const UString &pathPrefix, const UString &selectedName); + HRESULT Reload(); + + void OpenParentFolder(); + void SetPathEditText(); + void OnCreateDir(); + void OnItemEnter(); + void FinishOnOK(); + + int GetRealItemIndex(int indexInListView) const + { + LPARAM param; + if (!_list.GetItemParam(indexInListView, param)) + return (int)-1; + return (int)param; + } + +public: + bool FolderMode; + UString Title; + UString FilePath; // input/ result path + bool ShowAllFiles; + UStringVector Filters; + UString FilterDescription; + + CBrowseDialog(): _showDots(false), FolderMode(false), ShowAllFiles(true) {} + void SetFilter(const UString &s); + INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); } + int CompareItems(LPARAM lParam1, LPARAM lParam2); +}; + +void CBrowseDialog::SetFilter(const UString &s) +{ + Filters.Clear(); + UString mask; + unsigned i; + for (i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (c == ';') + { + if (!mask.IsEmpty()) + Filters.Add(mask); + mask.Empty(); + } + else + mask += c; + } + if (!mask.IsEmpty()) + Filters.Add(mask); + ShowAllFiles = Filters.IsEmpty(); + for (i = 0; i < Filters.Size(); i++) + { + const UString &f = Filters[i]; + if (f == L"*.*" || f == L"*") + { + ShowAllFiles = true; + break; + } + } +} + +bool CBrowseDialog::OnInit() +{ + #ifdef LANG + LangSetDlgItems(*this, NULL, 0); + #endif + if (!Title.IsEmpty()) + SetText(Title); + _list.Attach(GetItem(IDL_BROWSE)); + _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER)); + _pathEdit.Attach(GetItem(IDE_BROWSE_PATH)); + + if (FolderMode) + HideItem(IDC_BROWSE_FILTER); + else + EnableItem(IDC_BROWSE_FILTER, false); + + #ifndef UNDER_CE + _list.SetUnicodeFormat(); + #endif + + #ifndef _SFX + CFmSettings st; + st.Load(); + if (st.SingleClick) + _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); + _showDots = st.ShowDots; + #endif + + { + UString s; + if (!FilterDescription.IsEmpty()) + s = FilterDescription; + else if (ShowAllFiles) + s = "*.*"; + else + { + FOR_VECTOR (i, Filters) + { + if (i != 0) + s.Add_Space(); + s += Filters[i]; + } + } + _filterCombo.AddString(s); + _filterCombo.SetCurSel(0); + } + + _list.SetImageList(GetSysImageList(true), LVSIL_SMALL); + _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL); + + _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100); + _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100); + { + LV_COLUMNW column; + column.iSubItem = 2; + column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + column.fmt = LVCFMT_RIGHT; + column.cx = 100; + const UString s = LangString(IDS_PROP_SIZE); + column.pszText = s.Ptr_non_const(); + _list.InsertColumn(2, &column); + } + + _list.InsertItem(0, L"12345678901234567" + #ifndef UNDER_CE + L"1234567890" + #endif + ); + _list.SetSubItem(0, 1, L"2009-09-09" + #ifndef UNDER_CE + L" 09:09" + #endif + ); + _list.SetSubItem(0, 2, L"9999 MB"); + for (int i = 0; i < 3; i++) + _list.SetColumnWidthAuto(i); + _list.DeleteAllItems(); + + _ascending = true; + _sortIndex = 0; + + NormalizeSize(); + + _topDirPrefix.Empty(); + { + int rootSize = GetRootPrefixSize(FilePath); + #if defined(_WIN32) && !defined(UNDER_CE) + // We can go up from root folder to drives list + if (IsDrivePath(FilePath)) + rootSize = 0; + else if (IsSuperPath(FilePath)) + { + if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize))) + rootSize = kSuperPathPrefixSize; + } + #endif + _topDirPrefix.SetFrom(FilePath, rootSize); + } + + UString name; + if (!GetParentPath(FilePath, DirPrefix, name)) + DirPrefix = _topDirPrefix; + + for (;;) + { + UString baseFolder = DirPrefix; + if (Reload(baseFolder, name) == S_OK) + break; + name.Empty(); + if (DirPrefix.IsEmpty()) + break; + UString parent, name2; + GetParentPath(DirPrefix, parent, name2); + DirPrefix = parent; + } + + if (name.IsEmpty()) + name = FilePath; + if (FolderMode) + NormalizeDirPathPrefix(name); + _pathEdit.SetText(name); + + #ifndef UNDER_CE + /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible, + even if we use mouse for pressing the button to open this dialog. */ + PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS)); + #endif + + return CModalDialog::OnInit(); +} + +bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int mx, my; + { + RECT r; + GetClientRectOfItem(IDB_BROWSE_PARENT, r); + mx = r.left; + my = r.top; + } + InvalidateRect(NULL); + + int xLim = xSize - mx; + { + RECT r; + GetClientRectOfItem(IDT_BROWSE_FOLDER, r); + MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r)); + } + + int bx1, bx2, by; + GetItemSizes(IDCANCEL, bx1, by); + GetItemSizes(IDOK, bx2, by); + int y = ySize - my - by; + int x = xLim - bx1; + MoveItem(IDCANCEL, x, y, bx1, by); + MoveItem(IDOK, x - mx - bx2, y, bx2, by); + + // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead + + int yPathSize; + { + RECT r; + GetClientRectOfItem(IDE_BROWSE_PATH, r); + yPathSize = RECT_SIZE_Y(r); + _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize); + } + + { + RECT r; + GetClientRectOfItem(IDC_BROWSE_FILTER, r); + _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r)); + } + + { + RECT r; + GetClientRectOfItem(IDL_BROWSE, r); + _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top); + } + + return false; +} + +bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == k_Message_RefreshPathEdit) + { + SetPathEditText(); + return true; + } + return CModalDialog::OnMessage(message, wParam, lParam); +} + +bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header) +{ + if (header->hwndFrom != _list) + return false; + switch (header->code) + { + case LVN_ITEMACTIVATE: + if (g_LVN_ITEMACTIVATE_Support) + OnItemEnter(); + break; + case NM_DBLCLK: + case NM_RETURN: // probabably it's unused + if (!g_LVN_ITEMACTIVATE_Support) + OnItemEnter(); + break; + case LVN_COLUMNCLICK: + { + int index = LPNMLISTVIEW(header)->iSubItem; + if (index == _sortIndex) + _ascending = !_ascending; + else + { + _ascending = (index == 0); + _sortIndex = index; + } + Reload(); + return false; + } + case LVN_KEYDOWN: + { + bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header)); + Post_RefreshPathEdit(); + return boolResult; + } + case NM_RCLICK: + case NM_CLICK: + case LVN_BEGINDRAG: + Post_RefreshPathEdit(); + break; + } + return false; +} + +bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo) +{ + bool ctrl = IsKeyDown(VK_CONTROL); + + switch (keyDownInfo->wVKey) + { + case VK_BACK: + OpenParentFolder(); + return true; + case 'R': + if (ctrl) + { + Reload(); + return true; + } + return false; + case VK_F7: + OnCreateDir(); + return true; + } + return false; +} + +bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDB_BROWSE_PARENT: OpenParentFolder(); break; + case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break; + default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND); + } + _list.SetFocus(); + return true; +} + +void CBrowseDialog::OnOK() +{ + /* When we press "Enter" in listview, Windows sends message to first Button. + We check that message was from ListView; */ + if (GetFocus() == _list) + { + OnItemEnter(); + return; + } + FinishOnOK(); +} + + +bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name) +{ + parentPrefix.Empty(); + name.Empty(); + if (path.IsEmpty()) + return false; + if (_topDirPrefix == path) + return false; + UString s = path; + if (IS_PATH_SEPAR(s.Back())) + s.DeleteBack(); + if (s.IsEmpty()) + return false; + if (IS_PATH_SEPAR(s.Back())) + return false; + int pos = s.ReverseFind_PathSepar(); + parentPrefix.SetFrom(s, pos + 1); + name = s.Ptr((unsigned)(pos + 1)); + return true; +} + +int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) +{ + if (lParam1 == kParentIndex) return -1; + if (lParam2 == kParentIndex) return 1; + const CFileInfo &f1 = _files[(int)lParam1]; + const CFileInfo &f2 = _files[(int)lParam2]; + + bool isDir1 = f1.IsDir(); + bool isDir2 = f2.IsDir(); + if (isDir1 && !isDir2) return -1; + if (isDir2 && !isDir1) return 1; + + int res = 0; + switch (_sortIndex) + { + case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break; + case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break; + case 2: res = MyCompare(f1.Size, f2.Size); break; + } + return _ascending ? res: -res; +} + +static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) +{ + return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2); +} + +static void ConvertSizeToString(UInt64 v, wchar_t *s) +{ + Byte c = 0; + if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; } + else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; } + else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; } + ConvertUInt64ToString(v, s); + if (c != 0) + { + s += MyStringLen(s); + *s++ = ' '; + *s++ = c; + *s++ = 0; + } +} + +// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter + +HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) +{ + CObjectVector files; + + #ifndef UNDER_CE + bool isDrive = false; + if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix)) + { + isDrive = true; + FStringVector drives; + if (!MyGetLogicalDriveStrings(drives)) + return GetNormalizedError(); + FOR_VECTOR (i, drives) + { + FString d = drives[i]; + if (d.Len() < 3 || d.Back() != '\\') + return E_FAIL; + d.DeleteBack(); + CFileInfo &fi = files.AddNew(); + fi.SetAsDir(); + fi.Name = d; + } + } + else + #endif + { + CEnumerator enumerator; + enumerator.SetDirPrefix(us2fs(pathPrefix)); + for (;;) + { + bool found; + CFileInfo fi; + if (!enumerator.Next(fi, found)) + return GetNormalizedError(); + if (!found) + break; + if (!fi.IsDir()) + { + if (FolderMode) + continue; + if (!ShowAllFiles) + { + unsigned i; + for (i = 0; i < Filters.Size(); i++) + if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name))) + break; + if (i == Filters.Size()) + continue; + } + } + files.Add(fi); + } + } + + DirPrefix = pathPrefix; + + _files = files; + + SetItemText(IDT_BROWSE_FOLDER, DirPrefix); + + _list.SetRedraw(false); + _list.DeleteAllItems(); + + LVITEMW item; + + int index = 0; + int cursorIndex = -1; + + #ifndef _SFX + if (_showDots && _topDirPrefix != DirPrefix) + { + item.iItem = index; + const UString itemName (".."); + if (selectedName.IsEmpty()) + cursorIndex = index; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + int subItem = 0; + item.iSubItem = subItem++; + item.lParam = kParentIndex; + item.pszText = itemName.Ptr_non_const(); + item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix); + if (item.iImage < 0) + item.iImage = 0; + _list.InsertItem(&item); + _list.SetSubItem(index, subItem++, L""); + _list.SetSubItem(index, subItem++, L""); + index++; + } + #endif + + for (unsigned i = 0; i < _files.Size(); i++, index++) + { + item.iItem = index; + const CFileInfo &fi = _files[i]; + const UString name = fs2us(fi.Name); + if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0) + cursorIndex = index; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + int subItem = 0; + item.iSubItem = subItem++; + item.lParam = i; + item.pszText = name.Ptr_non_const(); + + const UString fullPath = DirPrefix + name; + #ifndef UNDER_CE + if (isDrive) + { + if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0) + item.iImage = 0; + } + else + #endif + item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); + if (item.iImage < 0) + item.iImage = 0; + _list.InsertItem(&item); + wchar_t s[32]; + { + s[0] = 0; + ConvertUtcFileTimeToString(fi.MTime, s, + #ifndef UNDER_CE + kTimestampPrintLevel_MIN + #else + kTimestampPrintLevel_DAY + #endif + ); + _list.SetSubItem(index, subItem++, s); + } + { + s[0] = 0; + if (!fi.IsDir()) + ConvertSizeToString(fi.Size, s); + _list.SetSubItem(index, subItem++, s); + } + } + + if (_list.GetItemCount() > 0 && cursorIndex >= 0) + _list.SetItemState_FocusedSelected(cursorIndex); + _list.SortItems(CompareItems2, (LPARAM)this); + if (_list.GetItemCount() > 0 && cursorIndex < 0) + _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); + _list.EnsureVisible(_list.GetFocusedItem(), false); + _list.SetRedraw(true); + _list.InvalidateRect(NULL, true); + return S_OK; +} + +HRESULT CBrowseDialog::Reload() +{ + UString selected; + int index = _list.GetNextSelectedItem(-1); + if (index >= 0) + { + int fileIndex = GetRealItemIndex(index); + if (fileIndex != kParentIndex) + selected = fs2us(_files[fileIndex].Name); + } + UString dirPathTemp = DirPrefix; + return Reload(dirPathTemp, selected); +} + +void CBrowseDialog::OpenParentFolder() +{ + UString parent, selected; + if (GetParentPath(DirPrefix, parent, selected)) + { + Reload(parent, selected); + SetPathEditText(); + } +} + +void CBrowseDialog::SetPathEditText() +{ + int index = _list.GetNextSelectedItem(-1); + if (index < 0) + { + if (FolderMode) + _pathEdit.SetText(DirPrefix); + return; + } + int fileIndex = GetRealItemIndex(index); + if (fileIndex == kParentIndex) + { + if (FolderMode) + _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR); + return; + } + const CFileInfo &file = _files[fileIndex]; + if (file.IsDir()) + { + if (!FolderMode) + return; + _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR); + } + else + _pathEdit.SetText(fs2us(file.Name)); +} + +void CBrowseDialog::OnCreateDir() +{ + UString name; + { + UString enteredName; + Dlg_CreateFolder((HWND)*this, enteredName); + if (enteredName.IsEmpty()) + return; + if (!CorrectFsPath(DirPrefix, enteredName, name)) + { + MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name); + return; + } + } + if (name.IsEmpty()) + return; + + FString destPath; + if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath)) + { + if (!NDir::CreateComplexDir(destPath)) + { + MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath)); + } + else + { + UString tempPath = DirPrefix; + Reload(tempPath, name); + SetPathEditText(); + } + _list.SetFocus(); + } +} + +void CBrowseDialog::OnItemEnter() +{ + int index = _list.GetNextSelectedItem(-1); + if (index < 0) + return; + int fileIndex = GetRealItemIndex(index); + if (fileIndex == kParentIndex) + OpenParentFolder(); + else + { + const CFileInfo &file = _files[fileIndex]; + if (!file.IsDir()) + { + if (!FolderMode) + FinishOnOK(); + /* + MessageBox_Error_Global(*this, FolderMode ? + L"You must select some folder": + L"You must select some file"); + */ + return; + } + UString s = DirPrefix; + s += fs2us(file.Name); + s.Add_PathSepar(); + HRESULT res = Reload(s, UString()); + if (res != S_OK) + MessageBox_HResError(*this, res, s); + SetPathEditText(); + } +} + +void CBrowseDialog::FinishOnOK() +{ + UString s; + _pathEdit.GetText(s); + FString destPath; + if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath)) + { + MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s); + return; + } + FilePath = fs2us(destPath); + if (FolderMode) + NormalizeDirPathPrefix(FilePath); + End(IDOK); +} + +#endif + +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath) +{ + resultPath.Empty(); + + #ifndef UNDER_CE + + #ifdef USE_MY_BROWSE_DIALOG + if (!IsSuperOrDevicePath(path)) + #endif + return NShell::BrowseForFolder(owner, title, path, resultPath); + + #endif + + #ifdef USE_MY_BROWSE_DIALOG + + CBrowseDialog dialog; + dialog.FolderMode = true; + if (title) + dialog.Title = title; + if (path) + dialog.FilePath = path; + if (dialog.Create(owner) != IDOK) + return false; + resultPath = dialog.FilePath; + #endif + + return true; +} + +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, + LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath) +{ + resultPath.Empty(); + + #ifndef UNDER_CE + + #ifdef USE_MY_BROWSE_DIALOG + if (!IsSuperOrDevicePath(path)) + #endif + { + if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath)) + return true; + #ifdef UNDER_CE + return false; + #else + // maybe we must use GetLastError in WinCE. + DWORD errorCode = CommDlgExtendedError(); + const char *errorMessage = NULL; + switch (errorCode) + { + case 0: return false; // cancel or close obn dialog + case FNERR_INVALIDFILENAME: errorMessage = "Invalid File Name"; break; + default: errorMessage = "Open Dialog Error"; + } + if (!errorMessage) + return false; + { + UString s (errorMessage); + s.Add_LF(); + s += path; + MessageBox_Error_Global(owner, s); + } + #endif + } + + #endif + + #ifdef USE_MY_BROWSE_DIALOG + CBrowseDialog dialog; + if (title) + dialog.Title = title; + if (path) + dialog.FilePath = path; + dialog.FolderMode = false; + if (filter) + dialog.SetFilter(filter); + if (filterDescription) + dialog.FilterDescription = filterDescription; + if (dialog.Create(owner) != IDOK) + return false; + resultPath = dialog.FilePath; + #endif + + return true; +} + + +#ifdef _WIN32 + +static void RemoveDotsAndSpaces(UString &path) +{ + while (!path.IsEmpty()) + { + wchar_t c = path.Back(); + if (c != ' ' && c != '.') + return; + path.DeleteBack(); + } +} + + +bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result) +{ + result.Empty(); + + UString path = path2; + path.Replace(L'/', WCHAR_PATH_SEPARATOR); + unsigned start = 0; + UString base; + + if (IsAbsolutePath(path)) + { + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsSuperOrDevicePath(path)) + { + result = path; + return true; + } + #endif + int pos = GetRootPrefixSize(path); + if (pos > 0) + start = pos; + } + else + { + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsSuperOrDevicePath(relBase)) + { + result = path; + return true; + } + #endif + base = relBase; + } + + /* We can't use backward, since we must change only disk paths */ + /* + for (;;) + { + if (path.Len() <= start) + break; + if (DoesFileOrDirExist(us2fs(path))) + break; + if (path.Back() == WCHAR_PATH_SEPARATOR) + { + path.DeleteBack(); + result.Insert(0, WCHAR_PATH_SEPARATOR); + } + int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1; + UString cur = path.Ptr(pos); + RemoveDotsAndSpaces(cur); + result.Insert(0, cur); + path.DeleteFrom(pos); + } + result.Insert(0, path); + return true; + */ + + result += path.Left(start); + bool checkExist = true; + UString cur; + + for (;;) + { + if (start == path.Len()) + break; + int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start); + cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start); + if (checkExist) + { + CFileInfo fi; + if (fi.Find(us2fs(base + result + cur))) + { + if (!fi.IsDir()) + { + result = path; + break; + } + } + else + checkExist = false; + } + if (!checkExist) + RemoveDotsAndSpaces(cur); + result += cur; + if (slashPos < 0) + break; + result.Add_PathSepar(); + start = slashPos + 1; + } + + return true; +} + +#else + +bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result) +{ + result = path; + return true; +} + +#endif + +bool Dlg_CreateFolder(HWND wnd, UString &destName) +{ + destName.Empty(); + CComboDialog dlg; + LangString(IDS_CREATE_FOLDER, dlg.Title); + LangString(IDS_CREATE_FOLDER_NAME, dlg.Static); + LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value); + if (dlg.Create(wnd) != IDOK) + return false; + destName = dlg.Value; + return true; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.h new file mode 100644 index 0000000..957af2e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialog.h @@ -0,0 +1,21 @@ +// BrowseDialog.h + +#ifndef __BROWSE_DIALOG_H +#define __BROWSE_DIALOG_H + +#include "../../../Common/MyString.h" + +bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath); +bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath); + +/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file) + But it doesn't change "bad" name in any of the following cases: + - path is Super Path (with \\?\ prefix) + - path is relative and relBase is Super Path + - there is file or dir in filesystem with specified "bad" name */ + +bool CorrectFsPath(const UString &relBase, const UString &path, UString &result); + +bool Dlg_CreateFolder(HWND wnd, UString &destName); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialogRes.h new file mode 100644 index 0000000..aff84ec --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/BrowseDialogRes.h @@ -0,0 +1,9 @@ +#define IDD_BROWSE 95 + +#define IDL_BROWSE 100 +#define IDT_BROWSE_FOLDER 101 +#define IDE_BROWSE_PATH 102 +#define IDC_BROWSE_FILTER 103 + +#define IDB_BROWSE_PARENT 110 +#define IDB_BROWSE_CREATE_DIR 112 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.cpp new file mode 100644 index 0000000..729743e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.cpp @@ -0,0 +1,64 @@ +// ComboDialog.cpp + +#include "StdAfx.h" +#include "ComboDialog.h" + +#include "../../../Windows/Control/Static.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +using namespace NWindows; + +bool CComboDialog::OnInit() +{ + #ifdef LANG + LangSetDlgItems(*this, NULL, 0); + #endif + _comboBox.Attach(GetItem(IDC_COMBO)); + + /* + // why it doesn't work ? + DWORD style = _comboBox.GetStyle(); + if (Sorted) + style |= CBS_SORT; + else + style &= ~CBS_SORT; + _comboBox.SetStyle(style); + */ + SetText(Title); + + NControl::CStatic staticContol; + staticContol.Attach(GetItem(IDT_COMBO)); + staticContol.SetText(Static); + _comboBox.SetText(Value); + FOR_VECTOR (i, Strings) + _comboBox.AddString(Strings[i]); + NormalizeSize(); + return CModalDialog::OnInit(); +} + +bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int mx, my; + GetMargins(8, mx, my); + int bx1, bx2, by; + GetItemSizes(IDCANCEL, bx1, by); + GetItemSizes(IDOK, bx2, by); + int y = ySize - my - by; + int x = xSize - mx - bx1; + + InvalidateRect(NULL); + + MoveItem(IDCANCEL, x, y, bx1, by); + MoveItem(IDOK, x - mx - bx2, y, bx2, by); + ChangeSubWindowSizeX(_comboBox, xSize - mx * 2); + return false; +} + +void CComboDialog::OnOK() +{ + _comboBox.GetText(Value); + CModalDialog::OnOK(); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.h new file mode 100644 index 0000000..29b28b5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialog.h @@ -0,0 +1,28 @@ +// ComboDialog.h + +#ifndef __COMBO_DIALOG_H +#define __COMBO_DIALOG_H + +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Dialog.h" + +#include "ComboDialogRes.h" + +class CComboDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CComboBox _comboBox; + virtual void OnOK(); + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); +public: + // bool Sorted; + UString Title; + UString Static; + UString Value; + UStringVector Strings; + + // CComboDialog(): Sorted(false) {}; + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialogRes.h new file mode 100644 index 0000000..a044797 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ComboDialogRes.h @@ -0,0 +1,4 @@ +#define IDD_COMBO 98 + +#define IDT_COMBO 100 +#define IDC_COMBO 101 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/DialogSize.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/DialogSize.h new file mode 100644 index 0000000..504541b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/DialogSize.h @@ -0,0 +1,16 @@ +// DialogSize.h + +#ifndef __DIALOG_SIZE_H +#define __DIALOG_SIZE_H + +#include "../../../Windows/Control/Dialog.h" + +#ifdef UNDER_CE +#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y); +#define SIZED_DIALOG(big) (isBig ? big : big ## _2) +#else +#define BIG_DIALOG_SIZE(x, y) +#define SIZED_DIALOG(big) big +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.cpp new file mode 100644 index 0000000..0e285f0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.cpp @@ -0,0 +1,1045 @@ +// ExtractCallback.cpp + +#include "StdAfx.h" + + +#include "../../../Common/ComTry.h" +#include "../../../Common/IntToString.h" +#include "../../../Common/Lang.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/PropVariantConv.h" + +#include "../../Common/FilePathAutoRename.h" +#include "../../Common/StreamUtils.h" +#include "../Common/ExtractingFilePath.h" + +#ifndef _SFX +#include "../Common/ZipRegistry.h" +#endif + +#include "../GUI/ExtractRes.h" +#include "resourceGui.h" + +#include "ExtractCallback.h" +#include "FormatUtils.h" +#include "LangUtils.h" +#include "OverwriteDialog.h" +#ifndef _NO_CRYPTO +#include "PasswordDialog.h" +#endif +#include "PropertyName.h" + +using namespace NWindows; +using namespace NFile; +using namespace NFind; + +CExtractCallbackImp::~CExtractCallbackImp() {} + +void CExtractCallbackImp::Init() +{ + _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING); + _lang_Testing = LangString(IDS_PROGRESS_TESTING); + _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING); + + NumArchiveErrors = 0; + ThereAreMessageErrors = false; + #ifndef _SFX + NumFolders = NumFiles = 0; + NeedAddFile = false; + #endif +} + +void CExtractCallbackImp::AddError_Message(LPCWSTR s) +{ + ThereAreMessageErrors = true; + ProgressDialog->Sync.AddError_Message(s); +} + +#ifndef _SFX + +STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64 + #ifndef _SFX + numFiles + #endif + ) +{ + #ifndef _SFX + ProgressDialog->Sync.Set_NumFilesTotal(numFiles); + #endif + return S_OK; +} + +#endif + +STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total) +{ + ProgressDialog->Sync.Set_NumBytesTotal(total); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value) +{ + return ProgressDialog->Sync.Set_NumBytesCur(value); +} + +HRESULT CExtractCallbackImp::Open_CheckBreak() +{ + return ProgressDialog->Sync.CheckStop(); +} + +HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes) +{ + HRESULT res = S_OK; + if (!MultiArcMode) + { + if (files) + { + _totalFilesDefined = true; + // res = ProgressDialog->Sync.Set_NumFilesTotal(*files); + } + else + _totalFilesDefined = false; + + if (bytes) + { + _totalBytesDefined = true; + ProgressDialog->Sync.Set_NumBytesTotal(*bytes); + } + else + _totalBytesDefined = false; + } + + return res; +} + +HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) +{ + if (!MultiArcMode) + { + if (files) + { + ProgressDialog->Sync.Set_NumFilesCur(*files); + } + + if (bytes) + { + } + } + + return ProgressDialog->Sync.CheckStop(); +} + +HRESULT CExtractCallbackImp::Open_Finished() +{ + return ProgressDialog->Sync.CheckStop(); +} + +#ifndef _NO_CRYPTO + +HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password) +{ + return CryptoGetTextPassword(password); +} + +/* +HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) +{ + passwordIsDefined = PasswordIsDefined; + password = Password; + return S_OK; +} + +bool CExtractCallbackImp::Open_WasPasswordAsked() +{ + return PasswordWasAsked; +} + +void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag() +{ + PasswordWasAsked = false; +} +*/ + +#endif + + +#ifndef _SFX +STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + ProgressDialog->Sync.Set_Ratio(inSize, outSize); + return S_OK; +} +#endif + +/* +STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total) +{ + ProgressDialog->Sync.SetNumFilesTotal(total); + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value) +{ + if (value != NULL) + ProgressDialog->Sync.SetNumFilesCur(*value); + return S_OK; +} +*/ + +STDMETHODIMP CExtractCallbackImp::AskOverwrite( + const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, + const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, + Int32 *answer) +{ + COverwriteDialog dialog; + + dialog.OldFileInfo.SetTime(existTime); + dialog.OldFileInfo.SetSize(existSize); + dialog.OldFileInfo.Name = existName; + + dialog.NewFileInfo.SetTime(newTime); + dialog.NewFileInfo.SetSize(newSize); + dialog.NewFileInfo.Name = newName; + + ProgressDialog->WaitCreating(); + INT_PTR writeAnswer = dialog.Create(*ProgressDialog); + + switch (writeAnswer) + { + case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT; + case IDYES: *answer = NOverwriteAnswer::kYes; break; + case IDNO: *answer = NOverwriteAnswer::kNo; break; + case IDB_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break; + case IDB_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break; + case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break; + default: return E_FAIL; + } + return S_OK; +} + + +STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */) +{ + _isFolder = IntToBool(isFolder); + _currentFilePath = name; + + const UString *msg = &_lang_Empty; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break; + case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break; + case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break; + // default: s = "Unknown operation"; + } + + return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder)); +} + +STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s) +{ + AddError_Message(s); + return S_OK; +} + +HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path) +{ + ThereAreMessageErrors = true; + ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path)); + return S_OK; +} + +#ifndef _SFX + +STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s) +{ + AddError_Message(s); + return S_OK; +} + +#endif + +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s); +void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s) +{ + s.Empty(); + + if (opRes == NArchive::NExtract::NOperationResult::kOK) + return; + + UINT messageID = 0; + UINT id = 0; + + switch (opRes) + { + case NArchive::NExtract::NOperationResult::kUnsupportedMethod: + messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD; + id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD; + break; + case NArchive::NExtract::NOperationResult::kDataError: + messageID = encrypted ? + IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_DATA_ERROR; + id = IDS_EXTRACT_MSG_DATA_ERROR; + break; + case NArchive::NExtract::NOperationResult::kCRCError: + messageID = encrypted ? + IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED: + IDS_EXTRACT_MESSAGE_CRC_ERROR; + id = IDS_EXTRACT_MSG_CRC_ERROR; + break; + case NArchive::NExtract::NOperationResult::kUnavailable: + id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA; + break; + case NArchive::NExtract::NOperationResult::kUnexpectedEnd: + id = IDS_EXTRACT_MSG_UEXPECTED_END; + break; + case NArchive::NExtract::NOperationResult::kDataAfterEnd: + id = IDS_EXTRACT_MSG_DATA_AFTER_END; + break; + case NArchive::NExtract::NOperationResult::kIsNotArc: + id = IDS_EXTRACT_MSG_IS_NOT_ARC; + break; + case NArchive::NExtract::NOperationResult::kHeadersError: + id = IDS_EXTRACT_MSG_HEADERS_ERROR; + break; + case NArchive::NExtract::NOperationResult::kWrongPassword: + id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM; + break; + /* + default: + messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR; + break; + */ + } + + UString msg; + UString msgOld; + + #ifndef _SFX + if (id != 0) + LangString_OnlyFromLangFile(id, msg); + if (messageID != 0 && msg.IsEmpty()) + LangString_OnlyFromLangFile(messageID, msgOld); + #endif + + if (msg.IsEmpty() && !msgOld.IsEmpty()) + s = MyFormatNew(msgOld, fileName); + else + { + if (msg.IsEmpty() && id != 0) + LangString(id, msg); + if (!msg.IsEmpty()) + s += msg; + else + { + s += "Error #"; + s.Add_UInt32(opRes); + } + + if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword) + { + // s += " : "; + // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED); + s += " : "; + AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); + } + s += " : "; + s += fileName; + } +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted) +{ + switch (opRes) + { + case NArchive::NExtract::NOperationResult::kOK: + break; + default: + { + UString s; + SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s); + Add_ArchiveName_Error(); + AddError_Message(s); + } + } + + #ifndef _SFX + if (_isFolder) + NumFolders++; + else + NumFiles++; + ProgressDialog->Sync.Set_NumFilesCur(NumFiles); + #endif + + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name) +{ + if (opRes != NArchive::NExtract::NOperationResult::kOK) + { + UString s; + SetExtractErrorMessage(opRes, encrypted, name, s); + Add_ArchiveName_Error(); + AddError_Message(s); + } + return S_OK; +} + +//////////////////////////////////////// +// IExtractCallbackUI + +HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */) +{ + #ifndef _SFX + RINOK(ProgressDialog->Sync.CheckStop()); + ProgressDialog->Sync.Set_TitleFileName(name); + #endif + _currentArchivePath = name; + return S_OK; +} + +HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path) +{ + _currentFilePath = path; + #ifndef _SFX + ProgressDialog->Sync.Set_FilePath(path); + #endif + return S_OK; +} + +#ifndef _SFX + +HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path) +{ + #ifndef _SFX + if (NeedAddFile) + NumFiles++; + NeedAddFile = true; + ProgressDialog->Sync.Set_NumFilesCur(NumFiles); + #endif + return SetCurrentFilePath2(path); +} + +#endif + +UString HResultToMessage(HRESULT errorCode); + +static const UInt32 k_ErrorFlagsIds[] = +{ + IDS_EXTRACT_MSG_IS_NOT_ARC, + IDS_EXTRACT_MSG_HEADERS_ERROR, + IDS_EXTRACT_MSG_HEADERS_ERROR, + IDS_OPEN_MSG_UNAVAILABLE_START, + IDS_OPEN_MSG_UNCONFIRMED_START, + IDS_EXTRACT_MSG_UEXPECTED_END, + IDS_EXTRACT_MSG_DATA_AFTER_END, + IDS_EXTRACT_MSG_UNSUPPORTED_METHOD, + IDS_OPEN_MSG_UNSUPPORTED_FEATURE, + IDS_EXTRACT_MSG_DATA_ERROR, + IDS_EXTRACT_MSG_CRC_ERROR +}; + +static void AddNewLineString(UString &s, const UString &m) +{ + s += m; + s.Add_LF(); +} + +UString GetOpenArcErrorMessage(UInt32 errorFlags); +UString GetOpenArcErrorMessage(UInt32 errorFlags) +{ + UString s; + + for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++) + { + UInt32 f = ((UInt32)1 << i); + if ((errorFlags & f) == 0) + continue; + UInt32 id = k_ErrorFlagsIds[i]; + UString m = LangString(id); + if (m.IsEmpty()) + continue; + if (f == kpv_ErrorFlags_EncryptedHeadersError) + { + m += " : "; + AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS); + } + if (!s.IsEmpty()) + s.Add_LF(); + s += m; + errorFlags &= ~f; + } + + if (errorFlags != 0) + { + char sz[16]; + sz[0] = '0'; + sz[1] = 'x'; + ConvertUInt32ToHex(errorFlags, sz + 2); + if (!s.IsEmpty()) + s.Add_LF(); + s += sz; + } + + return s; +} + +static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er) +{ + UInt32 errorFlags = er.GetErrorFlags(); + UInt32 warningFlags = er.GetWarningFlags(); + + if (errorFlags != 0) + AddNewLineString(s, GetOpenArcErrorMessage(errorFlags)); + + if (!er.ErrorMessage.IsEmpty()) + AddNewLineString(s, er.ErrorMessage); + + if (warningFlags != 0) + { + s += GetNameOfProperty(kpidWarningFlags, L"Warnings"); + s += ":"; + s.Add_LF(); + AddNewLineString(s, GetOpenArcErrorMessage(warningFlags)); + } + + if (!er.WarningMessage.IsEmpty()) + { + s += GetNameOfProperty(kpidWarning, L"Warning"); + s += ": "; + s += er.WarningMessage; + s.Add_LF(); + } +} + +static UString GetBracedType(const wchar_t *type) +{ + UString s ('['); + s += type; + s += ']'; + return s; +} + +void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result); +void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) +{ + FOR_VECTOR (level, arcLink.Arcs) + { + const CArc &arc = arcLink.Arcs[level]; + const CArcErrorInfo &er = arc.ErrorInfo; + + if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0) + continue; + + if (s.IsEmpty()) + { + s += name; + s.Add_LF(); + } + + if (level != 0) + { + AddNewLineString(s, arc.Path); + } + + ErrorInfo_Print(s, er); + + if (er.ErrorFormatIndex >= 0) + { + AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning")); + if (arc.FormatIndex == er.ErrorFormatIndex) + { + AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET)); + } + else + { + AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex)))); + AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex)))); + } + } + } + + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK) + { + s += name; + s.Add_LF(); + if (!arcLink.Arcs.IsEmpty()) + AddNewLineString(s, arcLink.NonOpen_ArcPath); + + if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE) + { + UINT id = IDS_CANT_OPEN_ARCHIVE; + UString param; + if (arcLink.PasswordWasAsked) + id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE; + else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0) + { + id = IDS_CANT_OPEN_AS_TYPE; + param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex)); + } + UString s2 = MyFormatNew(id, param); + s2.Replace(L" ''", L""); + s2.Replace(L"''", L""); + s += s2; + } + else + s += HResultToMessage(result); + + s.Add_LF(); + ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo); + } + + if (!s.IsEmpty() && s.Back() == '\n') + s.DeleteBack(); +} + +HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) +{ + _currentArchivePath = name; + _needWriteArchivePath = true; + + UString s; + OpenResult_GUI(s, codecs, arcLink, name, result); + if (!s.IsEmpty()) + { + NumArchiveErrors++; + AddError_Message(s); + _needWriteArchivePath = false; + } + + return S_OK; +} + +HRESULT CExtractCallbackImp::ThereAreNoFiles() +{ + return S_OK; +} + +void CExtractCallbackImp::Add_ArchiveName_Error() +{ + if (_needWriteArchivePath) + { + if (!_currentArchivePath.IsEmpty()) + AddError_Message(_currentArchivePath); + _needWriteArchivePath = false; + } +} + +HRESULT CExtractCallbackImp::ExtractResult(HRESULT result) +{ + if (result == S_OK) + return result; + NumArchiveErrors++; + if (result == E_ABORT + || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) + ) + return result; + + Add_ArchiveName_Error(); + if (!_currentFilePath.IsEmpty()) + MessageError(_currentFilePath); + MessageError(NError::MyFormatMessage(result)); + return S_OK; +} + +#ifndef _NO_CRYPTO + +HRESULT CExtractCallbackImp::SetPassword(const UString &password) +{ + PasswordIsDefined = true; + Password = password; + return S_OK; +} + +STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password) +{ + PasswordWasAsked = true; + if (!PasswordIsDefined) + { + CPasswordDialog dialog; + #ifndef _SFX + bool showPassword = NExtract::Read_ShowPassword(); + dialog.ShowPassword = showPassword; + #endif + ProgressDialog->WaitCreating(); + if (dialog.Create(*ProgressDialog) != IDOK) + return E_ABORT; + Password = dialog.Password; + PasswordIsDefined = true; + #ifndef _SFX + if (dialog.ShowPassword != showPassword) + NExtract::Save_ShowPassword(dialog.ShowPassword); + #endif + } + return StringToBstr(Password, password); +} + +#endif + +#ifndef _SFX + +STDMETHODIMP CExtractCallbackImp::AskWrite( + const wchar_t *srcPath, Int32 srcIsFolder, + const FILETIME *srcTime, const UInt64 *srcSize, + const wchar_t *destPath, + BSTR *destPathResult, + Int32 *writeAnswer) +{ + UString destPathResultTemp = destPath; + + // RINOK(StringToBstr(destPath, destPathResult)); + + *destPathResult = 0; + *writeAnswer = BoolToInt(false); + + FString destPathSys = us2fs(destPath); + bool srcIsFolderSpec = IntToBool(srcIsFolder); + CFileInfo destFileInfo; + + if (destFileInfo.Find(destPathSys)) + { + if (srcIsFolderSpec) + { + if (!destFileInfo.IsDir()) + { + RINOK(MessageError("Cannot replace file with folder with same name", destPathSys)); + return E_ABORT; + } + *writeAnswer = BoolToInt(false); + return S_OK; + } + + if (destFileInfo.IsDir()) + { + RINOK(MessageError("Cannot replace folder with file with same name", destPathSys)); + *writeAnswer = BoolToInt(false); + return S_OK; + } + + switch (OverwriteMode) + { + case NExtract::NOverwriteMode::kSkip: + return S_OK; + case NExtract::NOverwriteMode::kAsk: + { + Int32 overwriteResult; + UString destPathSpec = destPath; + int slashPos = destPathSpec.ReverseFind_PathSepar(); + destPathSpec.DeleteFrom((unsigned)(slashPos + 1)); + destPathSpec += fs2us(destFileInfo.Name); + + RINOK(AskOverwrite( + destPathSpec, + &destFileInfo.MTime, &destFileInfo.Size, + srcPath, + srcTime, srcSize, + &overwriteResult)); + + switch (overwriteResult) + { + case NOverwriteAnswer::kCancel: return E_ABORT; + case NOverwriteAnswer::kNo: return S_OK; + case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK; + case NOverwriteAnswer::kYes: break; + case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break; + case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break; + default: + return E_FAIL; + } + break; + } + default: + break; + } + + if (OverwriteMode == NExtract::NOverwriteMode::kRename) + { + if (!AutoRenamePath(destPathSys)) + { + RINOK(MessageError("Cannot create name for file", destPathSys)); + return E_ABORT; + } + destPathResultTemp = fs2us(destPathSys); + } + else + { + if (NFind::DoesFileExist_Raw(destPathSys)) + if (!NDir::DeleteFileAlways(destPathSys)) + if (GetLastError() != ERROR_FILE_NOT_FOUND) + { + RINOK(MessageError("Cannot delete output file", destPathSys)); + return E_ABORT; + } + } + } + *writeAnswer = BoolToInt(true); + return StringToBstr(destPathResultTemp, destPathResult); +} + + +STDMETHODIMP CExtractCallbackImp::UseExtractToStream(Int32 *res) +{ + *res = BoolToInt(StreamMode); + return S_OK; +} + +static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined) +{ + ftDefined = false; + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(propID, &prop)); + if (prop.vt == VT_FILETIME) + { + ft = prop.filetime; + ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0); + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + + +static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result) +{ + NCOM::CPropVariant prop; + result = false; + RINOK(getProp->GetProp(propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + + +STDMETHODIMP CExtractCallbackImp::GetStream7(const wchar_t *name, + Int32 isDir, + ISequentialOutStream **outStream, Int32 askExtractMode, + IGetProp *getProp) +{ + COM_TRY_BEGIN + *outStream = 0; + _newVirtFileWasAdded = false; + _hashStreamWasUsed = false; + _needUpdateStat = false; + + if (_hashStream) + _hashStreamSpec->ReleaseStream(); + + GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream); + + if (!ProcessAltStreams && _isAltStream) + return S_OK; + + _filePath = name; + _isFolder = IntToBool(isDir); + _curSize = 0; + _curSizeDefined = false; + + UInt64 size = 0; + bool sizeDefined; + { + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(kpidSize, &prop)); + sizeDefined = ConvertPropVariantToUInt64(prop, size); + } + + if (sizeDefined) + { + _curSize = size; + _curSizeDefined = true; + } + + if (askExtractMode != NArchive::NExtract::NAskMode::kExtract && + askExtractMode != NArchive::NExtract::NAskMode::kTest) + return S_OK; + + _needUpdateStat = true; + + CMyComPtr outStreamLoc; + + if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract) + { + CVirtFile &file = VirtFileSystemSpec->AddNewFile(); + _newVirtFileWasAdded = true; + file.Name = name; + file.IsDir = IntToBool(isDir); + file.IsAltStream = _isAltStream; + file.Size = 0; + + RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined)); + RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined)); + RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined)); + + NCOM::CPropVariant prop; + RINOK(getProp->GetProp(kpidAttrib, &prop)); + if (prop.vt == VT_UI4) + { + file.Attrib = prop.ulVal; + file.AttribDefined = true; + } + // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY; + + file.ExpectedSize = 0; + if (sizeDefined) + file.ExpectedSize = size; + outStreamLoc = VirtFileSystem; + } + + if (_hashStream) + { + { + _hashStreamSpec->SetStream(outStreamLoc); + outStreamLoc = _hashStream; + _hashStreamSpec->Init(true); + _hashStreamWasUsed = true; + } + } + + if (outStreamLoc) + *outStream = outStreamLoc.Detach(); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode) +{ + COM_TRY_BEGIN + _needUpdateStat = ( + askExtractMode == NArchive::NExtract::NAskMode::kExtract || + askExtractMode == NArchive::NExtract::NAskMode::kTest); + + /* + _extractMode = false; + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; + }; + */ + return SetCurrentFilePath2(_filePath); + COM_TRY_END +} + +STDMETHODIMP CExtractCallbackImp::SetOperationResult7(Int32 opRes, Int32 encrypted) +{ + COM_TRY_BEGIN + if (VirtFileSystem && _newVirtFileWasAdded) + { + // FIXME: probably we must request file size from VirtFileSystem + // _curSize = VirtFileSystem->GetLastFileSize() + // _curSizeDefined = true; + RINOK(VirtFileSystemSpec->CloseMemFile()); + } + if (_hashStream && _hashStreamWasUsed) + { + _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath); + _curSize = _hashStreamSpec->GetSize(); + _curSizeDefined = true; + _hashStreamSpec->ReleaseStream(); + _hashStreamWasUsed = false; + } + else if (_hashCalc && _needUpdateStat) + { + _hashCalc->SetSize(_curSize); + _hashCalc->Final(_isFolder, _isAltStream, _filePath); + } + return SetOperationResult(opRes, encrypted); + COM_TRY_END +} + + + +// static const UInt32 kBlockSize = ((UInt32)1 << 31); + +STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (!_fileMode) + { + CVirtFile &file = Files.Back(); + size_t rem = file.Data.Size() - (size_t)file.Size; + bool useMem = true; + if (rem < size) + { + UInt64 b = 0; + if (file.Data.Size() == 0) + b = file.ExpectedSize; + UInt64 a = file.Size + size; + if (b < a) + b = a; + a = (UInt64)file.Data.Size() * 2; + if (b < a) + b = a; + useMem = false; + const size_t b_sizet = (size_t)b; + if (b == b_sizet && b <= MaxTotalAllocSize) + useMem = file.Data.ReAlloc_KeepData(b_sizet, (size_t)file.Size); + } + if (useMem) + { + memcpy(file.Data + file.Size, data, size); + file.Size += size; + if (processedSize) + *processedSize = (UInt32)size; + return S_OK; + } + _fileMode = true; + } + RINOK(FlushToDisk(false)); + return _outFileStream->Write(data, size, processedSize); +} + +HRESULT CVirtFileSystem::FlushToDisk(bool closeLast) +{ + if (!_outFileStream) + { + _outFileStreamSpec = new COutFileStream; + _outFileStream = _outFileStreamSpec; + } + while (_numFlushed < Files.Size()) + { + const CVirtFile &file = Files[_numFlushed]; + const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name)); + if (!_fileIsOpen) + { + if (!_outFileStreamSpec->Create(path, false)) + { + _outFileStream.Release(); + return E_FAIL; + // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath)); + } + _fileIsOpen = true; + RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size)); + } + if (_numFlushed == Files.Size() - 1 && !closeLast) + break; + if (file.CTimeDefined || + file.ATimeDefined || + file.MTimeDefined) + _outFileStreamSpec->SetTime( + file.CTimeDefined ? &file.CTime : NULL, + file.ATimeDefined ? &file.ATime : NULL, + file.MTimeDefined ? &file.MTime : NULL); + _outFileStreamSpec->Close(); + _numFlushed++; + _fileIsOpen = false; + if (file.AttribDefined) + NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib); + } + return S_OK; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.h new file mode 100644 index 0000000..297492e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ExtractCallback.h @@ -0,0 +1,326 @@ +// ExtractCallback.h + +#ifndef __EXTRACT_CALLBACK_H +#define __EXTRACT_CALLBACK_H + +#include "../../../../C/Alloc.h" + +#include "../../../Common/MyCom.h" +#include "../../../Common/StringConvert.h" + +#ifndef _SFX +#include "../Agent/IFolderArchive.h" +#endif + +#include "../Common/ArchiveExtractCallback.h" +#include "../Common/ArchiveOpenCallback.h" + +#ifndef _NO_CRYPTO +#include "../../IPassword.h" +#endif + +#ifndef _SFX +#include "IFolder.h" +#endif + +#include "ProgressDialog2.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +#ifndef _SFX + +class CGrowBuf +{ + Byte *_items; + size_t _size; + + CLASS_NO_COPY(CGrowBuf); + +public: + bool ReAlloc_KeepData(size_t newSize, size_t keepSize) + { + void *buf = MyAlloc(newSize); + if (!buf) + return false; + if (keepSize != 0) + memcpy(buf, _items, keepSize); + MyFree(_items); + _items = (Byte *)buf; + _size = newSize; + return true; + } + + CGrowBuf(): _items(0), _size(0) {} + ~CGrowBuf() { MyFree(_items); } + + operator Byte *() { return _items; } + operator const Byte *() const { return _items; } + size_t Size() const { return _size; } +}; + +struct CVirtFile +{ + CGrowBuf Data; + + UInt64 Size; // real size + UInt64 ExpectedSize; // the size from props request. 0 if unknown + + UString Name; + + bool CTimeDefined; + bool ATimeDefined; + bool MTimeDefined; + bool AttribDefined; + + bool IsDir; + bool IsAltStream; + + DWORD Attrib; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + CVirtFile(): + CTimeDefined(false), + ATimeDefined(false), + MTimeDefined(false), + AttribDefined(false), + IsDir(false), + IsAltStream(false) {} +}; + +class CVirtFileSystem: + public ISequentialOutStream, + public CMyUnknownImp +{ + UInt64 _totalAllocSize; + + size_t _pos; + unsigned _numFlushed; + bool _fileIsOpen; + bool _fileMode; + COutFileStream *_outFileStreamSpec; + CMyComPtr _outFileStream; +public: + CObjectVector Files; + UInt64 MaxTotalAllocSize; + FString DirPrefix; + + CVirtFile &AddNewFile() + { + if (!Files.IsEmpty()) + { + MaxTotalAllocSize -= Files.Back().Data.Size(); + } + return Files.AddNew(); + } + HRESULT CloseMemFile() + { + if (_fileMode) + { + return FlushToDisk(true); + } + CVirtFile &file = Files.Back(); + if (file.Data.Size() != file.Size) + { + file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size); + } + return S_OK; + } + + bool IsStreamInMem() const + { + if (_fileMode) + return false; + if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir) + return false; + return true; + } + + size_t GetMemStreamWrittenSize() const { return _pos; } + + CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {} + + void Init() + { + _totalAllocSize = 0; + _fileMode = false; + _pos = 0; + _numFlushed = 0; + _fileIsOpen = false; + } + + HRESULT CloseFile(const FString &path); + HRESULT FlushToDisk(bool closeLast); + size_t GetPos() const { return _pos; } + + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +#endif + +class CExtractCallbackImp: + public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback + public IOpenCallbackUI, + public IFolderArchiveExtractCallback2, + #ifndef _SFX + public IFolderOperationsExtractCallback, + public IFolderExtractToStreamCallback, + public ICompressProgressInfo, + #endif + #ifndef _NO_CRYPTO + public ICryptoGetTextPassword, + #endif + public CMyUnknownImp +{ + HRESULT MessageError(const char *message, const FString &path); + void Add_ArchiveName_Error(); +public: + MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) + MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2) + #ifndef _SFX + MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback) + MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback) + MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo) + #endif + #ifndef _NO_CRYPTO + MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) + #endif + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + INTERFACE_IProgress(;) + INTERFACE_IOpenCallbackUI(;) + INTERFACE_IFolderArchiveExtractCallback(;) + INTERFACE_IFolderArchiveExtractCallback2(;) + // STDMETHOD(SetTotalFiles)(UInt64 total); + // STDMETHOD(SetCompletedFiles)(const UInt64 *value); + + INTERFACE_IExtractCallbackUI(;) + + #ifndef _SFX + // IFolderOperationsExtractCallback + STDMETHOD(AskWrite)( + const wchar_t *srcPath, + Int32 srcIsFolder, + const FILETIME *srcTime, + const UInt64 *srcSize, + const wchar_t *destPathRequest, + BSTR *destPathResult, + Int32 *writeAnswer); + STDMETHOD(ShowMessage)(const wchar_t *message); + STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath); + STDMETHOD(SetNumFiles)(UInt64 numFiles); + INTERFACE_IFolderExtractToStreamCallback(;) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + #endif + + // ICryptoGetTextPassword + #ifndef _NO_CRYPTO + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + #endif + +private: + UString _currentArchivePath; + bool _needWriteArchivePath; + + UString _currentFilePath; + bool _isFolder; + + bool _isAltStream; + UInt64 _curSize; + bool _curSizeDefined; + UString _filePath; + // bool _extractMode; + // bool _testMode; + bool _newVirtFileWasAdded; + bool _needUpdateStat; + + + HRESULT SetCurrentFilePath2(const wchar_t *filePath); + void AddError_Message(LPCWSTR message); + + #ifndef _SFX + bool _hashStreamWasUsed; + COutStreamWithHash *_hashStreamSpec; + CMyComPtr _hashStream; + IHashCalc *_hashCalc; // it's for stat in Test operation + #endif + +public: + + #ifndef _SFX + CVirtFileSystem *VirtFileSystemSpec; + CMyComPtr VirtFileSystem; + #endif + + bool ProcessAltStreams; + + bool StreamMode; + + CProgressDialog *ProgressDialog; + #ifndef _SFX + UInt64 NumFolders; + UInt64 NumFiles; + bool NeedAddFile; + #endif + UInt32 NumArchiveErrors; + bool ThereAreMessageErrors; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + #ifndef _NO_CRYPTO + bool PasswordIsDefined; + bool PasswordWasAsked; + UString Password; + #endif + + + UString _lang_Extracting; + UString _lang_Testing; + UString _lang_Skipping; + UString _lang_Empty; + + bool _totalFilesDefined; + bool _totalBytesDefined; + bool MultiArcMode; + + CExtractCallbackImp(): + #ifndef _SFX + _hashCalc(NULL), + #endif + ProcessAltStreams(true), + StreamMode(false), + OverwriteMode(NExtract::NOverwriteMode::kAsk), + #ifndef _NO_CRYPTO + PasswordIsDefined(false), + PasswordWasAsked(false), + #endif + _totalFilesDefined(false), + _totalBytesDefined(false), + MultiArcMode(false) + {} + + ~CExtractCallbackImp(); + void Init(); + + #ifndef _SFX + void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; } + + void SetHashMethods(IHashCalc *hash) + { + if (!hash) + return; + _hashStreamSpec = new COutStreamWithHash; + _hashStream = _hashStreamSpec; + _hashStreamSpec->_hash = hash; + } + #endif + + bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.cpp new file mode 100644 index 0000000..2143c3f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.cpp @@ -0,0 +1,28 @@ +// FormatUtils.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "FormatUtils.h" + +#include "LangUtils.h" + +UString NumberToString(UInt64 number) +{ + wchar_t numberString[32]; + ConvertUInt64ToString(number, numberString); + return numberString; +} + +UString MyFormatNew(const UString &format, const UString &argument) +{ + UString result = format; + result.Replace(L"{0}", argument); + return result; +} + +UString MyFormatNew(UINT resourceID, const UString &argument) +{ + return MyFormatNew(LangString(resourceID), argument); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.h new file mode 100644 index 0000000..993e803 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/FormatUtils.h @@ -0,0 +1,14 @@ +// FormatUtils.h + +#ifndef __FORMAT_UTILS_H +#define __FORMAT_UTILS_H + +#include "../../../Common/MyTypes.h" +#include "../../../Common/MyString.h" + +UString NumberToString(UInt64 number); + +UString MyFormatNew(const UString &format, const UString &argument); +UString MyFormatNew(UINT resourceID, const UString &argument); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/LangUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/LangUtils.h new file mode 100644 index 0000000..d63a443 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/LangUtils.h @@ -0,0 +1,40 @@ +// LangUtils.h + +#ifndef __LANG_UTILS_H +#define __LANG_UTILS_H + +#include "../../../Windows/ResourceString.h" + +#ifdef LANG + +extern UString g_LangID; + +struct CIDLangPair +{ + UInt32 ControlID; + UInt32 LangID; +}; + +void ReloadLang(); +void LoadLangOneTime(); +FString GetLangDirPrefix(); + +void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID); +void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems); +void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems); +void LangSetWindowText(HWND window, UInt32 langID); + +UString LangString(UInt32 langID); +void AddLangString(UString &s, UInt32 langID); +void LangString(UInt32 langID, UString &dest); +void LangString_OnlyFromLangFile(UInt32 langID, UString &dest); + +#else + +inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); } +inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); } +inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); } + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/MyWindowsNew.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/MyWindowsNew.h new file mode 100644 index 0000000..48a9535 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/MyWindowsNew.h @@ -0,0 +1,76 @@ +// MyWindowsNew.h + +#ifndef __MY_WINDOWS_NEW_H +#define __MY_WINDOWS_NEW_H + +#ifdef _MSC_VER + +#include + +#ifndef __ITaskbarList3_INTERFACE_DEFINED__ +#define __ITaskbarList3_INTERFACE_DEFINED__ + +typedef enum THUMBBUTTONFLAGS +{ + THBF_ENABLED = 0, + THBF_DISABLED = 0x1, + THBF_DISMISSONCLICK = 0x2, + THBF_NOBACKGROUND = 0x4, + THBF_HIDDEN = 0x8, + THBF_NONINTERACTIVE = 0x10 +} THUMBBUTTONFLAGS; + +typedef enum THUMBBUTTONMASK +{ + THB_BITMAP = 0x1, + THB_ICON = 0x2, + THB_TOOLTIP = 0x4, + THB_FLAGS = 0x8 +} THUMBBUTTONMASK; + +// #include + +typedef struct THUMBBUTTON +{ + THUMBBUTTONMASK dwMask; + UINT iId; + UINT iBitmap; + HICON hIcon; + WCHAR szTip[260]; + THUMBBUTTONFLAGS dwFlags; +} THUMBBUTTON; + +typedef struct THUMBBUTTON *LPTHUMBBUTTON; + +typedef enum TBPFLAG +{ + TBPF_NOPROGRESS = 0, + TBPF_INDETERMINATE = 0x1, + TBPF_NORMAL = 0x2, + TBPF_ERROR = 0x4, + TBPF_PAUSED = 0x8 +} TBPFLAG; + +DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF); + +struct ITaskbarList3: public ITaskbarList2 +{ + STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0; + STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0; + STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0; + STDMETHOD(UnregisterTab)(HWND hwndTab) = 0; + STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0; + STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0; + STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0; + STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0; + STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0; + STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0; + STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0; + STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0; +}; + +#endif + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.cpp new file mode 100644 index 0000000..b455b14 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.cpp @@ -0,0 +1,138 @@ +// OverwriteDialog.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/PropVariantConv.h" +#include "../../../Windows/ResourceString.h" + +#include "../../../Windows/Control/Static.h" + +#include "FormatUtils.h" +#include "LangUtils.h" +#include "OverwriteDialog.h" + +#include "PropertyNameRes.h" + +using namespace NWindows; + +#ifdef LANG +static const UInt32 kLangIDs[] = +{ + IDT_OVERWRITE_HEADER, + IDT_OVERWRITE_QUESTION_BEGIN, + IDT_OVERWRITE_QUESTION_END, + IDB_YES_TO_ALL, + IDB_NO_TO_ALL, + IDB_AUTO_RENAME +}; +#endif + +static const unsigned kCurrentFileNameSizeLimit = 82; +static const unsigned kCurrentFileNameSizeLimit2 = 30; + +void COverwriteDialog::ReduceString(UString &s) +{ + unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2; + if (s.Len() > size) + { + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); + } + if (!s.IsEmpty() && s.Back() == ' ') + { + // s += (wchar_t)(0x2423); + s.InsertAtFront(L'\"'); + s += L'\"'; + } +} + +void COverwriteDialog::SetFileInfoControl(int textID, int iconID, + const NOverwriteDialog::CFileInfo &fileInfo) +{ + UString sizeString; + if (fileInfo.SizeIsDefined) + sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size)); + + const UString &fileName = fileInfo.Name; + int slashPos = fileName.ReverseFind_PathSepar(); + UString s1 = fileName.Left((unsigned)(slashPos + 1)); + UString s2 = fileName.Ptr((unsigned)(slashPos + 1)); + + ReduceString(s1); + ReduceString(s2); + + UString s = s1; + s.Add_LF(); + s += s2; + s.Add_LF(); + s += sizeString; + s.Add_LF(); + + if (fileInfo.TimeIsDefined) + { + AddLangString(s, IDS_PROP_MTIME); + s += ": "; + char t[32]; + ConvertUtcFileTimeToString(fileInfo.Time, t); + s += t; + } + + NControl::CDialogChildControl control; + control.Init(*this, textID); + control.SetText(s); + + SHFILEINFO shellFileInfo; + if (::SHGetFileInfo( + GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo, + sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON)) + { + NControl::CStatic staticContol; + staticContol.Attach(GetItem(iconID)); + staticContol.SetIcon(shellFileInfo.hIcon); + } +} + +bool COverwriteDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(*this, IDD_OVERWRITE); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + #endif + SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo); + SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo); + NormalizePosition(); + + if (!ShowExtraButtons) + { + HideItem(IDB_YES_TO_ALL); + HideItem(IDB_NO_TO_ALL); + HideItem(IDB_AUTO_RENAME); + } + + if (DefaultButton_is_NO) + { + PostMsg(DM_SETDEFID, IDNO); + HWND h = GetItem(IDNO); + PostMsg(WM_NEXTDLGCTL, (WPARAM)h, TRUE); + // ::SetFocus(h); + } + + return CModalDialog::OnInit(); +} + +bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDYES: + case IDNO: + case IDB_YES_TO_ALL: + case IDB_NO_TO_ALL: + case IDB_AUTO_RENAME: + End(buttonID); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.h new file mode 100644 index 0000000..24e56ca --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.h @@ -0,0 +1,79 @@ +// OverwriteDialog.h + +#ifndef __OVERWRITE_DIALOG_H +#define __OVERWRITE_DIALOG_H + +#include "../../../Windows/Control/Dialog.h" + +#include "DialogSize.h" +#include "OverwriteDialogRes.h" + +namespace NOverwriteDialog +{ + struct CFileInfo + { + bool SizeIsDefined; + bool TimeIsDefined; + UInt64 Size; + FILETIME Time; + UString Name; + + void SetTime(const FILETIME *t) + { + if (!t) + TimeIsDefined = false; + else + { + TimeIsDefined = true; + Time = *t; + } + } + + void SetSize(UInt64 size) + { + SizeIsDefined = true; + Size = size; + } + + void SetSize(const UInt64 *size) + { + if (!size) + SizeIsDefined = false; + else + SetSize(*size); + } + }; +} + +class COverwriteDialog: public NWindows::NControl::CModalDialog +{ + bool _isBig; + + void SetFileInfoControl(int textID, int iconID, const NOverwriteDialog::CFileInfo &fileInfo); + virtual bool OnInit(); + bool OnButtonClicked(int buttonID, HWND buttonHWND); + void ReduceString(UString &s); + +public: + bool ShowExtraButtons; + bool DefaultButton_is_NO; + + + COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {} + + INT_PTR Create(HWND parent = 0) + { + BIG_DIALOG_SIZE(280, 200); + #ifdef UNDER_CE + _isBig = isBig; + #else + _isBig = true; + #endif + return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent); + } + + NOverwriteDialog::CFileInfo OldFileInfo; + NOverwriteDialog::CFileInfo NewFileInfo; +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.rc new file mode 100644 index 0000000..29f9912 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialog.rc @@ -0,0 +1,91 @@ +#include "OverwriteDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 280 +#define yc 200 + +#undef iconSize +#define iconSize 24 + +#undef x +#undef fx +#undef fy +#define x (m + iconSize + m) +#define fx (xc - iconSize - m) +#define fy 50 + +#define bSizeBig 104 +#undef bx1 +#define bx1 (xs - m - bSizeBig) + +IDD_OVERWRITE DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Confirm File Replace" +BEGIN + LTEXT "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8 + LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8 + + ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX + + LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8 + + ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX + + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bSizeBig, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys + PUSHBUTTON "&Cancel", IDCANCEL, xs - m - bxs, by1, bxs, bys +END + + +#ifdef UNDER_CE + +#undef m +#undef xc +#undef yc + +#define m 4 +#define xc 152 +#define yc 144 + +#undef fy +#define fy 40 + +#undef bxs +#define bxs 48 + +#undef bx1 + +#define bx1 (xs - m - bxs) + +IDD_OVERWRITE_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Confirm File Replace" +BEGIN + LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8 + + ICON "", IDI_OVERWRITE_OLD_FILE, m, 20, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX + + LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 60, xc, 8 + + ICON "", IDI_OVERWRITE_NEW_FILE, m, 72, iconSize, iconSize + LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX + + PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys + PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys + PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bxs, bys + PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys + PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys + PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys +END + +#endif + + +STRINGTABLE +BEGIN + IDS_FILE_SIZE "{0} bytes" +END diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialogRes.h new file mode 100644 index 0000000..b480ba1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/OverwriteDialogRes.h @@ -0,0 +1,17 @@ +#define IDD_OVERWRITE 3500 +#define IDD_OVERWRITE_2 13500 + +#define IDT_OVERWRITE_HEADER 3501 +#define IDT_OVERWRITE_QUESTION_BEGIN 3502 +#define IDT_OVERWRITE_QUESTION_END 3503 +#define IDS_FILE_SIZE 3504 + +#define IDB_AUTO_RENAME 3505 +#define IDB_YES_TO_ALL 440 +#define IDB_NO_TO_ALL 441 + +#define IDI_OVERWRITE_OLD_FILE 100 +#define IDI_OVERWRITE_NEW_FILE 101 + +#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102 +#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.cpp new file mode 100644 index 0000000..6ead39c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.cpp @@ -0,0 +1,58 @@ +// PasswordDialog.cpp + +#include "StdAfx.h" + +#include "PasswordDialog.h" + +#ifdef LANG +#include "LangUtils.h" +#endif + +#ifdef LANG +static const UInt32 kLangIDs[] = +{ + IDT_PASSWORD_ENTER, + IDX_PASSWORD_SHOW +}; +#endif + +void CPasswordDialog::ReadControls() +{ + _passwordEdit.GetText(Password); + ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW); +} + +void CPasswordDialog::SetTextSpec() +{ + _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*')); + _passwordEdit.SetText(Password); +} + +bool CPasswordDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(*this, IDD_PASSWORD); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + #endif + _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD)); + CheckButton(IDX_PASSWORD_SHOW, ShowPassword); + SetTextSpec(); + return CModalDialog::OnInit(); +} + +bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + if (buttonID == IDX_PASSWORD_SHOW) + { + ReadControls(); + SetTextSpec(); + return true; + } + return CDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CPasswordDialog::OnOK() +{ + ReadControls(); + CModalDialog::OnOK(); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.h new file mode 100644 index 0000000..339ebda --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.h @@ -0,0 +1,28 @@ +// PasswordDialog.h + +#ifndef __PASSWORD_DIALOG_H +#define __PASSWORD_DIALOG_H + +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/Edit.h" + +#include "PasswordDialogRes.h" + +class CPasswordDialog: public NWindows::NControl::CModalDialog +{ + NWindows::NControl::CEdit _passwordEdit; + + virtual void OnOK(); + virtual bool OnInit(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + void SetTextSpec(); + void ReadControls(); +public: + UString Password; + bool ShowPassword; + + CPasswordDialog(): ShowPassword(false) {} + INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.rc new file mode 100644 index 0000000..90c57ef --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialog.rc @@ -0,0 +1,14 @@ +#include "PasswordDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 140 +#define yc 72 + +IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Enter password" +BEGIN + LTEXT "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8 + EDITTEXT IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10 + OK_CANCEL +END diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialogRes.h new file mode 100644 index 0000000..1fe32e1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PasswordDialogRes.h @@ -0,0 +1,5 @@ +#define IDD_PASSWORD 3800 +#define IDT_PASSWORD_ENTER 3801 +#define IDX_PASSWORD_SHOW 3803 + +#define IDE_PASSWORD_PASSWORD 120 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.cpp new file mode 100644 index 0000000..b688a90 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.cpp @@ -0,0 +1,199 @@ +// ProgressDialog.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "resource.h" + +#include "ProgressDialog.h" + +using namespace NWindows; + +extern HINSTANCE g_hInstance; + +static const UINT_PTR kTimerID = 3; +static const UINT kTimerElapse = 100; + +#ifdef LANG +#include "LangUtils.h" +#endif + +HRESULT CProgressSync::ProcessStopAndPause() +{ + for (;;) + { + if (GetStopped()) + return E_ABORT; + if (!GetPaused()) + break; + ::Sleep(100); + } + return S_OK; +} + +#ifndef _SFX +CProgressDialog::~CProgressDialog() +{ + AddToTitle(L""); +} +void CProgressDialog::AddToTitle(LPCWSTR s) +{ + if (MainWindow != 0) + MySetWindowText(MainWindow, UString(s) + MainTitle); +} +#endif + + +bool CProgressDialog::OnInit() +{ + _range = (UInt64)(Int64)-1; + _prevPercentValue = -1; + + _wasCreated = true; + _dialogCreatedEvent.Set(); + + #ifdef LANG + LangSetDlgItems(*this, NULL, 0); + #endif + + m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); + + if (IconID >= 0) + { + HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID)); + SetIcon(ICON_BIG, icon); + } + + _timer = SetTimer(kTimerID, kTimerElapse); + SetText(_title); + CheckNeedClose(); + return CModalDialog::OnInit(); +} + +void CProgressDialog::OnCancel() { Sync.SetStopped(true); } +void CProgressDialog::OnOK() { } + +void CProgressDialog::SetRange(UInt64 range) +{ + _range = range; + _peviousPos = (UInt64)(Int64)-1; + _converter.Init(range); + m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100% +} + +void CProgressDialog::SetPos(UInt64 pos) +{ + bool redraw = true; + if (pos < _range && pos > _peviousPos) + { + UInt64 posDelta = pos - _peviousPos; + if (posDelta < (_range >> 10)) + redraw = false; + } + if (redraw) + { + m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100% + _peviousPos = pos; + } +} + +bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) +{ + if (Sync.GetPaused()) + return true; + + CheckNeedClose(); + + UInt64 total, completed; + Sync.GetProgress(total, completed); + if (total != _range) + SetRange(total); + SetPos(completed); + + if (total == 0) + total = 1; + + int percentValue = (int)(completed * 100 / total); + if (percentValue != _prevPercentValue) + { + wchar_t s[64]; + ConvertUInt64ToString(percentValue, s); + UString title = s; + title += "% "; + SetText(title + _title); + #ifndef _SFX + AddToTitle(title + MainAddTitle); + #endif + _prevPercentValue = percentValue; + } + return true; +} + +bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case kCloseMessage: + { + if (_timer) + { + KillTimer(kTimerID); + _timer = 0; + } + if (_inCancelMessageBox) + { + _externalCloseMessageWasReceived = true; + break; + } + return OnExternalCloseMessage(); + } + /* + case WM_SETTEXT: + { + if (_timer == 0) + return true; + } + */ + } + return CModalDialog::OnMessage(message, wParam, lParam); +} + +bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDCANCEL: + { + bool paused = Sync.GetPaused(); + Sync.SetPaused(true); + _inCancelMessageBox = true; + int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL); + _inCancelMessageBox = false; + Sync.SetPaused(paused); + if (res == IDCANCEL || res == IDNO) + { + if (_externalCloseMessageWasReceived) + OnExternalCloseMessage(); + return true; + } + break; + } + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CProgressDialog::CheckNeedClose() +{ + if (_needClose) + { + PostMsg(kCloseMessage); + _needClose = false; + } +} + +bool CProgressDialog::OnExternalCloseMessage() +{ + End(0); + return true; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.h new file mode 100644 index 0000000..35c182a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.h @@ -0,0 +1,170 @@ +// ProgressDialog.h + +#ifndef __PROGRESS_DIALOG_H +#define __PROGRESS_DIALOG_H + +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" + +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ProgressBar.h" + +#include "ProgressDialogRes.h" + +class CProgressSync +{ + NWindows::NSynchronization::CCriticalSection _cs; + bool _stopped; + bool _paused; + UInt64 _total; + UInt64 _completed; +public: + CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {} + + HRESULT ProcessStopAndPause(); + bool GetStopped() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + return _stopped; + } + void SetStopped(bool value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _stopped = value; + } + bool GetPaused() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + return _paused; + } + void SetPaused(bool value) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _paused = value; + } + void SetProgress(UInt64 total, UInt64 completed) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _total = total; + _completed = completed; + } + void SetPos(UInt64 completed) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _completed = completed; + } + void GetProgress(UInt64 &total, UInt64 &completed) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + total = _total; + completed = _completed; + } +}; + +class CU64ToI32Converter +{ + UInt64 _numShiftBits; +public: + void Init(UInt64 range) + { + // Windows CE doesn't like big number here. + for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++) + range >>= 1; + } + int Count(UInt64 value) { return int(value >> _numShiftBits); } +}; + +class CProgressDialog: public NWindows::NControl::CModalDialog +{ +private: + UINT_PTR _timer; + + UString _title; + CU64ToI32Converter _converter; + UInt64 _peviousPos; + UInt64 _range; + NWindows::NControl::CProgressBar m_ProgressBar; + + int _prevPercentValue; + + bool _wasCreated; + bool _needClose; + bool _inCancelMessageBox; + bool _externalCloseMessageWasReceived; + + bool OnTimer(WPARAM timerID, LPARAM callback); + void SetRange(UInt64 range); + void SetPos(UInt64 pos); + virtual bool OnInit(); + virtual void OnCancel(); + virtual void OnOK(); + NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; + #ifndef _SFX + void AddToTitle(LPCWSTR string); + #endif + bool OnButtonClicked(int buttonID, HWND buttonHWND); + + void WaitCreating() { _dialogCreatedEvent.Lock(); } + void CheckNeedClose(); + bool OnExternalCloseMessage(); +public: + CProgressSync Sync; + int IconID; + + #ifndef _SFX + HWND MainWindow; + UString MainTitle; + UString MainAddTitle; + ~CProgressDialog(); + #endif + + CProgressDialog(): _timer(0) + #ifndef _SFX + ,MainWindow(0) + #endif + { + IconID = -1; + _wasCreated = false; + _needClose = false; + _inCancelMessageBox = false; + _externalCloseMessageWasReceived = false; + + if (_dialogCreatedEvent.Create() != S_OK) + throw 1334987; + } + + INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0) + { + _title = title; + INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent); + thread.Wait_Close(); + return res; + } + + enum + { + kCloseMessage = WM_APP + 1 + }; + + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + + void ProcessWasFinished() + { + WaitCreating(); + if (_wasCreated) + PostMsg(kCloseMessage); + else + _needClose = true; + }; +}; + + +class CProgressCloser +{ + CProgressDialog *_p; +public: + CProgressCloser(CProgressDialog &p) : _p(&p) {} + ~CProgressCloser() { _p->ProcessWasFinished(); } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.rc new file mode 100644 index 0000000..55d9923 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog.rc @@ -0,0 +1,12 @@ +#include "ProgressDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 172 +#define yc 44 + +IDD_PROGRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Progress" +BEGIN + PUSHBUTTON "Cancel", IDCANCEL, bx, by, bxs, bys + CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14 +END diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.cpp new file mode 100644 index 0000000..7b13246 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -0,0 +1,1355 @@ +// ProgressDialog2.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/Control/Static.h" +#include "../../../Windows/ErrorMsg.h" + +#include "../GUI/ExtractRes.h" + +#include "LangUtils.h" + +#include "DialogSize.h" +#include "ProgressDialog2.h" +#include "ProgressDialog2Res.h" + +using namespace NWindows; + +extern HINSTANCE g_hInstance; + +static const UINT_PTR kTimerID = 3; + +static const UINT kCloseMessage = WM_APP + 1; +// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog + +static const UINT kTimerElapse = + #ifdef UNDER_CE + 500 + #else + 200 + #endif + ; + +static const UINT kCreateDelay = + #ifdef UNDER_CE + 2500 + #else + 500 + #endif + ; + +static const DWORD kPauseSleepTime = 100; + +#ifdef LANG + +static const UInt32 kLangIDs[] = +{ + IDT_PROGRESS_ELAPSED, + IDT_PROGRESS_REMAINING, + IDT_PROGRESS_TOTAL, + IDT_PROGRESS_SPEED, + IDT_PROGRESS_PROCESSED, + IDT_PROGRESS_RATIO, + IDT_PROGRESS_ERRORS, + IDB_PROGRESS_BACKGROUND, + IDB_PAUSE +}; + +static const UInt32 kLangIDs_Colon[] = +{ + IDT_PROGRESS_PACKED, + IDT_PROGRESS_FILES +}; + +#endif + + +#define UNDEFINED_VAL ((UInt64)(Int64)-1) +#define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL; +#define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL) +#define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL) + +CProgressSync::CProgressSync(): + _stopped(false), _paused(false), + _bytesProgressMode(true), + _totalBytes(UNDEFINED_VAL), _completedBytes(0), + _totalFiles(UNDEFINED_VAL), _curFiles(0), + _inSize(UNDEFINED_VAL), + _outSize(UNDEFINED_VAL), + _isDir(false) + {} + +#define CHECK_STOP if (_stopped) return E_ABORT; if (!_paused) return S_OK; +#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs); + +bool CProgressSync::Get_Paused() +{ + CRITICAL_LOCK + return _paused; +} + +HRESULT CProgressSync::CheckStop() +{ + for (;;) + { + { + CRITICAL_LOCK + CHECK_STOP + } + ::Sleep(kPauseSleepTime); + } +} + +HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir) +{ + { + CRITICAL_LOCK + _totalFiles = numFiles; + _totalBytes = totalSize; + _filePath = fs2us(fileName); + _isDir = isDir; + // _completedBytes = 0; + CHECK_STOP + } + return CheckStop(); +} + +HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val) +{ + { + CRITICAL_LOCK + _totalFiles = val; + CHECK_STOP + } + return CheckStop(); +} + +void CProgressSync::Set_NumBytesTotal(UInt64 val) +{ + CRITICAL_LOCK + _totalBytes = val; +} + +void CProgressSync::Set_NumFilesCur(UInt64 val) +{ + CRITICAL_LOCK + _curFiles = val; +} + +HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val) +{ + { + CRITICAL_LOCK + if (val) + _completedBytes = *val; + CHECK_STOP + } + return CheckStop(); +} + +HRESULT CProgressSync::Set_NumBytesCur(UInt64 val) +{ + { + CRITICAL_LOCK + _completedBytes = val; + CHECK_STOP + } + return CheckStop(); +} + +void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize) +{ + CRITICAL_LOCK + if (inSize) + _inSize = *inSize; + if (outSize) + _outSize = *outSize; +} + +void CProgressSync::Set_TitleFileName(const UString &fileName) +{ + CRITICAL_LOCK + _titleFileName = fileName; +} + +void CProgressSync::Set_Status(const UString &s) +{ + CRITICAL_LOCK + _status = s; +} + +HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir) +{ + { + CRITICAL_LOCK + _status = s; + if (path) + _filePath = path; + else + _filePath.Empty(); + _isDir = isDir; + } + return CheckStop(); +} + +void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir) +{ + CRITICAL_LOCK + if (path) + _filePath = path; + else + _filePath.Empty(); + _isDir = isDir; +} + + +void CProgressSync::AddError_Message(const wchar_t *message) +{ + CRITICAL_LOCK + Messages.Add(message); +} + +void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name) +{ + UString s; + if (name && *name != 0) + s += name; + if (message && *message != 0) + { + if (!s.IsEmpty()) + s.Add_LF(); + s += message; + if (!s.IsEmpty() && s.Back() == L'\n') + s.DeleteBack(); + } + AddError_Message(s); +} + +void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name) +{ + UString s = NError::MyFormatMessage(systemError); + if (systemError == 0) + s = "Error"; + AddError_Message_Name(s, name); +} + +CProgressDialog::CProgressDialog(): + _timer(0), + CompressingMode(true), + MainWindow(0) +{ + _isDir = false; + + _numMessages = 0; + IconID = -1; + MessagesDisplayed = false; + _wasCreated = false; + _needClose = false; + _inCancelMessageBox = false; + _externalCloseMessageWasReceived = false; + + _numPostedMessages = 0; + _numAutoSizeMessages = 0; + _errorsWereDisplayed = false; + _waitCloseByCancelButton = false; + _cancelWasPressed = false; + ShowCompressionInfo = true; + WaitMode = false; + if (_dialogCreatedEvent.Create() != S_OK) + throw 1334987; + if (_createDialogEvent.Create() != S_OK) + throw 1334987; + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList); + if (_taskbarList) + _taskbarList->HrInit(); + #endif +} + +#ifndef _SFX + +CProgressDialog::~CProgressDialog() +{ + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + SetTaskbarProgressState(TBPF_NOPROGRESS); + #endif + AddToTitle(L""); +} +void CProgressDialog::AddToTitle(LPCWSTR s) +{ + if (MainWindow != 0) + { + CWindow window(MainWindow); + window.SetText((UString)s + MainTitle); + } +} + +#endif + + +void CProgressDialog::SetTaskbarProgressState() +{ + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + if (_taskbarList && _hwndForTaskbar) + { + TBPFLAG tbpFlags; + if (Sync.Get_Paused()) + tbpFlags = TBPF_PAUSED; + else + tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL; + SetTaskbarProgressState(tbpFlags); + } + #endif +} + +static const unsigned kTitleFileNameSizeLimit = 36; +static const unsigned kCurrentFileNameSizeLimit = 82; + +static void ReduceString(UString &s, unsigned size) +{ + if (s.Len() <= size) + return; + s.Delete(size / 2, s.Len() - size); + s.Insert(size / 2, L" ... "); +} + +void CProgressDialog::EnableErrorsControls(bool enable) +{ + ShowItem_Bool(IDT_PROGRESS_ERRORS, enable); + ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable); + ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable); +} + +bool CProgressDialog::OnInit() +{ + _hwndForTaskbar = MainWindow; + if (!_hwndForTaskbar) + _hwndForTaskbar = GetParent(); + if (!_hwndForTaskbar) + _hwndForTaskbar = *this; + + INIT_AS_UNDEFINED(_progressBar_Range); + INIT_AS_UNDEFINED(_progressBar_Pos); + + INIT_AS_UNDEFINED(_prevPercentValue); + INIT_AS_UNDEFINED(_prevElapsedSec); + INIT_AS_UNDEFINED(_prevRemainingSec); + + INIT_AS_UNDEFINED(_prevSpeed); + _prevSpeed_MoveBits = 0; + + _prevTime = ::GetTickCount(); + _elapsedTime = 0; + + INIT_AS_UNDEFINED(_totalBytes_Prev); + INIT_AS_UNDEFINED(_processed_Prev); + INIT_AS_UNDEFINED(_packed_Prev); + INIT_AS_UNDEFINED(_ratio_Prev); + + _filesStr_Prev.Empty(); + _filesTotStr_Prev.Empty(); + + _foreground = true; + + m_ProgressBar.Attach(GetItem(IDC_PROGRESS1)); + _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES)); + _messageList.SetUnicodeFormat(); + + _wasCreated = true; + _dialogCreatedEvent.Set(); + + #ifdef LANG + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon)); + #endif + + CWindow window(GetItem(IDB_PROGRESS_BACKGROUND)); + window.GetText(_background_String); + _backgrounded_String = _background_String; + _backgrounded_String.RemoveChar(L'&'); + + window = GetItem(IDB_PAUSE); + window.GetText(_pause_String); + + LangString(IDS_PROGRESS_FOREGROUND, _foreground_String); + LangString(IDS_CONTINUE, _continue_String); + LangString(IDS_PROGRESS_PAUSED, _paused_String); + + SetText(_title); + SetPauseText(); + SetPriorityText(); + + _messageList.InsertColumn(0, L"", 30); + _messageList.InsertColumn(1, L"", 600); + + _messageList.SetColumnWidthAuto(0); + _messageList.SetColumnWidthAuto(1); + + EnableErrorsControls(false); + + GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY); + _numReduceSymbols = kCurrentFileNameSizeLimit; + NormalizeSize(true); + + if (!ShowCompressionInfo) + { + HideItem(IDT_PROGRESS_PACKED); + HideItem(IDT_PROGRESS_PACKED_VAL); + HideItem(IDT_PROGRESS_RATIO); + HideItem(IDT_PROGRESS_RATIO_VAL); + } + + if (IconID >= 0) + { + HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID)); + // SetIcon(ICON_SMALL, icon); + SetIcon(ICON_BIG, icon); + } + _timer = SetTimer(kTimerID, kTimerElapse); + #ifdef UNDER_CE + Foreground(); + #endif + + CheckNeedClose(); + + SetTaskbarProgressState(); + + return CModalDialog::OnInit(); +} + +static const UINT kIDs[] = +{ + IDT_PROGRESS_ELAPSED, IDT_PROGRESS_ELAPSED_VAL, + IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL, + IDT_PROGRESS_FILES, IDT_PROGRESS_FILES_VAL, + 0, IDT_PROGRESS_FILES_TOTAL, + IDT_PROGRESS_ERRORS, IDT_PROGRESS_ERRORS_VAL, + + IDT_PROGRESS_TOTAL, IDT_PROGRESS_TOTAL_VAL, + IDT_PROGRESS_SPEED, IDT_PROGRESS_SPEED_VAL, + IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL, + IDT_PROGRESS_PACKED, IDT_PROGRESS_PACKED_VAL, + IDT_PROGRESS_RATIO, IDT_PROGRESS_RATIO_VAL +}; + +bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) +{ + int sY; + int sStep; + int mx, my; + { + RECT r; + GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r); + mx = r.left; + my = r.top; + sY = RECT_SIZE_Y(r); + GetClientRectOfItem(IDT_PROGRESS_REMAINING, r); + sStep = r.top - my; + } + + InvalidateRect(NULL); + + int xSizeClient = xSize - mx * 2; + + { + int i; + for (i = 800; i > 40; i = i * 9 / 10) + if (Units_To_Pixels_X(i) <= xSizeClient) + break; + _numReduceSymbols = i / 4; + } + + int yPos = ySize - my - _buttonSizeY; + + ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2); + ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2); + ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2); + + int bSizeX = _buttonSizeX; + int mx2 = mx; + for (;; mx2--) + { + int bSize2 = bSizeX * 3 + mx2 * 2; + if (bSize2 <= xSizeClient) + break; + if (mx2 < 5) + { + bSizeX = (xSizeClient - mx2 * 2) / 3; + break; + } + } + if (bSizeX < 2) + bSizeX = 2; + + { + RECT r; + GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r); + int y = r.top; + int ySize2 = yPos - my - y; + const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4; + int xx = xSize - mx * 2; + if (ySize2 < kMinYSize) + { + ySize2 = kMinYSize; + if (xx > bSizeX * 2) + xx -= bSizeX; + } + + _messageList.Move(mx, y, xx, ySize2); + } + + { + int xPos = xSize - mx; + xPos -= bSizeX; + MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY); + xPos -= (mx2 + bSizeX); + MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY); + xPos -= (mx2 + bSizeX); + MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY); + } + + int valueSize; + int labelSize; + int padSize; + + labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN); + valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS); + padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS); + int requiredSize = (labelSize + valueSize) * 2 + padSize; + + int gSize; + { + if (requiredSize < xSizeClient) + { + int incr = (xSizeClient - requiredSize) / 3; + labelSize += incr; + } + else + labelSize = (xSizeClient - valueSize * 2 - padSize) / 2; + if (labelSize < 0) + labelSize = 0; + + gSize = labelSize + valueSize; + padSize = xSizeClient - gSize * 2; + } + + labelSize = gSize - valueSize; + + yPos = my; + for (unsigned i = 0; i < ARRAY_SIZE(kIDs); i += 2) + { + int x = mx; + const unsigned kNumColumn1Items = 5 * 2; + if (i >= kNumColumn1Items) + { + if (i == kNumColumn1Items) + yPos = my; + x = mx + gSize + padSize; + } + if (kIDs[i] != 0) + MoveItem(kIDs[i], x, yPos, labelSize, sY); + MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY); + yPos += sStep; + } + return false; +} + +void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); } +void CProgressDialog::OnOK() { } + +void CProgressDialog::SetProgressRange(UInt64 range) +{ + if (range == _progressBar_Range) + return; + _progressBar_Range = range; + INIT_AS_UNDEFINED(_progressBar_Pos); + _progressConv.Init(range); + m_ProgressBar.SetRange32(0, _progressConv.Count(range)); +} + +void CProgressDialog::SetProgressPos(UInt64 pos) +{ + if (pos >= _progressBar_Range || + pos <= _progressBar_Pos || + pos - _progressBar_Pos >= (_progressBar_Range >> 10)) + { + m_ProgressBar.SetPos(_progressConv.Count(pos)); + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + if (_taskbarList && _hwndForTaskbar) + _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range); + #endif + _progressBar_Pos = pos; + } +} + +#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; } + +void GetTimeString(UInt64 timeValue, wchar_t *s); +void GetTimeString(UInt64 timeValue, wchar_t *s) +{ + UInt64 hours = timeValue / 3600; + UInt32 seconds = (UInt32)(timeValue - hours * 3600); + UInt32 minutes = seconds / 60; + seconds %= 60; + if (hours > 99) + { + ConvertUInt64ToString(hours, s); + for (; *s != 0; s++); + } + else + { + UInt32 hours32 = (UInt32)hours; + UINT_TO_STR_2(hours32); + } + *s++ = ':'; UINT_TO_STR_2(minutes); + *s++ = ':'; UINT_TO_STR_2(seconds); + *s = 0; +} + +static void ConvertSizeToString(UInt64 v, wchar_t *s) +{ + Byte c = 0; + if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; } + else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; } + else if (v >= ((UInt64)100000 << 0)) { v >>= 10; c = 'K'; } + ConvertUInt64ToString(v, s); + if (c != 0) + { + s += MyStringLen(s); + *s++ = ' '; + *s++ = c; + *s++ = 'B'; + *s++ = 0; + } +} + +void CProgressDialog::ShowSize(int id, UInt64 val, UInt64 &prev) +{ + if (val == prev) + return; + prev = val; + wchar_t s[40]; + s[0] = 0; + if (IS_DEFINED_VAL(val)) + ConvertSizeToString(val, s); + SetItemText(id, s); +} + +static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged) +{ + hasChanged = !(prevStr == newStr); + if (hasChanged) + prevStr = newStr; +} + +static unsigned GetPower32(UInt32 val) +{ + const unsigned kStart = 32; + UInt32 mask = ((UInt32)1 << (kStart - 1)); + for (unsigned i = kStart;; i--) + { + if (i == 0 || (val & mask) != 0) + return i; + mask >>= 1; + } +} + +static unsigned GetPower64(UInt64 val) +{ + UInt32 high = (UInt32)(val >> 32); + if (high == 0) + return GetPower32((UInt32)val); + return GetPower32(high) + 32; +} + +static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider) +{ + unsigned pow1 = GetPower64(mult1); + unsigned pow2 = GetPower64(mult2); + while (pow1 + pow2 > 64) + { + if (pow1 > pow2) { pow1--; mult1 >>= 1; } + else { pow2--; mult2 >>= 1; } + divider >>= 1; + } + UInt64 res = mult1 * mult2; + if (divider != 0) + res /= divider; + return res; +} + +void CProgressDialog::UpdateStatInfo(bool showAll) +{ + UInt64 total, completed, totalFiles, completedFiles, inSize, outSize; + bool bytesProgressMode; + + bool titleFileName_Changed; + bool curFilePath_Changed; + bool status_Changed; + unsigned numErrors; + { + NSynchronization::CCriticalSectionLock lock(Sync._cs); + total = Sync._totalBytes; + completed = Sync._completedBytes; + totalFiles = Sync._totalFiles; + completedFiles = Sync._curFiles; + inSize = Sync._inSize; + outSize = Sync._outSize; + bytesProgressMode = Sync._bytesProgressMode; + + GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed); + GetChangedString(Sync._filePath, _filePath, curFilePath_Changed); + GetChangedString(Sync._status, _status, status_Changed); + if (_isDir != Sync._isDir) + { + curFilePath_Changed = true; + _isDir = Sync._isDir; + } + numErrors = Sync.Messages.Size(); + } + + UInt32 curTime = ::GetTickCount(); + + const UInt64 progressTotal = bytesProgressMode ? total : totalFiles; + const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles; + { + if (IS_UNDEFINED_VAL(progressTotal)) + { + // SetPos(0); + // SetRange(progressCompleted); + } + else + { + if (_progressBar_Pos != 0 || progressCompleted != 0 || + (_progressBar_Range == 0 && progressTotal != 0)) + { + SetProgressRange(progressTotal); + SetProgressPos(progressCompleted); + } + } + } + + ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev); + + _elapsedTime += (curTime - _prevTime); + _prevTime = curTime; + UInt64 elapsedSec = _elapsedTime / 1000; + bool elapsedChanged = false; + if (elapsedSec != _prevElapsedSec) + { + _prevElapsedSec = elapsedSec; + elapsedChanged = true; + wchar_t s[40]; + GetTimeString(elapsedSec, s); + SetItemText(IDT_PROGRESS_ELAPSED_VAL, s); + } + + bool needSetTitle = false; + if (elapsedChanged || showAll) + { + if (numErrors > _numPostedMessages) + { + UpdateMessagesDialog(); + wchar_t s[32]; + ConvertUInt64ToString(numErrors, s); + SetItemText(IDT_PROGRESS_ERRORS_VAL, s); + if (!_errorsWereDisplayed) + { + _errorsWereDisplayed = true; + EnableErrorsControls(true); + SetTaskbarProgressState(); + } + } + + if (progressCompleted != 0) + { + if (IS_UNDEFINED_VAL(progressTotal)) + { + if (IS_DEFINED_VAL(_prevRemainingSec)) + { + INIT_AS_UNDEFINED(_prevRemainingSec); + SetItemText(IDT_PROGRESS_REMAINING_VAL, L""); + } + } + else + { + UInt64 remainingTime = 0; + if (progressCompleted < progressTotal) + remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted); + UInt64 remainingSec = remainingTime / 1000; + if (remainingSec != _prevRemainingSec) + { + _prevRemainingSec = remainingSec; + wchar_t s[40]; + GetTimeString(remainingSec, s); + SetItemText(IDT_PROGRESS_REMAINING_VAL, s); + } + } + { + UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime; + UInt64 v = (progressCompleted * 1000) / elapsedTime; + Byte c = 0; + unsigned moveBits = 0; + if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; } + else if (v >= ((UInt64)10000 << 0)) { moveBits = 10; c = 'K'; } + v >>= moveBits; + if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed) + { + _prevSpeed_MoveBits = moveBits; + _prevSpeed = v; + wchar_t s[40]; + ConvertUInt64ToString(v, s); + unsigned pos = MyStringLen(s); + s[pos++] = ' '; + if (moveBits != 0) + s[pos++] = c; + s[pos++] = 'B'; + s[pos++] = '/'; + s[pos++] = 's'; + s[pos++] = 0; + SetItemText(IDT_PROGRESS_SPEED_VAL, s); + } + } + } + + { + UInt64 percent = 0; + { + if (IS_DEFINED_VAL(progressTotal)) + { + percent = progressCompleted * 100; + if (progressTotal != 0) + percent /= progressTotal; + } + } + if (percent != _prevPercentValue) + { + _prevPercentValue = percent; + needSetTitle = true; + } + } + + { + wchar_t s[64]; + + ConvertUInt64ToString(completedFiles, s); + if (_filesStr_Prev != s) + { + _filesStr_Prev = s; + SetItemText(IDT_PROGRESS_FILES_VAL, s); + } + + s[0] = 0; + if (IS_DEFINED_VAL(totalFiles)) + { + MyStringCopy(s, L" / "); + ConvertUInt64ToString(totalFiles, s + MyStringLen(s)); + } + if (_filesTotStr_Prev != s) + { + _filesTotStr_Prev = s; + SetItemText(IDT_PROGRESS_FILES_TOTAL, s); + } + } + + const UInt64 packSize = CompressingMode ? outSize : inSize; + const UInt64 unpackSize = CompressingMode ? inSize : outSize; + + if (IS_UNDEFINED_VAL(unpackSize) && + IS_UNDEFINED_VAL(packSize)) + { + ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev); + ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev); + } + else + { + ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev); + ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev); + + if (IS_DEFINED_VAL(packSize) && + IS_DEFINED_VAL(unpackSize) && + unpackSize != 0) + { + wchar_t s[32]; + UInt64 ratio = packSize * 100 / unpackSize; + if (_ratio_Prev != ratio) + { + _ratio_Prev = ratio; + ConvertUInt64ToString(ratio, s); + MyStringCat(s, L"%"); + SetItemText(IDT_PROGRESS_RATIO_VAL, s); + } + } + } + } + + if (needSetTitle || titleFileName_Changed) + SetTitleText(); + + if (status_Changed) + { + UString s = _status; + ReduceString(s, _numReduceSymbols); + SetItemText(IDT_PROGRESS_STATUS, _status); + } + + if (curFilePath_Changed) + { + UString s1, s2; + if (_isDir) + s1 = _filePath; + else + { + int slashPos = _filePath.ReverseFind_PathSepar(); + if (slashPos >= 0) + { + s1.SetFrom(_filePath, (unsigned)(slashPos + 1)); + s2 = _filePath.Ptr((unsigned)(slashPos + 1)); + } + else + s2 = _filePath; + } + ReduceString(s1, _numReduceSymbols); + ReduceString(s2, _numReduceSymbols); + s1.Add_LF(); + s1 += s2; + SetItemText(IDT_PROGRESS_FILE_NAME, s1); + } +} + +bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */) +{ + if (Sync.Get_Paused()) + return true; + CheckNeedClose(); + UpdateStatInfo(false); + return true; +} + +struct CWaitCursor +{ + HCURSOR _waitCursor; + HCURSOR _oldCursor; + CWaitCursor() + { + _waitCursor = LoadCursor(NULL, IDC_WAIT); + if (_waitCursor != NULL) + _oldCursor = SetCursor(_waitCursor); + } + ~CWaitCursor() + { + if (_waitCursor != NULL) + SetCursor(_oldCursor); + } +}; + +INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent) +{ + INT_PTR res = 0; + try + { + if (WaitMode) + { + CWaitCursor waitCursor; + HANDLE h[] = { thread, _createDialogEvent }; + + DWORD res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay); + if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage()) + return 0; + } + _title = title; + BIG_DIALOG_SIZE(360, 192); + res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent); + } + catch(...) + { + _wasCreated = true; + _dialogCreatedEvent.Set(); + } + thread.Wait_Close(); + if (!MessagesDisplayed) + MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR); + return res; +} + +bool CProgressDialog::OnExternalCloseMessage() +{ + // it doesn't work if there is MessageBox. + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + SetTaskbarProgressState(TBPF_NOPROGRESS); + #endif + // AddToTitle(L"Finished "); + // SetText(L"Finished2 "); + + UpdateStatInfo(true); + + SetItemText(IDCANCEL, LangString(IDS_CLOSE)); + ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); + HideItem(IDB_PROGRESS_BACKGROUND); + HideItem(IDB_PAUSE); + + ProcessWasFinished_GuiVirt(); + + bool thereAreMessages; + CProgressFinalMessage fm; + { + NSynchronization::CCriticalSectionLock lock(Sync._cs); + thereAreMessages = !Sync.Messages.IsEmpty(); + fm = Sync.FinalMessage; + } + + if (!fm.ErrorMessage.Message.IsEmpty()) + { + MessagesDisplayed = true; + if (fm.ErrorMessage.Title.IsEmpty()) + fm.ErrorMessage.Title = "7-Zip"; + MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR); + } + else if (!thereAreMessages) + { + MessagesDisplayed = true; + + if (!fm.OkMessage.Message.IsEmpty()) + { + if (fm.OkMessage.Title.IsEmpty()) + fm.OkMessage.Title = "7-Zip"; + MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK); + } + } + + if (thereAreMessages && !_cancelWasPressed) + { + _waitCloseByCancelButton = true; + UpdateMessagesDialog(); + return true; + } + + End(0); + return true; +} + +bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case kCloseMessage: + { + if (_timer) + { + /* 21.03 : KillTimer(kTimerID) instead of KillTimer(_timer). + But (_timer == kTimerID) in Win10. So it worked too */ + KillTimer(kTimerID); + _timer = 0; + } + if (_inCancelMessageBox) + { + _externalCloseMessageWasReceived = true; + break; + } + return OnExternalCloseMessage(); + } + /* + case WM_SETTEXT: + { + if (_timer == 0) + return true; + break; + } + */ + } + return CModalDialog::OnMessage(message, wParam, lParam); +} + +void CProgressDialog::SetTitleText() +{ + UString s; + if (Sync.Get_Paused()) + { + s += _paused_String; + s.Add_Space(); + } + if (IS_DEFINED_VAL(_prevPercentValue)) + { + char temp[32]; + ConvertUInt64ToString(_prevPercentValue, temp); + s += temp; + s += '%'; + } + if (!_foreground) + { + s.Add_Space(); + s += _backgrounded_String; + } + + s.Add_Space(); + #ifndef _SFX + { + unsigned len = s.Len(); + s += MainAddTitle; + AddToTitle(s); + s.DeleteFrom(len); + } + #endif + + s += _title; + if (!_titleFileName.IsEmpty()) + { + UString fileName = _titleFileName; + ReduceString(fileName, kTitleFileNameSizeLimit); + s.Add_Space(); + s += fileName; + } + SetText(s); +} + +void CProgressDialog::SetPauseText() +{ + SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String); + SetTitleText(); +} + +void CProgressDialog::OnPauseButton() +{ + bool paused = !Sync.Get_Paused(); + Sync.Set_Paused(paused); + UInt32 curTime = ::GetTickCount(); + if (paused) + _elapsedTime += (curTime - _prevTime); + SetTaskbarProgressState(); + _prevTime = curTime; + SetPauseText(); +} + +void CProgressDialog::SetPriorityText() +{ + SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ? + _background_String : + _foreground_String); + SetTitleText(); +} + +void CProgressDialog::OnPriorityButton() +{ + _foreground = !_foreground; + #ifndef UNDER_CE + SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS); + #endif + SetPriorityText(); +} + +void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber) +{ + int itemIndex = _messageList.GetItemCount(); + wchar_t sz[16]; + sz[0] = 0; + if (needNumber) + ConvertUInt32ToString(_numMessages + 1, sz); + _messageList.InsertItem(itemIndex, sz); + _messageList.SetSubItem(itemIndex, 1, message); +} + +void CProgressDialog::AddMessage(LPCWSTR message) +{ + UString s = message; + bool needNumber = true; + while (!s.IsEmpty()) + { + int pos = s.Find(L'\n'); + if (pos < 0) + break; + AddMessageDirect(s.Left(pos), needNumber); + needNumber = false; + s.DeleteFrontal(pos + 1); + } + AddMessageDirect(s, needNumber); + _numMessages++; +} + +static unsigned GetNumDigits(UInt32 val) +{ + unsigned i; + for (i = 0; val >= 10; i++) + val /= 10; + return i; +} + +void CProgressDialog::UpdateMessagesDialog() +{ + UStringVector messages; + { + NSynchronization::CCriticalSectionLock lock(Sync._cs); + unsigned num = Sync.Messages.Size(); + if (num > _numPostedMessages) + { + messages.ClearAndReserve(num - _numPostedMessages); + for (unsigned i = _numPostedMessages; i < num; i++) + messages.AddInReserved(Sync.Messages[i]); + _numPostedMessages = num; + } + } + if (!messages.IsEmpty()) + { + FOR_VECTOR (i, messages) + AddMessage(messages[i]); + if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages)) + { + _messageList.SetColumnWidthAuto(0); + _messageList.SetColumnWidthAuto(1); + _numAutoSizeMessages = _numPostedMessages; + } + } +} + + +bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON + case IDCANCEL: + { + if (_waitCloseByCancelButton) + { + MessagesDisplayed = true; + End(IDCLOSE); + break; + } + + bool paused = Sync.Get_Paused(); + if (!paused) + OnPauseButton(); + _inCancelMessageBox = true; + int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL); + _inCancelMessageBox = false; + if (!paused) + OnPauseButton(); + if (res == IDCANCEL || res == IDNO) + { + if (_externalCloseMessageWasReceived) + OnExternalCloseMessage(); + return true; + } + + _cancelWasPressed = true; + MessagesDisplayed = true; + break; + } + + case IDB_PAUSE: + OnPauseButton(); + return true; + case IDB_PROGRESS_BACKGROUND: + OnPriorityButton(); + return true; + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CProgressDialog::CheckNeedClose() +{ + if (_needClose) + { + PostMsg(kCloseMessage); + _needClose = false; + } +} + +void CProgressDialog::ProcessWasFinished() +{ + // Set Window title here. + if (!WaitMode) + WaitCreating(); + + if (_wasCreated) + PostMsg(kCloseMessage); + else + _needClose = true; +} + + +static THREAD_FUNC_DECL MyThreadFunction(void *param) +{ + CProgressThreadVirt *p = (CProgressThreadVirt *)param; + try + { + p->Process(); + p->ThreadFinishedOK = true; + } + catch (...) { p->Result = E_FAIL; } + return 0; +} + + +HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow) +{ + NWindows::CThread thread; + RINOK(thread.Create(MyThreadFunction, this)); + CProgressDialog::Create(title, thread, parentWindow); + return S_OK; +} + +static void AddMessageToString(UString &dest, const UString &src) +{ + if (!src.IsEmpty()) + { + if (!dest.IsEmpty()) + dest.Add_LF(); + dest += src; + } +} + +void CProgressThreadVirt::Process() +{ + CProgressCloser closer(*this); + UString m; + try { Result = ProcessVirt(); } + catch(const wchar_t *s) { m = s; } + catch(const UString &s) { m = s; } + catch(const char *s) { m = GetUnicodeString(s); } + catch(int v) + { + m = "Error #"; + m.Add_UInt32(v); + } + catch(...) { m = "Error"; } + if (Result != E_ABORT) + { + if (m.IsEmpty() && Result != S_OK) + m = HResultToMessage(Result); + } + AddMessageToString(m, FinalMessage.ErrorMessage.Message); + + { + FOR_VECTOR(i, ErrorPaths) + { + if (i >= 32) + break; + AddMessageToString(m, fs2us(ErrorPaths[i])); + } + } + + CProgressSync &sync = Sync; + NSynchronization::CCriticalSectionLock lock(sync._cs); + if (m.IsEmpty()) + { + if (!FinalMessage.OkMessage.Message.IsEmpty()) + sync.FinalMessage.OkMessage = FinalMessage.OkMessage; + } + else + { + sync.FinalMessage.ErrorMessage.Message = m; + if (Result == S_OK) + Result = E_FAIL; + } +} + +UString HResultToMessage(HRESULT errorCode) +{ + if (errorCode == E_OUTOFMEMORY) + return LangString(IDS_MEM_ERROR); + else + return NError::MyFormatMessage(errorCode); +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.h new file mode 100644 index 0000000..c17dd39 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -0,0 +1,353 @@ +// ProgressDialog2.h + +#ifndef __PROGRESS_DIALOG_2_H +#define __PROGRESS_DIALOG_2_H + +#include "../../../Common/MyCom.h" + +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/Synchronization.h" +#include "../../../Windows/Thread.h" + +#include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/ListView.h" +#include "../../../Windows/Control/ProgressBar.h" + +#include "MyWindowsNew.h" + +struct CProgressMessageBoxPair +{ + UString Title; + UString Message; +}; + +struct CProgressFinalMessage +{ + CProgressMessageBoxPair ErrorMessage; + CProgressMessageBoxPair OkMessage; + + bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); } +}; + +class CProgressSync +{ + bool _stopped; + bool _paused; + +public: + bool _bytesProgressMode; + UInt64 _totalBytes; + UInt64 _completedBytes; + UInt64 _totalFiles; + UInt64 _curFiles; + UInt64 _inSize; + UInt64 _outSize; + + UString _titleFileName; + UString _status; + UString _filePath; + bool _isDir; + + UStringVector Messages; + CProgressFinalMessage FinalMessage; + + NWindows::NSynchronization::CCriticalSection _cs; + + CProgressSync(); + + bool Get_Stopped() + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + return _stopped; + } + void Set_Stopped(bool val) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _stopped = val; + } + + bool Get_Paused(); + void Set_Paused(bool val) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _paused = val; + } + + void Set_BytesProgressMode(bool bytesProgressMode) + { + NWindows::NSynchronization::CCriticalSectionLock lock(_cs); + _bytesProgressMode = bytesProgressMode; + } + + HRESULT CheckStop(); + HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false); + + HRESULT Set_NumFilesTotal(UInt64 val); + void Set_NumBytesTotal(UInt64 val); + void Set_NumFilesCur(UInt64 val); + HRESULT Set_NumBytesCur(const UInt64 *val); + HRESULT Set_NumBytesCur(UInt64 val); + void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize); + + void Set_TitleFileName(const UString &fileName); + void Set_Status(const UString &s); + HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false); + void Set_FilePath(const wchar_t *path, bool isDir = false); + + void AddError_Message(const wchar_t *message); + void AddError_Message_Name(const wchar_t *message, const wchar_t *name); + void AddError_Code_Name(DWORD systemError, const wchar_t *name); + + bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); } +}; + +class CProgressDialog: public NWindows::NControl::CModalDialog +{ + UString _titleFileName; + UString _filePath; + UString _status; + bool _isDir; + + UString _background_String; + UString _backgrounded_String; + UString _foreground_String; + UString _pause_String; + UString _continue_String; + UString _paused_String; + + int _buttonSizeX; + int _buttonSizeY; + + UINT_PTR _timer; + + UString _title; + + class CU64ToI32Converter + { + unsigned _numShiftBits; + UInt64 _range; + public: + CU64ToI32Converter(): _numShiftBits(0), _range(1) {} + void Init(UInt64 range) + { + _range = range; + // Windows CE doesn't like big number for ProgressBar. + for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++) + range >>= 1; + } + int Count(UInt64 val) + { + int res = (int)(val >> _numShiftBits); + if (val == _range) + res++; + return res; + } + }; + + CU64ToI32Converter _progressConv; + UInt64 _progressBar_Pos; + UInt64 _progressBar_Range; + + NWindows::NControl::CProgressBar m_ProgressBar; + NWindows::NControl::CListView _messageList; + + int _numMessages; + + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + CMyComPtr _taskbarList; + #endif + HWND _hwndForTaskbar; + + UInt32 _prevTime; + UInt64 _elapsedTime; + + UInt64 _prevPercentValue; + UInt64 _prevElapsedSec; + UInt64 _prevRemainingSec; + + UInt64 _totalBytes_Prev; + UInt64 _processed_Prev; + UInt64 _packed_Prev; + UInt64 _ratio_Prev; + + UString _filesStr_Prev; + UString _filesTotStr_Prev; + + unsigned _prevSpeed_MoveBits; + UInt64 _prevSpeed; + + bool _foreground; + + unsigned _numReduceSymbols; + + bool _wasCreated; + bool _needClose; + + unsigned _numPostedMessages; + UInt32 _numAutoSizeMessages; + + bool _errorsWereDisplayed; + + bool _waitCloseByCancelButton; + bool _cancelWasPressed; + + bool _inCancelMessageBox; + bool _externalCloseMessageWasReceived; + + + #ifdef __ITaskbarList3_INTERFACE_DEFINED__ + void SetTaskbarProgressState(TBPFLAG tbpFlags) + { + if (_taskbarList && _hwndForTaskbar) + _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags); + } + #endif + void SetTaskbarProgressState(); + + void UpdateStatInfo(bool showAll); + bool OnTimer(WPARAM timerID, LPARAM callback); + void SetProgressRange(UInt64 range); + void SetProgressPos(UInt64 pos); + virtual bool OnInit(); + virtual bool OnSize(WPARAM wParam, int xSize, int ySize); + virtual void OnCancel(); + virtual void OnOK(); + NWindows::NSynchronization::CManualResetEvent _createDialogEvent; + NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent; + #ifndef _SFX + void AddToTitle(LPCWSTR string); + #endif + + void SetPauseText(); + void SetPriorityText(); + void OnPauseButton(); + void OnPriorityButton(); + bool OnButtonClicked(int buttonID, HWND buttonHWND); + bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + + void SetTitleText(); + void ShowSize(int id, UInt64 val, UInt64 &prev); + + void UpdateMessagesDialog(); + + void AddMessageDirect(LPCWSTR message, bool needNumber); + void AddMessage(LPCWSTR message); + + bool OnExternalCloseMessage(); + void EnableErrorsControls(bool enable); + + void ShowAfterMessages(HWND wndParent); + + void CheckNeedClose(); +public: + CProgressSync Sync; + bool CompressingMode; + bool WaitMode; + bool ShowCompressionInfo; + bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages. + int IconID; + + HWND MainWindow; + #ifndef _SFX + UString MainTitle; + UString MainAddTitle; + ~CProgressDialog(); + #endif + + CProgressDialog(); + void WaitCreating() + { + _createDialogEvent.Set(); + _dialogCreatedEvent.Lock(); + } + + INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0); + + + /* how it works: + 1) the working thread calls ProcessWasFinished() + that sends kCloseMessage message to CProgressDialog (GUI) thread + 2) CProgressDialog (GUI) thread receives kCloseMessage message and + calls ProcessWasFinished_GuiVirt(); + So we can implement ProcessWasFinished_GuiVirt() and show special + results window in GUI thread with CProgressDialog as parent window + */ + + void ProcessWasFinished(); + virtual void ProcessWasFinished_GuiVirt() {} +}; + + +class CProgressCloser +{ + CProgressDialog *_p; +public: + CProgressCloser(CProgressDialog &p) : _p(&p) {} + ~CProgressCloser() { _p->ProcessWasFinished(); } +}; + + +class CProgressThreadVirt: public CProgressDialog +{ +protected: + FStringVector ErrorPaths; + CProgressFinalMessage FinalMessage; + + // error if any of HRESULT, ErrorMessage, ErrorPath + virtual HRESULT ProcessVirt() = 0; +public: + HRESULT Result; + bool ThreadFinishedOK; // if there is no fatal exception + + void Process(); + void AddErrorPath(const FString &path) { ErrorPaths.Add(path); } + + HRESULT Create(const UString &title, HWND parentWindow = 0); + CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {} + + CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; } +}; + +UString HResultToMessage(HRESULT errorCode); + +/* +how it works: + +client code inherits CProgressThreadVirt and calls +CProgressThreadVirt::Create() +{ + it creates new thread that calls CProgressThreadVirt::Process(); + it creates modal progress dialog window with ProgressDialog.Create() +} + +CProgressThreadVirt::Process() +{ + { + Result = ProcessVirt(); // virtual function that must implement real work + } + if (exceptions) or FinalMessage.ErrorMessage.Message + { + set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message + } + else if (FinalMessage.OkMessage.Message) + { + set message to ProgressDialog.Sync.FinalMessage.OkMessage + } + + PostMsg(kCloseMessage); +} + + +CProgressDialog::OnExternalCloseMessage() +{ + if (ProgressDialog.Sync.FinalMessage) + { + WorkWasFinishedVirt(); + Show (ProgressDialog.Sync.FinalMessage) + MessagesDisplayed = true; + } +} + +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.rc new file mode 100644 index 0000000..4d0e0c7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2.rc @@ -0,0 +1,40 @@ +#include "ProgressDialog2Res.h" +#include "../../GuiCommon.rc" + +#undef DIALOG_ID +#define DIALOG_ID IDD_PROGRESS +#define xc 360 +#define k 11 +#define z1s 16 + +#include "ProgressDialog2a.rc" + +#ifdef UNDER_CE + +#include "../../GuiCommon.rc" + + +#undef DIALOG_ID +#undef m +#undef k +#undef z1s + +#define DIALOG_ID IDD_PROGRESS_2 +#define m 4 +#define k 8 +#define z1s 12 + +#define xc 280 + +#include "ProgressDialog2a.rc" + +#endif + +STRINGTABLE DISCARDABLE +{ + IDS_PROGRESS_PAUSED "Paused" + IDS_PROGRESS_FOREGROUND "&Foreground" + IDS_CONTINUE "&Continue" + IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?" + IDS_CLOSE "&Close" +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2Res.h new file mode 100644 index 0000000..736c717 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2Res.h @@ -0,0 +1,49 @@ +#define IDD_PROGRESS 97 +#define IDD_PROGRESS_2 10097 + +#define IDS_CLOSE 408 +#define IDS_CONTINUE 411 + +#define IDB_PROGRESS_BACKGROUND 444 +#define IDS_PROGRESS_FOREGROUND 445 +#define IDB_PAUSE 446 +#define IDS_PROGRESS_PAUSED 447 +#define IDS_PROGRESS_ASK_CANCEL 448 + +#define IDT_PROGRESS_PACKED 1008 +#define IDT_PROGRESS_FILES 1032 + +#define IDT_PROGRESS_ELAPSED 3900 +#define IDT_PROGRESS_REMAINING 3901 +#define IDT_PROGRESS_TOTAL 3902 +#define IDT_PROGRESS_SPEED 3903 +#define IDT_PROGRESS_PROCESSED 3904 +#define IDT_PROGRESS_RATIO 3905 +#define IDT_PROGRESS_ERRORS 3906 + +#define IDC_PROGRESS1 100 +#define IDL_PROGRESS_MESSAGES 101 +#define IDT_PROGRESS_FILE_NAME 102 +#define IDT_PROGRESS_STATUS 103 + +#define IDT_PROGRESS_PACKED_VAL 110 +#define IDT_PROGRESS_FILES_VAL 111 +#define IDT_PROGRESS_FILES_TOTAL 112 + +#define IDT_PROGRESS_ELAPSED_VAL 120 +#define IDT_PROGRESS_REMAINING_VAL 121 +#define IDT_PROGRESS_TOTAL_VAL 122 +#define IDT_PROGRESS_SPEED_VAL 123 +#define IDT_PROGRESS_PROCESSED_VAL 124 +#define IDT_PROGRESS_RATIO_VAL 125 +#define IDT_PROGRESS_ERRORS_VAL 126 + + +#ifdef UNDER_CE +#define MY_PROGRESS_VAL_UNITS 44 +#else +#define MY_PROGRESS_VAL_UNITS 72 +#endif +#define MY_PROGRESS_LABEL_UNITS_MIN 60 +#define MY_PROGRESS_LABEL_UNITS_START 90 +#define MY_PROGRESS_PAD_UNITS 4 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2a.rc new file mode 100644 index 0000000..d2fee8c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialog2a.rc @@ -0,0 +1,85 @@ +#undef bxs +#define bxs 80 + +#define x0s MY_PROGRESS_LABEL_UNITS_START +#define x1s MY_PROGRESS_VAL_UNITS +#define x2s MY_PROGRESS_LABEL_UNITS_START +#define x3s MY_PROGRESS_VAL_UNITS + +#define x1 (m + x0s) +#define x3 (xs - m - x3s) +#define x2 (x3 - x2s) + +#undef y0 +#undef y1 +#undef y2 +#undef y3 +#undef y4 + +#undef z0 +#undef z1 +#undef z2 +#undef z3 + +#define y0 m +#define y1 (y0 + k) +#define y2 (y1 + k) +#define y3 (y2 + k) +#define y4 (y3 + k) + +#define z3 (y4 + k + 1) + +#define z2 (z3 + k + 1) +#define z2s 24 + +#define z1 (z2 + z2s) + +#define z0 (z1 + z1s + m) +#define z0s 48 + +#define yc (z0 + z0s + bys) + + +DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT +CAPTION "Progress" +{ + DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys + PUSHBUTTON "&Pause", IDB_PAUSE, bx2, by, bxs, bys + PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys + + + LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8 + LTEXT "Remaining time:", IDT_PROGRESS_REMAINING, m, y1, x0s, 8 + LTEXT "Files:", IDT_PROGRESS_FILES, m, y2, x0s, 8 + + LTEXT "Errors:", IDT_PROGRESS_ERRORS, m, y4, x0s, 8 + + + LTEXT "Total size:", IDT_PROGRESS_TOTAL, x2, y0, x2s, 8 + LTEXT "Speed:", IDT_PROGRESS_SPEED, x2, y1, x2s, 8 + LTEXT "Processed:", IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8 + LTEXT "Compressed size:" , IDT_PROGRESS_PACKED, x2, y3, x2s, 8 + LTEXT "Compression ratio:", IDT_PROGRESS_RATIO, x2, y4, x2s, 8 + + + RTEXT "", IDT_PROGRESS_ELAPSED_VAL, x1, y0, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_FILES_VAL, x1, y2, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_FILES_TOTAL x1, y3, x1s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_ERRORS_VAL, x1, y4, x1s, MY_TEXT_NOPREFIX + + RTEXT "", IDT_PROGRESS_TOTAL_VAL, x3, y0, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_SPEED_VAL, x3, y1, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_PACKED_VAL, x3, y3, x3s, MY_TEXT_NOPREFIX + RTEXT "", IDT_PROGRESS_RATIO_VAL, x3, y4, x3s, MY_TEXT_NOPREFIX + + LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX + CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s + + CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s + + CONTROL "List1", IDL_PROGRESS_MESSAGES, "SysListView32", + LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, + m, z0, xc, z0s +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialogRes.h new file mode 100644 index 0000000..cbf3beb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/ProgressDialogRes.h @@ -0,0 +1,3 @@ +#define IDD_PROGRESS 97 + +#define IDC_PROGRESS1 100 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.cpp new file mode 100644 index 0000000..838b6e3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.cpp @@ -0,0 +1,23 @@ +// PropertyName.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" + +#include "LangUtils.h" +#include "PropertyName.h" + +UString GetNameOfProperty(PROPID propID, const wchar_t *name) +{ + if (propID < 1000) + { + UString s = LangString(1000 + propID); + if (!s.IsEmpty()) + return s; + } + if (name) + return name; + wchar_t temp[16]; + ConvertUInt32ToString(propID, temp); + return temp; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.h new file mode 100644 index 0000000..4f0d6dc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyName.h @@ -0,0 +1,10 @@ +// PropertyName.h + +#ifndef __PROPERTY_NAME_H +#define __PROPERTY_NAME_H + +#include "../../../Common/MyString.h" + +UString GetNameOfProperty(PROPID propID, const wchar_t *name); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyNameRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyNameRes.h new file mode 100644 index 0000000..67f3390 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/PropertyNameRes.h @@ -0,0 +1,95 @@ + + +#define IDS_PROP_PATH 1003 +#define IDS_PROP_NAME 1004 +#define IDS_PROP_EXTENSION 1005 +#define IDS_PROP_IS_FOLDER 1006 +#define IDS_PROP_SIZE 1007 +#define IDS_PROP_PACKED_SIZE 1008 +#define IDS_PROP_ATTRIBUTES 1009 +#define IDS_PROP_CTIME 1010 +#define IDS_PROP_ATIME 1011 +#define IDS_PROP_MTIME 1012 +#define IDS_PROP_SOLID 1013 +#define IDS_PROP_C0MMENTED 1014 +#define IDS_PROP_ENCRYPTED 1015 +#define IDS_PROP_SPLIT_BEFORE 1016 +#define IDS_PROP_SPLIT_AFTER 1017 +#define IDS_PROP_DICTIONARY_SIZE 1018 +#define IDS_PROP_CRC 1019 +#define IDS_PROP_FILE_TYPE 1020 +#define IDS_PROP_ANTI 1021 +#define IDS_PROP_METHOD 1022 +#define IDS_PROP_HOST_OS 1023 +#define IDS_PROP_FILE_SYSTEM 1024 +#define IDS_PROP_USER 1025 +#define IDS_PROP_GROUP 1026 +#define IDS_PROP_BLOCK 1027 +#define IDS_PROP_COMMENT 1028 +#define IDS_PROP_POSITION 1029 +#define IDS_PROP_PREFIX 1030 +#define IDS_PROP_FOLDERS 1031 +#define IDS_PROP_FILES 1032 +#define IDS_PROP_VERSION 1033 +#define IDS_PROP_VOLUME 1034 +#define IDS_PROP_IS_VOLUME 1035 +#define IDS_PROP_OFFSET 1036 +#define IDS_PROP_LINKS 1037 +#define IDS_PROP_NUM_BLOCKS 1038 +#define IDS_PROP_NUM_VOLUMES 1039 + +#define IDS_PROP_BIT64 1041 +#define IDS_PROP_BIG_ENDIAN 1042 +#define IDS_PROP_CPU 1043 +#define IDS_PROP_PHY_SIZE 1044 +#define IDS_PROP_HEADERS_SIZE 1045 +#define IDS_PROP_CHECKSUM 1046 +#define IDS_PROP_CHARACTS 1047 +#define IDS_PROP_VA 1048 +#define IDS_PROP_ID 1049 +#define IDS_PROP_SHORT_NAME 1050 +#define IDS_PROP_CREATOR_APP 1051 +#define IDS_PROP_SECTOR_SIZE 1052 +#define IDS_PROP_POSIX_ATTRIB 1053 +#define IDS_PROP_SYM_LINK 1054 +#define IDS_PROP_ERROR 1055 +#define IDS_PROP_TOTAL_SIZE 1056 +#define IDS_PROP_FREE_SPACE 1057 +#define IDS_PROP_CLUSTER_SIZE 1058 +#define IDS_PROP_VOLUME_NAME 1059 +#define IDS_PROP_LOCAL_NAME 1060 +#define IDS_PROP_PROVIDER 1061 +#define IDS_PROP_NT_SECURITY 1062 +#define IDS_PROP_ALT_STREAM 1063 +#define IDS_PROP_AUX 1064 +#define IDS_PROP_DELETED 1065 +#define IDS_PROP_IS_TREE 1066 +#define IDS_PROP_SHA1 1067 +#define IDS_PROP_SHA256 1068 +#define IDS_PROP_ERROR_TYPE 1069 +#define IDS_PROP_NUM_ERRORS 1070 +#define IDS_PROP_ERROR_FLAGS 1071 +#define IDS_PROP_WARNING_FLAGS 1072 +#define IDS_PROP_WARNING 1073 +#define IDS_PROP_NUM_STREAMS 1074 +#define IDS_PROP_NUM_ALT_STREAMS 1075 +#define IDS_PROP_ALT_STREAMS_SIZE 1076 +#define IDS_PROP_VIRTUAL_SIZE 1077 +#define IDS_PROP_UNPACK_SIZE 1078 +#define IDS_PROP_TOTAL_PHY_SIZE 1079 +#define IDS_PROP_VOLUME_INDEX 1080 +#define IDS_PROP_SUBTYPE 1081 +#define IDS_PROP_SHORT_COMMENT 1082 +#define IDS_PROP_CODE_PAGE 1083 +#define IDS_PROP_IS_NOT_ARC_TYPE 1084 +#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085 +#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086 +#define IDS_PROP_TAIL_SIZE 1087 +#define IDS_PROP_EMB_STUB_SIZE 1088 +#define IDS_PROP_NT_REPARSE 1089 +#define IDS_PROP_HARD_LINK 1090 +#define IDS_PROP_INODE 1091 +#define IDS_PROP_STREAM_ID 1092 +#define IDS_PROP_READ_ONLY 1093 +#define IDS_PROP_OUT_NAME 1094 +#define IDS_PROP_COPY_LINK 1095 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.cpp new file mode 100644 index 0000000..b756dfc --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.cpp @@ -0,0 +1,255 @@ +// SysIconUtils.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../../Common/StringConvert.h" +#endif + +#include "../../../Windows/FileDir.h" + +#include "SysIconUtils.h" + +#include + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +int GetIconIndexForCSIDL(int csidl) +{ + LPITEMIDLIST pidl = 0; + SHGetSpecialFolderLocation(NULL, csidl, &pidl); + if (pidl) + { + SHFILEINFO shellInfo; + SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL, + &shellInfo, sizeof(shellInfo), + SHGFI_PIDL | SHGFI_SYSICONINDEX); + IMalloc *pMalloc; + SHGetMalloc(&pMalloc); + if (pMalloc) + { + pMalloc->Free(pidl); + pMalloc->Release(); + } + return shellInfo.iIcon; + } + return 0; +} + +#ifndef _UNICODE +typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); + +static struct CSHGetFileInfoInit +{ + SHGetFileInfoWP shGetFileInfoW; + CSHGetFileInfoInit() + { + shGetFileInfoW = (SHGetFileInfoWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); + } +} g_SHGetFileInfoInit; +#endif + +static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) +{ + #ifdef _UNICODE + return SHGetFileInfo + #else + if (g_SHGetFileInfoInit.shGetFileInfoW == 0) + return 0; + return g_SHGetFileInfoInit.shGetFileInfoW + #endif + (pszPath, attrib, psfi, cbFileInfo, uFlags); +} + +DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + SHFILEINFO shellInfo; + DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); + iconIndex = shellInfo.iIcon; + return res; + } + else + #endif + { + SHFILEINFOW shellInfo; + DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); + iconIndex = shellInfo.iIcon; + return res; + } +} + +/* +DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + SHFILEINFO shellInfo; + shellInfo.szTypeName[0] = 0; + DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); + if (typeName) + *typeName = GetUnicodeString(shellInfo.szTypeName); + iconIndex = shellInfo.iIcon; + return res; + } + else + #endif + { + SHFILEINFOW shellInfo; + shellInfo.szTypeName[0] = 0; + DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, + sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); + if (typeName) + *typeName = shellInfo.szTypeName; + iconIndex = shellInfo.iIcon; + return res; + } +} +*/ + +static int FindInSorted_Attrib(const CRecordVector &vect, DWORD attrib, int &insertPos) +{ + unsigned left = 0, right = vect.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + DWORD midAttrib = vect[mid].Attrib; + if (attrib == midAttrib) + return mid; + if (attrib < midAttrib) + right = mid; + else + left = mid + 1; + } + insertPos = left; + return -1; +} + +static int FindInSorted_Ext(const CObjectVector &vect, const wchar_t *ext, int &insertPos) +{ + unsigned left = 0, right = vect.Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + int compare = MyStringCompareNoCase(ext, vect[mid].Ext); + if (compare == 0) + return mid; + if (compare < 0) + right = mid; + else + left = mid + 1; + } + insertPos = left; + return -1; +} + +int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) +{ + int dotPos = -1; + unsigned i; + for (i = 0;; i++) + { + wchar_t c = fileName[i]; + if (c == 0) + break; + if (c == '.') + dotPos = i; + } + + /* + if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0) + { + char s[256]; + sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib); + OutputDebugStringA(s); + OutputDebugStringW(fileName); + } + */ + + if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) + { + int insertPos = 0; + int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); + if (index >= 0) + { + // if (typeName) *typeName = _attribMap[index].TypeName; + return _attribMap[index].IconIndex; + } + CAttribIconPair pair; + GetRealIconIndex( + #ifdef UNDER_CE + FTEXT("\\") + #endif + FTEXT("__DIR__") + , attrib, pair.IconIndex + // , pair.TypeName + ); + + /* + char s[256]; + sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); + OutputDebugStringA(s); + */ + + pair.Attrib = attrib; + _attribMap.Insert(insertPos, pair); + // if (typeName) *typeName = pair.TypeName; + return pair.IconIndex; + } + + const wchar_t *ext = fileName + dotPos + 1; + int insertPos = 0; + int index = FindInSorted_Ext(_extMap, ext, insertPos); + if (index >= 0) + { + const CExtIconPair &pa = _extMap[index]; + // if (typeName) *typeName = pa.TypeName; + return pa.IconIndex; + } + + for (i = 0;; i++) + { + wchar_t c = ext[i]; + if (c == 0) + break; + if (c < L'0' || c > L'9') + break; + } + if (i != 0 && ext[i] == 0) + { + // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003 + if (!SplitIconIndex_Defined) + { + GetRealIconIndex( + #ifdef UNDER_CE + FTEXT("\\") + #endif + FTEXT("__FILE__.001"), 0, SplitIconIndex); + SplitIconIndex_Defined = true; + } + return SplitIconIndex; + } + + CExtIconPair pair; + pair.Ext = ext; + GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex); + _extMap.Insert(insertPos, pair); + // if (typeName) *typeName = pair.TypeName; + return pair.IconIndex; +} + +/* +int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) +{ + return GetIconIndex(attrib, fileName, NULL); +} +*/ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.h new file mode 100644 index 0000000..fde16e4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/SysIconUtils.h @@ -0,0 +1,62 @@ +// SysIconUtils.h + +#ifndef __SYS_ICON_UTILS_H +#define __SYS_ICON_UTILS_H + +#include "../../../Common/MyWindows.h" + +#include + +#include "../../../Common/MyString.h" + +struct CExtIconPair +{ + UString Ext; + int IconIndex; + // UString TypeName; + + // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); } +}; + +struct CAttribIconPair +{ + DWORD Attrib; + int IconIndex; + // UString TypeName; + + // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); } +}; + +class CExtToIconMap +{ +public: + CRecordVector _attribMap; + CObjectVector _extMap; + int SplitIconIndex; + int SplitIconIndex_Defined; + + CExtToIconMap(): SplitIconIndex_Defined(false) {} + + void Clear() + { + SplitIconIndex_Defined = false; + _extMap.Clear(); + _attribMap.Clear(); + } + int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */); + // int GetIconIndex(DWORD attrib, const UString &fileName); +}; + +DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex); +int GetIconIndexForCSIDL(int csidl); + +inline HIMAGELIST GetSysImageList(bool smallIcons) +{ + SHFILEINFO shellInfo; + return (HIMAGELIST)SHGetFileInfo(TEXT(""), + FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY, + &shellInfo, sizeof(shellInfo), + SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON)); +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resource.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resource.h new file mode 100644 index 0000000..98cb4fd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resource.h @@ -0,0 +1,182 @@ +#include "resourceGui.h" + +#define IDR_MENUBAR1 70 +#define IDM_MENU 71 +#define IDR_ACCELERATOR1 72 + +#define IDB_ADD 100 +#define IDB_EXTRACT 101 +#define IDB_TEST 102 +#define IDB_COPY 103 +#define IDB_MOVE 104 +#define IDB_DELETE 105 +#define IDB_INFO 106 + +#define IDB_ADD2 150 +#define IDB_EXTRACT2 151 +#define IDB_TEST2 152 +#define IDB_COPY2 153 +#define IDB_MOVE2 154 +#define IDB_DELETE2 155 +#define IDB_INFO2 156 + +#define IDM_HASH_ALL 101 +#define IDM_CRC32 102 +#define IDM_CRC64 103 +#define IDM_SHA1 104 +#define IDM_SHA256 105 + +#define IDM_OPEN 540 +#define IDM_OPEN_INSIDE 541 +#define IDM_OPEN_OUTSIDE 542 +#define IDM_FILE_VIEW 543 +#define IDM_FILE_EDIT 544 +#define IDM_RENAME 545 +#define IDM_COPY_TO 546 +#define IDM_MOVE_TO 547 +#define IDM_DELETE 548 +#define IDM_SPLIT 549 +#define IDM_COMBINE 550 +#define IDM_PROPERTIES 551 +#define IDM_COMMENT 552 +#define IDM_CRC 553 +#define IDM_DIFF 554 +#define IDM_CREATE_FOLDER 555 +#define IDM_CREATE_FILE 556 +// #define IDM_EXIT 557 +#define IDM_LINK 558 +#define IDM_ALT_STREAMS 559 + +#define IDM_VER_EDIT 580 +#define IDM_VER_COMMIT 581 +#define IDM_VER_REVERT 582 +#define IDM_VER_DIFF 583 + +#define IDM_OPEN_INSIDE_ONE 590 +#define IDM_OPEN_INSIDE_PARSER 591 + +#define IDM_SELECT_ALL 600 +#define IDM_DESELECT_ALL 601 +#define IDM_INVERT_SELECTION 602 +#define IDM_SELECT 603 +#define IDM_DESELECT 604 +#define IDM_SELECT_BY_TYPE 605 +#define IDM_DESELECT_BY_TYPE 606 + +#define IDM_VIEW_LARGE_ICONS 700 +#define IDM_VIEW_SMALL_ICONS 701 +#define IDM_VIEW_LIST 702 +#define IDM_VIEW_DETAILS 703 + +#define IDM_VIEW_ARANGE_BY_NAME 710 +#define IDM_VIEW_ARANGE_BY_TYPE 711 +#define IDM_VIEW_ARANGE_BY_DATE 712 +#define IDM_VIEW_ARANGE_BY_SIZE 713 + +#define IDM_VIEW_ARANGE_NO_SORT 730 +#define IDM_VIEW_FLAT_VIEW 731 +#define IDM_VIEW_TWO_PANELS 732 +#define IDM_VIEW_TOOLBARS 733 +#define IDM_OPEN_ROOT_FOLDER 734 +#define IDM_OPEN_PARENT_FOLDER 735 +#define IDM_FOLDERS_HISTORY 736 +#define IDM_VIEW_REFRESH 737 +#define IDM_VIEW_AUTO_REFRESH 738 +// #define IDM_VIEW_SHOW_DELETED 739 +// #define IDM_VIEW_SHOW_STREAMS 740 + +#define IDM_VIEW_ARCHIVE_TOOLBAR 750 +#define IDM_VIEW_STANDARD_TOOLBAR 751 +#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752 +#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753 + +#define IDM_VIEW_TIME 761 + +#define IDS_BOOKMARK 801 + +#define IDM_OPTIONS 900 +#define IDM_BENCHMARK 901 +#define IDM_BENCHMARK2 902 + +#define IDM_HELP_CONTENTS 960 +#define IDM_ABOUT 961 + +#define IDS_OPTIONS 2100 + +#define IDS_N_SELECTED_ITEMS 3002 + +#define IDS_FILE_EXIST 3008 +#define IDS_WANT_UPDATE_MODIFIED_FILE 3009 +#define IDS_CANNOT_UPDATE_FILE 3010 +#define IDS_CANNOT_START_EDITOR 3011 +#define IDS_VIRUS 3012 +#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 3013 +#define IDS_SELECT_ONE_FILE 3014 +#define IDS_SELECT_FILES 3015 +#define IDS_TOO_MANY_ITEMS 3016 + +#define IDS_COPY 6000 +#define IDS_MOVE 6001 +#define IDS_COPY_TO 6002 +#define IDS_MOVE_TO 6003 +#define IDS_COPYING 6004 +#define IDS_MOVING 6005 +#define IDS_RENAMING 6006 + +#define IDS_OPERATION_IS_NOT_SUPPORTED 6008 +#define IDS_ERROR_RENAMING 6009 +#define IDS_CONFIRM_FILE_COPY 6010 +#define IDS_WANT_TO_COPY_FILES 6011 + +#define IDS_CONFIRM_FILE_DELETE 6100 +#define IDS_CONFIRM_FOLDER_DELETE 6101 +#define IDS_CONFIRM_ITEMS_DELETE 6102 +#define IDS_WANT_TO_DELETE_FILE 6103 +#define IDS_WANT_TO_DELETE_FOLDER 6104 +#define IDS_WANT_TO_DELETE_ITEMS 6105 +#define IDS_DELETING 6106 +#define IDS_ERROR_DELETING 6107 +#define IDS_ERROR_LONG_PATH_TO_RECYCLE 6108 + +#define IDS_CREATE_FOLDER 6300 +#define IDS_CREATE_FILE 6301 +#define IDS_CREATE_FOLDER_NAME 6302 +#define IDS_CREATE_FILE_NAME 6303 +#define IDS_CREATE_FOLDER_DEFAULT_NAME 6304 +#define IDS_CREATE_FILE_DEFAULT_NAME 6305 +#define IDS_CREATE_FOLDER_ERROR 6306 +#define IDS_CREATE_FILE_ERROR 6307 + +#define IDS_COMMENT 6400 +#define IDS_COMMENT2 6401 +#define IDS_SELECT 6402 +#define IDS_DESELECT 6403 +#define IDS_SELECT_MASK 6404 + +#define IDS_PROPERTIES 6600 +#define IDS_FOLDERS_HISTORY 6601 + +#define IDS_COMPUTER 7100 +#define IDS_NETWORK 7101 +#define IDS_DOCUMENTS 7102 +#define IDS_SYSTEM 7103 + +#define IDS_ADD 7200 +#define IDS_EXTRACT 7201 +#define IDS_TEST 7202 +#define IDS_BUTTON_COPY 7203 +#define IDS_BUTTON_MOVE 7204 +#define IDS_BUTTON_DELETE 7205 +#define IDS_BUTTON_INFO 7206 + +#define IDS_SPLITTING 7303 +#define IDS_SPLIT_CONFIRM_TITLE 7304 +#define IDS_SPLIT_CONFIRM_MESSAGE 7305 +#define IDS_SPLIT_VOL_MUST_BE_SMALLER 7306 + +#define IDS_COMBINE 7400 +#define IDS_COMBINE_TO 7401 +#define IDS_COMBINING 7402 +#define IDS_COMBINE_SELECT_ONE_FILE 7403 +#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404 +#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resourceGui.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resourceGui.h new file mode 100644 index 0000000..7c1b40e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/FileManager/resourceGui.h @@ -0,0 +1,15 @@ +#define IDI_ICON 1 + +#define IDS_MESSAGE_NO_ERRORS 3001 + +#define IDS_PROGRESS_TESTING 3302 +#define IDS_OPENNING 3303 +#define IDS_SCANNING 3304 + +#define IDS_CHECKSUM_CALCULATING 7500 +#define IDS_CHECKSUM_INFORMATION 7501 +#define IDS_CHECKSUM_CRC_DATA 7502 +#define IDS_CHECKSUM_CRC_DATA_NAMES 7503 +#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504 + +#define IDS_INCORRECT_VOLUME_SIZE 7307 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/Extract.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/Extract.rc new file mode 100644 index 0000000..36bfb00 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/Extract.rc @@ -0,0 +1,59 @@ +#include "ExtractRes.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE DISCARDABLE +BEGIN + IDS_MEM_ERROR "The system cannot allocate the required amount of memory" + IDS_CANNOT_CREATE_FOLDER "Cannot create folder '{0}'" + IDS_UPDATE_NOT_SUPPORTED "Update operations are not supported for this archive." + IDS_CANT_OPEN_ARCHIVE "Cannot open file '{0}' as archive" + IDS_CANT_OPEN_ENCRYPTED_ARCHIVE "Cannot open encrypted archive '{0}'. Wrong password?" + IDS_UNSUPPORTED_ARCHIVE_TYPE "Unsupported archive type" + + IDS_CANT_OPEN_AS_TYPE "Cannot open the file as {0} archive" + IDS_IS_OPEN_AS_TYPE "The file is open as {0} archive" + IDS_IS_OPEN_WITH_OFFSET "The archive is open with offset" + + IDS_PROGRESS_EXTRACTING "Extracting" + + IDS_PROGRESS_SKIPPING "Skipping" + + IDS_EXTRACT_SET_FOLDER "Specify a location for extracted files." + + IDS_EXTRACT_PATHS_FULL "Full pathnames" + IDS_EXTRACT_PATHS_NO "No pathnames" + IDS_EXTRACT_PATHS_ABS "Absolute pathnames" + IDS_PATH_MODE_RELAT "Relative pathnames" + + IDS_EXTRACT_OVERWRITE_ASK "Ask before overwrite" + IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT "Overwrite without prompt" + IDS_EXTRACT_OVERWRITE_SKIP_EXISTING "Skip existing files" + IDS_EXTRACT_OVERWRITE_RENAME "Auto rename" + IDS_EXTRACT_OVERWRITE_RENAME_EXISTING "Auto rename existing files" + + IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD "Unsupported compression method for '{0}'." + IDS_EXTRACT_MESSAGE_DATA_ERROR "Data error in '{0}'. File is broken" + IDS_EXTRACT_MESSAGE_CRC_ERROR "CRC failed in '{0}'. File is broken." + IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED "Data error in encrypted file '{0}'. Wrong password?" + IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED "CRC failed in encrypted file '{0}'. Wrong password?" + + IDS_EXTRACT_MSG_WRONG_PSW_GUESS "Wrong password?" + // IDS_EXTRACT_MSG_ENCRYPTED "Encrypted file" + + IDS_EXTRACT_MSG_UNSUPPORTED_METHOD "Unsupported compression method" + IDS_EXTRACT_MSG_DATA_ERROR "Data error" + IDS_EXTRACT_MSG_CRC_ERROR "CRC failed" + IDS_EXTRACT_MSG_UNAVAILABLE_DATA "Unavailable data" + IDS_EXTRACT_MSG_UEXPECTED_END "Unexpected end of data" + IDS_EXTRACT_MSG_DATA_AFTER_END "There are some data after the end of the payload data" + IDS_EXTRACT_MSG_IS_NOT_ARC "Is not archive" + IDS_EXTRACT_MSG_HEADERS_ERROR "Headers Error" + IDS_EXTRACT_MSG_WRONG_PSW_CLAIM "Wrong password" + + IDS_OPEN_MSG_UNAVAILABLE_START "Unavailable start of archive" + IDS_OPEN_MSG_UNCONFIRMED_START "Unconfirmed start of archive" + // IDS_OPEN_MSG_ERROR_FLAGS + 5 "Unexpected end of archive" + // IDS_OPEN_MSG_ERROR_FLAGS + 6 "There are data after the end of archive" + IDS_OPEN_MSG_UNSUPPORTED_FEATURE "Unsupported feature" +END diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.cpp new file mode 100644 index 0000000..5132084 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -0,0 +1,421 @@ +// ExtractDialog.cpp + +#include "StdAfx.h" + +#include "../../../Common/StringConvert.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/FileName.h" +#include "../../../Windows/FileDir.h" +#include "../../../Windows/ResourceString.h" + +#ifndef NO_REGISTRY +#include "../FileManager/HelpUtils.h" +#endif + + +#include "../FileManager/BrowseDialog.h" +#include "../FileManager/LangUtils.h" +#include "../FileManager/resourceGui.h" + +#include "ExtractDialog.h" +#include "ExtractDialogRes.h" +#include "ExtractRes.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +extern HINSTANCE g_hInstance; + +#ifndef _SFX + +static const UInt32 kPathMode_IDs[] = +{ + IDS_EXTRACT_PATHS_FULL, + IDS_EXTRACT_PATHS_NO, + IDS_EXTRACT_PATHS_ABS +}; + +static const UInt32 kOverwriteMode_IDs[] = +{ + IDS_EXTRACT_OVERWRITE_ASK, + IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT, + IDS_EXTRACT_OVERWRITE_SKIP_EXISTING, + IDS_EXTRACT_OVERWRITE_RENAME, + IDS_EXTRACT_OVERWRITE_RENAME_EXISTING +}; + +static const + // NExtract::NPathMode::EEnum + int + kPathModeButtonsVals[] = +{ + NExtract::NPathMode::kFullPaths, + NExtract::NPathMode::kNoPaths, + NExtract::NPathMode::kAbsPaths +}; + +static const + int + // NExtract::NOverwriteMode::EEnum + kOverwriteButtonsVals[] = +{ + NExtract::NOverwriteMode::kAsk, + NExtract::NOverwriteMode::kOverwrite, + NExtract::NOverwriteMode::kSkip, + NExtract::NOverwriteMode::kRename, + NExtract::NOverwriteMode::kRenameExisting +}; + +#endif + +#ifdef LANG + +static const UInt32 kLangIDs[] = +{ + IDT_EXTRACT_EXTRACT_TO, + IDT_EXTRACT_PATH_MODE, + IDT_EXTRACT_OVERWRITE_MODE, + // IDX_EXTRACT_ALT_STREAMS, + IDX_EXTRACT_NT_SECUR, + IDX_EXTRACT_ELIM_DUP, + IDG_PASSWORD, + IDX_PASSWORD_SHOW +}; +#endif + +// static const int kWildcardsButtonIndex = 2; + +#ifndef NO_REGISTRY +static const unsigned kHistorySize = 16; +#endif + +#ifndef _SFX + +// it's used in CompressDialog also +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal) +{ + int curSel = 0; + for (unsigned i = 0; i < numItems; i++) + { + UString s = LangString(langIDs[i]); + s.RemoveChar(L'&'); + int index = (int)combo.AddString(s); + combo.SetItemData(index, i); + if (values[i] == curVal) + curSel = i; + } + combo.SetCurSel(curSel); +} + +// it's used in CompressDialog also +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2) +{ + if (b1.Def) return b1.Val; + if (b2.Def) return b2.Val; + return b1.Val; +} + +void CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) +{ + CheckButton(id, GetBoolsVal(b1, b2)); +} + +void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) +{ + bool val = IsButtonCheckedBool(id); + bool oldVal = GetBoolsVal(b1, b2); + if (val != oldVal) + b1.Def = b2.Def = true; + b1.Val = b2.Val = val; +} + +#endif + +bool CExtractDialog::OnInit() +{ + #ifdef LANG + { + UString s; + LangString_OnlyFromLangFile(IDD_EXTRACT, s); + if (s.IsEmpty()) + GetText(s); + if (!ArcPath.IsEmpty()) + { + s += " : "; + s += ArcPath; + } + SetText(s); + // LangSetWindowText(*this, IDD_EXTRACT); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + } + #endif + + #ifndef _SFX + _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD)); + _passwordControl.SetText(Password); + _passwordControl.SetPasswordChar(TEXT('*')); + _pathName.Attach(GetItem(IDE_EXTRACT_NAME)); + #endif + + #ifdef NO_REGISTRY + + PathMode = NExtract::NPathMode::kFullPaths; + OverwriteMode = NExtract::NOverwriteMode::kAsk; + + #else + + _info.Load(); + + if (_info.PathMode == NExtract::NPathMode::kCurPaths) + _info.PathMode = NExtract::NPathMode::kFullPaths; + + if (!PathMode_Force && _info.PathMode_Force) + PathMode = _info.PathMode; + if (!OverwriteMode_Force && _info.OverwriteMode_Force) + OverwriteMode = _info.OverwriteMode; + + // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); + CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); + CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + + CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val); + UpdatePasswordControl(); + + #endif + + _path.Attach(GetItem(IDC_EXTRACT_PATH)); + + UString pathPrefix = DirPath; + + #ifndef _SFX + + if (_info.SplitDest.Val) + { + CheckButton(IDX_EXTRACT_NAME_ENABLE, true); + UString pathName; + SplitPathToParts_Smart(DirPath, pathPrefix, pathName); + if (pathPrefix.IsEmpty()) + pathPrefix = pathName; + else + _pathName.SetText(pathName); + } + else + ShowItem_Bool(IDE_EXTRACT_NAME, false); + + #endif + + _path.SetText(pathPrefix); + + #ifndef NO_REGISTRY + for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++) + _path.AddString(_info.Paths[i]); + #endif + + /* + if (_info.Paths.Size() > 0) + _path.SetCurSel(0); + else + _path.SetCurSel(-1); + */ + + #ifndef _SFX + + _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE)); + _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE)); + + AddComboItems(_pathMode, kPathMode_IDs, ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode); + AddComboItems(_overwriteMode, kOverwriteMode_IDs, ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode); + + #endif + + HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON)); + SetIcon(ICON_BIG, icon); + + // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES); + // filesWindow.Enable(_enableFilesButton); + + NormalizePosition(); + + return CModalDialog::OnInit(); +} + +#ifndef _SFX +void CExtractDialog::UpdatePasswordControl() +{ + _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*')); + UString password; + _passwordControl.GetText(password); + _passwordControl.SetText(password); +} +#endif + +bool CExtractDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDB_EXTRACT_SET_PATH: + OnButtonSetPath(); + return true; + #ifndef _SFX + case IDX_EXTRACT_NAME_ENABLE: + ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE)); + return true; + case IDX_PASSWORD_SHOW: + { + UpdatePasswordControl(); + return true; + } + #endif + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CExtractDialog::OnButtonSetPath() +{ + UString currentPath; + _path.GetText(currentPath); + UString title = LangString(IDS_EXTRACT_SET_FOLDER); + UString resultPath; + if (!MyBrowseForFolder(*this, title, currentPath, resultPath)) + return; + #ifndef NO_REGISTRY + _path.SetCurSel(-1); + #endif + _path.SetText(resultPath); +} + +void AddUniqueString(UStringVector &list, const UString &s); +void AddUniqueString(UStringVector &list, const UString &s) +{ + FOR_VECTOR (i, list) + if (s.IsEqualTo_NoCase(list[i])) + return; + list.Add(s); +} + +void CExtractDialog::OnOK() +{ + #ifndef _SFX + int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()]; + if (PathMode != NExtract::NPathMode::kCurPaths || + pathMode2 != NExtract::NPathMode::kFullPaths) + PathMode = (NExtract::NPathMode::EEnum)pathMode2; + + OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()]; + + // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode(); + + _passwordControl.GetText(Password); + + #endif + + #ifndef NO_REGISTRY + + // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams); + GetButton_Bools(IDX_EXTRACT_NT_SECUR, NtSecurity, _info.NtSecurity); + GetButton_Bools(IDX_EXTRACT_ELIM_DUP, ElimDup, _info.ElimDup); + + bool showPassword = IsShowPasswordChecked(); + if (showPassword != _info.ShowPassword.Val) + { + _info.ShowPassword.Def = true; + _info.ShowPassword.Val = showPassword; + } + + if (_info.PathMode != pathMode2) + { + _info.PathMode_Force = true; + _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2; + /* + // we allow kAbsPaths in registry. + if (_info.PathMode == NExtract::NPathMode::kAbsPaths) + _info.PathMode = NExtract::NPathMode::kFullPaths; + */ + } + + if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode) + _info.OverwriteMode_Force = true; + _info.OverwriteMode = OverwriteMode; + + + #else + + ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); + + #endif + + UString s; + + #ifdef NO_REGISTRY + + _path.GetText(s); + + #else + + int currentItem = _path.GetCurSel(); + if (currentItem == CB_ERR) + { + _path.GetText(s); + if (_path.GetCount() >= (int)kHistorySize) + currentItem = _path.GetCount() - 1; + } + else + _path.GetLBText(currentItem, s); + + #endif + + s.Trim(); + NName::NormalizeDirPathPrefix(s); + + #ifndef _SFX + + bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE); + if (splitDest) + { + UString pathName; + _pathName.GetText(pathName); + pathName.Trim(); + s += pathName; + NName::NormalizeDirPathPrefix(s); + } + if (splitDest != _info.SplitDest.Val) + { + _info.SplitDest.Def = true; + _info.SplitDest.Val = splitDest; + } + + #endif + + DirPath = s; + + #ifndef NO_REGISTRY + _info.Paths.Clear(); + #ifndef _SFX + AddUniqueString(_info.Paths, s); + #endif + for (int i = 0; i < _path.GetCount(); i++) + if (i != currentItem) + { + UString sTemp; + _path.GetLBText(i, sTemp); + sTemp.Trim(); + AddUniqueString(_info.Paths, sTemp); + } + _info.Save(); + #endif + + CModalDialog::OnOK(); +} + +#ifndef NO_REGISTRY +#define kHelpTopic "fm/plugins/7-zip/extract.htm" +void CExtractDialog::OnHelp() +{ + ShowHelpWindow(kHelpTopic); + CModalDialog::OnHelp(); +} +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.h new file mode 100644 index 0000000..33349ff --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.h @@ -0,0 +1,113 @@ +// ExtractDialog.h + +#ifndef __EXTRACT_DIALOG_H +#define __EXTRACT_DIALOG_H + +#include "ExtractDialogRes.h" + +#include "../../../Windows/Control/ComboBox.h" +#include "../../../Windows/Control/Edit.h" + +#include "../Common/ExtractMode.h" + +#include "../FileManager/DialogSize.h" + +#ifndef NO_REGISTRY +#include "../Common/ZipRegistry.h" +#endif + +namespace NExtractionDialog +{ + /* + namespace NFilesMode + { + enum EEnum + { + kSelected, + kAll, + kSpecified + }; + } + */ +} + +class CExtractDialog: public NWindows::NControl::CModalDialog +{ + #ifdef NO_REGISTRY + NWindows::NControl::CDialogChildControl _path; + #else + NWindows::NControl::CComboBox _path; + #endif + + #ifndef _SFX + NWindows::NControl::CEdit _pathName; + NWindows::NControl::CEdit _passwordControl; + NWindows::NControl::CComboBox _pathMode; + NWindows::NControl::CComboBox _overwriteMode; + #endif + + #ifndef _SFX + // int GetFilesMode() const; + void UpdatePasswordControl(); + #endif + + void OnButtonSetPath(); + + void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); + void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); + virtual bool OnInit(); + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK(); + + #ifndef NO_REGISTRY + + virtual void OnHelp(); + + NExtract::CInfo _info; + + #endif + + bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); } +public: + // bool _enableSelectedFilesButton; + // bool _enableFilesButton; + // NExtractionDialog::NFilesMode::EEnum FilesMode; + + UString DirPath; + UString ArcPath; + + #ifndef _SFX + UString Password; + #endif + bool PathMode_Force; + bool OverwriteMode_Force; + NExtract::NPathMode::EEnum PathMode; + NExtract::NOverwriteMode::EEnum OverwriteMode; + + #ifndef _SFX + // CBoolPair AltStreams; + CBoolPair NtSecurity; + #endif + + CBoolPair ElimDup; + + INT_PTR Create(HWND aWndParent = 0) + { + #ifdef _SFX + BIG_DIALOG_SIZE(240, 64); + #else + BIG_DIALOG_SIZE(300, 160); + #endif + return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent); + } + + CExtractDialog(): + PathMode_Force(false), + OverwriteMode_Force(false) + { + ElimDup.Val = true; + } + +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.rc b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.rc new file mode 100644 index 0000000..3728b96 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -0,0 +1,98 @@ +#include "ExtractDialogRes.h" +#include "../../GuiCommon.rc" + +#define xc 336 +#define yc 168 + +#undef g1xs +#undef g2x +#undef g2x2 +#undef g2xs +#undef g2xs2 + +#define g1xs 160 + +#define gSpace 20 +#define g2x (m + g1xs + gSpace) +#define g2x2 (g2x + m) +#define g2xs (xc - g1xs - gSpace) +#define g2xs2 (g2xs - m - m) + +#undef GROUP_Y_SIZE +#ifdef UNDER_CE +#define GROUP_Y_SIZE 8 +#else +#define GROUP_Y_SIZE 56 +#endif + +IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Extract" +BEGIN + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 + COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP + + CONTROL "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10 + EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL + + LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8 + COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO + + CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, + m, m + 84, g1xs, 10 + + LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8 + COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO + + + GROUPBOX "Password", IDG_PASSWORD, g2x, m + 36, g2xs, GROUP_Y_SIZE + EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 50, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72, g2xs2, 10 + +// CONTROL "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX, +// g2x, m + 104, g2xs, 10 + CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX, + g2x, m + 104, g2xs, 10 + + DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP + PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys + PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys +END + + +#ifdef UNDER_CE + +#undef m +#define m 4 + +#undef xc +#undef yc + +#define xc 152 +#define yc 128 + +#undef g1xs + +#define g1xs 64 + +IDD_EXTRACT_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT +CAPTION "Extract" +BEGIN + LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc - bxsDots - 8, 8 + COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 8, 100, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 3, bxsDots, bys, WS_GROUP + + LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 36, g1xs, 8 + COMBOBOX IDC_EXTRACT_PATH_MODE, m + g1xs, m + 36, xc - g1xs, 100, MY_COMBO + + LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 56, g1xs, 8 + COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m + g1xs, m + 56, xc - g1xs, 100, MY_COMBO + + LTEXT "Password", IDG_PASSWORD, m, m + 76, g1xs, 8 + EDITTEXT IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10 + + OK_CANCEL +END + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialogRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialogRes.h new file mode 100644 index 0000000..ed12bfb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractDialogRes.h @@ -0,0 +1,24 @@ +#define IDD_EXTRACT 3400 +#define IDD_EXTRACT_2 13400 + +#define IDC_EXTRACT_PATH 100 +#define IDB_EXTRACT_SET_PATH 101 +#define IDC_EXTRACT_PATH_MODE 102 +#define IDC_EXTRACT_OVERWRITE_MODE 103 + +#define IDE_EXTRACT_PASSWORD 120 + +#define IDE_EXTRACT_NAME 130 +#define IDX_EXTRACT_NAME_ENABLE 131 + + +#define IDT_EXTRACT_EXTRACT_TO 3401 +#define IDT_EXTRACT_PATH_MODE 3410 +#define IDT_EXTRACT_OVERWRITE_MODE 3420 + +#define IDX_EXTRACT_ELIM_DUP 3430 +#define IDX_EXTRACT_NT_SECUR 3431 +// #define IDX_EXTRACT_ALT_STREAMS 3432 + +#define IDX_PASSWORD_SHOW 3803 +#define IDG_PASSWORD 3807 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.cpp b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.cpp new file mode 100644 index 0000000..1e37efb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -0,0 +1,280 @@ +// ExtractGUI.cpp + +#include "StdAfx.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileFind.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/Thread.h" + +#include "../FileManager/ExtractCallback.h" +#include "../FileManager/FormatUtils.h" +#include "../FileManager/LangUtils.h" +#include "../FileManager/resourceGui.h" +#include "../FileManager/OverwriteDialogRes.h" + +#include "../Common/ArchiveExtractCallback.h" +#include "../Common/PropIDUtils.h" + +#include "../Explorer/MyMessages.h" + +#include "resource2.h" +#include "ExtractRes.h" + +#include "ExtractDialog.h" +#include "ExtractGUI.h" +#include "HashGUI.h" + +#include "../FileManager/PropertyNameRes.h" + +using namespace NWindows; +using namespace NFile; +using namespace NDir; + +static const wchar_t * const kIncorrectOutDir = L"Incorrect output directory path"; + +#ifndef _SFX + +static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true) +{ + AddLangString(s, resourceID); + if (addColon) + s += ':'; + s.Add_Space(); + char sz[32]; + ConvertUInt64ToString(value, sz); + s += sz; + s.Add_LF(); +} + +static void AddSizePair(UString &s, UINT resourceID, UInt64 value) +{ + AddLangString(s, resourceID); + s += ": "; + AddSizeValue(s, value); + s.Add_LF(); +} + +#endif + +class CThreadExtracting: public CProgressThreadVirt +{ + HRESULT ProcessVirt(); +public: + CCodecs *codecs; + CExtractCallbackImp *ExtractCallbackSpec; + const CObjectVector *FormatIndices; + const CIntVector *ExcludedFormatIndices; + + UStringVector *ArchivePaths; + UStringVector *ArchivePathsFull; + const NWildcard::CCensorNode *WildcardCensor; + const CExtractOptions *Options; + + #ifndef _SFX + CHashBundle *HashBundle; + virtual void ProcessWasFinished_GuiVirt(); + #endif + + CMyComPtr ExtractCallback; + UString Title; + + CPropNameValPairs Pairs; +}; + + +#ifndef _SFX +void CThreadExtracting::ProcessWasFinished_GuiVirt() +{ + if (HashBundle && !Pairs.IsEmpty()) + ShowHashResults(Pairs, *this); +} +#endif + +HRESULT CThreadExtracting::ProcessVirt() +{ + CDecompressStat Stat; + + #ifndef _SFX + /* + if (HashBundle) + HashBundle->Init(); + */ + #endif + + HRESULT res = Extract(codecs, + *FormatIndices, *ExcludedFormatIndices, + *ArchivePaths, *ArchivePathsFull, + *WildcardCensor, *Options, ExtractCallbackSpec, ExtractCallback, + #ifndef _SFX + HashBundle, + #endif + FinalMessage.ErrorMessage.Message, Stat); + + #ifndef _SFX + if (res == S_OK && ExtractCallbackSpec->IsOK()) + { + if (HashBundle) + { + AddValuePair(Pairs, IDS_ARCHIVES_COLON, Stat.NumArchives); + AddSizeValuePair(Pairs, IDS_PROP_PACKED_SIZE, Stat.PackSize); + AddHashBundleRes(Pairs, *HashBundle); + } + else if (Options->TestMode) + { + UString s; + + AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false); + AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize); + + if (Stat.NumFolders != 0) + AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders); + AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles); + AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize); + if (Stat.NumAltStreams != 0) + { + s.Add_LF(); + AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams); + AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize); + } + s.Add_LF(); + AddLangString(s, IDS_MESSAGE_NO_ERRORS); + FinalMessage.OkMessage.Title = Title; + FinalMessage.OkMessage.Message = s; + } + } + #endif + + return res; +} + + + +HRESULT ExtractGUI( + CCodecs *codecs, + const CObjectVector &formatIndices, + const CIntVector &excludedFormatIndices, + UStringVector &archivePaths, + UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + CExtractOptions &options, + #ifndef _SFX + CHashBundle *hb, + #endif + bool showDialog, + bool &messageWasDisplayed, + CExtractCallbackImp *extractCallback, + HWND hwndParent) +{ + messageWasDisplayed = false; + + CThreadExtracting extracter; + extracter.codecs = codecs; + extracter.FormatIndices = &formatIndices; + extracter.ExcludedFormatIndices = &excludedFormatIndices; + + if (!options.TestMode) + { + FString outputDir = options.OutputDir; + #ifndef UNDER_CE + if (outputDir.IsEmpty()) + GetCurrentDir(outputDir); + #endif + if (showDialog) + { + CExtractDialog dialog; + FString outputDirFull; + if (!MyGetFullPathName(outputDir, outputDirFull)) + { + ShowErrorMessage(kIncorrectOutDir); + messageWasDisplayed = true; + return E_FAIL; + } + NName::NormalizeDirPathPrefix(outputDirFull); + + dialog.DirPath = fs2us(outputDirFull); + + dialog.OverwriteMode = options.OverwriteMode; + dialog.OverwriteMode_Force = options.OverwriteMode_Force; + dialog.PathMode = options.PathMode; + dialog.PathMode_Force = options.PathMode_Force; + dialog.ElimDup = options.ElimDup; + + if (archivePathsFull.Size() == 1) + dialog.ArcPath = archivePathsFull[0]; + + #ifndef _SFX + // dialog.AltStreams = options.NtOptions.AltStreams; + dialog.NtSecurity = options.NtOptions.NtSecurity; + if (extractCallback->PasswordIsDefined) + dialog.Password = extractCallback->Password; + #endif + + if (dialog.Create(hwndParent) != IDOK) + return E_ABORT; + + outputDir = us2fs(dialog.DirPath); + + options.OverwriteMode = dialog.OverwriteMode; + options.PathMode = dialog.PathMode; + options.ElimDup = dialog.ElimDup; + + #ifndef _SFX + // options.NtOptions.AltStreams = dialog.AltStreams; + options.NtOptions.NtSecurity = dialog.NtSecurity; + extractCallback->Password = dialog.Password; + extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty(); + #endif + } + if (!MyGetFullPathName(outputDir, options.OutputDir)) + { + ShowErrorMessage(kIncorrectOutDir); + messageWasDisplayed = true; + return E_FAIL; + } + NName::NormalizeDirPathPrefix(options.OutputDir); + + /* + if (!CreateComplexDirectory(options.OutputDir)) + { + UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError())); + UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, + #ifdef LANG + 0x02000603, + #endif + options.OutputDir); + s2.Add_LF(); + s2 += s; + MyMessageBox(s2); + return E_FAIL; + } + */ + } + + UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING); + + extracter.Title = title; + extracter.ExtractCallbackSpec = extractCallback; + extracter.ExtractCallbackSpec->ProgressDialog = &extracter; + extracter.ExtractCallback = extractCallback; + extracter.ExtractCallbackSpec->Init(); + + extracter.CompressingMode = false; + + extracter.ArchivePaths = &archivePaths; + extracter.ArchivePathsFull = &archivePathsFull; + extracter.WildcardCensor = &wildcardCensor; + extracter.Options = &options; + #ifndef _SFX + extracter.HashBundle = hb; + #endif + + extracter.IconID = IDI_ICON; + + RINOK(extracter.Create(title, hwndParent)); + messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed; + return extracter.Result; +} diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.h new file mode 100644 index 0000000..d55b30d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractGUI.h @@ -0,0 +1,38 @@ +// GUI/ExtractGUI.h + +#ifndef __EXTRACT_GUI_H +#define __EXTRACT_GUI_H + +#include "../Common/Extract.h" + +#include "../FileManager/ExtractCallback.h" + +/* + RESULT can be S_OK, even if there are errors!!! + if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI(). + + RESULT = E_ABORT - user break. + RESULT != E_ABORT: + { + messageWasDisplayed = true - message was displayed already. + messageWasDisplayed = false - there was some internal error, so you must show error message. + } +*/ + +HRESULT ExtractGUI( + CCodecs *codecs, + const CObjectVector &formatIndices, + const CIntVector &excludedFormatIndices, + UStringVector &archivePaths, + UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + CExtractOptions &options, + #ifndef _SFX + CHashBundle *hb, + #endif + bool showDialog, + bool &messageWasDisplayed, + CExtractCallbackImp *extractCallback, + HWND hwndParent = NULL); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractRes.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractRes.h new file mode 100644 index 0000000..634ba6b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/ExtractRes.h @@ -0,0 +1,51 @@ +#define IDS_MEM_ERROR 3000 + +#define IDS_CANNOT_CREATE_FOLDER 3003 +#define IDS_UPDATE_NOT_SUPPORTED 3004 +#define IDS_CANT_OPEN_ARCHIVE 3005 +#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006 +#define IDS_UNSUPPORTED_ARCHIVE_TYPE 3007 + +#define IDS_CANT_OPEN_AS_TYPE 3017 +#define IDS_IS_OPEN_AS_TYPE 3018 +#define IDS_IS_OPEN_WITH_OFFSET 3019 + +#define IDS_PROGRESS_EXTRACTING 3300 + +#define IDS_PROGRESS_SKIPPING 3325 + +#define IDS_EXTRACT_SET_FOLDER 3402 + +#define IDS_EXTRACT_PATHS_FULL 3411 +#define IDS_EXTRACT_PATHS_NO 3412 +#define IDS_EXTRACT_PATHS_ABS 3413 +#define IDS_PATH_MODE_RELAT 3414 + +#define IDS_EXTRACT_OVERWRITE_ASK 3421 +#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT 3422 +#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING 3423 +#define IDS_EXTRACT_OVERWRITE_RENAME 3424 +#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425 + +#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD 3700 +#define IDS_EXTRACT_MESSAGE_DATA_ERROR 3701 +#define IDS_EXTRACT_MESSAGE_CRC_ERROR 3702 +#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED 3703 +#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED 3704 + +#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS 3710 +// #define IDS_EXTRACT_MSG_ENCRYPTED 3711 + +#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD 3721 +#define IDS_EXTRACT_MSG_DATA_ERROR 3722 +#define IDS_EXTRACT_MSG_CRC_ERROR 3723 +#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA 3724 +#define IDS_EXTRACT_MSG_UEXPECTED_END 3725 +#define IDS_EXTRACT_MSG_DATA_AFTER_END 3726 +#define IDS_EXTRACT_MSG_IS_NOT_ARC 3727 +#define IDS_EXTRACT_MSG_HEADERS_ERROR 3728 +#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM 3729 + +#define IDS_OPEN_MSG_UNAVAILABLE_START 3763 +#define IDS_OPEN_MSG_UNCONFIRMED_START 3764 +#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE 3768 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/HashGUI.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/HashGUI.h new file mode 100644 index 0000000..8264453 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/HashGUI.h @@ -0,0 +1,27 @@ +// HashGUI.h + +#ifndef __HASH_GUI_H +#define __HASH_GUI_H + +#include "../Common/HashCalc.h" +#include "../Common/Property.h" + +HRESULT HashCalcGUI( + DECL_EXTERNAL_CODECS_LOC_VARS + const NWildcard::CCensor &censor, + const CHashOptions &options, + bool &messageWasDisplayed); + +typedef CObjectVector CPropNameValPairs; + +void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value); +void AddSizeValue(UString &s, UInt64 value); +void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value); + +void AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb); +void AddHashBundleRes(UString &s, const CHashBundle &hb); + +void ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd); +void ShowHashResults(const CHashBundle &hb, HWND hwnd); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/resource2.h b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/resource2.h new file mode 100644 index 0000000..cd88292 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/UI/GUI/resource2.h @@ -0,0 +1,2 @@ +#define IDS_PROGRESS_COMPRESSING 3301 +#define IDS_ARCHIVES_COLON 3907 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang.mak new file mode 100644 index 0000000..e62e1e6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang.mak @@ -0,0 +1,3 @@ +include ../../var_clang.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_arm64.mak new file mode 100644 index 0000000..3f6b02b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_clang_arm64.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x64.mak new file mode 100644 index 0000000..b61e2af --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x64.mak @@ -0,0 +1,3 @@ +include ../../var_clang_x64.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x86.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x86.mak new file mode 100644 index 0000000..0e5cb76 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_clang_x86.mak @@ -0,0 +1,3 @@ +include ../../var_clang_x86.mak +include ../../warn_clang.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc.mak new file mode 100644 index 0000000..7a1aef2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc.mak @@ -0,0 +1,3 @@ +include ../../var_gcc.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_arm64.mak new file mode 100644 index 0000000..53a8584 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_arm64.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x64.mak new file mode 100644 index 0000000..500c30e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x64.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_x64.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x86.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x86.mak new file mode 100644 index 0000000..e768707 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_gcc_x86.mak @@ -0,0 +1,3 @@ +include ../../var_gcc_x86.mak +include ../../warn_gcc.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_arm64.mak new file mode 100644 index 0000000..941028e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_arm64.mak @@ -0,0 +1,3 @@ +include ../../var_mac_arm64.mak +include ../../warn_clang_mac.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_x64.mak new file mode 100644 index 0000000..d3aa039 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/cmpl_mac_x64.mak @@ -0,0 +1,3 @@ +include ../../var_mac_x64.mak +include ../../warn_clang_mac.mak +include makefile.gcc diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_clang.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang.mak new file mode 100644 index 0000000..a6df26e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang.mak @@ -0,0 +1,11 @@ +PLATFORM= +O=b/c +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_arm64.mak new file mode 100644 index 0000000..4b35409 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x64.mak new file mode 100644 index 0000000..fefed51 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x64.mak @@ -0,0 +1,12 @@ +PLATFORM=x64 +O=b/c_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x86.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x86.mak new file mode 100644 index 0000000..5f3c2d9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_clang_x86.mak @@ -0,0 +1,12 @@ +PLATFORM=x86 +O=b/c_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc.mak new file mode 100644 index 0000000..664491c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc.mak @@ -0,0 +1,12 @@ +PLATFORM= +O=b/g +IS_X64= +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM= +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_arm64.mak new file mode 100644 index 0000000..4bbb687 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_arm64.mak @@ -0,0 +1,12 @@ +PLATFORM=arm64 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-mtune=cortex-a53 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + +# -march=armv8-a+crc+crypto diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x64.mak new file mode 100644 index 0000000..1acf604 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x64.mak @@ -0,0 +1,10 @@ +PLATFORM=x64 +O=b/g_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH= +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x86.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x86.mak new file mode 100644 index 0000000..288bf94 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_gcc_x86.mak @@ -0,0 +1,11 @@ +PLATFORM=x86 +O=b/g_$(PLATFORM) +IS_X64= +IS_X86=1 +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-m32 +USE_ASM=1 +CC=$(CROSS_COMPILE)gcc +CXX=$(CROSS_COMPILE)g++ + diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_arm64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_arm64.mak new file mode 100644 index 0000000..adf5fa1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_arm64.mak @@ -0,0 +1,11 @@ +PLATFORM=arm64 +O=b/m_$(PLATFORM) +IS_X64= +IS_X86= +IS_ARM64=1 +CROSS_COMPILE= +MY_ARCH=-arch arm64 +USE_ASM=1 +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_x64.mak b/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_x64.mak new file mode 100644 index 0000000..13d7aa7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/var_mac_x64.mak @@ -0,0 +1,11 @@ +PLATFORM=x64 +O=b/m_$(PLATFORM) +IS_X64=1 +IS_X86= +IS_ARM64= +CROSS_COMPILE= +MY_ARCH=-arch x86_64 +USE_ASM= +CC=$(CROSS_COMPILE)clang +CXX=$(CROSS_COMPILE)clang++ +USE_CLANG=1 diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang.mak b/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang.mak new file mode 100644 index 0000000..ed4f908 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang.mak @@ -0,0 +1,37 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + +CFLAGS_WARN_1 = \ + -Wno-deprecated-copy-dtor \ + + + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_1) diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang_mac.mak b/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang_mac.mak new file mode 100644 index 0000000..aadf14f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/warn_clang_mac.mak @@ -0,0 +1,39 @@ +CFLAGS_WARN_CLANG_3_8_UNIQ = \ + -Wno-reserved-id-macro \ + -Wno-old-style-cast \ + -Wno-c++11-long-long \ + -Wno-unused-macros \ + +CFLAGS_WARN_CLANG_3_8 = \ + $(CFLAGS_WARN_CLANG_3_8_UNIQ) \ + -Weverything \ + -Wno-extra-semi \ + -Wno-sign-conversion \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-cast-qual \ + -Wno-padded \ + -Wno-exit-time-destructors \ + -Wno-weak-vtables \ + +CFLAGS_WARN_CLANG_12= $(CFLAGS_WARN_CLANG_3_8) \ + -Wno-extra-semi-stmt \ + -Wno-zero-as-null-pointer-constant \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-c++98-compat-pedantic \ + -Wno-atomic-implicit-seq-cst \ + -Wconversion \ + -Wno-sign-conversion \ + -Wno-suggest-override \ + -Wno-suggest-destructor-override \ + +CFLAGS_WARN_MAC = \ + -Wno-poison-system-directories \ + -Wno-c++11-long-long \ + -Wno-atomic-implicit-seq-cst \ + + +CFLAGS_WARN = $(CFLAGS_WARN_CLANG_12) $(CFLAGS_WARN_MAC) diff --git a/3rdparty/lzma-21.03beta/CPP/7zip/warn_gcc.mak b/3rdparty/lzma-21.03beta/CPP/7zip/warn_gcc.mak new file mode 100644 index 0000000..3185326 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/7zip/warn_gcc.mak @@ -0,0 +1,57 @@ +CFLAGS_WARN_GCC_4_5 = \ + +CFLAGS_WARN_GCC_6 = \ + -Waddress \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wcast-align \ + -Wcomment \ + -Wdiv-by-zero \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Winit-self \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + +# -Wno-strict-aliasing + +CFLAGS_WARN_GCC_9 = \ + -Waddress \ + -Waddress-of-packed-member \ + -Waggressive-loop-optimizations \ + -Wattributes \ + -Wbool-compare \ + -Wbool-operation \ + -Wcast-align \ + -Wcast-align=strict \ + -Wcomment \ + -Wdangling-else \ + -Wdiv-by-zero \ + -Wduplicated-branches \ + -Wduplicated-cond \ + -Wformat-contains-nul \ + -Wimplicit-fallthrough=5 \ + -Winit-self \ + -Wint-in-bool-context \ + -Wint-to-pointer-cast \ + -Wunused \ + -Wunused-macros \ + -Wconversion \ + +# -Wno-sign-conversion \ + +CFLAGS_WARN_GCC_10 = $(CFLAGS_WARN_GCC_9) \ + -Wmaybe-uninitialized \ + -Wmisleading-indentation \ + +CFLAGS_WARN_GCC_PPMD_UNALIGNED = \ + -Wno-strict-aliasing \ + + +CFLAGS_WARN = $(CFLAGS_WARN_GCC_9) \ + +# $(CFLAGS_WARN_GCC_PPMD_UNALIGNED) + + \ No newline at end of file diff --git a/3rdparty/lzma-21.03beta/CPP/Build.mak b/3rdparty/lzma-21.03beta/CPP/Build.mak new file mode 100644 index 0000000..1ef676e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Build.mak @@ -0,0 +1,200 @@ +LIBS = $(LIBS) oleaut32.lib ole32.lib + +!IFNDEF MY_NO_UNICODE +CFLAGS = $(CFLAGS) -DUNICODE -D_UNICODE +!ENDIF + +!IFNDEF O +!IFDEF PLATFORM +O=$(PLATFORM) +!ELSE +O=o +!ENDIF +!ENDIF + +!IF "$(CC)" != "clang-cl" +# CFLAGS = $(CFLAGS) -FAsc -Fa$O/asm/ +!ENDIF + + +!IF "$(PLATFORM)" == "x64" +MY_ML = ml64 -WX +#-Dx64 +!ELSEIF "$(PLATFORM)" == "arm" +MY_ML = armasm -WX +!ELSE +MY_ML = ml -WX +# -DABI_CDECL +!ENDIF + +# MY_ML = "$(MY_ML) -Fl$O\asm\ + + +!IFDEF UNDER_CE +RFLAGS = $(RFLAGS) -dUNDER_CE +!IFDEF MY_CONSOLE +LFLAGS = $(LFLAGS) /ENTRY:mainACRTStartup +!ENDIF +!ELSE +!IFDEF OLD_COMPILER +LFLAGS = $(LFLAGS) -OPT:NOWIN98 +!ENDIF +!IF "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +CFLAGS = $(CFLAGS) -Gr +!ENDIF +LIBS = $(LIBS) user32.lib advapi32.lib shell32.lib +!ENDIF + +!IF "$(PLATFORM)" == "arm" +COMPL_ASM = $(MY_ML) $** $O/$(*B).obj +!ELSE +COMPL_ASM = $(MY_ML) -c -Fo$O/ $** +!ENDIF + +CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -W4 -WX -EHsc -Gy -GR- -GF + +!IF "$(CC)" == "clang-cl" + +CFLAGS = $(CFLAGS) \ + -Werror \ + -Wextra \ + -Wall \ + -Weverything \ + -Wno-extra-semi-stmt \ + -Wno-extra-semi \ + -Wno-zero-as-null-pointer-constant \ + -Wno-sign-conversion \ + -Wno-old-style-cast \ + -Wno-reserved-id-macro \ + -Wno-deprecated-dynamic-exception-spec \ + -Wno-language-extension-token \ + -Wno-global-constructors \ + -Wno-non-virtual-dtor \ + -Wno-deprecated-copy-dtor \ + -Wno-exit-time-destructors \ + -Wno-switch-enum \ + -Wno-covered-switch-default \ + -Wno-nonportable-system-include-path \ + -Wno-c++98-compat-pedantic \ + -Wno-cast-qual \ + -Wc++11-extensions \ + +!ENDIF + +!IFDEF MY_DYNAMIC_LINK +CFLAGS = $(CFLAGS) -MD +!ELSE +!IFNDEF MY_SINGLE_THREAD +CFLAGS = $(CFLAGS) -MT +!ENDIF +!ENDIF + + +CFLAGS = $(CFLAGS_COMMON) $(CFLAGS) + +!IFNDEF OLD_COMPILER +CFLAGS = $(CFLAGS) -GS- -Zc:forScope -Zc:wchar_t +!IFNDEF UNDER_CE +!IF "$(CC)" != "clang-cl" +CFLAGS = $(CFLAGS) -MP4 +!ENDIF +!IFNDEF PLATFORM +# CFLAGS = $(CFLAGS) -arch:IA32 +!ENDIF +!ENDIF +!ELSE +CFLAGS = $(CFLAGS) +!ENDIF + +!IFDEF MY_CONSOLE +CFLAGS = $(CFLAGS) -D_CONSOLE +!ENDIF + +!IFNDEF UNDER_CE +!IF "$(PLATFORM)" == "arm" +CFLAGS = $(CFLAGS) -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +!ENDIF +!ENDIF + +!IF "$(PLATFORM)" == "x64" +CFLAGS_O1 = $(CFLAGS) -O1 +!ELSE +CFLAGS_O1 = $(CFLAGS) -O1 +!ENDIF +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:REF -OPT:ICF + +!IFNDEF UNDER_CE +LFLAGS = $(LFLAGS) /LARGEADDRESSAWARE +!ENDIF + +!IFDEF DEF_FILE +LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) +!ELSE +!IF defined(MY_FIXED) && "$(PLATFORM)" != "arm" && "$(PLATFORM)" != "arm64" +LFLAGS = $(LFLAGS) /FIXED +!ELSE +LFLAGS = $(LFLAGS) /FIXED:NO +!ENDIF +# /BASE:0x400000 +!ENDIF + + +# !IF "$(PLATFORM)" == "x64" + +!IFDEF SUB_SYS_VER + +MY_SUB_SYS_VER=5.02 + +!IFDEF MY_CONSOLE +LFLAGS = $(LFLAGS) /SUBSYSTEM:console,$(MY_SUB_SYS_VER) +!ELSE +LFLAGS = $(LFLAGS) /SUBSYSTEM:windows,$(MY_SUB_SYS_VER) +!ENDIF + +!ENDIF + + +PROGPATH = $O\$(PROG) + +COMPL_O1 = $(CC) $(CFLAGS_O1) $** +COMPL_O2 = $(CC) $(CFLAGS_O2) $** +COMPL_PCH = $(CC) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** +COMPL = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** + +COMPLB = $(CC) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $< +# COMPLB_O2 = $(CC) $(CFLAGS_O2) -Yu"StdAfx.h" -Fp$O/a.pch $< +COMPLB_O2 = $(CC) $(CFLAGS_O2) $< + +CFLAGS_C_ALL = $(CFLAGS_O2) $(CFLAGS_C_SPEC) +CCOMPL_PCH = $(CC) $(CFLAGS_C_ALL) -Yc"Precomp.h" -Fp$O/a.pch $** +CCOMPL_USE = $(CC) $(CFLAGS_C_ALL) -Yu"Precomp.h" -Fp$O/a.pch $** +CCOMPL = $(CC) $(CFLAGS_C_ALL) $** +CCOMPLB = $(CC) $(CFLAGS_C_ALL) $< + +!IF "$(CC)" == "clang-cl" +COMPL = $(COMPL) -FI StdAfx.h +COMPLB = $(COMPLB) -FI StdAfx.h +CCOMPL_USE = $(CCOMPL_USE) -FI Precomp.h +!ENDIF + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O\*.asm + +$O: + if not exist "$O" mkdir "$O" +$O/asm: + if not exist "$O/asm" mkdir "$O/asm" + +$(PROGPATH): $O $O/asm $(OBJS) $(DEF_FILE) + link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) + +!IFNDEF NO_DEFAULT_RES +$O\resource.res: $(*B).rc + rc $(RFLAGS) -fo$@ $** +!ENDIF +$O\StdAfx.obj: $(*B).cpp + $(COMPL_PCH) diff --git a/3rdparty/lzma-21.03beta/CPP/Common/AutoPtr.h b/3rdparty/lzma-21.03beta/CPP/Common/AutoPtr.h new file mode 100644 index 0000000..006d315 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/AutoPtr.h @@ -0,0 +1,35 @@ +// Common/AutoPtr.h + +#ifndef __COMMON_AUTOPTR_H +#define __COMMON_AUTOPTR_H + +template class CMyAutoPtr +{ + T *_p; +public: + CMyAutoPtr(T *p = 0) : _p(p) {} + CMyAutoPtr(CMyAutoPtr& p): _p(p.release()) {} + CMyAutoPtr& operator=(CMyAutoPtr& p) + { + reset(p.release()); + return (*this); + } + ~CMyAutoPtr() { delete _p; } + T& operator*() const { return *_p; } + // T* operator->() const { return (&**this); } + T* get() const { return _p; } + T* release() + { + T *tmp = _p; + _p = 0; + return tmp; + } + void reset(T* p = 0) + { + if (p != _p) + delete _p; + _p = p; + } +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/CRC.cpp b/3rdparty/lzma-21.03beta/CPP/Common/CRC.cpp new file mode 100644 index 0000000..c6b7d5e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/CRC.cpp @@ -0,0 +1,7 @@ +// Common/CRC.cpp + +#include "StdAfx.h" + +#include "../../C/7zCrc.h" + +static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; diff --git a/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.cpp b/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.cpp new file mode 100644 index 0000000..4bd3fad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.cpp @@ -0,0 +1,3 @@ +// Common/C_FileIO.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.h b/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.h new file mode 100644 index 0000000..6818558 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/C_FileIO.h @@ -0,0 +1,6 @@ +// Common/C_FileIO.h + +#ifndef __COMMON_C_FILEIO_H +#define __COMMON_C_FILEIO_H + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/ComTry.h b/3rdparty/lzma-21.03beta/CPP/Common/ComTry.h new file mode 100644 index 0000000..297c407 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/ComTry.h @@ -0,0 +1,21 @@ +// ComTry.h + +#ifndef __COM_TRY_H +#define __COM_TRY_H + +#include "MyWindows.h" +// #include "Exception.h" +// #include "NewHandler.h" + +#define COM_TRY_BEGIN try { +#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } + +/* +#define COM_TRY_END } \ + catch(const CNewException &) { return E_OUTOFMEMORY; } \ + catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \ +*/ + // catch(const CSystemException &e) { return e.ErrorCode; } + // catch(...) { return E_FAIL; } + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.cpp b/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.cpp new file mode 100644 index 0000000..465e0fd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.cpp @@ -0,0 +1,197 @@ +// CommandLineParser.cpp + +#include "StdAfx.h" + +#include "CommandLineParser.h" + +namespace NCommandLineParser { + +bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2) +{ + dest1.Empty(); + dest2.Empty(); + bool quoteMode = false; + unsigned i; + for (i = 0; i < src.Len(); i++) + { + wchar_t c = src[i]; + if ((c == L' ' || c == L'\t') && !quoteMode) + { + dest2 = src.Ptr(i + 1); + return i != 0; + } + if (c == L'\"') + quoteMode = !quoteMode; + else + dest1 += c; + } + return i != 0; +} + +void SplitCommandLine(const UString &s, UStringVector &parts) +{ + UString sTemp (s); + sTemp.Trim(); + parts.Clear(); + for (;;) + { + UString s1, s2; + if (SplitCommandLine(sTemp, s1, s2)) + parts.Add(s1); + if (s2.IsEmpty()) + break; + sTemp = s2; + } +} + + +static const char * const kStopSwitchParsing = "--"; + +static bool inline IsItSwitchChar(wchar_t c) +{ + return (c == '-'); +} + +CParser::CParser(): + _switches(NULL), + StopSwitchIndex(-1) +{ +} + +CParser::~CParser() +{ + delete []_switches; +} + + +// if (s) contains switch then function updates switch structures +// out: true, if (s) is a switch +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches) +{ + if (s.IsEmpty() || !IsItSwitchChar(s[0])) + return false; + + unsigned pos = 1; + unsigned switchIndex = 0; + int maxLen = -1; + + for (unsigned i = 0; i < numSwitches; i++) + { + const char * const key = switchForms[i].Key; + unsigned switchLen = MyStringLen(key); + if ((int)switchLen <= maxLen || pos + switchLen > s.Len()) + continue; + if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key)) + { + switchIndex = i; + maxLen = (int)switchLen; + } + } + + if (maxLen < 0) + { + ErrorMessage = "Unknown switch:"; + return false; + } + + pos += (unsigned)maxLen; + + CSwitchResult &sw = _switches[switchIndex]; + const CSwitchForm &form = switchForms[switchIndex]; + + if (!form.Multi && sw.ThereIs) + { + ErrorMessage = "Multiple instances for switch:"; + return false; + } + + sw.ThereIs = true; + + const unsigned rem = s.Len() - pos; + if (rem < form.MinLen) + { + ErrorMessage = "Too short switch:"; + return false; + } + + sw.WithMinus = false; + sw.PostCharIndex = -1; + + switch (form.Type) + { + case NSwitchType::kMinus: + if (rem == 1) + { + sw.WithMinus = (s[pos] == '-'); + if (sw.WithMinus) + return true; + ErrorMessage = "Incorrect switch postfix:"; + return false; + } + break; + + case NSwitchType::kChar: + if (rem == 1) + { + wchar_t c = s[pos]; + if (c <= 0x7F) + { + sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c); + if (sw.PostCharIndex >= 0) + return true; + } + ErrorMessage = "Incorrect switch postfix:"; + return false; + } + break; + + case NSwitchType::kString: + { + sw.PostStrings.Add(s.Ptr(pos)); + return true; + } + } + + if (pos != s.Len()) + { + ErrorMessage = "Too long switch:"; + return false; + } + return true; +} + + +bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings) +{ + StopSwitchIndex = -1; + ErrorMessage.Empty(); + ErrorLine.Empty(); + NonSwitchStrings.Clear(); + delete []_switches; + _switches = NULL; + _switches = new CSwitchResult[numSwitches]; + + FOR_VECTOR (i, commandStrings) + { + const UString &s = commandStrings[i]; + if (StopSwitchIndex < 0) + { + if (s.IsEqualTo(kStopSwitchParsing)) + { + StopSwitchIndex = (int)NonSwitchStrings.Size(); + continue; + } + if (!s.IsEmpty() && IsItSwitchChar(s[0])) + { + if (ParseString(s, switchForms, numSwitches)) + continue; + ErrorLine = s; + return false; + } + } + NonSwitchStrings.Add(s); + } + return true; +} + +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.h b/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.h new file mode 100644 index 0000000..fbd4fa5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/CommandLineParser.h @@ -0,0 +1,63 @@ +// Common/CommandLineParser.h + +#ifndef __COMMON_COMMAND_LINE_PARSER_H +#define __COMMON_COMMAND_LINE_PARSER_H + +#include "MyString.h" + +namespace NCommandLineParser { + +bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2); +void SplitCommandLine(const UString &s, UStringVector &parts); + +namespace NSwitchType +{ + enum EEnum + { + kSimple, + kMinus, + kString, + kChar + }; +} + +struct CSwitchForm +{ + const char *Key; + Byte Type; + bool Multi; + Byte MinLen; + // int MaxLen; + const char *PostCharSet; +}; + +struct CSwitchResult +{ + bool ThereIs; + bool WithMinus; + int PostCharIndex; + UStringVector PostStrings; + + CSwitchResult(): ThereIs(false) {} +}; + +class CParser +{ + CSwitchResult *_switches; + + bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches); +public: + UStringVector NonSwitchStrings; + int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--" + AString ErrorMessage; + UString ErrorLine; + + CParser(); + ~CParser(); + bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings); + const CSwitchResult& operator[](unsigned index) const { return _switches[index]; } +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Common.h b/3rdparty/lzma-21.03beta/CPP/Common/Common.h new file mode 100644 index 0000000..8dac613 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Common.h @@ -0,0 +1,57 @@ +// Common.h + +#ifndef __COMMON_COMMON_H +#define __COMMON_COMMON_H + +/* +This file is included to all cpp files in 7-Zip. +Each folder contains StdAfx.h file that includes "Common.h". +So 7-Zip includes "Common.h" in both modes: + with precompiled StdAfx.h +and + without precompiled StdAfx.h + +If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip. +If you don't need some things that are used in 7-Zip, +you can change this h file or h files included in this file. +*/ + +// compiler pragmas to disable some warnings +#include "../../C/Compiler.h" + +// it's or code that defines windows things, if it's not _WIN32 +#include "MyWindows.h" + +// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers +#include "NewHandler.h" + + + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + + +/* There is BUG in MSVC 6.0 compiler for operator new[]: + It doesn't check overflow, when it calculates size in bytes for allocated array. + So we can use MY_ARRAY_NEW macro instead of new[] operator. */ + +#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) + #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size]; +#else + #define MY_ARRAY_NEW(p, T, size) p = new T[size]; +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 8)) + #define MY_ATTR_NORETURN __attribute__((noreturn)) +#elif (defined(__clang__) && (__clang_major__ >= 3)) + #if __has_feature(cxx_attributes) + #define MY_ATTR_NORETURN [[noreturn]] + #else + #define MY_ATTR_NORETURN __attribute__ ((noreturn)) + #endif +#elif (defined(_MSC_VER) && (_MSC_VER >= 1900)) + #define MY_ATTR_NORETURN [[noreturn]] +#else + #define MY_ATTR_NORETURN +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/CrcReg.cpp b/3rdparty/lzma-21.03beta/CPP/Common/CrcReg.cpp new file mode 100644 index 0000000..fdbba77 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/CrcReg.cpp @@ -0,0 +1,95 @@ +// CrcReg.cpp + +#include "StdAfx.h" + +#include "../../C/7zCrc.h" +#include "../../C/CpuArch.h" + +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +EXTERN_C_BEGIN + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); + +extern CRC_FUNC g_CrcUpdate; +extern CRC_FUNC g_CrcUpdateT4; +extern CRC_FUNC g_CrcUpdateT8; +extern CRC_FUNC g_CrcUpdateT0_32; +extern CRC_FUNC g_CrcUpdateT0_64; + +EXTERN_C_END + +class CCrcHasher: + public IHasher, + public ICompressSetCoderProperties, + public CMyUnknownImp +{ + UInt32 _crc; + CRC_FUNC _updateFunc; + Byte mtDummy[1 << 7]; + + bool SetFunctions(UInt32 tSize); +public: + CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); } + + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) + INTERFACE_IHasher(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +bool CCrcHasher::SetFunctions(UInt32 tSize) +{ + CRC_FUNC f = NULL; + if (tSize == 0) f = g_CrcUpdate; + else if (tSize == 1) f = CrcUpdateT1; + else if (tSize == 4) f = g_CrcUpdateT4; + else if (tSize == 8) f = g_CrcUpdateT8; + else if (tSize == 32) f = g_CrcUpdateT0_32; + else if (tSize == 64) f = g_CrcUpdateT0_64; + + if (!f) + { + _updateFunc = g_CrcUpdate; + return false; + } + _updateFunc = f; + return true; +} + +STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (!SetFunctions(prop.ulVal)) + return E_NOTIMPL; + } + } + return S_OK; +} + +STDMETHODIMP_(void) CCrcHasher::Init() throw() +{ + _crc = CRC_INIT_VAL; +} + +STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) throw() +{ + _crc = _updateFunc(_crc, data, size, g_CrcTable); +} + +STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) throw() +{ + UInt32 val = CRC_GET_DIGEST(_crc); + SetUi32(digest, val); +} + +REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4) diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Defs.h b/3rdparty/lzma-21.03beta/CPP/Common/Defs.h new file mode 100644 index 0000000..9adb88c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Defs.h @@ -0,0 +1,16 @@ +// Common/Defs.h + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template inline T MyMin(T a, T b) { return a < b ? a : b; } +template inline T MyMax(T a, T b) { return a > b ? a : b; } + +template inline int MyCompare(T a, T b) + { return a == b ? 0 : (a < b ? -1 : 1); } + +inline int BoolToInt(bool v) { return (v ? 1 : 0); } +inline unsigned BoolToUInt(bool v) { return (v ? (unsigned)1 : (unsigned)0); } +inline bool IntToBool(int v) { return (v != 0); } + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/DynamicBuffer.h b/3rdparty/lzma-21.03beta/CPP/Common/DynamicBuffer.h new file mode 100644 index 0000000..f6f6b15 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/DynamicBuffer.h @@ -0,0 +1,64 @@ +// Common/DynamicBuffer.h + +#ifndef __COMMON_DYNAMIC_BUFFER_H +#define __COMMON_DYNAMIC_BUFFER_H + +template class CDynamicBuffer +{ + T *_items; + size_t _size; + size_t _pos; + + CDynamicBuffer(const CDynamicBuffer &buffer); + void operator=(const CDynamicBuffer &buffer); + + void Grow(size_t size) + { + size_t delta = _size >= 64 ? _size : 64; + if (delta < size) + delta = size; + size_t newCap = _size + delta; + if (newCap < delta) + { + newCap = _size + size; + if (newCap < size) + throw 20120116; + } + + T *newBuffer = new T[newCap]; + if (_pos != 0) + memcpy(newBuffer, _items, _pos * sizeof(T)); + delete []_items; + _items = newBuffer; + _size = newCap; + } + +public: + CDynamicBuffer(): _items(0), _size(0), _pos(0) {} + // operator T *() { return _items; } + operator const T *() const { return _items; } + ~CDynamicBuffer() { delete []_items; } + + T *GetCurPtrAndGrow(size_t addSize) + { + size_t rem = _size - _pos; + if (rem < addSize) + Grow(addSize - rem); + T *res = _items + _pos; + _pos += addSize; + return res; + } + + void AddData(const T *data, size_t size) + { + memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T)); + } + + size_t GetPos() const { return _pos; } + + // void Empty() { _pos = 0; } +}; + +typedef CDynamicBuffer CByteDynamicBuffer; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/IntToString.cpp b/3rdparty/lzma-21.03beta/CPP/Common/IntToString.cpp new file mode 100644 index 0000000..c87643c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/IntToString.cpp @@ -0,0 +1,192 @@ +// Common/IntToString.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "IntToString.h" + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = (charType)temp[i]; } \ + *s = 0; \ + return s; + +char * ConvertUInt32ToString(UInt32 val, char *s) throw() +{ + CONVERT_INT_TO_STR(char, 16); +} + +char * ConvertUInt64ToString(UInt64 val, char *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) + { + return ConvertUInt32ToString((UInt32)val, s); + } + CONVERT_INT_TO_STR(char, 24); +} + +void ConvertUInt64ToOct(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 3; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0x7); + val >>= 3; + s[--i] = (char)('0' + t); + } + while (i); +} + + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); } + + +void ConvertUInt32ToHex(UInt32 val, char *s) throw() +{ + UInt32 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + + +void ConvertUInt64ToHex(UInt64 val, char *s) throw() +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw() +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = GET_HEX_CHAR(t);; + } +} + +/* +void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s) +{ + s[8] = 0; + for (int i = 7; i >= 0; i--) + { + unsigned t = val & 0xF; + val >>= 4; + s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); + } +} +*/ + +wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw() +{ + CONVERT_INT_TO_STR(wchar_t, 16); +} + +wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw() +{ + if (val <= (UInt32)0xFFFFFFFF) + { + return ConvertUInt32ToString((UInt32)val, s); + } + CONVERT_INT_TO_STR(wchar_t, 24); +} + +void ConvertInt64ToString(Int64 val, char *s) throw() +{ + if (val < 0) + { + *s++ = '-'; + val = -val; + } + ConvertUInt64ToString((UInt64)val, s); +} + +void ConvertInt64ToString(Int64 val, wchar_t *s) throw() +{ + if (val < 0) + { + *s++ = L'-'; + val = -val; + } + ConvertUInt64ToString((UInt64)val, s); +} + + +static void ConvertByteToHex2Digits(unsigned v, char *s) throw() +{ + s[0] = GetHexChar(v >> 4); + s[1] = GetHexChar(v & 0xF); +} + +static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw() +{ + ConvertByteToHex2Digits(val >> 8, s); + ConvertByteToHex2Digits(val & 0xFF, s + 2); +} + +char *RawLeGuidToString(const Byte *g, char *s) throw() +{ + ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-'; + ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-'; + for (unsigned i = 0; i < 8; i++) + { + if (i == 2) + *s++ = '-'; + ConvertByteToHex2Digits(g[8 + i], s); + s += 2; + } + *s = 0; + return s; +} + +char *RawLeGuidToString_Braced(const Byte *g, char *s) throw() +{ + *s++ = '{'; + s = RawLeGuidToString(g, s); + *s++ = '}'; + *s = 0; + return s; +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/IntToString.h b/3rdparty/lzma-21.03beta/CPP/Common/IntToString.h new file mode 100644 index 0000000..d0a96ef --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/IntToString.h @@ -0,0 +1,30 @@ +// Common/IntToString.h + +#ifndef __COMMON_INT_TO_STRING_H +#define __COMMON_INT_TO_STRING_H + +#include "MyTypes.h" + +// return: the pointer to the "terminating" null character after written characters + +char * ConvertUInt32ToString(UInt32 value, char *s) throw(); +char * ConvertUInt64ToString(UInt64 value, char *s) throw(); + +wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw(); +wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw(); + +void ConvertUInt64ToOct(UInt64 value, char *s) throw(); + +void ConvertUInt32ToHex(UInt32 value, char *s) throw(); +void ConvertUInt64ToHex(UInt64 value, char *s) throw(); +void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw(); +// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw(); + +void ConvertInt64ToString(Int64 value, char *s) throw(); +void ConvertInt64ToString(Int64 value, wchar_t *s) throw(); + +// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian. +char *RawLeGuidToString(const Byte *guid, char *s) throw(); +char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw(); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Lang.h b/3rdparty/lzma-21.03beta/CPP/Common/Lang.h new file mode 100644 index 0000000..cc66677 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Lang.h @@ -0,0 +1,23 @@ +// Common/Lang.h + +#ifndef __COMMON_LANG_H +#define __COMMON_LANG_H + +#include "MyString.h" + +class CLang +{ + wchar_t *_text; + CRecordVector _ids; + CRecordVector _offsets; + + bool OpenFromString(const AString &s); +public: + CLang(): _text(0) {} + ~CLang() { Clear(); } + bool Open(CFSTR fileName, const char *id); + void Clear() throw(); + const wchar_t *Get(UInt32 id) const throw(); +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.cpp b/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.cpp new file mode 100644 index 0000000..b361b37 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.cpp @@ -0,0 +1,150 @@ +// Common/ListFileUtils.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "ListFileUtils.h" +#include "MyBuffer.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +#include "../Windows/FileIO.h" + +#define CSysInFile NWindows::NFile::NIO::CInFile +#define MY_GET_LAST_ERROR ::GetLastError() + + +#define kQuoteChar '\"' + + +static void AddName(UStringVector &strings, UString &s) +{ + s.Trim(); + if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar) + { + s.DeleteBack(); + s.Delete(0); + } + if (!s.IsEmpty()) + strings.Add(s); +} + + +static bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError) +{ + size_t processed; + if (!file.ReadFull(data, size, processed)) + { + lastError = MY_GET_LAST_ERROR; + return false; + } + if (processed != size) + { + lastError = 1; // error: size of listfile was changed + return false; + } + return true; +} + + +bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError) +{ + lastError = 0; + CSysInFile file; + if (!file.Open(fileName)) + { + lastError = MY_GET_LAST_ERROR; + return false; + } + UInt64 fileSize; + if (!file.GetLength(fileSize)) + { + lastError = MY_GET_LAST_ERROR; + return false; + } + if (fileSize >= ((UInt32)1 << 31) - 32) + return false; + UString u; + if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE) + { + if ((fileSize & 1) != 0) + return false; + CByteArr buf((size_t)fileSize); + + if (!My_File_Read(file, buf, (size_t)fileSize, lastError)) + return false; + + file.Close(); + const unsigned num = (unsigned)fileSize / 2; + wchar_t *p = u.GetBuf(num); + if (codePage == MY__CP_UTF16) + for (unsigned i = 0; i < num; i++) + { + wchar_t c = GetUi16(buf + (size_t)i * 2); + if (c == 0) + return false; + p[i] = c; + } + else + for (unsigned i = 0; i < num; i++) + { + wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2); + if (c == 0) + return false; + p[i] = c; + } + p[num] = 0; + u.ReleaseBuf_SetLen(num); + } + else + { + AString s; + char *p = s.GetBuf((unsigned)fileSize); + + if (!My_File_Read(file, p, (size_t)fileSize, lastError)) + return false; + + file.Close(); + s.ReleaseBuf_CalcLen((unsigned)fileSize); + if (s.Len() != fileSize) + return false; + + // #ifdef CP_UTF8 + if (codePage == CP_UTF8) + { + // we must check UTF8 here, if convert function doesn't check + if (!CheckUTF8_AString(s)) + return false; + if (!ConvertUTF8ToUnicode(s, u)) + return false; + } + else + // #endif + MultiByteToUnicodeString2(u, s, codePage); + } + + const wchar_t kGoodBOM = 0xFEFF; + // const wchar_t kBadBOM = 0xFFFE; + + UString s; + unsigned i = 0; + for (; i < u.Len() && u[i] == kGoodBOM; i++); + for (; i < u.Len(); i++) + { + wchar_t c = u[i]; + /* + if (c == kGoodBOM || c == kBadBOM) + return false; + */ + if (c == '\n' || c == 0xD) + { + AddName(strings, s); + s.Empty(); + } + else + s += c; + } + AddName(strings, s); + return true; +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.h b/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.h new file mode 100644 index 0000000..a91e4b1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/ListFileUtils.h @@ -0,0 +1,18 @@ +// Common/ListFileUtils.h + +#ifndef __COMMON_LIST_FILE_UTILS_H +#define __COMMON_LIST_FILE_UTILS_H + +#include "MyString.h" +#include "MyTypes.h" + +#define MY__CP_UTF16 1200 +#define MY__CP_UTF16BE 1201 + +// bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); + + // = CP_OEMCP +bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, + DWORD &lastError); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/LzFindPrepare.cpp b/3rdparty/lzma-21.03beta/CPP/Common/LzFindPrepare.cpp new file mode 100644 index 0000000..8845e4a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/LzFindPrepare.cpp @@ -0,0 +1,7 @@ +// Sha256Prepare.cpp + +#include "StdAfx.h" + +#include "../../C/LzFind.h" + +static struct CLzFindPrepare { CLzFindPrepare() { LzFindPrepare(); } } g_CLzFindPrepare; diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer.h b/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer.h new file mode 100644 index 0000000..18ab6fa --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer.h @@ -0,0 +1,277 @@ +// Common/MyBuffer.h + +#ifndef __COMMON_MY_BUFFER_H +#define __COMMON_MY_BUFFER_H + +#include "Defs.h" +#include "MyTypes.h" + +/* 7-Zip now uses CBuffer only as CByteBuffer. + So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */ + +template class CBuffer +{ + T *_items; + size_t _size; + +public: + void Free() + { + if (_items) + { + delete []_items; + _items = 0; + } + _size = 0; + } + + CBuffer(): _items(0), _size(0) {}; + CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; } + CBuffer(const CBuffer &buffer): _items(0), _size(0) + { + size_t size = buffer._size; + if (size != 0) + { + _items = new T[size]; + memcpy(_items, buffer._items, size * sizeof(T)); + _size = size; + } + } + + ~CBuffer() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (size != _size) + { + Free(); + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + } + + void AllocAtLeast(size_t size) + { + if (size > _size) + { + Free(); + _items = new T[size]; + _size = size; + } + } + + void CopyFrom(const T *data, size_t size) + { + Alloc(size); + if (size != 0) + memcpy(_items, data, size * sizeof(T)); + } + + void ChangeSize_KeepData(size_t newSize, size_t keepSize) + { + if (newSize == _size) + return; + T *newBuffer = NULL; + if (newSize != 0) + { + newBuffer = new T[newSize]; + if (keepSize > _size) + keepSize = _size; + if (keepSize != 0) + memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T)); + } + delete []_items; + _items = newBuffer; + _size = newSize; + } + + void Wipe() + { + if (_size != 0) + memset(_items, 0, _size * sizeof(T)); + } + + CBuffer& operator=(const CBuffer &buffer) + { + if (&buffer != this) + CopyFrom(buffer, buffer._size); + return *this; + } +}; + +template +bool operator==(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return false; + if (size1 == 0) + return true; + return memcmp(b1, b2, size1 * sizeof(T)) == 0; +} + +template +bool operator!=(const CBuffer& b1, const CBuffer& b2) +{ + size_t size1 = b1.Size(); + if (size1 != b2.Size()) + return true; + if (size1 == 0) + return false; + return memcmp(b1, b2, size1 * sizeof(T)) != 0; +} + + +// typedef CBuffer CCharBuffer; +// typedef CBuffer CWCharBuffer; +typedef CBuffer CByteBuffer; + + +class CByteBuffer_Wipe: public CByteBuffer +{ + CLASS_NO_COPY(CByteBuffer_Wipe) +public: + // CByteBuffer_Wipe(): CBuffer() {} + CByteBuffer_Wipe(size_t size): CBuffer(size) {} + ~CByteBuffer_Wipe() { Wipe(); } +}; + + + +template class CObjArray +{ +protected: + T *_items; +private: + // we disable copy + CObjArray(const CObjArray &buffer); + void operator=(const CObjArray &buffer); +public: + void Free() + { + delete []_items; + _items = 0; + } + CObjArray(size_t size): _items(0) + { + if (size != 0) + { + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; + } + } + CObjArray(): _items(0) {}; + ~CObjArray() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + + void Alloc(size_t newSize) + { + delete []_items; + _items = 0; + MY_ARRAY_NEW(_items, T, newSize) + // _items = new T[newSize]; + } +}; + +typedef CObjArray CByteArr; +typedef CObjArray CBoolArr; +typedef CObjArray CIntArr; +typedef CObjArray CUIntArr; + + +template class CObjArray2 +{ + T *_items; + unsigned _size; + + // we disable copy + CObjArray2(const CObjArray2 &buffer); + void operator=(const CObjArray2 &buffer); +public: + + void Free() + { + delete []_items; + _items = 0; + _size = 0; + } + CObjArray2(): _items(0), _size(0) {}; + /* + CObjArray2(const CObjArray2 &buffer): _items(0), _size(0) + { + size_t newSize = buffer._size; + if (newSize != 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + } + */ + /* + CObjArray2(size_t size): _items(0), _size(0) + { + if (size != 0) + { + _items = new T[size]; + _size = size; + } + } + */ + + ~CObjArray2() { delete []_items; } + + operator T *() { return _items; } + operator const T *() const { return _items; } + + unsigned Size() const { return (unsigned)_size; } + bool IsEmpty() const { return _size == 0; } + + // SetSize doesn't keep old items. It allocates new array if size is not equal + void SetSize(unsigned size) + { + if (size == _size) + return; + T *newBuffer = NULL; + if (size != 0) + { + MY_ARRAY_NEW(newBuffer, T, size) + // newBuffer = new T[size]; + } + delete []_items; + _items = newBuffer; + _size = size; + } + + /* + CObjArray2& operator=(const CObjArray2 &buffer) + { + Free(); + size_t newSize = buffer._size; + if (newSize != 0) + { + T *newBuffer = new T[newSize];; + _items = newBuffer; + _size = newSize; + const T *src = buffer; + for (size_t i = 0; i < newSize; i++) + newBuffer[i] = src[i]; + } + return *this; + } + */ +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer2.h b/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer2.h new file mode 100644 index 0000000..372d478 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyBuffer2.h @@ -0,0 +1,139 @@ +// Common/MyBuffer2.h + +#ifndef __COMMON_MY_BUFFER2_H +#define __COMMON_MY_BUFFER2_H + +#include "../../C/Alloc.h" + +#include "MyTypes.h" + +class CMidBuffer +{ + Byte *_data; + size_t _size; + + CLASS_NO_COPY(CMidBuffer) + +public: + CMidBuffer(): _data(NULL), _size(0) {} + ~CMidBuffer() { ::MidFree(_data); } + + void Free() { ::MidFree(_data); _data = NULL; _size = 0; } + + bool IsAllocated() const { return _data != NULL; } + operator Byte *() { return _data; } + operator const Byte *() const { return _data; } + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (!_data || size != _size) + { + ::MidFree(_data); + _size = 0; + _data = NULL; + _data = (Byte *)::MidAlloc(size); + if (_data) + _size = size; + } + } + + void AllocAtLeast(size_t size) + { + if (!_data || size > _size) + { + ::MidFree(_data); + const size_t kMinSize = (size_t)1 << 16; + if (size < kMinSize) + size = kMinSize; + _size = 0; + _data = NULL; + _data = (Byte *)::MidAlloc(size); + if (_data) + _size = size; + } + } +}; + + +class CAlignedBuffer +{ + Byte *_data; + size_t _size; + + CLASS_NO_COPY(CAlignedBuffer) + +public: + CAlignedBuffer(): _data(NULL), _size(0) {} + ~CAlignedBuffer() + { + ISzAlloc_Free(&g_AlignedAlloc, _data); + } + + CAlignedBuffer(size_t size): _size(0) + { + _data = NULL; + _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); + if (!_data) + throw 1; + _size = size; + } + + void Free() + { + ISzAlloc_Free(&g_AlignedAlloc, _data); + _data = NULL; + _size = 0; + } + + bool IsAllocated() const { return _data != NULL; } + operator Byte *() { return _data; } + operator const Byte *() const { return _data; } + size_t Size() const { return _size; } + + void Alloc(size_t size) + { + if (!_data || size != _size) + { + ISzAlloc_Free(&g_AlignedAlloc, _data); + _size = 0; + _data = NULL; + _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); + if (_data) + _size = size; + } + } + + void AllocAtLeast(size_t size) + { + if (!_data || size > _size) + { + ISzAlloc_Free(&g_AlignedAlloc, _data); + _size = 0; + _data = NULL; + _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size); + if (_data) + _size = size; + } + } +}; + +/* + CMidAlignedBuffer must return aligned pointer. + - in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc() + VirtualAlloc(): Memory allocated is automatically initialized to zero. + MidAlloc(0) returns NULL + - in non-Windows systems it uses g_AlignedAlloc. + g_AlignedAlloc::Alloc(size = 0) can return non NULL. +*/ + +typedef +#ifdef _WIN32 + CMidBuffer +#else + CAlignedBuffer +#endif + CMidAlignedBuffer; + + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyCom.h b/3rdparty/lzma-21.03beta/CPP/Common/MyCom.h new file mode 100644 index 0000000..524f6ef --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyCom.h @@ -0,0 +1,306 @@ +// MyCom.h + +#ifndef __MY_COM_H +#define __MY_COM_H + +#include "MyWindows.h" +#include "MyTypes.h" + +#ifndef RINOK +#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } +#endif + +template +class CMyComPtr +{ + T* _p; +public: + CMyComPtr(): _p(NULL) {} + CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + #ifdef _WIN32 + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + #endif + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template + HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) +{ + *bstr = ::SysAllocString(src); + return (*bstr) ? S_OK : E_OUTOFMEMORY; +} + +class CMyComBSTR +{ + BSTR m_str; + CLASS_NO_COPY(CMyComBSTR) +public: + CMyComBSTR(): m_str(NULL) {} + ~CMyComBSTR() { ::SysFreeString(m_str); } + BSTR* operator&() { return &m_str; } + operator LPCOLESTR() const { return m_str; } + // operator bool() const { return m_str != NULL; } + // bool operator!() const { return m_str == NULL; } + + void Wipe_and_Free() + { + if (m_str) + { + memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str)); + Empty(); + } + } + +private: + // operator BSTR() const { return m_str; } + + CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + + /* + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + */ + + CMyComBSTR& operator=(LPCOLESTR src) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(src); + return *this; + } + + unsigned Len() const { return ::SysStringLen(m_str); } + + BSTR MyCopy() const + { + // We don't support Byte BSTRs here + return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); + /* + UINT byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + if (res && byteLen != 0 && m_str) + memcpy(res, m_str, byteLen); + return res; + */ + } + + /* + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + */ + + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } +}; + + +class CMyComBSTR_Wipe: public CMyComBSTR +{ + CLASS_NO_COPY(CMyComBSTR_Wipe) +public: + CMyComBSTR_Wipe(): CMyComBSTR() {} + ~CMyComBSTR_Wipe() { Wipe_and_Free(); } +}; + + + +/* + If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. + But if some class_1 derived from CMyUnknownImp + uses MY_ADDREF_RELEASE and IUnknown::Release() + and some another class_2 is derived from class_1, + then class_1 must use virtual destructor: + virtual ~class_1(); + In that case, class_1::Release() calls correct destructor of class_2. + + We use virtual ~CMyUnknownImp() to disable warning + "class has virtual functions, but destructor is not virtual". + + also we can use virtual ~IUnknown() {} in MyWindows.h +*/ + +class CMyUnknownImp +{ + CLASS_NO_COPY(CMyUnknownImp) +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} + + #ifdef _WIN32 + #if defined(__GNUC__) || defined(__clang__) + virtual // to disable GCC/CLANG varnings + #endif + #endif + ~CMyUnknownImp() {} +}; + + + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ +(REFGUID iid, void **outObject) throw() { *outObject = NULL; + +#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; } + +#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ + { *outObject = (void *)(IUnknown *)(i *)this; } + +#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) + +#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) + +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) + +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + ) + +#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + ) + +#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + MY_QUERYINTERFACE_ENTRY(i6) \ + MY_QUERYINTERFACE_ENTRY(i7) \ + ) + +const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyException.h b/3rdparty/lzma-21.03beta/CPP/Common/MyException.h new file mode 100644 index 0000000..f0ad111 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyException.h @@ -0,0 +1,14 @@ +// Common/Exception.h + +#ifndef __COMMON_EXCEPTION_H +#define __COMMON_EXCEPTION_H + +#include "MyWindows.h" + +struct CSystemException +{ + HRESULT ErrorCode; + CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} +}; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyGuidDef.h b/3rdparty/lzma-21.03beta/CPP/Common/MyGuidDef.h new file mode 100644 index 0000000..38aad6e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyGuidDef.h @@ -0,0 +1,57 @@ +// Common/MyGuidDef.h + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "MyTypes.h" + +typedef struct { + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +// typedef GUID IID; +typedef GUID CLSID; + +#define REFCLSID REFGUID +#define REFIID REFGUID + +#ifdef __cplusplus +inline int operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < (int)sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return 0; + return 1; +} +inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } +#endif + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#endif + + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyInitGuid.h b/3rdparty/lzma-21.03beta/CPP/Common/MyInitGuid.h new file mode 100644 index 0000000..04d77e2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyInitGuid.h @@ -0,0 +1,49 @@ +// Common/MyInitGuid.h + +#ifndef __COMMON_MY_INITGUID_H +#define __COMMON_MY_INITGUID_H + +/* +This file must be included only to one C++ file in project before +declarations of COM interfaces with DEFINE_GUID macro. + +Each GUID must be initialized exactly once in project. +There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h): + - if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name. + - if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID. + +Also we need IID_IUnknown that is initialized in some file for linking: + MSVC: by default the linker uses some lib file that contains IID_IUnknown + MinGW: add -luuid switch for linker + WinCE: we define IID_IUnknown in this file + Other: we define IID_IUnknown in this file +*/ + +#ifdef __clang__ + #pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#endif + +#ifdef _WIN32 + +#ifdef UNDER_CE +#include +#endif + +#include + +#ifdef UNDER_CE +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +#endif + +#else + +#define INITGUID +#include "MyGuidDef.h" +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + +#endif + + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyLinux.h b/3rdparty/lzma-21.03beta/CPP/Common/MyLinux.h new file mode 100644 index 0000000..1a91899 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyLinux.h @@ -0,0 +1,42 @@ +// MyLinux.h + +#ifndef __MY_LIN_LINUX_H +#define __MY_LIN_LINUX_H + +#define MY_LIN_S_IFMT 00170000 +#define MY_LIN_S_IFSOCK 0140000 +#define MY_LIN_S_IFLNK 0120000 +#define MY_LIN_S_IFREG 0100000 +#define MY_LIN_S_IFBLK 0060000 +#define MY_LIN_S_IFDIR 0040000 +#define MY_LIN_S_IFCHR 0020000 +#define MY_LIN_S_IFIFO 0010000 + +#define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK) +#define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG) +#define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR) +#define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR) +#define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK) +#define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO) +#define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK) + +#define MY_LIN_S_ISUID 0004000 +#define MY_LIN_S_ISGID 0002000 +#define MY_LIN_S_ISVTX 0001000 + +#define MY_LIN_S_IRWXU 00700 +#define MY_LIN_S_IRUSR 00400 +#define MY_LIN_S_IWUSR 00200 +#define MY_LIN_S_IXUSR 00100 + +#define MY_LIN_S_IRWXG 00070 +#define MY_LIN_S_IRGRP 00040 +#define MY_LIN_S_IWGRP 00020 +#define MY_LIN_S_IXGRP 00010 + +#define MY_LIN_S_IRWXO 00007 +#define MY_LIN_S_IROTH 00004 +#define MY_LIN_S_IWOTH 00002 +#define MY_LIN_S_IXOTH 00001 + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyString.cpp b/3rdparty/lzma-21.03beta/CPP/Common/MyString.cpp new file mode 100644 index 0000000..821c9b3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyString.cpp @@ -0,0 +1,1722 @@ +// Common/MyString.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "IntToString.h" + +#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING) +#include "StringConvert.h" +#endif + +#include "MyString.h" + +#define MY_STRING_NEW(_T_, _size_) new _T_[_size_] +// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_))) + +/* +inline const char* MyStringGetNextCharPointer(const char *p) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return CharNextA(p); + #else + return p + 1; + #endif +} +*/ + +#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_) +#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_) + + +int FindCharPosInString(const char *s, char c) throw() +{ + for (const char *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + // MyStringGetNextCharPointer(p); + } +} + +int FindCharPosInString(const wchar_t *s, wchar_t c) throw() +{ + for (const wchar_t *p = s;; p++) + { + if (*p == c) + return (int)(p - s); + if (*p == 0) + return -1; + } +} + +/* +void MyStringUpper_Ascii(char *s) throw() +{ + for (;;) + { + char c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} + +void MyStringUpper_Ascii(wchar_t *s) throw() +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharUpper_Ascii(c); + } +} +*/ + +void MyStringLower_Ascii(char *s) throw() +{ + for (;;) + { + char c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } +} + +void MyStringLower_Ascii(wchar_t *s) throw() +{ + for (;;) + { + wchar_t c = *s; + if (c == 0) + return; + *s++ = MyCharLower_Ascii(c); + } +} + +#ifdef _WIN32 + +#ifdef _UNICODE + +// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +// for WinCE - FString - char +// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; } + +#else + +// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); } +// char * MyStringUpper(char *s) { return CharUpperA(s); } +// char * MyStringLower(char *s) { return CharLowerA(s); } + +wchar_t MyCharUpper_WIN(wchar_t c) throw() +{ + wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) + return c; + s[numChars] = 0; + ::CharUpperA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} + +/* +wchar_t MyCharLower_WIN(wchar_t c) +{ + wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned)(UINT_PTR)res; + const int kBufSize = 4; + char s[kBufSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0); + if (numChars == 0 || numChars > kBufSize) + return c; + s[numChars] = 0; + ::CharLowerA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} +*/ + +/* +wchar_t * MyStringUpper(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharUpperW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeUpper(); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; +} +*/ + +/* +wchar_t * MyStringLower(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharLowerW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeLower(); + MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); + return s; +} +*/ + +#endif + +#endif + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw() +{ + for (;;) + { + unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true; + unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false; + } +} + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false; + if (c1 == 0) return true; + } +} + +// ---------- ASCII ---------- + +bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() +{ + const char *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + char c1 = *s1++; + if (MyCharLower_Ascii(c1) != + MyCharLower_Ascii(c2)) + return false; + } +} + +bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw() +{ + const wchar_t *s1 = _chars; + for (;;) + { + char c2 = *s++; + if (c2 == 0) + return true; + wchar_t c1 = *s1++; + if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } +} + +bool StringsAreEqual_Ascii(const char *u, const char *a) throw() +{ + for (;;) + { + char c = *a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} + +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw() +{ + for (;;) + { + unsigned char c = (unsigned char)*a; + if (c != *u) + return false; + if (c == 0) + return true; + a++; + u++; + } +} + +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw() +{ + for (;;) + { + char c1 = *s1++; + char c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } +} + +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2)) + return false; + if (c1 == 0) + return true; + } +} + +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + char c2 = *s2++; + if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))) + return false; + if (c1 == 0) + return true; + } +} + +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true; + wchar_t c1 = *s1++; if (c1 != c2) return false; + } +} + +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw() +{ + for (;;) + { + char c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)) + return false; + } +} + +bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c2 = *s2++; if (c2 == 0) return true; + wchar_t c1 = *s1++; + if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) + return false; + } +} + +// NTFS order: uses upper case +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw() +{ + for (;;) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } +} + +/* +int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) +{ + for (; num != 0; num--) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } + return 0; +} +*/ + +// ---------- AString ---------- + +void AString::InsertSpace(unsigned &index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +#define k_Alloc_Len_Limit 0x40000000 + +void AString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1); + char *newBuf = MY_STRING_NEW_char(newLimit + 1); + memcpy(newBuf, _chars, (size_t)(_len + 1)); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void AString::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130220; + // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0); + char *newBuf = MY_STRING_NEW_char(newLimit + 1); + newBuf[0] = 0; + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void AString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_char(len + 1); + _len = len; + _limit = len; +} + +void AString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void AString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +AString::AString(unsigned num, const char *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + memcpy(_chars, s, num); + _chars[num] = 0; +} + +AString::AString(unsigned num, const AString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + memcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +AString::AString(const AString &s, char c) +{ + SetStartLen(s.Len() + 1); + char *chars = _chars; + unsigned len = s.Len(); + memcpy(chars, s, len); + chars[len] = c; + chars[(size_t)len + 1] = 0; +} + +AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + char *chars = _chars; + memcpy(chars, s1, num1); + memcpy(chars + num1, s2, num2 + 1); +} + +AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); } +AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); } +AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); } + +static const unsigned kStartStringCapacity = 4; + +AString::AString() +{ + _chars = 0; + _chars = MY_STRING_NEW_char(kStartStringCapacity); + _len = 0; + _limit = kStartStringCapacity - 1; + _chars[0] = 0; +} + +AString::AString(char c) +{ + SetStartLen(1); + char *chars = _chars; + chars[0] = c; + chars[1] = 0; +} + +AString::AString(const char *s) +{ + SetStartLen(MyStringLen(s)); + MyStringCopy(_chars, s); +} + +AString::AString(const AString &s) +{ + SetStartLen(s._len); + MyStringCopy(_chars, s._chars); +} + +AString &AString::operator=(char c) +{ + if (1 > _limit) + { + char *newBuf = MY_STRING_NEW_char(1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + char *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} + +AString &AString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +AString &AString::operator=(const AString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +void AString::SetFromWStr_if_Ascii(const wchar_t *s) +{ + unsigned len = 0; + { + for (;; len++) + { + wchar_t c = s[len]; + if (c == 0) + break; + if (c >= 0x80) + return; + } + } + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + char *dest = _chars; + unsigned i; + for (i = 0; i < len; i++) + dest[i] = (char)s[i]; + dest[i] = 0; +} + +/* +void AString::SetFromBstr_if_Ascii(BSTR s) +{ + unsigned len = ::SysStringLen(s); + { + for (unsigned i = 0; i < len; i++) + if (s[i] <= 0 || s[i] >= 0x80) + return; + } + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + char *dest = _chars; + unsigned i; + for (i = 0; i < len; i++) + dest[i] = (char)s[i]; + dest[i] = 0; +} +*/ + +void AString::Add_Space() { operator+=(' '); } +void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } +void AString::Add_LF() { operator+=('\n'); } + +AString &AString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + MyStringCopy(_chars + _len, s); + _len += len; + return *this; +} + +void AString::Add_OptSpaced(const char *s) +{ + Add_Space_if_NotEmpty(); + (*this) += s; +} + +AString &AString::operator+=(const AString &s) +{ + Grow(s._len); + MyStringCopy(_chars + _len, s._chars); + _len += s._len; + return *this; +} + +void AString::Add_UInt32(UInt32 v) +{ + Grow(10); + _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); +} + +void AString::SetFrom(const char *s, unsigned len) // no check +{ + if (len > _limit) + { + char *newBuf = MY_STRING_NEW_char(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + if (len != 0) + memcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check +{ + unsigned i; + for (i = 0; i < len; i++) + if (s[i] == 0) + break; + SetFrom(s, i); +} + +int AString::Find(const char *s, unsigned startIndex) const throw() +{ + const char *fs = strstr(_chars + startIndex, s); + if (!fs) + return -1; + return (int)(fs - _chars); + + /* + if (s[0] == 0) + return startIndex; + unsigned len = MyStringLen(s); + const char *p = _chars + startIndex; + for (;; p++) + { + const char c = *p; + if (c != s[0]) + { + if (c == 0) + return -1; + continue; + } + unsigned i; + for (i = 1; i < len; i++) + if (p[i] != s[i]) + break; + if (i == len) + return (int)(p - _chars); + } + */ +} + +int AString::ReverseFind(char c) const throw() +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; // p = GetPrevCharPointer(_chars, p); + } +} + +int AString::ReverseFind_PathSepar() const throw() +{ + if (_len == 0) + return -1; + const char *p = _chars + _len - 1; + for (;;) + { + char c = *p; + if (IS_PATH_SEPAR(c)) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void AString::TrimLeft() throw() +{ + const char *p = _chars; + for (;; p++) + { + char c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void AString::TrimRight() throw() +{ + const char *p = _chars; + unsigned i; + for (i = _len; i != 0; i--) + { + char c = p[(size_t)i - 1]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + if (i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void AString::InsertAtFront(char c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void AString::Insert(unsigned index, char c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void AString::Insert(unsigned index, const char *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::Insert(unsigned index, const AString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + memcpy(_chars + index, s, num); + _len += num; + } +} + +void AString::RemoveChar(char ch) throw() +{ + char *src = _chars; + + for (;;) + { + char c = *src++; + if (c == 0) + return; + if (c == ch) + break; + } + + char *dest = src - 1; + + for (;;) + { + char c = *src++; + if (c == 0) + break; + if (c != ch) + *dest++ = c; + } + + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void AString::Replace(char oldChar, char newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + char *chars = _chars; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, (unsigned)pos); + if (pos < 0) + break; + chars[(unsigned)pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void AString::Replace(const AString &oldString, const AString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, (unsigned)pos); + if (pos < 0) + break; + Delete((unsigned)pos, oldLen); + Insert((unsigned)pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void AString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void AString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void AString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + +/* +AString operator+(const AString &s1, const AString &s2) +{ + AString result(s1); + result += s2; + return result; +} + +AString operator+(const AString &s, const char *chars) +{ + AString result(s); + result += chars; + return result; +} + +AString operator+(const char *chars, const AString &s) +{ + AString result(chars); + result += s; + return result; +} + +AString operator+(const AString &s, char c) +{ + AString result(s); + result += c; + return result; +} +*/ + +/* +AString operator+(char c, const AString &s) +{ + AString result(c); + result += s; + return result; +} +*/ + + + + +// ---------- UString ---------- + +void UString::InsertSpace(unsigned index, unsigned size) +{ + Grow(size); + MoveItems(index + size, index); +} + +void UString::ReAlloc(unsigned newLimit) +{ + if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); + wmemcpy(newBuf, _chars, _len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void UString::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); + wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1); + newBuf[0] = 0; + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = newLimit; +} + +void UString::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(len + 1); + _len = len; + _limit = len; +} + +void UString::Grow_1() +{ + unsigned next = _len; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + +void UString::Grow(unsigned n) +{ + unsigned freeSize = _limit - _len; + if (n <= freeSize) + return; + + unsigned next = _len + n; + next += next / 2; + next += 16; + next &= ~(unsigned)15; + ReAlloc(next - 1); +} + + +UString::UString(unsigned num, const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (num > len) + num = len; + SetStartLen(num); + wmemcpy(_chars, s, num); + _chars[num] = 0; +} + + +UString::UString(unsigned num, const UString &s) +{ + if (num > s._len) + num = s._len; + SetStartLen(num); + wmemcpy(_chars, s._chars, num); + _chars[num] = 0; +} + +UString::UString(const UString &s, wchar_t c) +{ + SetStartLen(s.Len() + 1); + wchar_t *chars = _chars; + unsigned len = s.Len(); + wmemcpy(chars, s, len); + chars[len] = c; + chars[(size_t)len + 1] = 0; +} + +UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2) +{ + SetStartLen(num1 + num2); + wchar_t *chars = _chars; + wmemcpy(chars, s1, num1); + wmemcpy(chars + num1, s2, num2 + 1); +} + +UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); } +UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); } +UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); } + +UString::UString() +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity); + _len = 0; + _limit = kStartStringCapacity - 1; + _chars[0] = 0; +} + +UString::UString(wchar_t c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; +} + +UString::UString(char c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = (unsigned char)c; + chars[1] = 0; +} + +UString::UString(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wmemcpy(_chars, s, len + 1); +} + +UString::UString(const char *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; +} + +UString::UString(const UString &s) +{ + SetStartLen(s._len); + wmemcpy(_chars, s._chars, s._len + 1); +} + +UString &UString::operator=(wchar_t c) +{ + if (1 > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = 1; + } + _len = 1; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} + +UString &UString::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + wmemcpy(_chars, s, len + 1); + return *this; +} + +UString &UString::operator=(const UString &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + wmemcpy(_chars, s._chars, len + 1); + return *this; +} + +void UString::SetFrom(const wchar_t *s, unsigned len) // no check +{ + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + if (len != 0) + wmemcpy(_chars, s, len); + _chars[len] = 0; + _len = len; +} + +void UString::SetFromBstr(LPCOLESTR s) +{ + unsigned len = ::SysStringLen((BSTR)(void *)(s)); + + /* + #if WCHAR_MAX > 0xffff + size_t num_wchars = 0; + for (size_t i = 0; i < len;) + { + wchar_t c = s[i++]; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = s[i]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + i++; + } + } + num_wchars++; + } + len = num_wchars; + #endif + */ + + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + _len = len; + + /* + #if WCHAR_MAX > 0xffff + + wchar_t *chars = _chars; + for (size_t i = 0; i <= len; i++) + { + wchar_t c = *s++; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = *s; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + s++; + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + } + } + chars[i] = c; + } + + #else + */ + + // if (s) + wmemcpy(_chars, s, len + 1); + + // #endif +} + +UString &UString::operator=(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _limit) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + MY_STRING_DELETE(_chars); + _chars = newBuf; + _limit = len; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len = len; + return *this; +} + +void UString::Add_Space() { operator+=(L' '); } +void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); } + +void UString::Add_LF() +{ + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = L'\n'; + chars[len] = 0; + _len = len; +} + +UString &UString::operator+=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wmemcpy(_chars + _len, s, len + 1); + _len += len; + return *this; +} + +UString &UString::operator+=(const UString &s) +{ + Grow(s._len); + wmemcpy(_chars + _len, s._chars, s._len + 1); + _len += s._len; + return *this; +} + +UString &UString::operator+=(const char *s) +{ + unsigned len = MyStringLen(s); + Grow(len); + wchar_t *chars = _chars + _len; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len += len; + return *this; +} + + +void UString::Add_UInt32(UInt32 v) +{ + Grow(10); + _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); +} + + +int UString::Find(const wchar_t *s, unsigned startIndex) const throw() +{ + const wchar_t *fs = wcsstr(_chars + startIndex, s); + if (!fs) + return -1; + return (int)(fs - _chars); + + /* + if (s[0] == 0) + return startIndex; + unsigned len = MyStringLen(s); + const wchar_t *p = _chars + startIndex; + for (;; p++) + { + const wchar_t c = *p; + if (c != s[0]) + { + if (c == 0) + return -1; + continue; + } + unsigned i; + for (i = 1; i < len; i++) + if (p[i] != s[i]) + break; + if (i == len) + return (int)(p - _chars); + } + */ +} + +int UString::ReverseFind(wchar_t c) const throw() +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +int UString::ReverseFind_PathSepar() const throw() +{ + if (_len == 0) + return -1; + const wchar_t *p = _chars + _len - 1; + for (;;) + { + wchar_t c = *p; + if (IS_PATH_SEPAR(c)) + return (int)(p - _chars); + if (p == _chars) + return -1; + p--; + } +} + +void UString::TrimLeft() throw() +{ + const wchar_t *p = _chars; + for (;; p++) + { + wchar_t c = *p; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + unsigned pos = (unsigned)(p - _chars); + if (pos != 0) + { + MoveItems(0, pos); + _len -= pos; + } +} + +void UString::TrimRight() throw() +{ + const wchar_t *p = _chars; + unsigned i; + for (i = _len; i != 0; i--) + { + wchar_t c = p[(size_t)i - 1]; + if (c != ' ' && c != '\n' && c != '\t') + break; + } + if (i != _len) + { + _chars[i] = 0; + _len = i; + } +} + +void UString::InsertAtFront(wchar_t c) +{ + if (_limit == _len) + Grow_1(); + MoveItems(1, 0); + _chars[0] = c; + _len++; +} + +/* +void UString::Insert_wchar_t(unsigned index, wchar_t c) +{ + InsertSpace(index, 1); + _chars[index] = c; + _len++; +} +*/ + +void UString::Insert(unsigned index, const wchar_t *s) +{ + unsigned num = MyStringLen(s); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::Insert(unsigned index, const UString &s) +{ + unsigned num = s.Len(); + if (num != 0) + { + InsertSpace(index, num); + wmemcpy(_chars + index, s, num); + _len += num; + } +} + +void UString::RemoveChar(wchar_t ch) throw() +{ + wchar_t *src = _chars; + + for (;;) + { + wchar_t c = *src++; + if (c == 0) + return; + if (c == ch) + break; + } + + wchar_t *dest = src - 1; + + for (;;) + { + wchar_t c = *src++; + if (c == 0) + break; + if (c != ch) + *dest++ = c; + } + + *dest = 0; + _len = (unsigned)(dest - _chars); +} + +// !!!!!!!!!!!!!!! test it if newChar = '\0' +void UString::Replace(wchar_t oldChar, wchar_t newChar) throw() +{ + if (oldChar == newChar) + return; // 0; + // unsigned number = 0; + int pos = 0; + wchar_t *chars = _chars; + while ((unsigned)pos < _len) + { + pos = Find(oldChar, (unsigned)pos); + if (pos < 0) + break; + chars[(unsigned)pos] = newChar; + pos++; + // number++; + } + return; // number; +} + +void UString::Replace(const UString &oldString, const UString &newString) +{ + if (oldString.IsEmpty()) + return; // 0; + if (oldString == newString) + return; // 0; + unsigned oldLen = oldString.Len(); + unsigned newLen = newString.Len(); + // unsigned number = 0; + int pos = 0; + while ((unsigned)pos < _len) + { + pos = Find(oldString, (unsigned)pos); + if (pos < 0) + break; + Delete((unsigned)pos, oldLen); + Insert((unsigned)pos, newString); + pos += newLen; + // number++; + } + // return number; +} + +void UString::Delete(unsigned index) throw() +{ + MoveItems(index, index + 1); + _len--; +} + +void UString::Delete(unsigned index, unsigned count) throw() +{ + if (index + count > _len) + count = _len - index; + if (count > 0) + { + MoveItems(index, index + count); + _len -= count; + } +} + +void UString::DeleteFrontal(unsigned num) throw() +{ + if (num != 0) + { + MoveItems(0, num); + _len -= num; + } +} + + +// ---------- UString2 ---------- + +void UString2::ReAlloc2(unsigned newLimit) +{ + if (newLimit >= k_Alloc_Len_Limit) throw 20130221; + // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0); + _chars = MY_STRING_NEW_wchar_t(newLimit + 1); +} + +void UString2::SetStartLen(unsigned len) +{ + _chars = 0; + _chars = MY_STRING_NEW_wchar_t(len + 1); + _len = len; +} + + +/* +UString2::UString2(wchar_t c) +{ + SetStartLen(1); + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; +} +*/ + +UString2::UString2(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + SetStartLen(len); + wmemcpy(_chars, s, len + 1); +} + +UString2::UString2(const UString2 &s): _chars(NULL), _len(0) +{ + if (s._chars) + { + SetStartLen(s._len); + wmemcpy(_chars, s._chars, s._len + 1); + } +} + +/* +UString2 &UString2::operator=(wchar_t c) +{ + if (1 > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = 1; + wchar_t *chars = _chars; + chars[0] = c; + chars[1] = 0; + return *this; +} +*/ + +UString2 &UString2::operator=(const wchar_t *s) +{ + unsigned len = MyStringLen(s); + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = len; + MyStringCopy(_chars, s); + return *this; +} + +void UString2::SetFromAscii(const char *s) +{ + unsigned len = MyStringLen(s); + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + wchar_t *chars = _chars; + for (unsigned i = 0; i < len; i++) + chars[i] = (unsigned char)s[i]; + chars[len] = 0; + _len = len; +} + +UString2 &UString2::operator=(const UString2 &s) +{ + if (&s == this) + return *this; + unsigned len = s._len; + if (len > _len) + { + wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1); + if (_chars) + MY_STRING_DELETE(_chars); + _chars = newBuf; + } + _len = len; + MyStringCopy(_chars, s._chars); + return *this; +} + +bool operator==(const UString2 &s1, const UString2 &s2) +{ + return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0); +} + +bool operator==(const UString2 &s1, const wchar_t *s2) +{ + if (s1.IsEmpty()) + return (*s2 == 0); + return wcscmp(s1.GetRawPtr(), s2) == 0; +} + +bool operator==(const wchar_t *s1, const UString2 &s2) +{ + if (s2.IsEmpty()) + return (*s1 == 0); + return wcscmp(s1, s2.GetRawPtr()) == 0; +} + + + +// ---------------------------------------- + +/* +int MyStringCompareNoCase(const char *s1, const char *s2) +{ + return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); +} +*/ + +#if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE) + +static inline UINT GetCurrentCodePage() +{ + #if defined(UNDER_CE) || !defined(_WIN32) + return CP_ACP; + #else + return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif +} + +#endif + +#ifdef USE_UNICODE_FSTRING + +#ifndef _UNICODE + +AString fs2fas(CFSTR s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +FString fas2fs(const char *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +FString fas2fs(const AString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +#endif // _UNICODE + +#else // USE_UNICODE_FSTRING + +UString fs2us(const FChar *s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +UString fs2us(const FString &s) +{ + return MultiByteToUnicodeString(s, GetCurrentCodePage()); +} + +FString us2fs(const wchar_t *s) +{ + return UnicodeStringToMultiByte(s, GetCurrentCodePage()); +} + +#endif // USE_UNICODE_FSTRING diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyString.h b/3rdparty/lzma-21.03beta/CPP/Common/MyString.h new file mode 100644 index 0000000..c242d92 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyString.h @@ -0,0 +1,932 @@ +// Common/String.h + +#ifndef __COMMON_STRING_H +#define __COMMON_STRING_H + +#include + +#ifndef _WIN32 +#include +#include +#endif + +#include "MyWindows.h" +#include "MyTypes.h" +#include "MyVector.h" + + +#ifdef _MSC_VER + #ifdef _NATIVE_WCHAR_T_DEFINED + #define MY_NATIVE_WCHAR_T_DEFINED + #endif +#else + #define MY_NATIVE_WCHAR_T_DEFINED +#endif + +/* + native support for wchar_t: + _MSC_VER == 1600 : /Zc:wchar_t is not supported + _MSC_VER == 1310 (VS2003) + ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short + /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED + _MSC_VER > 1400 (VS2008+) + /Zc:wchar_t[-] + /Zc:wchar_t is on by default +*/ + +#ifdef _WIN32 +#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/') +#else +#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR) +#endif + +inline bool IsPathSepar(char c) { return IS_PATH_SEPAR(c); } +inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); } + +inline unsigned MyStringLen(const char *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} + +inline void MyStringCopy(char *dest, const char *src) +{ + while ((*dest++ = *src++) != 0); +} + +inline char *MyStpCpy(char *dest, const char *src) +{ + for (;;) + { + char c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} + +inline unsigned MyStringLen(const wchar_t *s) +{ + unsigned i; + for (i = 0; s[i] != 0; i++); + return i; +} + +inline void MyStringCopy(wchar_t *dest, const wchar_t *src) +{ + while ((*dest++ = *src++) != 0); +} + +inline void MyStringCat(wchar_t *dest, const wchar_t *src) +{ + MyStringCopy(dest + MyStringLen(dest), src); +} + + +/* +inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src) +{ + for (;;) + { + wchar_t c = *src; + *dest = c; + if (c == 0) + return dest; + src++; + dest++; + } +} +*/ + +int FindCharPosInString(const char *s, char c) throw(); +int FindCharPosInString(const wchar_t *s, wchar_t c) throw(); + +#ifdef _WIN32 + #ifndef _UNICODE + #define STRING_UNICODE_THROW + #endif +#endif + +#ifndef STRING_UNICODE_THROW + #define STRING_UNICODE_THROW throw() +#endif + + +inline char MyCharUpper_Ascii(char c) +{ + if (c >= 'a' && c <= 'z') + return (char)((unsigned char)c - 0x20); + return c; +} + +/* +inline wchar_t MyCharUpper_Ascii(wchar_t c) +{ + if (c >= 'a' && c <= 'z') + return (wchar_t)(c - 0x20); + return c; +} +*/ + +inline char MyCharLower_Ascii(char c) +{ + if (c >= 'A' && c <= 'Z') + return (char)((unsigned char)c + 0x20); + return c; +} + +inline wchar_t MyCharLower_Ascii(wchar_t c) +{ + if (c >= 'A' && c <= 'Z') + return (wchar_t)(c + 0x20); + return c; +} + +wchar_t MyCharUpper_WIN(wchar_t c) throw(); + +inline wchar_t MyCharUpper(wchar_t c) throw() +{ + if (c < 'a') return c; + if (c <= 'z') return (wchar_t)(c - 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharUpper_WIN(c); + #endif + #else + return (wchar_t)towupper((wint_t)c); + #endif +} + +/* +wchar_t MyCharLower_WIN(wchar_t c) throw(); + +inline wchar_t MyCharLower(wchar_t c) throw() +{ + if (c < 'A') return c; + if (c <= 'Z') return (wchar_t)(c + 0x20); + if (c <= 0x7F) return c; + #ifdef _WIN32 + #ifdef _UNICODE + return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c); + #else + return (wchar_t)MyCharLower_WIN(c); + #endif + #else + return (wchar_t)tolower(c); + #endif +} +*/ + +// char *MyStringUpper(char *s) throw(); +// char *MyStringLower(char *s) throw(); + +// void MyStringUpper_Ascii(char *s) throw(); +// void MyStringUpper_Ascii(wchar_t *s) throw(); +void MyStringLower_Ascii(char *s) throw(); +void MyStringLower_Ascii(wchar_t *s) throw(); +// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW; +// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW; + +bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +bool IsString1PrefixedByString2(const char *s1, const char *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw(); +bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw(); +bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw(); +bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MyStringCompare(s1, s2) wcscmp(s1, s2) +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw(); +// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw(); + +// ---------- ASCII ---------- +// char values in ASCII strings must be less then 128 +bool StringsAreEqual_Ascii(const char *u, const char *a) throw(); +bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw(); +bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw(); +bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw(); + +#define MY_STRING_DELETE(_p_) delete []_p_; +// #define MY_STRING_DELETE(_p_) my_delete(_p_); + + +#define FORBID_STRING_OPS_2(cls, t) \ + void Find(t) const; \ + void Find(t, unsigned startIndex) const; \ + void ReverseFind(t) const; \ + void InsertAtFront(t); \ + void RemoveChar(t); \ + void Replace(t, t); \ + +#define FORBID_STRING_OPS(cls, t) \ + explicit cls(t); \ + explicit cls(const t *); \ + cls &operator=(t); \ + cls &operator=(const t *); \ + cls &operator+=(t); \ + cls &operator+=(const t *); \ + FORBID_STRING_OPS_2(cls, t) \ + +/* + cls &operator+(t); \ + cls &operator+(const t *); \ +*/ + +#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t) +#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t) +#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t) + +class AString +{ + char *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) + { + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char)); + } + + void InsertSpace(unsigned &index, unsigned size); + + void ReAlloc(unsigned newLimit); + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + AString(unsigned num, const char *s); + AString(unsigned num, const AString &s); + AString(const AString &s, char c); // it's for String + char + AString(const char *s1, unsigned num1, const char *s2, unsigned num2); + + friend AString operator+(const AString &s, char c) { return AString(s, c); } + // friend AString operator+(char c, const AString &s); // is not supported + + friend AString operator+(const AString &s1, const AString &s2); + friend AString operator+(const AString &s1, const char *s2); + friend AString operator+(const char *s1, const AString &s2); + + // ---------- forbidden functions ---------- + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_AString(wchar_t) + #endif + + FORBID_STRING_OPS_AString(signed char) + FORBID_STRING_OPS_AString(unsigned char) + FORBID_STRING_OPS_AString(short) + FORBID_STRING_OPS_AString(unsigned short) + FORBID_STRING_OPS_AString(int) + FORBID_STRING_OPS_AString(unsigned) + FORBID_STRING_OPS_AString(long) + FORBID_STRING_OPS_AString(unsigned long) + +public: + explicit AString(); + explicit AString(char c); + explicit AString(const char *s); + AString(const AString &s); + ~AString() { MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const char *() const { return _chars; } + char *Ptr_non_const() const { return _chars; } + const char *Ptr() const { return _chars; } + const char *Ptr(unsigned pos) const { return _chars + pos; } + const char *RightPtr(unsigned num) const { return _chars + _len - num; } + char Back() const { return _chars[(size_t)_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; } + + char *GetBuf() { return _chars; } + /* GetBuf(minLen): provides the buffer that can store + at least (minLen) characters and additional null terminator. + 9.35: GetBuf doesn't preserve old characters and terminator */ + char *GetBuf(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + return _chars; + } + char *GetBuf_SetEnd(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + char *chars = _chars; + chars[minLen] = 0; + _len = minLen; + return chars; + } + + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + void ReleaseBuf_CalcLen(unsigned maxLen) + { + char *chars = _chars; + chars[maxLen] = 0; + _len = MyStringLen(chars); + } + + AString &operator=(char c); + AString &operator=(const char *s); + AString &operator=(const AString &s); + void SetFromWStr_if_Ascii(const wchar_t *s); + // void SetFromBstr_if_Ascii(BSTR s); + + AString &operator+=(char c) + { + if (_limit == _len) + Grow_1(); + unsigned len = _len; + char *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; + } + + void Add_Space(); + void Add_Space_if_NotEmpty(); + void Add_OptSpaced(const char *s); + void Add_LF(); + void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); } + + AString &operator+=(const char *s); + AString &operator+=(const AString &s); + + void Add_UInt32(UInt32 v); + + void SetFrom(const char *s, unsigned len); // no check + void SetFrom_CalcLen(const char *s, unsigned len); + + AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } + AString Left(unsigned count) const { return AString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeLower() { MyStringLower(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + + bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; } + bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } + // int Compare(const char *s) const { return MyStringCompare(_chars, s); } + // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); + + bool IsAscii() const + { + unsigned len = Len(); + const char *s = _chars; + for (unsigned i = 0; i < len; i++) + if ((unsigned char)s[i] >= 0x80) + return false; + return true; + } + int Find(char c) const { return FindCharPosInString(_chars, c); } + int Find(char c, unsigned startIndex) const + { + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; + } + + int ReverseFind(char c) const throw(); + int ReverseFind_Dot() const throw() { return ReverseFind('.'); } + int ReverseFind_PathSepar() const throw(); + + int Find(const char *s) const { return Find(s, 0); } + int Find(const char *s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() + { + TrimRight(); + TrimLeft(); + } + + void InsertAtFront(char c); + // void Insert(unsigned index, char c); + void Insert(unsigned index, const char *s); + void Insert(unsigned index, const AString &s); + + void RemoveChar(char ch) throw(); + + void Replace(char oldChar, char newChar) throw(); + void Replace(const AString &oldString, const AString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) + { + if (index < _len) + { + _len = index; + _chars[index] = 0; + } + } + + void Wipe_and_Empty() + { + if (_chars) + { + memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); + _len = 0; + } + } +}; + + +class AString_Wipe: public AString +{ + CLASS_NO_COPY(AString_Wipe) +public: + AString_Wipe(): AString() {} + // AString_Wipe(const AString &s): AString(s) {} + // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; } + // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; } + ~AString_Wipe() { Wipe_and_Empty(); } +}; + + +bool operator<(const AString &s1, const AString &s2); +bool operator>(const AString &s1, const AString &s2); + +/* +bool operator==(const AString &s1, const AString &s2); +bool operator==(const AString &s1, const char *s2); +bool operator==(const char *s1, const AString &s2); + +bool operator!=(const AString &s1, const AString &s2); +bool operator!=(const AString &s1, const char *s2); +bool operator!=(const char *s1, const AString &s2); +*/ + +inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; } +inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; } +inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; } + +inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; } +inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; } +inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; } + +// ---------- forbidden functions ---------- + +void operator==(char c1, const AString &s2); +void operator==(const AString &s1, char c2); + +void operator+(char c, const AString &s); // this function can be OK, but we don't use it + +void operator+(const AString &s, int c); +void operator+(const AString &s, unsigned c); +void operator+(int c, const AString &s); +void operator+(unsigned c, const AString &s); +void operator-(const AString &s, int c); +void operator-(const AString &s, unsigned c); + + +class UString +{ + wchar_t *_chars; + unsigned _len; + unsigned _limit; + + void MoveItems(unsigned dest, unsigned src) + { + memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t)); + } + + void InsertSpace(unsigned index, unsigned size); + + void ReAlloc(unsigned newLimit); + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + void Grow_1(); + void Grow(unsigned n); + + UString(unsigned num, const wchar_t *s); // for Mid + UString(unsigned num, const UString &s); // for Left + UString(const UString &s, wchar_t c); // it's for String + char + UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2); + + friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); } + // friend UString operator+(wchar_t c, const UString &s); // is not supported + + friend UString operator+(const UString &s1, const UString &s2); + friend UString operator+(const UString &s1, const wchar_t *s2); + friend UString operator+(const wchar_t *s1, const UString &s2); + + // ---------- forbidden functions ---------- + + FORBID_STRING_OPS_UString(signed char) + FORBID_STRING_OPS_UString(unsigned char) + FORBID_STRING_OPS_UString(short) + + #ifdef MY_NATIVE_WCHAR_T_DEFINED + FORBID_STRING_OPS_UString(unsigned short) + #endif + + FORBID_STRING_OPS_UString(int) + FORBID_STRING_OPS_UString(unsigned) + FORBID_STRING_OPS_UString(long) + FORBID_STRING_OPS_UString(unsigned long) + + FORBID_STRING_OPS_2(UString, char) + +public: + UString(); + explicit UString(wchar_t c); + explicit UString(char c); + explicit UString(const char *s); + // UString(const AString &s); + UString(const wchar_t *s); + UString(const UString &s); + ~UString() { MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + void Empty() { _len = 0; _chars[0] = 0; } + + operator const wchar_t *() const { return _chars; } + wchar_t *Ptr_non_const() const { return _chars; } + const wchar_t *Ptr() const { return _chars; } + const wchar_t *Ptr(unsigned pos) const { return _chars + pos; } + const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; } + wchar_t Back() const { return _chars[(size_t)_len - 1]; } + + void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; } + + wchar_t *GetBuf() { return _chars; } + + wchar_t *GetBuf(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + return _chars; + } + wchar_t *GetBuf_SetEnd(unsigned minLen) + { + if (minLen > _limit) + ReAlloc2(minLen); + wchar_t *chars = _chars; + chars[minLen] = 0; + _len = minLen; + return chars; + } + + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; } + void ReleaseBuf_CalcLen(unsigned maxLen) + { + wchar_t *chars = _chars; + chars[maxLen] = 0; + _len = MyStringLen(chars); + } + + UString &operator=(wchar_t c); + UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); } + UString &operator=(const wchar_t *s); + UString &operator=(const UString &s); + void SetFrom(const wchar_t *s, unsigned len); // no check + void SetFromBstr(LPCOLESTR s); + UString &operator=(const char *s); + UString &operator=(const AString &s) { return operator=(s.Ptr()); } + + UString &operator+=(wchar_t c) + { + if (_limit == _len) + Grow_1(); + unsigned len = _len; + wchar_t *chars = _chars; + chars[len++] = c; + chars[len] = 0; + _len = len; + return *this; + } + + UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); } + + void Add_Space(); + void Add_Space_if_NotEmpty(); + void Add_LF(); + void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); } + + UString &operator+=(const wchar_t *s); + UString &operator+=(const UString &s); + UString &operator+=(const char *s); + UString &operator+=(const AString &s) { return operator+=(s.Ptr()); } + + void Add_UInt32(UInt32 v); + + UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } + UString Left(unsigned count) const { return UString(count, *this); } + + // void MakeUpper() { MyStringUpper(_chars); } + // void MakeUpper() { MyStringUpper_Ascii(_chars); } + // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); } + void MakeLower_Ascii() { MyStringLower_Ascii(_chars); } + + bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); } + bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); } + bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); } + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); } + // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); } + // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); } + bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); } + bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); } + bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw(); + + bool IsAscii() const + { + unsigned len = Len(); + const wchar_t *s = _chars; + for (unsigned i = 0; i < len; i++) + if (s[i] >= 0x80) + return false; + return true; + } + int Find(wchar_t c) const { return FindCharPosInString(_chars, c); } + int Find(wchar_t c, unsigned startIndex) const + { + int pos = FindCharPosInString(_chars + startIndex, c); + return pos < 0 ? -1 : (int)startIndex + pos; + } + + int ReverseFind(wchar_t c) const throw(); + int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); } + int ReverseFind_PathSepar() const throw(); + + int Find(const wchar_t *s) const { return Find(s, 0); } + int Find(const wchar_t *s, unsigned startIndex) const throw(); + + void TrimLeft() throw(); + void TrimRight() throw(); + void Trim() + { + TrimRight(); + TrimLeft(); + } + + void InsertAtFront(wchar_t c); + // void Insert_wchar_t(unsigned index, wchar_t c); + void Insert(unsigned index, const wchar_t *s); + void Insert(unsigned index, const UString &s); + + void RemoveChar(wchar_t ch) throw(); + + void Replace(wchar_t oldChar, wchar_t newChar) throw(); + void Replace(const UString &oldString, const UString &newString); + + void Delete(unsigned index) throw(); + void Delete(unsigned index, unsigned count) throw(); + void DeleteFrontal(unsigned num) throw(); + void DeleteBack() { _chars[--_len] = 0; } + void DeleteFrom(unsigned index) + { + if (index < _len) + { + _len = index; + _chars[index] = 0; + } + } + + void Wipe_and_Empty() + { + if (_chars) + { + memset(_chars, 0, (_limit + 1) * sizeof(*_chars)); + _len = 0; + } + } +}; + + +class UString_Wipe: public UString +{ + CLASS_NO_COPY(UString_Wipe) +public: + UString_Wipe(): UString() {} + // UString_Wipe(const UString &s): UString(s) {} + // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; } + // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; } + ~UString_Wipe() { Wipe_and_Empty(); } +}; + + +bool operator<(const UString &s1, const UString &s2); +bool operator>(const UString &s1, const UString &s2); + +inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; } +inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; } +inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; } + +inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; } +inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; } +inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; } + + +// ---------- forbidden functions ---------- + +void operator==(wchar_t c1, const UString &s2); +void operator==(const UString &s1, wchar_t c2); + +void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it + +void operator+(const AString &s1, const UString &s2); +void operator+(const UString &s1, const AString &s2); + +void operator+(const UString &s1, const char *s2); +void operator+(const char *s1, const UString &s2); + +void operator+(const UString &s, char c); +void operator+(const UString &s, unsigned char c); +void operator+(char c, const UString &s); +void operator+(unsigned char c, const UString &s); +void operator-(const UString &s1, wchar_t c); + +#ifdef _WIN32 +// can we forbid these functions, if wchar_t is 32-bit ? +void operator+(const UString &s, int c); +void operator+(const UString &s, unsigned c); +void operator+(int c, const UString &s); +void operator+(unsigned c, const UString &s); +void operator-(const UString &s1, int c); +void operator-(const UString &s1, unsigned c); +#endif + + + + + + + +class UString2 +{ + wchar_t *_chars; + unsigned _len; + + void ReAlloc2(unsigned newLimit); + void SetStartLen(unsigned len); + + // ---------- forbidden functions ---------- + + FORBID_STRING_OPS_UString2(char) + FORBID_STRING_OPS_UString2(signed char) + FORBID_STRING_OPS_UString2(unsigned char) + FORBID_STRING_OPS_UString2(short) + + UString2 &operator=(wchar_t c); + UString2(wchar_t c); + +public: + UString2(): _chars(NULL), _len(0) {} + UString2(const wchar_t *s); + UString2(const UString2 &s); + ~UString2() { if (_chars) MY_STRING_DELETE(_chars); } + + unsigned Len() const { return _len; } + bool IsEmpty() const { return _len == 0; } + // void Empty() { _len = 0; _chars[0] = 0; } + + // operator const wchar_t *() const { return _chars; } + const wchar_t *GetRawPtr() const { return _chars; } + + int Compare(const wchar_t *s) const { return wcscmp(_chars, s); } + + wchar_t *GetBuf(unsigned minLen) + { + if (!_chars || minLen > _len) + ReAlloc2(minLen); + return _chars; + } + void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; } + + UString2 &operator=(const wchar_t *s); + UString2 &operator=(const UString2 &s); + void SetFromAscii(const char *s); +}; + +bool operator==(const UString2 &s1, const UString2 &s2); +bool operator==(const UString2 &s1, const wchar_t *s2); +bool operator==(const wchar_t *s1, const UString2 &s2); + +inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); } +inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); } +inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); } + + +// ---------- forbidden functions ---------- + +void operator==(wchar_t c1, const UString2 &s2); +void operator==(const UString2 &s1, wchar_t c2); +bool operator<(const UString2 &s1, const UString2 &s2); +bool operator>(const UString2 &s1, const UString2 &s2); + +void operator+(const UString2 &s1, const UString2 &s2); +void operator+(const UString2 &s1, const wchar_t *s2); +void operator+(const wchar_t *s1, const UString2 &s2); +void operator+(wchar_t c, const UString2 &s); +void operator+(const UString2 &s, wchar_t c); +void operator+(const UString2 &s, char c); +void operator+(const UString2 &s, unsigned char c); +void operator+(char c, const UString2 &s); +void operator+(unsigned char c, const UString2 &s); +void operator-(const UString2 &s1, wchar_t c); + + + + + + +typedef CObjectVector AStringVector; +typedef CObjectVector UStringVector; + +#ifdef _UNICODE + typedef UString CSysString; +#else + typedef AString CSysString; +#endif + +typedef CObjectVector CSysStringVector; + + +// ---------- FString ---------- + +#ifdef _WIN32 + #define USE_UNICODE_FSTRING +#endif + +#ifdef USE_UNICODE_FSTRING + + #define __FTEXT(quote) L##quote + + typedef wchar_t FChar; + typedef UString FString; + + #define fs2us(_x_) (_x_) + #define us2fs(_x_) (_x_) + FString fas2fs(const char *s); + FString fas2fs(const AString &s); + AString fs2fas(const FChar *s); + +#else + + #define __FTEXT(quote) quote + + typedef char FChar; + typedef AString FString; + + UString fs2us(const FChar *s); + UString fs2us(const FString &s); + FString us2fs(const wchar_t *s); + #define fas2fs(_x_) (_x_) + #define fs2fas(_x_) (_x_) + +#endif + +#define FTEXT(quote) __FTEXT(quote) + +#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR) +#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR) + +// #define FCHAR_ANY_MASK FTEXT('*') +// #define FSTRING_ANY_MASK FTEXT("*") + +typedef const FChar *CFSTR; + +typedef CObjectVector FStringVector; + +#endif + + + +#if defined(_WIN32) + // #include + // WCHAR_MAX is defined as ((wchar_t)-1) + #define _WCHART_IS_16BIT 1 +#elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \ + || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2)) + #define _WCHART_IS_16BIT 1 +#endif + +#if WCHAR_PATH_SEPARATOR == L'\\' +// WSL scheme +#define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\')) +// #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT '_' +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyTypes.h b/3rdparty/lzma-21.03beta/CPP/Common/MyTypes.h new file mode 100644 index 0000000..2b1acce --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyTypes.h @@ -0,0 +1,46 @@ +// Common/MyTypes.h + +#ifndef __COMMON_MY_TYPES_H +#define __COMMON_MY_TYPES_H + +#include "../../C/7zTypes.h" + +typedef int HRes; + +struct CBoolPair +{ + bool Val; + bool Def; + + CBoolPair(): Val(false), Def(false) {} + + void Init() + { + Val = false; + Def = false; + } + + void SetTrueTrue() + { + Val = true; + Def = true; + } +}; + +#define CLASS_NO_COPY(cls) \ + private: \ + cls(const cls &); \ + cls &operator=(const cls &); + +class CUncopyable +{ +protected: + CUncopyable() {} // allow constructor + // ~CUncopyable() {} +CLASS_NO_COPY(CUncopyable) +}; + +#define MY_UNCOPYABLE :private CUncopyable +// #define MY_UNCOPYABLE + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyUnknown.h b/3rdparty/lzma-21.03beta/CPP/Common/MyUnknown.h new file mode 100644 index 0000000..ff025cb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyUnknown.h @@ -0,0 +1,17 @@ +// MyUnknown.h + +#ifndef __MY_UNKNOWN_H +#define __MY_UNKNOWN_H + +#include "MyWindows.h" + +/* +#ifdef _WIN32 +#include +#include +#else +#include "MyWindows.h" +#endif +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyVector.cpp b/3rdparty/lzma-21.03beta/CPP/Common/MyVector.cpp new file mode 100644 index 0000000..0b1baf4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyVector.cpp @@ -0,0 +1,3 @@ +// Common/MyVector.cpp + +#include "StdAfx.h" diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyVector.h b/3rdparty/lzma-21.03beta/CPP/Common/MyVector.h new file mode 100644 index 0000000..c851234 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyVector.h @@ -0,0 +1,634 @@ +// Common/MyVector.h + +#ifndef __COMMON_MY_VECTOR_H +#define __COMMON_MY_VECTOR_H + +#include + +template +class CRecordVector +{ + T *_items; + unsigned _size; + unsigned _capacity; + + void MoveItems(unsigned destIndex, unsigned srcIndex) + { + memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T)); + } + + void ReserveOnePosition() + { + if (_size == _capacity) + { + unsigned newCapacity = _capacity + (_capacity >> 2) + 1; + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + +public: + + CRecordVector(): _items(NULL), _size(0), _capacity(0) {} + + CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0) + { + unsigned size = v.Size(); + if (size != 0) + { + _items = new T[size]; + _size = size; + _capacity = size; + memcpy(_items, v._items, (size_t)size * sizeof(T)); + } + } + + unsigned Size() const { return _size; } + bool IsEmpty() const { return _size == 0; } + + void ConstructReserve(unsigned size) + { + if (size != 0) + { + MY_ARRAY_NEW(_items, T, size) + // _items = new T[size]; + _capacity = size; + } + } + + void Reserve(unsigned newCapacity) + { + if (newCapacity > _capacity) + { + T *p; + MY_ARRAY_NEW(p, T, newCapacity); + // p = new T[newCapacity]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newCapacity; + } + } + + void ClearAndReserve(unsigned newCapacity) + { + Clear(); + if (newCapacity > _capacity) + { + delete []_items; + _items = NULL; + _capacity = 0; + MY_ARRAY_NEW(_items, T, newCapacity) + // _items = new T[newCapacity]; + _capacity = newCapacity; + } + } + + void ClearAndSetSize(unsigned newSize) + { + ClearAndReserve(newSize); + _size = newSize; + } + + void ChangeSize_KeepData(unsigned newSize) + { + if (newSize > _capacity) + { + T *p; + MY_ARRAY_NEW(p, T, newSize) + // p = new T[newSize]; + if (_size != 0) + memcpy(p, _items, (size_t)_size * sizeof(T)); + delete []_items; + _items = p; + _capacity = newSize; + } + _size = newSize; + } + + void ReserveDown() + { + if (_size == _capacity) + return; + T *p = NULL; + if (_size != 0) + { + p = new T[_size]; + memcpy(p, _items, (size_t)_size * sizeof(T)); + } + delete []_items; + _items = p; + _capacity = _size; + } + + ~CRecordVector() { delete []_items; } + + void ClearAndFree() + { + delete []_items; + _items = NULL; + _size = 0; + _capacity = 0; + } + + void Clear() { _size = 0; } + + void DeleteBack() { _size--; } + + void DeleteFrom(unsigned index) + { + // if (index <= _size) + _size = index; + } + + void DeleteFrontal(unsigned num) + { + if (num != 0) + { + MoveItems(0, num); + _size -= num; + } + } + + void Delete(unsigned index) + { + MoveItems(index, index + 1); + _size -= 1; + } + + /* + void Delete(unsigned index, unsigned num) + { + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } + } + */ + + CRecordVector& operator=(const CRecordVector &v) + { + if (&v == this) + return *this; + unsigned size = v.Size(); + if (size > _capacity) + { + delete []_items; + _capacity = 0; + _size = 0; + _items = NULL; + _items = new T[size]; + _capacity = size; + } + _size = size; + if (size != 0) + memcpy(_items, v._items, (size_t)size * sizeof(T)); + return *this; + } + + CRecordVector& operator+=(const CRecordVector &v) + { + unsigned size = v.Size(); + Reserve(_size + size); + if (size != 0) + memcpy(_items + _size, v._items, (size_t)size * sizeof(T)); + _size += size; + return *this; + } + + unsigned Add(const T item) + { + ReserveOnePosition(); + _items[_size] = item; + return _size++; + } + + void AddInReserved(const T item) + { + _items[_size++] = item; + } + + void Insert(unsigned index, const T item) + { + ReserveOnePosition(); + MoveItems(index + 1, index); + _items[index] = item; + _size++; + } + + void MoveToFront(unsigned index) + { + if (index != 0) + { + T temp = _items[index]; + memmove(_items + 1, _items, (size_t)index * sizeof(T)); + _items[0] = temp; + } + } + + const T& operator[](unsigned index) const { return _items[index]; } + T& operator[](unsigned index) { return _items[index]; } + const T& Front() const { return _items[0]; } + T& Front() { return _items[0]; } + const T& Back() const { return _items[(size_t)_size - 1]; } + T& Back() { return _items[(size_t)_size - 1]; } + + /* + void Swap(unsigned i, unsigned j) + { + T temp = _items[i]; + _items[i] = _items[j]; + _items[j] = temp; + } + */ + + int FindInSorted(const T item, unsigned left, unsigned right) const + { + while (left != right) + { + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) + return (int)mid; + if (item < midVal) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int FindInSorted2(const T &item, unsigned left, unsigned right) const + { + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return (int)mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + return -1; + } + + int FindInSorted(const T item) const + { + return FindInSorted(item, 0, _size); + } + + int FindInSorted2(const T &item) const + { + return FindInSorted2(item, 0, _size); + } + + unsigned AddToUniqueSorted(const T item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T midVal = (*this)[mid]; + if (item == midVal) + return mid; + if (item < midVal) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + unsigned AddToUniqueSorted2(const T &item) + { + unsigned left = 0, right = _size; + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && compare(p + s + 1, p + s, param) > 0) + s++; + if (compare(&temp, p + s, param) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort(int (*compare)(const T*, const T*, void *), void *param) + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown(p, i, size, compare, param); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown(p, 1, size, compare, param); + } + while (size > 1); + } + + static void SortRefDown2(T* p, unsigned k, unsigned size) + { + T temp = p[k]; + for (;;) + { + unsigned s = (k << 1); + if (s > size) + break; + if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0) + s++; + if (temp.Compare(p[s]) >= 0) + break; + p[k] = p[s]; + k = s; + } + p[k] = temp; + } + + void Sort2() + { + unsigned size = _size; + if (size <= 1) + return; + T* p = (&Front()) - 1; + { + unsigned i = size >> 1; + do + SortRefDown2(p, i, size); + while (--i != 0); + } + do + { + T temp = p[size]; + p[size--] = p[1]; + p[1] = temp; + SortRefDown2(p, 1, size); + } + while (size > 1); + } +}; + +typedef CRecordVector CIntVector; +typedef CRecordVector CUIntVector; +typedef CRecordVector CBoolVector; +typedef CRecordVector CByteVector; +typedef CRecordVector CPointerVector; + +template +class CObjectVector +{ + CPointerVector _v; +public: + unsigned Size() const { return _v.Size(); } + bool IsEmpty() const { return _v.IsEmpty(); } + void ReserveDown() { _v.ReserveDown(); } + // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); } + void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); } + + CObjectVector() {} + CObjectVector(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.ConstructReserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + } + CObjectVector& operator=(const CObjectVector &v) + { + if (&v == this) + return *this; + Clear(); + unsigned size = v.Size(); + _v.Reserve(size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; + } + + CObjectVector& operator+=(const CObjectVector &v) + { + unsigned size = v.Size(); + _v.Reserve(Size() + size); + for (unsigned i = 0; i < size; i++) + _v.AddInReserved(new T(v[i])); + return *this; + } + + const T& operator[](unsigned index) const { return *((T *)_v[index]); } + T& operator[](unsigned index) { return *((T *)_v[index]); } + const T& Front() const { return operator[](0); } + T& Front() { return operator[](0); } + const T& Back() const { return *(T *)_v.Back(); } + T& Back() { return *(T *)_v.Back(); } + + void MoveToFront(unsigned index) { _v.MoveToFront(index); } + + unsigned Add(const T& item) { return _v.Add(new T(item)); } + + void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); } + + T& AddNew() + { + T *p = new T; + _v.Add(p); + return *p; + } + + T& AddNewInReserved() + { + T *p = new T; + _v.AddInReserved(p); + return *p; + } + + void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); } + + T& InsertNew(unsigned index) + { + T *p = new T; + _v.Insert(index, p); + return *p; + } + + ~CObjectVector() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + } + + void ClearAndFree() + { + Clear(); + _v.ClearAndFree(); + } + + void Clear() + { + for (unsigned i = _v.Size(); i != 0;) + delete (T *)_v[--i]; + _v.Clear(); + } + + void DeleteFrom(unsigned index) + { + unsigned size = _v.Size(); + for (unsigned i = index; i < size; i++) + delete (T *)_v[i]; + _v.DeleteFrom(index); + } + + void DeleteFrontal(unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[i]; + _v.DeleteFrontal(num); + } + + void DeleteBack() + { + delete (T *)_v.Back(); + _v.DeleteBack(); + } + + void Delete(unsigned index) + { + delete (T *)_v[index]; + _v.Delete(index); + } + + /* + void Delete(unsigned index, unsigned num) + { + for (unsigned i = 0; i < num; i++) + delete (T *)_v[index + i]; + _v.Delete(index, num); + } + */ + + /* + int Find(const T& item) const + { + unsigned size = Size(); + for (unsigned i = 0; i < size; i++) + if (item == (*this)[i]) + return i; + return -1; + } + */ + + int FindInSorted(const T& item) const + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return (int)mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + return -1; + } + + unsigned AddToUniqueSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + return mid; + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + /* + unsigned AddToSorted(const T& item) + { + unsigned left = 0, right = Size(); + while (left != right) + { + unsigned mid = (left + right) / 2; + const T& midVal = (*this)[mid]; + int comp = item.Compare(midVal); + if (comp == 0) + { + right = mid + 1; + break; + } + if (comp < 0) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + */ + + void Sort(int (*compare)(void *const *, void *const *, void *), void *param) + { _v.Sort(compare, param); } + + static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) + { return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); } + + void Sort() { _v.Sort(CompareObjectItems, NULL); } +}; + +#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++) + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.cpp b/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.cpp new file mode 100644 index 0000000..88f312f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.cpp @@ -0,0 +1,292 @@ +// MyWindows.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include +#include +#ifdef __GNUC__ +#include +#endif + +#include "MyWindows.h" + +static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } +static inline void FreeForBSTR(void *pv) { ::free(pv);} + +/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string. + We must select CBstrSizeType for another systems (not Win32): + + if (CBstrSizeType is UINT32), + then we support only strings smaller than 4 GB. + Win32 version always has that limitation. + + if (CBstrSizeType is UINT), + (UINT can be 16/32/64-bit) + We can support strings larger than 4 GB (if UINT is 64-bit), + but sizeof(UINT) can be different in parts compiled by + different compilers/settings, + and we can't send such BSTR strings between such parts. +*/ + +typedef UINT32 CBstrSizeType; +// typedef UINT CBstrSizeType; + +#define k_BstrSize_Max 0xFFFFFFFF +// #define k_BstrSize_Max UINT_MAX +// #define k_BstrSize_Max ((UINT)(INT)-1) + +BSTR SysAllocStringByteLen(LPCSTR s, UINT len) +{ + /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end. + We provide also aligned null OLECHAR at the end. */ + + if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType))) + return NULL; + + UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1); + void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)len; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, len); + for (; len < size; len++) + ((Byte *)bstr)[len] = 0; + return bstr; +} + +BSTR SysAllocStringLen(const OLECHAR *s, UINT len) +{ + if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR)) + return NULL; + + UINT size = len * (UINT)sizeof(OLECHAR); + void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR)); + if (!p) + return NULL; + *(CBstrSizeType *)p = (CBstrSizeType)size; + BSTR bstr = (BSTR)((CBstrSizeType *)p + 1); + if (s) + memcpy(bstr, s, size); + bstr[len] = 0; + return bstr; +} + +BSTR SysAllocString(const OLECHAR *s) +{ + if (!s) + return 0; + const OLECHAR *s2 = s; + while (*s2 != 0) + s2++; + return SysAllocStringLen(s, (UINT)(s2 - s)); +} + +void SysFreeString(BSTR bstr) +{ + if (bstr) + FreeForBSTR((CBstrSizeType *)bstr - 1); +} + +UINT SysStringByteLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1); +} + +UINT SysStringLen(BSTR bstr) +{ + if (!bstr) + return 0; + return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR); +} + + +HRESULT VariantClear(VARIANTARG *prop) +{ + if (prop->vt == VT_BSTR) + SysFreeString(prop->bstrVal); + prop->vt = VT_EMPTY; + return S_OK; +} + +HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src) +{ + HRESULT res = ::VariantClear(dest); + if (res != S_OK) + return res; + if (src->vt == VT_BSTR) + { + dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal, + SysStringByteLen(src->bstrVal)); + if (!dest->bstrVal) + return E_OUTOFMEMORY; + dest->vt = VT_BSTR; + } + else + *dest = *src; + return S_OK; +} + +LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) +{ + if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1; + if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1; + if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1; + if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1; + return 0; +} + +DWORD GetLastError() +{ + return (DWORD)errno; +} + +void SetLastError(DWORD dw) +{ + errno = (int)dw; +} + + +static LONG TIME_GetBias() +{ + time_t utc = time(NULL); + struct tm *ptm = localtime(&utc); + int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ + ptm = gmtime(&utc); + ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ + LONG bias = (int)(mktime(ptm)-utc); + return bias; +} + +#define TICKS_PER_SEC 10000000 +/* +#define SECS_PER_DAY (24 * 60 * 60) +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC) +*/ + +#define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32)) + +#define SET_FILETIME(ft, v64) \ + (ft)->dwLowDateTime = (DWORD)v64; \ + (ft)->dwHighDateTime = (DWORD)(v64 >> 32); + + +BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime) +{ + UInt64 v = GET_TIME_64(fileTime); + v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC); + SET_FILETIME(localFileTime, v); + return TRUE; +} + +BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime) +{ + UInt64 v = GET_TIME_64(localFileTime); + v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC); + SET_FILETIME(fileTime, v); + return TRUE; +} + +/* +VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft) +{ + UInt64 t = 0; + timeval tv; + if (gettimeofday(&tv, NULL) == 0) + { + t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970; + t += tv.tv_usec * 10; + } + SET_FILETIME(ft, t); +} +*/ + +DWORD WINAPI GetTickCount(VOID) +{ + #ifndef _WIN32 + // gettimeofday() doesn't work in some MINGWs by unknown reason + timeval tv; + if (gettimeofday(&tv, NULL) == 0) + { + // tv_sec and tv_usec are (long) + return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000); + } + #endif + return (DWORD)time(NULL) * 1000; +} + + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st) +{ + UInt32 v; + UInt64 v64 = GET_TIME_64(ft); + v64 /= 10000; + st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000; + st->wSecond = (WORD)(v64 % 60); v64 /= 60; + st->wMinute = (WORD)(v64 % 60); v64 /= 60; + v = (UInt32)v64; + st->wHour = (WORD)(v % 24); v /= 24; + + // 1601-01-01 was Monday + st->wDayOfWeek = (WORD)((v + 1) % 7); + + UInt32 leaps, year, day, mon; + leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4; + v += 28188 + leaps; + // leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01 + // (1959 / 64) - converts day from 03-01 to month + year = (20 * v - 2442) / (5 * PERIOD_4); + day = v - (year * PERIOD_4) / 4; + mon = (64 * day) / 1959; + st->wDay = (WORD)(day - (1959 * mon) / 64); + mon -= 1; + year += 1524; + if (mon > 12) + { + mon -= 12; + year++; + } + st->wMonth = (WORD)mon; + st->wYear = (WORD)year; + + /* + unsigned year, mon; + unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + + year = (WORD)(1601 + v / PERIOD_400 * 400); + v %= PERIOD_400; + + t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; + t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; + t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; + + st->wYear = (WORD)year; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 0;; mon++) + { + unsigned d = ms[mon]; + if (v < d) + break; + v -= d; + } + st->wDay = (WORD)(v + 1); + st->wMonth = (WORD)(mon + 1); + */ + + return TRUE; +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.h b/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.h new file mode 100644 index 0000000..0664a5e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/MyWindows.h @@ -0,0 +1,268 @@ +// MyWindows.h + +#ifndef __MY_WINDOWS_H +#define __MY_WINDOWS_H + +#ifdef _WIN32 + +#include + +#ifdef UNDER_CE + #undef VARIANT_TRUE + #define VARIANT_TRUE ((VARIANT_BOOL)-1) +#endif + +#else // _WIN32 + +#include // for wchar_t +#include +// #include // for uintptr_t + +#include "MyGuidDef.h" + +// WINAPI is __stdcall in Windows-MSVC in windef.h +#define WINAPI +#define EXTERN_C MY_EXTERN_C + +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; +typedef short VARIANT_BOOL; + +#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff)) +#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) + +// MS uses long for BOOL, but long is 32-bit in MS. So we use int. +// typedef long BOOL; +typedef int BOOL; + +#ifndef FALSE + #define FALSE 0 + #define TRUE 1 +#endif + +// typedef size_t ULONG_PTR; +// typedef size_t DWORD_PTR; +// typedef uintptr_t UINT_PTR; +// typedef ptrdiff_t UINT_PTR; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; +typedef OLECHAR *BSTR; +typedef const OLECHAR *LPCOLESTR; +typedef OLECHAR *LPOLESTR; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME; + +#define HRESULT LONG +#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) +#define FAILED(hr) ((HRESULT)(hr) < 0) +typedef ULONG PROPID; +typedef LONG SCODE; + + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOINTERFACE ((HRESULT)0x80004002L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L) + + +#ifdef _MSC_VER +#define STDMETHODCALLTYPE __stdcall +#define STDAPICALLTYPE __stdcall +#else +// do we need __export here? +#define STDMETHODCALLTYPE +#define STDAPICALLTYPE +#endif + +#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE + +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0 + +#define MIDL_INTERFACE(x) struct + +#ifdef __cplusplus + +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +struct IUnknown +{ + STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; + virtual ~IUnknown() {} + // We use virtual ~IUnknown() here for binary compatibility with 7z.so from p7zip +}; + +typedef IUnknown *LPUNKNOWN; + +#endif + +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +enum VARENUM +{ + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_FILETIME = 64 +}; + +typedef unsigned short VARTYPE; +typedef WORD PROPVAR_PAD1; +typedef WORD PROPVAR_PAD2; +typedef WORD PROPVAR_PAD3; + +typedef struct tagPROPVARIANT +{ + VARTYPE vt; + PROPVAR_PAD1 wReserved1; + PROPVAR_PAD2 wReserved2; + PROPVAR_PAD3 wReserved3; + union + { + CHAR cVal; + UCHAR bVal; + SHORT iVal; + USHORT uiVal; + LONG lVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + SCODE scode; + FILETIME filetime; + BSTR bstrVal; + }; +} PROPVARIANT; + +typedef PROPVARIANT tagVARIANT; +typedef tagVARIANT VARIANT; +typedef VARIANT VARIANTARG; + +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src); + +typedef struct tagSTATPROPSTG +{ + LPOLESTR lpwstrName; + PROPID propid; + VARTYPE vt; +} STATPROPSTG; + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); + +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C void SetLastError(DWORD dwCode); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); + +MY_EXTERN_C DWORD GetCurrentThreadId(); +MY_EXTERN_C DWORD GetCurrentProcessId(); + +#define MAX_PATH 1024 + +#define CP_ACP 0 +#define CP_OEMCP 1 +#define CP_UTF8 65001 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + + + +typedef struct _SYSTEMTIME +{ + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME; + +BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime); +BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime); +BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime); +// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime); + +DWORD GetTickCount(); + + +#define CREATE_NEW 1 +#define CREATE_ALWAYS 2 +#define OPEN_EXISTING 3 +#define OPEN_ALWAYS 4 +#define TRUNCATE_EXISTING 5 + + +#endif // _WIN32 + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.cpp b/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.cpp new file mode 100644 index 0000000..7e5b1d4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.cpp @@ -0,0 +1,163 @@ +// NewHandler.cpp + +#include "StdAfx.h" + +#include + +#include "NewHandler.h" + +// #define DEBUG_MEMORY_LEAK + +#ifndef DEBUG_MEMORY_LEAK + +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW + +/* +void * my_new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void my_delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +void * my_Realloc(void *p, size_t newSize, size_t oldSize) +{ + void *newBuf = my_new(newSize); + if (oldSize != 0) + memcpy(newBuf, p, oldSize); + my_delete(p); + return newBuf; +} +*/ + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} + +/* +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw() +{ + // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); + ::free(p); +} +*/ + +#endif + +#else + +#include + +// #pragma init_seg(lib) +const int kDebugSize = 1000000; +static void *a[kDebugSize]; +static int index = 0; + +static int numAllocs = 0; +void * __cdecl operator new(size_t size) +{ + numAllocs++; + void *p = HeapAlloc(GetProcessHeap(), 0, size); + if (index < kDebugSize) + { + a[index] = p; + index++; + } + if (p == 0) + throw CNewException(); + printf("Alloc %6d, size = %8u\n", numAllocs, (unsigned)size); + return p; +} + +class CC +{ +public: + CC() + { + for (int i = 0; i < kDebugSize; i++) + a[i] = 0; + } + ~CC() + { + for (int i = 0; i < kDebugSize; i++) + if (a[i] != 0) + return; + } +} g_CC; + + +void __cdecl operator delete(void *p) +{ + if (p == 0) + return; + /* + for (int i = 0; i < index; i++) + if (a[i] == p) + a[i] = 0; + */ + HeapFree(GetProcessHeap(), 0, p); + numAllocs--; + printf("Free %d\n", numAllocs); +} + +#endif + +/* +int MemErrorVC(size_t) +{ + throw CNewException(); + // return 1; +} +CNewHandlerSetter::CNewHandlerSetter() +{ + // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); +} +CNewHandlerSetter::~CNewHandlerSetter() +{ + // _set_new_handler(MemErrorOldVCFunction); +} +*/ diff --git a/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.h b/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.h new file mode 100644 index 0000000..aedeca6 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/NewHandler.h @@ -0,0 +1,88 @@ +// Common/NewHandler.h + +#ifndef __COMMON_NEW_HANDLER_H +#define __COMMON_NEW_HANDLER_H + +/* +NewHandler.h and NewHandler.cpp allows to solve problem with compilers that +don't throw exception in operator new(). + +This file must be included before any code that uses operators new() or delete() +and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler. + +The operator new() in some MSVC versions doesn't throw exception std::bad_alloc. +MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception. +The code produced by some another MSVC compilers also can be linked +to library that doesn't throw exception. +We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc. +For older _MSC_VER versions we redefine operator new() and operator delete(). +Our version of operator new() throws CNewException() exception on failure. + +It's still allowed to use redefined version of operator new() from "NewHandler.cpp" +with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions. +But if you use some additional code (outside of 7-Zip's code), you must check +that redefined version of operator new() is not problem for your code. +*/ + +#include + +#ifdef _WIN32 +// We can compile my_new and my_delete with _fastcall +/* +void * my_new(size_t size); +void my_delete(void *p) throw(); +// void * my_Realloc(void *p, size_t newSize, size_t oldSize); +*/ +#endif + + +#if defined(_MSC_VER) && (_MSC_VER < 1900) + // If you want to use default operator new(), you can disable the following line + #define _7ZIP_REDEFINE_OPERATOR_NEW +#endif + + +#ifdef _7ZIP_REDEFINE_OPERATOR_NEW + +// std::bad_alloc can require additional DLL dependency. +// So we don't define CNewException as std::bad_alloc here. + +class CNewException {}; + +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw(); + +#else + +#include + +#define CNewException std::bad_alloc + +#endif + +/* +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new[](size_t size); + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete[](void *p) throw(); +#endif +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Sha256Prepare.cpp b/3rdparty/lzma-21.03beta/CPP/Common/Sha256Prepare.cpp new file mode 100644 index 0000000..1ec242b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Sha256Prepare.cpp @@ -0,0 +1,7 @@ +// Sha256Prepare.cpp + +#include "StdAfx.h" + +#include "../../C/Sha256.h" + +static struct CSha256Prepare { CSha256Prepare() { Sha256Prepare(); } } g_Sha256Prepare; diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Sha256Reg.cpp b/3rdparty/lzma-21.03beta/CPP/Common/Sha256Reg.cpp new file mode 100644 index 0000000..5f3a35b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Sha256Reg.cpp @@ -0,0 +1,70 @@ +// Sha256Reg.cpp + +#include "StdAfx.h" + +#include "../../C/Sha256.h" + +#include "../Common/MyBuffer2.h" +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +class CSha256Hasher: + public IHasher, + public ICompressSetCoderProperties, + public CMyUnknownImp +{ + CAlignedBuffer _buf; + Byte mtDummy[1 << 7]; + + CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_buf; } +public: + CSha256Hasher(): + _buf(sizeof(CSha256)) + { + Sha256_SetFunction(Sha(), 0); + Sha256_InitState(Sha()); + } + + MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties) + INTERFACE_IHasher(;) + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); +}; + +STDMETHODIMP_(void) CSha256Hasher::Init() throw() +{ + Sha256_InitState(Sha()); +} + +STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw() +{ + Sha256_Update(Sha(), (const Byte *)data, size); +} + +STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw() +{ + Sha256_Final(Sha(), digest); +} + + +STDMETHODIMP CSha256Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) +{ + unsigned algo = 0; + for (UInt32 i = 0; i < numProps; i++) + { + const PROPVARIANT &prop = coderProps[i]; + if (propIDs[i] == NCoderPropID::kDefaultProp) + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal > 2) + return E_NOTIMPL; + algo = (unsigned)prop.ulVal; + } + } + if (!Sha256_SetFunction(Sha(), algo)) + return E_NOTIMPL; + return S_OK; +} + +REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE) diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/Common/StdAfx.h new file mode 100644 index 0000000..420f5c3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.cpp b/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.cpp new file mode 100644 index 0000000..abad34b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.cpp @@ -0,0 +1,95 @@ +// Common/StdInStream.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#endif + +#include "StdInStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +// #define kEOFMessage "Unexpected end of input stream" +// #define kReadErrorMessage "Error reading input stream" +// #define kIllegalCharMessage "Illegal zero character in input stream" + +#define kFileOpenMode TEXT("r") + +CStdInStream g_StdIn(stdin); + +bool CStdInStream::Open(LPCTSTR fileName) throw() +{ + Close(); + _stream = + #ifdef _WIN32 + _tfopen + #else + fopen + #endif + (fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdInStream::Close() throw() +{ + if (!_streamIsOpen) + return true; + _streamIsOpen = (fclose(_stream) != 0); + return !_streamIsOpen; +} + +bool CStdInStream::ScanAStringUntilNewLine(AString &s) +{ + s.Empty(); + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + return true; + char c = (char)intChar; + if (c == 0) + return false; + if (c == '\n') + return true; + s += c; + } +} + +bool CStdInStream::ScanUStringUntilNewLine(UString &dest) +{ + dest.Empty(); + AString s; + bool res = ScanAStringUntilNewLine(s); + int codePage = CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUTF8ToUnicode(s, dest); + else + MultiByteToUnicodeString2(dest, s, (UINT)codePage); + return res; +} + +/* +bool CStdInStream::ReadToString(AString &resultString) +{ + resultString.Empty(); + for (;;) + { + int intChar = GetChar(); + if (intChar == EOF) + return !Error(); + char c = (char)intChar; + if (c == 0) + return false; + resultString += c; + } +} +*/ + +int CStdInStream::GetChar() +{ + return fgetc(_stream); // getc() doesn't work in BeOS? +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.h b/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.h new file mode 100644 index 0000000..71578eb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StdInStream.h @@ -0,0 +1,44 @@ +// Common/StdInStream.h + +#ifndef __COMMON_STD_IN_STREAM_H +#define __COMMON_STD_IN_STREAM_H + +#include + +#include "MyString.h" +#include "MyTypes.h" + +class CStdInStream +{ + FILE *_stream; + bool _streamIsOpen; +public: + int CodePage; + + CStdInStream(FILE *stream = NULL): + _stream(stream), + _streamIsOpen(false), + CodePage(-1) + {}; + + ~CStdInStream() { Close(); } + + bool Open(LPCTSTR fileName) throw(); + bool Close() throw(); + + // returns: + // false, if ZERO character in stream + // true, if EOF or '\n' + bool ScanAStringUntilNewLine(AString &s); + bool ScanUStringUntilNewLine(UString &s); + // bool ReadToString(AString &resultString); + + bool Eof() const throw() { return (feof(_stream) != 0); } + bool Error() const throw() { return (ferror(_stream) != 0); } + + int GetChar(); +}; + +extern CStdInStream g_StdIn; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.cpp b/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.cpp new file mode 100644 index 0000000..40799e2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.cpp @@ -0,0 +1,158 @@ +// Common/StdOutStream.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include +#endif + +#include "IntToString.h" +#include "StdOutStream.h" +#include "StringConvert.h" +#include "UTFConvert.h" + +#define kFileOpenMode "wt" + +CStdOutStream g_StdOut(stdout); +CStdOutStream g_StdErr(stderr); + +bool CStdOutStream::Open(const char *fileName) throw() +{ + Close(); + _stream = fopen(fileName, kFileOpenMode); + _streamIsOpen = (_stream != 0); + return _streamIsOpen; +} + +bool CStdOutStream::Close() throw() +{ + if (!_streamIsOpen) + return true; + if (fclose(_stream) != 0) + return false; + _stream = 0; + _streamIsOpen = false; + return true; +} + +bool CStdOutStream::Flush() throw() +{ + return (fflush(_stream) == 0); +} + +CStdOutStream & endl(CStdOutStream & outStream) throw() +{ + return outStream << '\n'; +} + +CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) +{ + AString temp; + UString s2(s); + PrintUString(s2, temp); + return *this; +} + +void CStdOutStream::PrintUString(const UString &s, AString &temp) +{ + Convert_UString_to_AString(s, temp); + *this << (const char *)temp; +} + +void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest) +{ + int codePage = CodePage; + if (codePage == -1) + codePage = CP_OEMCP; + if (codePage == CP_UTF8) + ConvertUnicodeToUTF8(src, dest); + else + UnicodeStringToMultiByte2(dest, src, (UINT)codePage); +} + + +static const wchar_t kReplaceChar = '_'; + +void CStdOutStream::Normalize_UString__LF_Allowed(UString &s) +{ + unsigned len = s.Len(); + wchar_t *d = s.GetBuf(); + + if (IsTerminalMode) + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c <= 13 && c >= 7 && c != '\n') + d[i] = kReplaceChar; + } +} + +void CStdOutStream::Normalize_UString(UString &s) +{ + unsigned len = s.Len(); + wchar_t *d = s.GetBuf(); + + if (IsTerminalMode) + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c <= 13 && c >= 7) + d[i] = kReplaceChar; + } + else + for (unsigned i = 0; i < len; i++) + { + wchar_t c = d[i]; + if (c == '\n') + d[i] = kReplaceChar; + } +} + +void CStdOutStream::NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA) +{ + tempU = s; + Normalize_UString(tempU); + PrintUString(tempU, tempA); +} + +void CStdOutStream::NormalizePrint_UString(const UString &s) +{ + NormalizePrint_wstr(s); +} + +void CStdOutStream::NormalizePrint_wstr(const wchar_t *s) +{ + UString tempU = s; + Normalize_UString(tempU); + AString tempA; + PrintUString(tempU, tempA); +} + + +CStdOutStream & CStdOutStream::operator<<(Int32 number) throw() +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(Int64 number) throw() +{ + char s[32]; + ConvertInt64ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw() +{ + char s[16]; + ConvertUInt32ToString(number, s); + return operator<<(s); +} + +CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw() +{ + char s[32]; + ConvertUInt64ToString(number, s); + return operator<<(s); +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.h b/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.h new file mode 100644 index 0000000..93f1dfa --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StdOutStream.h @@ -0,0 +1,76 @@ +// Common/StdOutStream.h + +#ifndef __COMMON_STD_OUT_STREAM_H +#define __COMMON_STD_OUT_STREAM_H + +#include + +#include "MyString.h" +#include "MyTypes.h" + +class CStdOutStream +{ + FILE *_stream; + bool _streamIsOpen; +public: + bool IsTerminalMode; + int CodePage; + + CStdOutStream(FILE *stream = 0): + _stream(stream), + _streamIsOpen(false), + IsTerminalMode(false), + CodePage(-1) + {}; + + ~CStdOutStream() { Close(); } + + // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; } + // bool IsDefined() const { return _stream != NULL; } + + operator FILE *() { return _stream; } + bool Open(const char *fileName) throw(); + bool Close() throw(); + bool Flush() throw(); + + CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &)) + { + (*func)(*this); + return *this; + } + + CStdOutStream & operator<<(const char *s) throw() + { + fputs(s, _stream); + return *this; + } + + CStdOutStream & operator<<(char c) throw() + { + fputc((unsigned char)c, _stream); + return *this; + } + + CStdOutStream & operator<<(Int32 number) throw(); + CStdOutStream & operator<<(Int64 number) throw(); + CStdOutStream & operator<<(UInt32 number) throw(); + CStdOutStream & operator<<(UInt64 number) throw(); + + CStdOutStream & operator<<(const wchar_t *s); + void PrintUString(const UString &s, AString &temp); + void Convert_UString_to_AString(const UString &src, AString &dest); + + void Normalize_UString__LF_Allowed(UString &s); + void Normalize_UString(UString &s); + + void NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA); + void NormalizePrint_UString(const UString &s); + void NormalizePrint_wstr(const wchar_t *s); +}; + +CStdOutStream & endl(CStdOutStream & outStream) throw(); + +extern CStdOutStream g_StdOut; +extern CStdOutStream g_StdErr; + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.cpp b/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.cpp new file mode 100644 index 0000000..c0bde0f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.cpp @@ -0,0 +1,757 @@ +// Common/StringConvert.cpp + +#include "StdAfx.h" + +#include "StringConvert.h" + +#ifndef _WIN32 +// #include +#include +#endif + +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) +#include "UTFConvert.h" +#endif + +#ifdef ENV_HAVE_LOCALE +#include +#endif + +static const char k_DefultChar = '_'; + +#ifdef _WIN32 + +/* +MultiByteToWideChar(CodePage, DWORD dwFlags, + LPCSTR lpMultiByteStr, int cbMultiByte, + LPWSTR lpWideCharStr, int cchWideChar) + + if (cbMultiByte == 0) + return: 0. ERR: ERROR_INVALID_PARAMETER + + if (cchWideChar == 0) + return: the required buffer size in characters. + + if (supplied buffer size was not large enough) + return: 0. ERR: ERROR_INSUFFICIENT_BUFFER + The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex) + + If there are illegal characters: + if MB_ERR_INVALID_CHARS is set in dwFlags: + - the function stops conversion on illegal character. + - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION. + + if MB_ERR_INVALID_CHARS is NOT set in dwFlags: + before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0. + in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal + character is converted to U+FFFD, which is REPLACEMENT CHARACTER. +*/ + + +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + { + /* + wchar_t *d = dest.GetBuf(src.Len()); + const char *s = (const char *)src; + unsigned i; + + for (i = 0;;) + { + Byte c = (Byte)s[i]; + if (c >= 0x80 || c == 0) + break; + d[i++] = (wchar_t)c; + } + + if (i != src.Len()) + { + unsigned len = MultiByteToWideChar(codePage, 0, s + i, + src.Len() - i, d + i, + src.Len() + 1 - i); + if (len == 0) + throw 282228; + i += len; + } + + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + */ + unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0); + if (len == 0) + { + if (GetLastError() != 0) + throw 282228; + } + else + { + len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len); + if (len == 0) + throw 282228; + dest.ReleaseBuf_SetEnd(len); + } + } +} + +/* + int WideCharToMultiByte( + UINT CodePage, DWORD dwFlags, + LPCWSTR lpWideCharStr, int cchWideChar, + LPSTR lpMultiByteStr, int cbMultiByte, + LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); + +if (lpDefaultChar == NULL), + - it uses system default value. + +if (CodePage == CP_UTF7 || CodePage == CP_UTF8) + if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL) + return: 0. ERR: ERROR_INVALID_PARAMETER. + +The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL) + +*/ + +static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + dest.Empty(); + defaultCharWasUsed = false; + if (src.IsEmpty()) + return; + { + /* + unsigned numRequiredBytes = src.Len() * 2; + char *d = dest.GetBuf(numRequiredBytes); + const wchar_t *s = (const wchar_t *)src; + unsigned i; + + for (i = 0;;) + { + wchar_t c = s[i]; + if (c >= 0x80 || c == 0) + break; + d[i++] = (char)c; + } + + if (i != src.Len()) + { + BOOL defUsed = FALSE; + defaultChar = defaultChar; + + bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); + unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i, + d + i, numRequiredBytes + 1 - i, + (isUtf ? NULL : &defaultChar), + (isUtf ? NULL : &defUsed)); + defaultCharWasUsed = (defUsed != FALSE); + if (len == 0) + throw 282229; + i += len; + } + + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + */ + + /* + if (codePage != CP_UTF7) + { + const wchar_t *s = (const wchar_t *)src; + unsigned i; + for (i = 0;; i++) + { + wchar_t c = s[i]; + if (c >= 0x80 || c == 0) + break; + } + + if (s[i] == 0) + { + char *d = dest.GetBuf(src.Len()); + for (i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + break; + d[i++] = (char)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + return; + } + } + */ + + unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL); + if (len == 0) + { + if (GetLastError() != 0) + throw 282228; + } + else + { + BOOL defUsed = FALSE; + bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7); + // defaultChar = defaultChar; + len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), + dest.GetBuf(len), (int)len, + (isUtf ? NULL : &defaultChar), + (isUtf ? NULL : &defUsed) + ); + if (!isUtf) + defaultCharWasUsed = (defUsed != FALSE); + if (len == 0) + throw 282228; + dest.ReleaseBuf_SetEnd(len); + } + } +} + +/* +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &src) +{ + AString dest; + const unsigned len = src.Len() * 2; + CharToOem(src, dest.GetBuf(len)); + dest.ReleaseBuf_CalcLen(len); + return dest; +} +#endif +*/ + +#else // _WIN32 + +// #include +/* + if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff), + and utf-8 string contains big unicode character > 0xffff), + then we still use 16-bit surrogate pair in UString. + It simplifies another code where utf-16 encoding is used. + So we use surrogate-conversion code only in is file. +*/ + +/* + mbstowcs() returns error if there is error in utf-8 stream, + mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream +*/ + +/* +static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + + const size_t limit = ((size_t)src.Len() + 1) * 2; + wchar_t *d = dest.GetBuf((unsigned)limit); + const size_t len = mbstowcs(d, src, limit); + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + return; + } + dest.ReleaseBuf_SetEnd(0); +} +*/ + +bool g_ForceToUTF8 = true; // false; + +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + + if (codePage == CP_UTF8 || g_ForceToUTF8) + { + ConvertUTF8ToUnicode(src, dest); + return; + } + + const size_t limit = ((size_t)src.Len() + 1) * 2; + wchar_t *d = dest.GetBuf((unsigned)limit); + const size_t len = mbstowcs(d, src, limit); + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + + #if WCHAR_MAX > 0xffff + d = dest.GetBuf(); + for (size_t i = 0;; i++) + { + // wchar_t c = dest[i]; + wchar_t c = d[i]; + if (c == 0) + break; + if (c >= 0x10000 && c < 0x110000) + { + /* + c -= 0x10000; + unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); + dest.ReplaceOneCharAtPos(i, c0); + i++; + c = 0xdc00 + (c & 0x3FF); + dest.Insert_wchar_t(i, c); + */ + UString temp = d + i; + + for (size_t t = 0;; t++) + { + wchar_t w = temp[t]; + if (w == 0) + break; + if (i == limit) + break; // unexpected error + if (w >= 0x10000 && w < 0x110000) + { + if (i + 1 == limit) + break; // unexpected error + w -= 0x10000; + d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3FF); + w = 0xdc00 + (w & 0x3FF); + } + d[i++] = w; + } + dest.ReleaseBuf_SetEnd((unsigned)i); + } + } + + #endif + + /* + printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr()); + printf("char: "); + for (unsigned i = 0; i < src.Len(); i++) + printf (" %02x", (int)(Byte)src[i]); + printf("\n"); + printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr()); + printf("wchar_t: "); + for (unsigned i = 0; i < dest.Len(); i++) + { + printf (" %02x", (int)dest[i]); + } + printf("\n"); + */ + + return; + } + + /* if there is mbstowcs() error, we have two ways: + + 1) change 0x80+ characters to some character: '_' + in that case we lose data, but we have correct UString() + and that scheme can show errors to user in early stages, + when file converted back to mbs() cannot be found + + 2) transfer bad characters in some UTF-16 range. + it can be non-original Unicode character. + but later we still can restore original character. + */ + + + // printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr()); + { + unsigned i; + const char *s = (const char *)src; + for (i = 0;;) + { + Byte c = (Byte)s[i]; + if (c == 0) + break; + // we can use ascii compatibilty character '_' + // if (c > 0x7F) c = '_'; // we replace "bad: character + d[i++] = (wchar_t)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + } +} + +static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src) +{ + dest.Empty(); + if (src.IsEmpty()) + return; + + const size_t limit = ((size_t)src.Len() + 1) * 6; + char *d = dest.GetBuf((unsigned)limit); + + const size_t len = wcstombs(d, src, limit); + + if (len != (size_t)-1) + { + dest.ReleaseBuf_SetEnd((unsigned)len); + return; + } + dest.ReleaseBuf_SetEnd(0); +} + + +static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + // if (codePage == 1234567) // for debug purposes + if (codePage == CP_UTF8 || g_ForceToUTF8) + { + defaultCharWasUsed = false; + ConvertUnicodeToUTF8(src2, dest); + return; + } + + UString src = src2; + #if WCHAR_MAX > 0xffff + { + src.Empty(); + for (unsigned i = 0; i < src2.Len();) + { + wchar_t c = src2[i]; + if (c >= 0xd800 && c < 0xdc00 && i + 1 != src2.Len()) + { + const wchar_t c2 = src2[i + 1]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + // printf("%4x\n", (int)c); + i++; + } + } + src += c; + i++; + } + } + #endif + + dest.Empty(); + defaultCharWasUsed = false; + if (src.IsEmpty()) + return; + + const size_t len = wcstombs(NULL, src, 0); + + if (len != (size_t)-1) + { + const unsigned limit = ((unsigned)len); + if (limit == len) + { + char *d = dest.GetBuf(limit); + + /* + { + printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr()); + for (unsigned i = 0; i < src.Len(); i++) + printf (" %02x", (int)src[i]); + printf("\n"); + printf("\ndest Limit = %d \n", limit); + } + */ + + const size_t len2 = wcstombs(d, src, len + 1); + + if (len2 != (size_t)-1 && len2 <= limit) + { + /* + printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr()); + for (unsigned i = 0; i < len2; i++) + printf(" %02x", (int)(Byte)dest[i]); + printf("\n"); + */ + dest.ReleaseBuf_SetEnd((unsigned)len2); + return; + } + } + } + + { + const wchar_t *s = (const wchar_t *)src; + char *d = dest.GetBuf(src.Len()); + + unsigned i; + for (i = 0;;) + { + wchar_t c = s[i]; + if (c == 0) + break; + if (c >= + 0x100 + // 0x80 + ) + { + c = defaultChar; + defaultCharWasUsed = true; + } + + d[i++] = (char)c; + } + d[i] = 0; + dest.ReleaseBuf_SetLen(i); + /* + printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len()); + printf("ERROR: %s\n", dest.Ptr()); + */ + } +} + +#endif // _WIN32 + + +UString MultiByteToUnicodeString(const AString &src, UINT codePage) +{ + UString dest; + MultiByteToUnicodeString2(dest, src, codePage); + return dest; +} + +UString MultiByteToUnicodeString(const char *src, UINT codePage) +{ + return MultiByteToUnicodeString(AString(src), codePage); +} + + +void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage) +{ + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); +} + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed) +{ + AString dest; + UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed); + return dest; +} + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage) +{ + AString dest; + bool defaultCharWasUsed; + UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed); + return dest; +} + + + + + +#ifdef _WIN32 +#define U_to_A(a, b, c) UnicodeStringToMultiByte2 +// #define A_to_U(a, b, c) MultiByteToUnicodeString2 +#else +// void MultiByteToUnicodeString2_Native(UString &dest, const AString &src); +#define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b) +// #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b) +#endif + +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) + +bool IsNativeUTF8() +{ + UString u; + AString a, a2; + // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1) + for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1) + { + u.Empty(); + u += (wchar_t)c; + /* + if (Unicode_Is_There_Utf16SurrogateError(u)) + continue; + #ifndef _WIN32 + if (Unicode_Is_There_BmpEscape(u)) + continue; + #endif + */ + ConvertUnicodeToUTF8(u, a); + U_to_A(a2, u, CP_OEMCP); + if (a != a2) + return false; + } + return true; +} + +#endif + + +#ifdef ENV_HAVE_LOCALE + +const char *GetLocale(void) +{ + #ifdef ENV_HAVE_LOCALE + // printf("\n\nsetlocale(LC_CTYPE, NULL) : return : "); + const char *s = setlocale(LC_CTYPE, NULL); + if (!s) + { + // printf("[NULL]\n"); + s = "C"; + } + else + { + // ubuntu returns "C" after program start + // printf("\"%s\"\n", s); + } + return s; + #elif defined(LOCALE_IS_UTF8) + return "utf8"; + #else + return "C"; + #endif +} + +#ifdef _WIN32 + static void Set_ForceToUTF8(bool) {} +#else + static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; } +#endif + +static bool Is_Default_Basic_Locale(const char *locale) +{ + const AString a (locale); + if (a.IsEqualTo_Ascii_NoCase("") + || a.IsEqualTo_Ascii_NoCase("C") + || a.IsEqualTo_Ascii_NoCase("POSIX")) + return true; + return false; +} + +static bool Is_Default_Basic_Locale() +{ + return Is_Default_Basic_Locale(GetLocale()); +} + + +void MY_SetLocale() +{ + #ifdef ENV_HAVE_LOCALE + /* + { + const char *s = GetLocale(); + printf("\nGetLocale() : returned : \"%s\"\n", s); + } + */ + + unsigned start = 0; + // unsigned lim = 0; + unsigned lim = 3; + + /* + #define MY_SET_LOCALE_FLAGS__FROM_ENV 1 + #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2 + + unsigned flags = + MY_SET_LOCALE_FLAGS__FROM_ENV | + MY_SET_LOCALE_FLAGS__TRY_UTF8 + + if (flags != 0) + { + if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV) + lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1; + else + { + start = 1; + lim = 2; + } + } + */ + + for (unsigned i = start; i < lim; i++) + { + /* + man7: "If locale is an empty string, "", each part of the locale that + should be modified is set according to the environment variables. + for glibc: glibc, first from the user's environment variables: + 1) the environment variable LC_ALL, + 2) environment variable with the same name as the category (see the + 3) the environment variable LANG + The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems. + + for WIN32 : MSDN : + Sets the locale to the default, which is the user-default + ANSI code page obtained from the operating system. + The locale name is set to the value returned by GetUserDefaultLocaleName. + The code page is set to the value returned by GetACP + */ + const char *newLocale = ""; + + #ifdef __APPLE__ + + /* look also CFLocale + there is no C.UTF-8 in macos + macos has UTF-8 locale only with some language like en_US.UTF-8 + what is best way to set UTF-8 locale in macos? */ + if (i == 1) + newLocale = "en_US.UTF-8"; + + /* file open with non-utf8 sequencies return + #define EILSEQ 92 // "Illegal byte sequence" + */ +#else + // newLocale = "C"; + if (i == 1) + { + newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu + // newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime + // newLocale = "en_US.utf8"; // supported by ubuntu ? + // newLocale = "en_US.UTF-8"; + /* setlocale() in ubuntu allows locales with minor chracter changes in strings + "en_US.UTF-8" / "en_US.utf8" */ + } + +#endif + + // printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale); + + // const char *s = + setlocale(LC_ALL, newLocale); + + /* + if (!s) + printf("NULL: can't set locale"); + else + printf("\"%s\"\n", s); + */ + + // request curent locale of program + const char *locale = GetLocale(); + if (locale) + { + AString a (locale); + a.MakeLower_Ascii(); + // if (a.Find("utf") >= 0) + { + if (IsNativeUTF8()) + { + Set_ForceToUTF8(true); + return; + } + } + if (!Is_Default_Basic_Locale(locale)) + { + // if there is some non-default and non-utf locale, we want to use it + break; // comment it for debug + } + } + } + + if (IsNativeUTF8()) + { + Set_ForceToUTF8(true); + return; + } + + if (Is_Default_Basic_Locale()) + { + Set_ForceToUTF8(true); + return; + } + + Set_ForceToUTF8(false); + + #elif defined(LOCALE_IS_UTF8) + // assume LC_CTYPE="utf8" + #else + // assume LC_CTYPE="C" + #endif +} +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.h b/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.h new file mode 100644 index 0000000..865c025 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StringConvert.h @@ -0,0 +1,110 @@ +// Common/StringConvert.h + +#ifndef __COMMON_STRING_CONVERT_H +#define __COMMON_STRING_CONVERT_H + +#include "MyString.h" +#include "MyWindows.h" + +UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP); +UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP); + +// optimized versions that work faster for ASCII strings +void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP); +// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage); + +AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed); +AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP); + +inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; } +inline const UString& GetUnicodeString(const UString &u) { return u; } + +inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); } +inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); } + +inline UString GetUnicodeString(const AString &a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } +inline UString GetUnicodeString(const char *a, UINT codePage) + { return MultiByteToUnicodeString(a, codePage); } + +inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; } +inline const UString& GetUnicodeString(const UString &u, UINT) { return u; } + +inline const char* GetAnsiString(const char *a) { return a; } +inline const AString& GetAnsiString(const AString &a) { return a; } + +inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } +inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); } + +/* +inline const char* GetOemString(const char* oem) + { return oem; } +inline const AString& GetOemString(const AString &oem) + { return oem; } +*/ +const char* GetOemString(const char* oem); +const AString& GetOemString(const AString &oem); +inline AString GetOemString(const UString &u) + { return UnicodeStringToMultiByte(u, CP_OEMCP); } + +#ifdef _UNICODE + inline const wchar_t* GetSystemString(const wchar_t *u) { return u;} + inline const UString& GetSystemString(const UString &u) { return u;} + inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;} + inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;} + + inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); } + inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); } + inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); } +#else + inline const char* GetSystemString(const char *a) { return a; } + inline const AString& GetSystemString(const AString &a) { return a; } + inline const char* GetSystemString(const char *a, UINT) { return a; } + inline const AString& GetSystemString(const AString &a, UINT) { return a; } + + inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); } + inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); } + inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); } + + + + /* + inline AString GetSystemString(const wchar_t *u) + { + UString s; + s = u; + return UnicodeStringToMultiByte(s); + } + */ + +#endif + +#ifndef UNDER_CE +AString SystemStringToOemString(const CSysString &src); +#endif + + +#ifdef _WIN32 +/* we don't need locale functions in Windows + but we can define ENV_HAVE_LOCALE here for debug purposes */ +// #define ENV_HAVE_LOCALE +#else +#define ENV_HAVE_LOCALE +#endif + +#ifdef ENV_HAVE_LOCALE +void MY_SetLocale(); +const char *GetLocale(void); +#endif + +#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE) +bool IsNativeUTF8(); +#endif + +#ifndef _WIN32 +extern bool g_ForceToUTF8; +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.cpp b/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.cpp new file mode 100644 index 0000000..839867a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.cpp @@ -0,0 +1,144 @@ +// Common/StringToInt.cpp + +#include "StdAfx.h" + +#include "StringToInt.h" + +static const UInt32 k_UInt32_max = 0xFFFFFFFF; +static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF); +// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1; + +#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \ + uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \ + if (end) *end = s; \ + uintType res = 0; \ + for (;; s++) { \ + charTypeUnsigned c = (charTypeUnsigned)*s; \ + if (c < '0' || c > '9') { if (end) *end = s; return res; } \ + if (res > (k_ ## uintType ## _max) / 10) return 0; \ + res *= 10; \ + unsigned v = (unsigned)(c - '0'); \ + if (res > (k_ ## uintType ## _max) - v) return 0; \ + res += v; }} + +CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte) +CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t) +CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte) +CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t) + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw() +{ + if (end) + *end = s; + const wchar_t *s2 = s; + if (*s == '-') + s2++; + if (*s2 == 0) + return 0; + const wchar_t *end2; + UInt32 res = ConvertStringToUInt32(s2, &end2); + if (*s == '-') + { + if (res > ((UInt32)1 << (32 - 1))) + return 0; + } + else if ((res & ((UInt32)1 << (32 - 1))) != 0) + return 0; + if (end) + *end = end2; + if (*s == '-') + return -(Int32)res; + return (Int32)res; +} + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) + { + unsigned c = (unsigned char)*s; + if (c < '0' || c > '7') + { + if (end) + *end = s; + return res; + } + if ((res & (UInt32)7 << (32 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); + } +} + +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) + { + unsigned c = (unsigned char)*s; + if (c < '0' || c > '7') + { + if (end) + *end = s; + return res; + } + if ((res & (UInt64)7 << (64 - 3)) != 0) + return 0; + res <<= 3; + res |= (unsigned)(c - '0'); + } +} + +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt32 res = 0; + for (;; s++) + { + unsigned c = (Byte)*s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end) + *end = s; + return res; + } + if ((res & (UInt32)0xF << (32 - 4)) != 0) + return 0; + res <<= 4; + res |= v; + } +} + +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw() +{ + if (end) + *end = s; + UInt64 res = 0; + for (;; s++) + { + unsigned c = (Byte)*s; + unsigned v; + if (c >= '0' && c <= '9') v = (c - '0'); + else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); + else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); + else + { + if (end) + *end = s; + return res; + } + if ((res & (UInt64)0xF << (64 - 4)) != 0) + return 0; + res <<= 4; + res |= v; + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.h b/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.h new file mode 100644 index 0000000..5c5d7d7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/StringToInt.h @@ -0,0 +1,21 @@ +// Common/StringToInt.h + +#ifndef __COMMON_STRING_TO_INT_H +#define __COMMON_STRING_TO_INT_H + +#include "MyTypes.h" + +UInt32 ConvertStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertStringToUInt64(const char *s, const char **end) throw(); +UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw(); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw(); + +Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw(); + +UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw(); + +UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw(); +UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw(); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.cpp b/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.cpp new file mode 100644 index 0000000..1428aab --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.cpp @@ -0,0 +1,124 @@ +// Common/TextConfig.cpp + +#include "StdAfx.h" + +#include "TextConfig.h" +#include "UTFConvert.h" + +static inline bool IsDelimitChar(char c) +{ + return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t'); +} + +static AString GetIDString(const char *s, unsigned &finishPos) +{ + AString result; + for (finishPos = 0; ; finishPos++) + { + char c = s[finishPos]; + if (IsDelimitChar(c) || c == '=') + break; + result += c; + } + return result; +} + +static bool WaitNextLine(const AString &s, unsigned &pos) +{ + for (; pos < s.Len(); pos++) + if (s[pos] == 0x0A) + return true; + return false; +} + +static bool SkipSpaces(const AString &s, unsigned &pos) +{ + for (; pos < s.Len(); pos++) + { + char c = s[pos]; + if (!IsDelimitChar(c)) + { + if (c != ';') + return true; + if (!WaitNextLine(s, pos)) + return false; + } + } + return false; +} + +bool GetTextConfig(const AString &s, CObjectVector &pairs) +{ + pairs.Clear(); + unsigned pos = 0; + + ///////////////////// + // read strings + + for (;;) + { + if (!SkipSpaces(s, pos)) + break; + CTextConfigPair pair; + unsigned finishPos; + const AString temp (GetIDString(((const char *)s) + pos, finishPos)); + if (!ConvertUTF8ToUnicode(temp, pair.ID)) + return false; + if (finishPos == 0) + return false; + pos += finishPos; + if (!SkipSpaces(s, pos)) + return false; + if (s[pos] != '=') + return false; + pos++; + if (!SkipSpaces(s, pos)) + return false; + if (s[pos] != '\"') + return false; + pos++; + AString message; + for (;;) + { + if (pos >= s.Len()) + return false; + char c = s[pos++]; + if (c == '\"') + break; + if (c == '\\') + { + c = s[pos++]; + switch (c) + { + case 'n': message += '\n'; break; + case 't': message += '\t'; break; + case '\\': message += '\\'; break; + case '\"': message += '\"'; break; + default: message += '\\'; message += c; break; + } + } + else + message += c; + } + if (!ConvertUTF8ToUnicode(message, pair.String)) + return false; + pairs.Add(pair); + } + return true; +} + +int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw() +{ + FOR_VECTOR (i, pairs) + if (pairs[i].ID.IsEqualTo(id)) + return i; + return -1; +} + +UString GetTextConfigValue(const CObjectVector &pairs, const char *id) +{ + int index = FindTextConfigItem(pairs, id); + if (index < 0) + return UString(); + return pairs[index].String; +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.h b/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.h new file mode 100644 index 0000000..cc7ce41 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/TextConfig.h @@ -0,0 +1,19 @@ +// Common/TextConfig.h + +#ifndef __COMMON_TEXT_CONFIG_H +#define __COMMON_TEXT_CONFIG_H + +#include "MyString.h" + +struct CTextConfigPair +{ + UString ID; + UString String; +}; + +bool GetTextConfig(const AString &text, CObjectVector &pairs); + +int FindTextConfigItem(const CObjectVector &pairs, const char *id) throw(); +UString GetTextConfigValue(const CObjectVector &pairs, const char *id); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.cpp b/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.cpp new file mode 100644 index 0000000..ac069db --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.cpp @@ -0,0 +1,863 @@ +// UTFConvert.cpp + +#include "StdAfx.h" + +// #include + +#include "MyTypes.h" +#include "UTFConvert.h" + + +#ifndef _WCHART_IS_16BIT +#ifndef __APPLE__ + // we define it if the system supports files with non-utf8 symbols: + #define _UTF8_RAW_NON_UTF8_SUPPORTED +#endif +#endif + +/* + _UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte + + n : _UTF8_START(n) : Bits of code point + + 0 : 0x80 : : unused + 1 : 0xC0 : 11 : + 2 : 0xE0 : 16 : Basic Multilingual Plane + 3 : 0xF0 : 21 : Unicode space + 4 : 0xF8 : 26 : + 5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value + 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value + 7 : 0xFF : +*/ + +#define _UTF8_START(n) (0x100 - (1 << (7 - (n)))) + +#define _UTF8_HEAD_PARSE2(n) \ + if (c < _UTF8_START((n) + 1)) \ + { numBytes = (n); val -= _UTF8_START(n); } + +#ifndef _WCHART_IS_16BIT + +/* + if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence, + when we convert wchar_t strings to UTF-8: + (_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode + (_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4 + (_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack) +*/ + +#define _UTF8_NUM_TAIL_BYTES_MAX 5 +#endif + +/* +#define _UTF8_HEAD_PARSE \ + UInt32 val = c; \ + _UTF8_HEAD_PARSE2(1) \ + else _UTF8_HEAD_PARSE2(2) \ + else _UTF8_HEAD_PARSE2(3) \ + else _UTF8_HEAD_PARSE2(4) \ + else _UTF8_HEAD_PARSE2(5) \ + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + else _UTF8_HEAD_PARSE2(6) + #endif +*/ + +#define _UTF8_HEAD_PARSE_MAX_3_BYTES \ + UInt32 val = c; \ + _UTF8_HEAD_PARSE2(1) \ + else _UTF8_HEAD_PARSE2(2) \ + else { numBytes = 3; val -= _UTF8_START(3); } + + +#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6)) + + +#define START_POINT_FOR_SURROGATE 0x10000 + + +/* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes + Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000) + to simplify internal intermediate conversion in Linux: + RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8 +*/ + + +#if defined(_WCHART_IS_16BIT) + +#define UTF_ESCAPE_PLANE 0 + +#else + +/* +we can place 128 ESCAPE chars to + ef 80 - ee be 80 (3-bytes utf-8) : similar to WSL + ef ff - ee bf bf + +1f ef 80 - f7 be be 80 (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) +1f ef ff - f7 be bf bf (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode) +*/ + +// #define UTF_ESCAPE_PLANE_HIGH (0x1f << 16) +// #define UTF_ESCAPE_PLANE UTF_ESCAPE_PLANE_HIGH +#define UTF_ESCAPE_PLANE 0 + +/* + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is set) + { + if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH) + { + we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane. + But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive) + So we still need a way to extract 8-bit Escapes and BMP-Escapes-8 + from same BMP-Escapes-16 stored in 7z. + And if we want to restore any 8-bit from 7z archive, + we still must use UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT for (utf-8 -> utf-16) + Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21 + } + else (UTF_ESCAPE_PLANE == 0) + { + we must convert original 3-bytes utf-8 BMP-Escape point to sequence + of 3 BMP-Escape-16 points with UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + so we can extract original RAW-UTF-8 from UTFD-16 later. + } + } +*/ + +#endif + + + +#define UTF_ESCAPE_BASE 0xef00 + + +#ifdef UTF_ESCAPE_BASE +#define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80) +#endif + +#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800) +#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffC00) == 0xdc00) + + +#define _ERROR_UTF8_CHECK \ + { NonUtf = true; continue; } + +void CUtf8Check::Check_Buf(const char *src, size_t size) throw() +{ + Clear(); + // Byte maxByte = 0; + + for (;;) + { + if (size == 0) + break; + + const Byte c = (Byte)(*src++); + size--; + + if (c == 0) + { + ZeroChar = true; + continue; + } + + /* + if (c > maxByte) + maxByte = c; + */ + + if (c < 0x80) + continue; + + if (c < 0xc0 + 2)// it's limit for 0x140000 unicode codes : win32 compatibility + _ERROR_UTF8_CHECK + + unsigned numBytes; + + UInt32 val = c; + _UTF8_HEAD_PARSE2(1) + else _UTF8_HEAD_PARSE2(2) + else _UTF8_HEAD_PARSE2(4) + else _UTF8_HEAD_PARSE2(5) + else + { + _ERROR_UTF8_CHECK + } + + unsigned pos = 0; + do + { + if (pos == size) + break; + unsigned c2 = (Byte)src[pos]; + c2 -= 0x80; + if (c2 >= 0x40) + break; + val <<= 6; + val |= c2; + if (pos == 0) + if (val < (((unsigned)1 << 7) >> numBytes)) + break; + pos++; + } + while (--numBytes); + + if (numBytes != 0) + { + if (pos == size) + Truncated = true; + else + _ERROR_UTF8_CHECK + } + + #ifdef UTF_ESCAPE_BASE + if (IS_ESCAPE_POINT(val, 0)) + Escape = true; + #endif + + if (MaxHighPoint < val) + MaxHighPoint = val; + + if (IS_SURROGATE_POINT(val)) + SingleSurrogate = true; + + src += pos; + size -= pos; + } + + // MaxByte = maxByte; +} + +bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw() +{ + CUtf8Check check; + check.Check_Buf(src, size); + return check.IsOK(allowReduced); +} + +/* +bool CheckUTF8_chars(const char *src, bool allowReduced) throw() +{ + CUtf8Check check; + check.CheckBuf(src, strlen(src)); + return check.IsOK(allowReduced); +} +*/ + +bool CheckUTF8_AString(const AString &s) throw() +{ + CUtf8Check check; + check.Check_AString(s); + return check.IsOK(); +} + + +/* +bool CheckUTF8(const char *src, bool allowReduced) throw() +{ + // return Check_UTF8_Buf(src, strlen(src), allowReduced); + + for (;;) + { + const Byte c = (Byte)(*src++); + if (c == 0) + return true; + + if (c < 0x80) + continue; + if (c < 0xC0 + 2 || c >= 0xf5) + return false; + + unsigned numBytes; + _UTF8_HEAD_PARSE + else + return false; + + unsigned pos = 0; + + do + { + Byte c2 = (Byte)(*src++); + if (c2 < 0x80 || c2 >= 0xC0) + return allowReduced && c2 == 0; + val <<= 6; + val |= (c2 - 0x80); + pos++; + } + while (--numBytes); + + if (val < _UTF8_RANGE(pos - 1)) + return false; + + if (val >= 0x110000) + return false; + } +} +*/ + +// in case of UTF-8 error we have two ways: +// 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version +// 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols + +#define UTF_REPLACEMENT_CHAR 0xfffd + + + +#define UTF_ESCAPE(c) \ + ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) ? \ + UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR) + +/* +#define _HARD_ERROR_UTF8 + { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ + destPos++; ok = false; continue; } +*/ + +// we ignore utf errors, and don't change (ok) variable! + +#define _ERROR_UTF8 \ + { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \ + destPos++; continue; } + +// we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points: + +// for debug puposes only we can store UTF-32 in wchar_t: +// #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1) + + +/* + WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found. + Ant it can emit single 0xfffd from 2 src bytes. + It doesn't emit single 0xfffd from 3-4 src bytes. + We can + 1) emit Escape point for each incorrect byte. So we can data recover later + 2) emit 0xfffd for each incorrect byte. + That scheme is similar to Escape scheme, but we emit 0xfffd + instead of each Escape point. + 3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme +*/ + +static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw() +{ + size_t destPos = 0; + bool ok = true; + + for (;;) + { + if (src == srcLim) + { + *destLen = destPos; + return ok; + } + + const Byte c = (Byte)(*src++); + + if (c < 0x80) + { + if (dest) + dest[destPos] = (wchar_t)c; + destPos++; + continue; + } + + if (c < 0xc0 + 2 + || c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility + { + _ERROR_UTF8 + } + + unsigned numBytes; + + _UTF8_HEAD_PARSE_MAX_3_BYTES + + unsigned pos = 0; + do + { + if (src + pos == srcLim) + break; + unsigned c2 = (Byte)src[pos]; + c2 -= 0x80; + if (c2 >= 0x40) + break; + val <<= 6; + val |= c2; + pos++; + if (pos == 1) + { + if (val < (((unsigned)1 << 7) >> numBytes)) + break; + if (numBytes == 2) + { + if (flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) + if ((val & (0xF800 >> 6)) == (0xd800 >> 6)) + break; + } + else if (numBytes == 3 && val >= (0x110000 >> 12)) + break; + } + } + while (--numBytes); + + if (numBytes != 0) + { + if ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) == 0) + { + // the following code to emit the 0xfffd chars as win32 Utf8 function. + // disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode + src += pos; + } + _ERROR_UTF8 + } + + /* + if (val < _UTF8_RANGE(pos - 1)) + _ERROR_UTF8 + */ + + #ifdef UTF_ESCAPE_BASE + + if ((flags & UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT) + && IS_ESCAPE_POINT(val, 0)) + { + // We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes) + _ERROR_UTF8 + } + + #endif + + /* + We don't expect virtual Escape-21 points in UTF-8 stream. + And we don't check for Escape-21. + So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points. + Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases? + */ + + if (val < START_POINT_FOR_SURROGATE) + { + /* + if ((flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) + && IS_SURROGATE_POINT(val)) + { + // We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes) + _ERROR_UTF8 + } + */ + if (dest) + dest[destPos] = (wchar_t)val; + destPos++; + } + else + { + /* + if (val >= 0x110000) + { + // We will emit utf16-Escape-16-21 point from each source byte + _ERROR_UTF8 + } + */ + if (dest) + { + dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10)); + dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff)); + } + destPos += 2; + } + src += pos; + } +} + + + +#define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n))))) +#define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F))) + +static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags) +{ + size_t size = (size_t)(srcLim - src); + for (;;) + { + if (src == srcLim) + return size; + + UInt32 val = (UInt32)(*src++); + + if (val < 0x80) + continue; + + if (val < _UTF8_RANGE(1)) + { + size++; + continue; + } + + #ifdef UTF_ESCAPE_BASE + + #if UTF_ESCAPE_PLANE != 0 + if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE) + if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) + continue; + #endif + + if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE) + if (IS_ESCAPE_POINT(val, 0)) + continue; + + #endif + + if (IS_SURROGATE_POINT(val)) + { + // it's hack to UTF-8 encoding + + if (val < 0xdc00 && src != srcLim) + { + const UInt32 c2 = (UInt32)*src; + if (c2 >= 0xdc00 && c2 < 0xe000) + src++; + } + size += 2; + continue; + } + + #ifdef _WCHART_IS_16BIT + + size += 2; + + #else + + if (val < _UTF8_RANGE(2)) size += 2; + else if (val < _UTF8_RANGE(3)) size += 3; + else if (val < _UTF8_RANGE(4)) size += 4; + else if (val < _UTF8_RANGE(5)) size += 5; + else + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + size += 6; + #else + size += 3; + #endif + + #endif + } +} + + +static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags) +{ + for (;;) + { + if (src == srcLim) + return dest; + + UInt32 val = (UInt32)*src++; + + if (val < 0x80) + { + *dest++ = (char)val; + continue; + } + + if (val < _UTF8_RANGE(1)) + { + dest[0] = _UTF8_HEAD(1, val); + dest[1] = _UTF8_CHAR(0, val); + dest += 2; + continue; + } + + #ifdef UTF_ESCAPE_BASE + + #if UTF_ESCAPE_PLANE != 0 + /* + if (wchar_t is 32-bit) + && (UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE is set) + && (point is virtual escape plane) + we extract 8-bit byte from virtual HIGH-ESCAPE PLANE. + */ + if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE) + if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE)) + { + *dest++ = (char)(val); + continue; + } + #endif // UTF_ESCAPE_PLANE != 0 + + /* if (UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE is defined) + we extract 8-bit byte from BMP-ESCAPE PLANE. */ + + if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE) + if (IS_ESCAPE_POINT(val, 0)) + { + *dest++ = (char)(val); + continue; + } + + #endif // UTF_ESCAPE_BASE + + if (IS_SURROGATE_POINT(val)) + { + // it's hack to UTF-8 encoding + if (val < 0xdc00 && src != srcLim) + { + const UInt32 c2 = (UInt32)*src; + if (IS_LOW_SURROGATE_POINT(c2)) + { + src++; + val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000; + dest[0] = _UTF8_HEAD(3, val); + dest[1] = _UTF8_CHAR(2, val); + dest[2] = _UTF8_CHAR(1, val); + dest[3] = _UTF8_CHAR(0, val); + dest += 4; + continue; + } + } + if (flags & UTF_FLAG__TO_UTF8__SURROGATE_ERROR) + val = UTF_REPLACEMENT_CHAR; // WIN32 function does it + } + + #ifndef _WCHART_IS_16BIT + if (val < _UTF8_RANGE(2)) + #endif + { + dest[0] = _UTF8_HEAD(2, val); + dest[1] = _UTF8_CHAR(1, val); + dest[2] = _UTF8_CHAR(0, val); + dest += 3; + continue; + } + + #ifndef _WCHART_IS_16BIT + + // we don't expect this case. so we can throw exception + // throw 20210407; + + char b; + unsigned numBits; + if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); } + else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); } + else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); } + #if _UTF8_NUM_TAIL_BYTES_MAX >= 6 + else { numBits = 6 * 6; b = (char)_UTF8_START(6); } + #else + else + { + val = UTF_REPLACEMENT_CHAR; + { numBits = 6 * 3; b = _UTF8_HEAD(3, val); } + } + #endif + + *dest++ = b; + + do + { + numBits -= 6; + *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F)); + } + while (numBits != 0); + + #endif + } +} + +bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags) +{ + dest.Empty(); + size_t destLen = 0; + Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags); + bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags); + dest.ReleaseBuf_SetEnd((unsigned)destLen); + return res; +} + +bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags) +{ + return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest, flags); +} + + +static +unsigned g_UTF8_To_Unicode_Flags = + UTF_FLAG__FROM_UTF8__USE_ESCAPE + #ifndef _WCHART_IS_16BIT + | UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED + | UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + #endif + #endif + ; + + +/* +bool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest) +{ + return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); +} +*/ + +bool ConvertUTF8ToUnicode(const AString &src, UString &dest) +{ + return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags); +} + +void Print_UString(const UString &a); + +void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags) +{ + /* + if (src.Len()== 24) + throw "202104"; + */ + dest.Empty(); + const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); + char *destStart = dest.GetBuf((unsigned)destLen); + const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags); + dest.ReleaseBuf_SetEnd((unsigned)destLen); + // printf("\nlen = %d\n", src.Len()); + if (destLen != (size_t)(destEnd - destStart)) + { + /* + // dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart)); + printf("\nlen = %d\n", (unsigned)destLen); + printf("\n(destEnd - destStart) = %d\n", (unsigned)(destEnd - destStart)); + printf("\n"); + // Print_UString(src); + printf("\n"); + // printf("\nlen = %d\n", destLen); + */ + throw 20210406; + } +} + + + +unsigned g_Unicode_To_UTF8_Flags = + // UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE + 0 + #ifndef _WIN32 + #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED + | UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE + #else + | UTF_FLAG__TO_UTF8__SURROGATE_ERROR; + #endif + #endif + ; + +void ConvertUnicodeToUTF8(const UString &src, AString &dest) +{ + ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags); +} + +void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest) +{ + const unsigned flags = g_Unicode_To_UTF8_Flags; + dest.Free(); + const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags); + dest.Alloc(destLen); + const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags); + if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest)) + throw 202104; +} + +/* + +#ifndef _WIN32 +void Convert_UTF16_To_UTF32(const UString &src, UString &dest) +{ + dest.Empty(); + for (size_t i = 0; i < src.Len();) + { + wchar_t c = src[i++]; + if (c >= 0xd800 && c < 0xdc00 && i < src.Len()) + { + const wchar_t c2 = src[i]; + if (c2 >= 0xdc00 && c2 < 0x10000) + { + // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + // printf("%4x\n", (int)c); + i++; + } + } + dest += c; + } +} + +void Convert_UTF32_To_UTF16(const UString &src, UString &dest) +{ + dest.Empty(); + for (size_t i = 0; i < src.Len();) + { + wchar_t w = src[i++]; + if (w >= 0x10000 && w < 0x110000) + { + w -= 0x10000; + dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff)); + w = 0xdc00 + (w & 0x3ff); + } + dest += w; + } +} + +bool UTF32_IsThere_BigPoint(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 c = (UInt32)src[i++]; + if (c >= 0x110000) + return true; + } + return false; +} + +bool Unicode_IsThere_BmpEscape(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 c = (UInt32)src[i++]; + if (IS_ESCAPE_POINT(c, 0)) + return true; + } + return false; +} + + +#endif + +bool Unicode_IsThere_Utf16SurrogateError(const UString &src) +{ + for (size_t i = 0; i < src.Len();) + { + const UInt32 val = (UInt32)src[i++]; + if (IS_SURROGATE_POINT(val)) + { + // it's hack to UTF-8 encoding + if (val >= 0xdc00 || i == src.Len()) + return true; + const UInt32 c2 = (UInt32)*src; + if (!IS_LOW_SURROGATE_POINT(c2)) + return true; + } + } + return false; +} +*/ + +#ifndef _WCHART_IS_16BIT + +void Convert_UnicodeEsc16_To_UnicodeEscHigh +#if UTF_ESCAPE_PLANE == 0 + (UString &) {} +#else + (UString &s) +{ + const unsigned len = s.Len(); + for (unsigned i = 0; i < len; i++) + { + wchar_t c = s[i]; + if (IS_ESCAPE_POINT(c, 0)) + { + c += UTF_ESCAPE_PLANE; + s.ReplaceOneCharAtPos(i, c); + } + } +} +#endif +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.h b/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.h new file mode 100644 index 0000000..37c4975 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/UTFConvert.h @@ -0,0 +1,384 @@ +// Common/UTFConvert.h + +#ifndef __COMMON_UTF_CONVERT_H +#define __COMMON_UTF_CONVERT_H + +#include "MyBuffer.h" +#include "MyString.h" + +struct CUtf8Check +{ + // Byte MaxByte; // in original src stream + bool NonUtf; + bool ZeroChar; + bool SingleSurrogate; + bool Escape; + bool Truncated; + UInt32 MaxHighPoint; // only for points >= 0x80 + + CUtf8Check() { Clear(); } + + void Clear() + { + // MaxByte = 0; + NonUtf = false; + ZeroChar = false; + SingleSurrogate = false; + Escape = false; + Truncated = false; + MaxHighPoint = 0; + } + + void Update(const CUtf8Check &c) + { + if (c.NonUtf) NonUtf = true; + if (c.ZeroChar) ZeroChar = true; + if (c.SingleSurrogate) SingleSurrogate = true; + if (c.Escape) Escape = true; + if (c.Truncated) Truncated = true; + if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint; + } + + void PrintStatus(AString &s) const + { + s.Empty(); + + // s.Add_OptSpaced("MaxByte="); + // s.Add_UInt32(MaxByte); + + if (NonUtf) s.Add_OptSpaced("non-UTF8"); + if (ZeroChar) s.Add_OptSpaced("ZeroChar"); + if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate"); + if (Escape) s.Add_OptSpaced("Escape"); + if (Truncated) s.Add_OptSpaced("Truncated"); + + if (MaxHighPoint != 0) + { + s.Add_OptSpaced("MaxUnicode="); + s.Add_UInt32(MaxHighPoint); + } + } + + + bool IsOK(bool allowReduced = false) const + { + if (NonUtf || SingleSurrogate || ZeroChar) + return false; + if (MaxHighPoint >= 0x110000) + return false; + if (Truncated && !allowReduced) + return false; + return true; + } + + // it checks full buffer as specified in (size) and it doesn't stop on zero char + void Check_Buf(const char *src, size_t size) throw(); + + void Check_AString(const AString &s) throw() + { + Check_Buf(s.Ptr(), s.Len()); + } +}; + +/* +if (allowReduced == false) - all UTF-8 character sequences must be finished. +if (allowReduced == true) - it allows truncated last character-Utf8-sequence +*/ + +bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw(); +bool CheckUTF8_AString(const AString &s) throw(); + +#define UTF_FLAG__FROM_UTF8__SURROGATE_ERROR (1 << 0) +#define UTF_FLAG__FROM_UTF8__USE_ESCAPE (1 << 1) +#define UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT (1 << 2) + +/* +UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + + if (flag is NOT set) + { + it processes SINGLE-SURROGATE-8 as valid Unicode point. + it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16 + Note: some sequencies of two SINGLE-SURROGATE-8 points + will generate correct SURROGATE-16-PAIR, and + that SURROGATE-16-PAIR later will be converted to correct + UTF8-SURROGATE-21 point. So we don't restore original + STR-8 sequence in that case. + } + + if (flag is set) + { + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is defined) + it generates ESCAPE for SINGLE-SURROGATE-8, + if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is not defined) + it generates U+fffd for SINGLE-SURROGATE-8, + } + + +UTF_FLAG__FROM_UTF8__USE_ESCAPE + + if (flag is NOT set) + it generates (U+fffd) code for non-UTF-8 (invalid) characters + + if (flag is set) + { + It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters. + And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes. + } + +UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + + if (flag is NOT set) + { + it process ESCAPE-8 points as another Unicode points. + In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences, + so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW + } + + if (flag is set) + { + it generates ESCAPE-16-21 for ESCAPE-8 points + so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21. + } + + +Main USE CASES with UTF-8 <-> UTF-16 conversions: + + WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW + { + set UTF_FLAG__FROM_UTF8__USE_ESCAPE + Do NOT set UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + Do NOT set UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + + So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8. + } + + Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW + { + we want restore original UTF-8-RAW sequence later from that ESCAPE-16. + Set the flags: + UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + UTF_FLAG__FROM_UTF8__USE_ESCAPE + UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT + } + + MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW + { + we want to restore correct UTF-8 without any BMP processing: + Set the flags: + UTF_FLAG__FROM_UTF8__SURROGATE_ERROR + UTF_FLAG__FROM_UTF8__USE_ESCAPE + } + +*/ + +// zero char is not allowed in (src) buf +bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0); + +bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0); +bool ConvertUTF8ToUnicode(const AString &src, UString &dest); + +#define UTF_FLAG__TO_UTF8__SURROGATE_ERROR (1 << 8) +#define UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE (1 << 9) +// #define UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE (1 << 10) + +/* +UTF_FLAG__TO_UTF8__SURROGATE_ERROR + + if (flag is NOT set) + { + we extract SINGLE-SURROGATE as normal UTF-8 + + In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in . + + In Linux : + use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE, + if (UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) is used. + use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux) + will generate SINGLE-SURROGATE-UTF-8 here. + } + + if (flag is set) + { + we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE + it can be used for compatibility mode with WIN32 UTF function + or if we want UTF-8 stream without any errors + } + + +UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE + + if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16 + if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16 + + in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive): + if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane. + if (we don't use High-Escape-Plane), we must use UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE. + + +UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE + // that flag affects the code only if (wchar_t is 32-bit) + // that mode with high-escape can be disabled now in UTFConvert.cpp + if (flag is NOT set) + it doesn't extract raw 8-bit symbol from High-Escape-Plane + if (flag is set) + it extracts raw 8-bit symbol from High-Escape-Plane + +Main use cases: + +WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW + { + Do NOT set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE. + Do NOT set UTF_FLAG__TO_UTF8__SURROGATE_ERROR. + So we restore original UTF-16-RAW. + } + +Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes + set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive + set UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE for intermediate UTF-16. + Note: high esacape mode can be ignored now in UTFConvert.cpp + +macOS: + the system doesn't support incorrect UTF-8 in file names. + set UTF_FLAG__TO_UTF8__SURROGATE_ERROR +*/ + +extern unsigned g_Unicode_To_UTF8_Flags; + +void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0); +void ConvertUnicodeToUTF8(const UString &src, AString &dest); + +void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest); + +/* +#ifndef _WIN32 +void Convert_UTF16_To_UTF32(const UString &src, UString &dest); +void Convert_UTF32_To_UTF16(const UString &src, UString &dest); +bool UTF32_IsThere_BigPoint(const UString &src); +bool Unicode_IsThere_BmpEscape(const UString &src); +#endif + +bool Unicode_IsThere_Utf16SurrogateError(const UString &src); +*/ + +#ifdef _WCHART_IS_16BIT +#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s) +#else +void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s); +#endif + +/* +// #include "../../C/CpuArch.h" + +// ---------- Utf16 Little endian functions ---------- + +// We store 16-bit surrogates even in 32-bit WCHARs in Linux. +// So now we don't use the following code: + +#if WCHAR_MAX > 0xffff + +// void *p : pointer to src bytes stream +// size_t len : num Utf16 characters : it can include or not include NULL character + +inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len) +{ + #if WCHAR_MAX > 0xffff + size_t num_wchars = 0; + for (size_t i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = GetUi16(p); + if (c2 >= 0xdc00 && c2 < 0xe000) + { + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + p = (const void *)((const Byte *)p + 2); + i++; + } + } + num_wchars++; + } + return num_wchars; + #else + UNUSED_VAR(p) + return len; + #endif +} + +// #include + +inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest) +{ + for (size_t i = 0; i < len; i++) + { + wchar_t c = GetUi16(p); + p = (const void *)((const Byte *)p + 2); + + #if WCHAR_PATH_SEPARATOR != L'/' + if (c == L'/') + c = WCHAR_PATH_SEPARATOR; + #endif + + #if WCHAR_MAX > 0xffff + + if (c >= 0xd800 && c < 0xdc00 && i + 1 != len) + { + wchar_t c2 = GetUi16(p); + if (c2 >= 0xdc00 && c2 < 0xe000) + { + // printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2); + c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff); + p = (const void *)((const Byte *)p + 2); + i++; + // printf("%4x\n", (int)c); + } + } + + #endif + + *dest++ = c; + } + return dest; +} + + +inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p) +{ + size_t num = 0; + for (;;) + { + wchar_t c = *p++; + if (c == 0) + return num; + num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1); + } + return num; +} + +inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest) +{ + for (;;) + { + wchar_t c = *p++; + if (c == 0) + return dest; + if (c >= 0x10000 && c < 0x110000) + { + SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF))); + SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF))); + dest += 4; + } + else + { + SetUi16(dest, c); + dest += 2; + } + } +} + +#endif +*/ + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.cpp b/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.cpp new file mode 100644 index 0000000..e204012 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.cpp @@ -0,0 +1,708 @@ +// Common/Wildcard.cpp + +#include "StdAfx.h" + +#include "Wildcard.h" + +extern +bool g_CaseSensitive; +bool g_CaseSensitive = + #ifdef _WIN32 + false; + #elif defined (__APPLE__) + #ifdef TARGET_OS_IPHONE + true; + #else + false; + #endif + #else + true; + #endif + + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) +{ + if (g_CaseSensitive) + return IsString1PrefixedByString2(s1, s2); + return IsString1PrefixedByString2_NoCase(s1, s2); +} + +// #include + +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW +{ + /* + printf("\nCompareFileNames"); + printf("\n S1: %ls", s1); + printf("\n S2: %ls", s2); + printf("\n"); + */ + if (g_CaseSensitive) + return MyStringCompare(s1, s2); + return MyStringCompareNoCase(s1, s2); +} + +#ifndef USE_UNICODE_FSTRING +int CompareFileNames(const char *s1, const char *s2) +{ + const UString u1 = fs2us(s1); + const UString u2 = fs2us(s2); + if (g_CaseSensitive) + return MyStringCompare(u1, u2); + return MyStringCompareNoCase(u1, u2); +} +#endif + +// ----------------------------------------- +// this function compares name with mask +// ? - any char +// * - any char or empty + +static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) +{ + for (;;) + { + wchar_t m = *mask; + wchar_t c = *name; + if (m == 0) + return (c == 0); + if (m == '*') + { + if (EnhancedMaskTest(mask + 1, name)) + return true; + if (c == 0) + return false; + } + else + { + if (m == '?') + { + if (c == 0) + return false; + } + else if (m != c) + if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) + return false; + mask++; + } + name++; + } +} + +// -------------------------------------------------- +// Splits path to strings + +void SplitPathToParts(const UString &path, UStringVector &pathParts) +{ + pathParts.Clear(); + unsigned len = path.Len(); + if (len == 0) + return; + UString name; + unsigned prev = 0; + for (unsigned i = 0; i < len; i++) + if (IsPathSepar(path[i])) + { + name.SetFrom(path.Ptr(prev), i - prev); + pathParts.Add(name); + prev = i + 1; + } + name.SetFrom(path.Ptr(prev), len - prev); + pathParts.Add(name); +} + +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) + break; + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + if (p != start) + { + if (IsPathSepar(*(p - 1))) + p--; + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) + break; + } + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +/* +UString ExtractDirPrefixFromPath(const UString &path) +{ + return path.Left(path.ReverseFind_PathSepar() + 1)); +} +*/ + +UString ExtractFileNameFromPath(const UString &path) +{ + return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1))); +} + + +bool DoesWildcardMatchName(const UString &mask, const UString &name) +{ + return EnhancedMaskTest(mask, name); +} + +bool DoesNameContainWildcard(const UString &path) +{ + for (unsigned i = 0; i < path.Len(); i++) + { + wchar_t c = path[i]; + if (c == '*' || c == '?') + return true; + } + return false; +} + + +// ----------------------------------------------------------' +// NWildcard + +namespace NWildcard { + +/* + +M = MaskParts.Size(); +N = TestNameParts.Size(); + + File Dir +ForFile rec M<=N [N-M, N) - +!ForDir nonrec M=N [0, M) - + +ForDir rec M &items = include ? IncludeItems : ExcludeItems; + items.Add(item); +} + +void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) +{ + if (item.PathParts.Size() <= 1) + { + if (item.PathParts.Size() != 0 && item.WildcardMatching) + { + if (!DoesNameContainWildcard(item.PathParts.Front())) + item.WildcardMatching = false; + } + AddItemSimple(include, item); + return; + } + + const UString &front = item.PathParts.Front(); + + // WIN32 doesn't support wildcards in file names + if (item.WildcardMatching + && ignoreWildcardIndex != 0 + && DoesNameContainWildcard(front)) + { + AddItemSimple(include, item); + return; + } + CCensorNode &subNode = Find_SubNode_Or_Add_New(front); + item.PathParts.Delete(0); + subNode.AddItem(include, item, ignoreWildcardIndex - 1); +} + +void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching) +{ + CItem item; + SplitPathToParts(path, item.PathParts); + item.Recursive = recursive; + item.ForFile = forFile; + item.ForDir = forDir; + item.WildcardMatching = wildcardMatching; + AddItem(include, item); +} + +bool CCensorNode::NeedCheckSubDirs() const +{ + FOR_VECTOR (i, IncludeItems) + { + const CItem &item = IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() > 1) + return true; + } + return false; +} + +bool CCensorNode::AreThereIncludeItems() const +{ + if (IncludeItems.Size() > 0) + return true; + FOR_VECTOR (i, SubNodes) + if (SubNodes[i].AreThereIncludeItems()) + return true; + return false; +} + +bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const +{ + const CObjectVector &items = include ? IncludeItems : ExcludeItems; + FOR_VECTOR (i, items) + if (items[i].CheckPath(pathParts, isFile)) + return true; + return false; +} + +bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const +{ + if (CheckPathCurrent(false, pathParts, isFile)) + { + include = false; + return true; + } + if (pathParts.Size() > 1) + { + int index = FindSubNode(pathParts.Front()); + if (index >= 0) + { + UStringVector pathParts2 = pathParts; + pathParts2.Delete(0); + if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include)) + return true; + } + } + bool finded = CheckPathCurrent(true, pathParts, isFile); + include = finded; // if (!finded), then (true) is allowed also + return finded; +} + +/* +bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + if (CheckPathVect(pathParts, isFile, include)) + { + if (!include || !isAltStream) + return true; + } + if (isAltStream && !pathParts.IsEmpty()) + { + UString &back = pathParts.Back(); + int pos = back.Find(L':'); + if (pos > 0) + { + back.DeleteFrom(pos); + return CheckPathVect(pathParts, isFile, include); + } + } + return false; +} + +bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const +{ + bool include; + if (CheckPath2(isAltStream, path, isFile, include)) + return include; + return false; +} +*/ + +bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const +{ + if (CheckPathCurrent(include, pathParts, isFile)) + return true; + if (!Parent) + return false; + pathParts.Insert(0, Name); + return Parent->CheckPathToRoot_Change(include, pathParts, isFile); +} + +bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const +{ + if (CheckPathCurrent(include, pathParts, isFile)) + return true; + if (!Parent) + return false; + UStringVector pathParts2; + pathParts2.Add(Name); + pathParts2 += pathParts; + return Parent->CheckPathToRoot_Change(include, pathParts2, isFile); +} + +/* +bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + return CheckPathToRoot(include, pathParts, isFile); +} +*/ + +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + if (path.IsEmpty()) + return; + bool forFile = true; + bool forFolder = true; + UString path2 (path); + if (IsPathSepar(path.Back())) + { + path2.DeleteBack(); + forFile = false; + } + AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching); +} + +void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) +{ + ExcludeItems += fromNodes.ExcludeItems; + FOR_VECTOR (i, fromNodes.SubNodes) + { + const CCensorNode &node = fromNodes.SubNodes[i]; + Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node); + } +} + +int CCensor::FindPairForPrefix(const UString &prefix) const +{ + FOR_VECTOR (i, Pairs) + if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) + return (int)i; + return -1; +} + +#ifdef _WIN32 + +bool IsDriveColonName(const wchar_t *s) +{ + wchar_t c = s[0]; + return c != 0 + && s[1] == ':' + && s[2] == 0 + && ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z')); +} + +unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + unsigned testIndex = 0; + if (pathParts[0].IsEmpty()) + { + if (pathParts.Size() < 4 + || !pathParts[1].IsEmpty() + || pathParts[2] != L"?") + return 0; + testIndex = 3; + } + if (NWildcard::IsDriveColonName(pathParts[testIndex])) + return testIndex + 1; + return 0; +} + +#endif + +static unsigned GetNumPrefixParts(const UStringVector &pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + #ifdef _WIN32 + + if (IsDriveColonName(pathParts[0])) + return 1; + if (!pathParts[0].IsEmpty()) + return 0; + + if (pathParts.Size() == 1) + return 1; + if (!pathParts[1].IsEmpty()) + return 1; + if (pathParts.Size() == 2) + return 2; + if (pathParts[2] == L".") + return 3; + + unsigned networkParts = 2; + if (pathParts[2] == L"?") + { + if (pathParts.Size() == 3) + return 3; + if (IsDriveColonName(pathParts[3])) + return 4; + if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC")) + return 3; + networkParts = 4; + } + + networkParts += + // 2; // server/share + 1; // server + if (pathParts.Size() <= networkParts) + return pathParts.Size(); + return networkParts; + + #else + + return pathParts[0].IsEmpty() ? 1 : 0; + + #endif +} + +void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + if (path.IsEmpty()) + throw "Empty file path"; + + UStringVector pathParts; + SplitPathToParts(path, pathParts); + + bool forFile = true; + if (pathParts.Back().IsEmpty()) + { + forFile = false; + pathParts.DeleteBack(); + } + + UString prefix; + + int ignoreWildcardIndex = -1; + + // #ifdef _WIN32 + // we ignore "?" wildcard in "\\?\" prefix. + if (pathParts.Size() >= 3 + && pathParts[0].IsEmpty() + && pathParts[1].IsEmpty() + && pathParts[2] == L"?") + ignoreWildcardIndex = 2; + // #endif + + if (pathMode != k_AbsPath) + { + ignoreWildcardIndex = -1; + + const unsigned numPrefixParts = GetNumPrefixParts(pathParts); + unsigned numSkipParts = numPrefixParts; + + if (pathMode != k_FullPath) + { + if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts) + numSkipParts = pathParts.Size() - 1; + } + { + int dotsIndex = -1; + for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + dotsIndex = (int)i; + } + + if (dotsIndex >= 0) + { + if (dotsIndex == (int)pathParts.Size() - 1) + numSkipParts = pathParts.Size(); + else + numSkipParts = pathParts.Size() - 1; + } + } + + for (unsigned i = 0; i < numSkipParts; i++) + { + { + const UString &front = pathParts.Front(); + // WIN32 doesn't support wildcards in file names + if (wildcardMatching) + if (i >= numPrefixParts && DoesNameContainWildcard(front)) + break; + prefix += front; + prefix.Add_PathSepar(); + } + pathParts.Delete(0); + } + } + + int index = FindPairForPrefix(prefix); + if (index < 0) + { + index = (int)Pairs.Size(); + Pairs.AddNew().Prefix = prefix; + } + + if (pathMode != k_AbsPath) + { + if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty())) + { + // we create universal item, if we skip all parts as prefix (like \ or L:\ ) + pathParts.Clear(); + pathParts.Add(UString("*")); + forFile = true; + wildcardMatching = true; + recursive = false; + } + } + + CItem item; + item.PathParts = pathParts; + item.ForDir = true; + item.ForFile = forFile; + item.Recursive = recursive; + item.WildcardMatching = wildcardMatching; + Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex); +} + +/* +bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const +{ + bool finded = false; + FOR_VECTOR (i, Pairs) + { + bool include; + if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} +*/ + +void CCensor::ExtendExclude() +{ + unsigned i; + for (i = 0; i < Pairs.Size(); i++) + if (Pairs[i].Prefix.IsEmpty()) + break; + if (i == Pairs.Size()) + return; + unsigned index = i; + for (i = 0; i < Pairs.Size(); i++) + if (index != i) + Pairs[i].Head.ExtendExclude(Pairs[index].Head); +} + +void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) +{ + FOR_VECTOR(i, CensorPaths) + { + const CCensorPath &cp = CensorPaths[i]; + AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching); + } + CensorPaths.Clear(); +} + +void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + CCensorPath &cp = CensorPaths.AddNew(); + cp.Path = path; + cp.Include = include; + cp.Recursive = recursive; + cp.WildcardMatching = wildcardMatching; +} + +} diff --git a/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.h b/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.h new file mode 100644 index 0000000..32b1521 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/Wildcard.h @@ -0,0 +1,177 @@ +// Common/Wildcard.h + +#ifndef __COMMON_WILDCARD_H +#define __COMMON_WILDCARD_H + +#include "MyString.h" + +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW; +#ifndef USE_UNICODE_FSTRING + int CompareFileNames(const char *s1, const char *s2); +#endif + +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2); + +void SplitPathToParts(const UString &path, UStringVector &pathParts); +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name); +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path) + +UString ExtractDirPrefixFromPath(const UString &path); +UString ExtractFileNameFromPath(const UString &path); + +bool DoesNameContainWildcard(const UString &path); +bool DoesWildcardMatchName(const UString &mask, const UString &name); + +namespace NWildcard { + +#ifdef _WIN32 +// returns true, if name is like "a:", "c:", ... +bool IsDriveColonName(const wchar_t *s); +unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts); +#endif + +struct CItem +{ + UStringVector PathParts; + bool Recursive; + bool ForFile; + bool ForDir; + bool WildcardMatching; + + #ifdef _WIN32 + bool IsDriveItem() const + { + return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]); + } + #endif + + // CItem(): WildcardMatching(true) {} + + bool AreAllAllowed() const; + bool CheckPath(const UStringVector &pathParts, bool isFile) const; +}; + + +class CCensorNode MY_UNCOPYABLE +{ + CCensorNode *Parent; + + bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; + void AddItemSimple(bool include, CItem &item); +public: + CCensorNode(): Parent(NULL) { }; + CCensorNode(const UString &name, CCensorNode *parent): Parent(parent), Name(name) { }; + + UString Name; // WIN32 doesn't support wildcards in file names + CObjectVector SubNodes; + CObjectVector IncludeItems; + CObjectVector ExcludeItems; + + CCensorNode &Find_SubNode_Or_Add_New(const UString &name) + { + int i = FindSubNode(name); + if (i >= 0) + return SubNodes[(unsigned)i]; + // return SubNodes.Add(CCensorNode(name, this)); + CCensorNode &node = SubNodes.AddNew(); + node.Parent = this; + node.Name = name; + return node; + } + + bool AreAllAllowed() const; + + int FindSubNode(const UString &path) const; + + void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1); + void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching); + void AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching); + + // NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs + bool NeedCheckSubDirs() const; + bool AreThereIncludeItems() const; + + /* + CheckPathVect() doesn't check path in Parent CCensorNode + so use CheckPathVect() for root CCensorNode + OUT: + returns (true) && (include = false) - file in exlude list + returns (true) && (include = true) - file in include list and is not in exlude list + returns (false) - file is not in (include/exlude) list + */ + bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const; + + // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const; + // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; + + // CheckPathToRoot_Change() changes pathParts !!! + bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const; + bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const; + + // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; + void ExtendExclude(const CCensorNode &fromNodes); +}; + + +struct CPair MY_UNCOPYABLE +{ + UString Prefix; + CCensorNode Head; + + // CPair(const UString &prefix): Prefix(prefix) { }; +}; + + +enum ECensorPathMode +{ + k_RelatPath, // absolute prefix as Prefix, remain path in Tree + k_FullPath, // drive prefix as Prefix, remain path in Tree + k_AbsPath // full path in Tree +}; + + +struct CCensorPath +{ + UString Path; + bool Include; + bool Recursive; + bool WildcardMatching; + + CCensorPath(): + Include(true), + Recursive(false), + WildcardMatching(true) + {} +}; + + +class CCensor MY_UNCOPYABLE +{ + int FindPairForPrefix(const UString &prefix) const; +public: + CObjectVector Pairs; + + CObjectVector CensorPaths; + + bool AllAreRelative() const + { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } + + void AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching); + // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const; + void ExtendExclude(); + + void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode); + void AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching); + void AddPreItem(const UString &path) + { + AddPreItem(true, path, false, false); + } + void AddPreItem_Wildcard() + { + AddPreItem(true, UString("*"), false, true); + } +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Init.cpp b/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Init.cpp new file mode 100644 index 0000000..5cb8e67 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Init.cpp @@ -0,0 +1,7 @@ +// XzCrc64Init.cpp + +#include "StdAfx.h" + +#include "../../C/XzCrc64.h" + +static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit; diff --git a/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Reg.cpp b/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Reg.cpp new file mode 100644 index 0000000..33b5249 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Common/XzCrc64Reg.cpp @@ -0,0 +1,42 @@ +// XzCrc64Reg.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" +#include "../../C/XzCrc64.h" + +#include "../Common/MyCom.h" + +#include "../7zip/Common/RegisterCodec.h" + +class CXzCrc64Hasher: + public IHasher, + public CMyUnknownImp +{ + UInt64 _crc; + Byte mtDummy[1 << 7]; + +public: + CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {} + + MY_UNKNOWN_IMP1(IHasher) + INTERFACE_IHasher(;) +}; + +STDMETHODIMP_(void) CXzCrc64Hasher::Init() throw() +{ + _crc = CRC64_INIT_VAL; +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) throw() +{ + _crc = Crc64Update(_crc, data, size); +} + +STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) throw() +{ + UInt64 val = CRC64_GET_DIGEST(_crc); + SetUi64(digest, val); +} + +REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8) diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/COM.h b/3rdparty/lzma-21.03beta/CPP/Windows/COM.h new file mode 100644 index 0000000..cee7f70 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/COM.h @@ -0,0 +1,70 @@ +// Windows/COM.h + +#ifndef __WINDOWS_COM_H +#define __WINDOWS_COM_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NCOM { + +#ifdef _WIN32 + +class CComInitializer +{ +public: + CComInitializer() + { + #ifdef UNDER_CE + CoInitializeEx(NULL, COINIT_MULTITHREADED); + #else + // it's single thread. Do we need multithread? + CoInitialize(NULL); + #endif + }; + ~CComInitializer() { CoUninitialize(); } +}; + +class CStgMedium +{ + STGMEDIUM _object; +public: + bool _mustBeReleased; + CStgMedium(): _mustBeReleased(false) {} + ~CStgMedium() { Free(); } + void Free() + { + if (_mustBeReleased) + ReleaseStgMedium(&_object); + _mustBeReleased = false; + } + const STGMEDIUM* operator->() const { return &_object;} + STGMEDIUM* operator->() { return &_object;} + STGMEDIUM* operator&() { return &_object; } +}; + +#endif + +/* +////////////////////////////////// +// GUID <--> String Conversions +UString GUIDToStringW(REFGUID guid); +AString GUIDToStringA(REFGUID guid); +#ifdef UNICODE + #define GUIDToString GUIDToStringW +#else + #define GUIDToString GUIDToStringA +#endif + +HRESULT StringToGUIDW(const wchar_t *string, GUID &classID); +HRESULT StringToGUIDA(const char *string, GUID &classID); +#ifdef UNICODE + #define StringToGUID StringToGUIDW +#else + #define StringToGUID StringToGUIDA +#endif +*/ + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.cpp new file mode 100644 index 0000000..eaaecad --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.cpp @@ -0,0 +1,208 @@ +// Windows/CommonDialog.cpp + +#include "StdAfx.h" + +#include "../Common/MyWindows.h" + +#ifdef UNDER_CE +#include +#endif + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "CommonDialog.h" +#include "Defs.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE + +class CDoubleZeroStringListA +{ + LPTSTR Buf; + unsigned Size; +public: + CDoubleZeroStringListA(LPSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCSTR s) throw(); + void Finish() { *Buf = 0; } +}; + +bool CDoubleZeroStringListA::Add(LPCSTR s) throw() +{ + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; +} + +#endif + +class CDoubleZeroStringListW +{ + LPWSTR Buf; + unsigned Size; +public: + CDoubleZeroStringListW(LPWSTR buf, unsigned size): Buf(buf), Size(size) {} + bool Add(LPCWSTR s) throw(); + void Finish() { *Buf = 0; } +}; + +bool CDoubleZeroStringListW::Add(LPCWSTR s) throw() +{ + unsigned len = MyStringLen(s) + 1; + if (len >= Size) + return false; + MyStringCopy(Buf, s); + Buf += len; + Size -= len; + return true; +} + + +#ifdef UNDER_CE +#define MY__OFN_PROJECT 0x00400000 +#define MY__OFN_SHOW_ALL 0x01000000 +#endif + +/* if (lpstrFilter == NULL && nFilterIndex == 0) + MSDN : "the system doesn't show any files", + but WinXP-64 shows all files. Why ??? */ + +/* +structures + OPENFILENAMEW + OPENFILENAMEA +contain additional members: +#if (_WIN32_WINNT >= 0x0500) + void *pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +#endif + +If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions +will not work at NT 4.0, if we use sizeof(OPENFILENAME*). +So we use size of old version of structure. */ + +#if defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500) +// || !defined(WINVER) + #ifndef _UNICODE + #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA) + #endif + #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW) +#else + + // MinGW doesn't support some required macros. So we define them here: + #ifndef CDSIZEOF_STRUCT + #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member)) + #endif + #ifndef _UNICODE + #ifndef OPENFILENAME_SIZE_VERSION_400A + #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName) + #endif + #endif + #ifndef OPENFILENAME_SIZE_VERSION_400W + #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName) + #endif + + #ifndef _UNICODE + #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A + #endif + #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W +#endif + +#ifndef _UNICODE +#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; } +#endif + +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, + LPCWSTR filePath, + LPCWSTR filterDescription, + LPCWSTR filter, + UString &resPath + #ifdef UNDER_CE + , bool openFolder + #endif + ) +{ + const unsigned kBufSize = MAX_PATH * 2; + const unsigned kFilterBufSize = MAX_PATH; + if (!filter) + filter = L"*.*"; + #ifndef _UNICODE + if (!g_IsNT) + { + CHAR buf[kBufSize]; + MyStringCopy(buf, (const char *)GetSystemString(filePath)); + // OPENFILENAME_NT4A + OPENFILENAMEA p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEA_size; + p.hwndOwner = hwnd; + CHAR filterBuf[kFilterBufSize]; + { + CDoubleZeroStringListA dz(filterBuf, kFilterBufSize); + dz.Add(GetSystemString(filterDescription ? filterDescription : filter)); + dz.Add(GetSystemString(filter)); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; + } + + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + CONV_U_To_A(p.lpstrInitialDir, initialDir, initialDirA); + CONV_U_To_A(p.lpstrTitle, title, titleA); + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; + + bool res = BOOLToBool(::GetOpenFileNameA(&p)); + resPath = GetUnicodeString(buf); + return res; + } + else + #endif + { + WCHAR buf[kBufSize]; + MyStringCopy(buf, filePath); + // OPENFILENAME_NT4W + OPENFILENAMEW p; + memset(&p, 0, sizeof(p)); + p.lStructSize = my_compatib_OPENFILENAMEW_size; + p.hwndOwner = hwnd; + + WCHAR filterBuf[kFilterBufSize]; + { + CDoubleZeroStringListW dz(filterBuf, kFilterBufSize); + dz.Add(filterDescription ? filterDescription : filter); + dz.Add(filter); + dz.Finish(); + p.lpstrFilter = filterBuf; + p.nFilterIndex = 1; + } + + p.lpstrFile = buf; + p.nMaxFile = kBufSize; + p.lpstrInitialDir = initialDir; + p.lpstrTitle = title; + p.Flags = OFN_EXPLORER | OFN_HIDEREADONLY + #ifdef UNDER_CE + | (openFolder ? (MY__OFN_PROJECT | MY__OFN_SHOW_ALL) : 0) + #endif + ; + + bool res = BOOLToBool(::GetOpenFileNameW(&p)); + resPath = buf; + return res; + } +} + +} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.h b/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.h new file mode 100644 index 0000000..aaf17ac --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/CommonDialog.h @@ -0,0 +1,23 @@ +// Windows/CommonDialog.h + +#ifndef __WINDOWS_COMMON_DIALOG_H +#define __WINDOWS_COMMON_DIALOG_H + +#include "../Common/MyString.h" + +namespace NWindows { + +bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, + LPCWSTR initialDir, // can be NULL, so dir prefix in filePath will be used + LPCWSTR filePath, // full path + LPCWSTR filterDescription, // like "All files (*.*)" + LPCWSTR filter, // like "*.exe" + UString &resPath + #ifdef UNDER_CE + , bool openFolder = false + #endif +); + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.cpp new file mode 100644 index 0000000..f6ed8d3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.cpp @@ -0,0 +1,66 @@ +// Windows/Control/ComboBox.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "ComboBox.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +LRESULT CComboBox::GetLBText(int index, CSysString &s) +{ + s.Empty(); + LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character + if (len == CB_ERR) + return len; + LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len)); + if (len2 == CB_ERR) + return len; + if (len > len2) + len = len2; + s.ReleaseBuf_CalcLen((unsigned)len); + return len; +} + +#ifndef _UNICODE +LRESULT CComboBox::AddString(LPCWSTR s) +{ + if (g_IsNT) + return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s); + return AddString(GetSystemString(s)); +} + +LRESULT CComboBox::GetLBText(int index, UString &s) +{ + s.Empty(); + if (g_IsNT) + { + LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); + if (len == CB_ERR) + return len; + LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len)); + if (len2 == CB_ERR) + return len; + if (len > len2) + len = len2; + s.ReleaseBuf_CalcLen((unsigned)len); + return len; + } + AString sa; + LRESULT len = GetLBText(index, sa); + if (len == CB_ERR) + return len; + s = GetUnicodeString(sa); + return s.Len(); +} +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.h new file mode 100644 index 0000000..f08b1f7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ComboBox.h @@ -0,0 +1,77 @@ +// Windows/Control/ComboBox.h + +#ifndef __WINDOWS_CONTROL_COMBOBOX_H +#define __WINDOWS_CONTROL_COMBOBOX_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +#define MY__int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i)) + +class CComboBox: public CWindow +{ +public: + void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); } + LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); } + #ifndef _UNICODE + LRESULT AddString(LPCWSTR s); + #endif + + /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ + LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY__int_TO_WPARAM(index), 0); } + + /* If no item is selected, it returns CB_ERR (-1) */ + int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); } + + /* If an error occurs, it is CB_ERR (-1) */ + int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); } + + LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY__int_TO_WPARAM(index), 0); } + LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY__int_TO_WPARAM(index), (LPARAM)s); } + LRESULT GetLBText(int index, CSysString &s); + #ifndef _UNICODE + LRESULT GetLBText(int index, UString &s); + #endif + + LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY__int_TO_WPARAM(index), lParam); } + LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY__int_TO_WPARAM(index), 0); } + + LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); } + + void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0); } +}; + +#ifndef UNDER_CE + +class CComboBoxEx: public CComboBox +{ +public: + bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); } + + /* Returns: + an INT value that represents the number of items remaining in the control. + If (index) is invalid, the message returns CB_ERR. */ + LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY__int_TO_WPARAM(index), 0); } + + LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); } + #ifndef _UNICODE + LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); } + #endif + + LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); } + DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, exStyle); } + HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); } + HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); } +}; + +#endif + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/CommandBar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/CommandBar.h new file mode 100644 index 0000000..a619744 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/CommandBar.h @@ -0,0 +1,52 @@ +// Windows/Control/CommandBar.h + +#ifndef __WINDOWS_CONTROL_COMMANDBAR_H +#define __WINDOWS_CONTROL_COMMANDBAR_H + +#ifdef UNDER_CE + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CCommandBar: public NWindows::CWindow +{ +public: + bool Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar) + { + _window = ::CommandBar_Create(hInst, hwndParent, idCmdBar); + return (_window != NULL); + } + + // Macros + // void Destroy() { CommandBar_Destroy(_window); } + // bool AddButtons(UINT numButtons, LPTBBUTTON buttons) { return BOOLToBool(SendMsg(TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)buttons)); } + bool InsertButton(int iButton, LPTBBUTTON button) { return BOOLToBool(SendMsg(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)button)); } + BOOL AddToolTips(UINT numToolTips, LPTSTR toolTips) { return BOOLToBool(SendMsg(TB_SETTOOLTIPS, (WPARAM)numToolTips, (LPARAM)toolTips)); } + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } + + bool AddAdornments(DWORD dwFlags) { return BOOLToBool(::CommandBar_AddAdornments(_window, dwFlags, 0)); } + int AddBitmap(HINSTANCE hInst, int idBitmap, int iNumImages, int iImageWidth, int iImageHeight) { return ::CommandBar_AddBitmap(_window, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight); } + bool DrawMenuBar(WORD iButton) { return BOOLToBool(::CommandBar_DrawMenuBar(_window, iButton)); } + HMENU GetMenu(WORD iButton) { return ::CommandBar_GetMenu(_window, iButton); } + int Height() { return CommandBar_Height(_window); } + HWND InsertComboBox(HINSTANCE hInst, int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton) { return ::CommandBar_InsertComboBox(_window, hInst, iWidth, dwStyle, idComboBox, iButton); } + bool InsertMenubar(HINSTANCE hInst, WORD idMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubar(_window, hInst, idMenu, iButton)); } + bool InsertMenubarEx(HINSTANCE hInst, LPTSTR pszMenu, WORD iButton) { return BOOLToBool(::CommandBar_InsertMenubarEx(_window, hInst, pszMenu, iButton)); } + bool Show(bool cmdShow) { return BOOLToBool(::CommandBar_Show(_window, BoolToBOOL(cmdShow))); } + + + // CE 4.0 + void AlignAdornments() { CommandBar_AlignAdornments(_window); } +}; + +}} + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.cpp new file mode 100644 index 0000000..6a9d7d9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.cpp @@ -0,0 +1,260 @@ +// Windows/Control/Dialog.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "Dialog.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(dialogHWND); + if (message == WM_INITDIALOG) + tempDialog.SetUserDataLongPtr(lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (dialog == NULL) + return FALSE; + if (message == WM_INITDIALOG) + dialog->Attach(dialogHWND); + + /* MSDN: The dialog box procedure should return + TRUE - if it processed the message + FALSE - if it did not process the message + If the dialog box procedure returns FALSE, + the dialog manager performs the default dialog operation in response to the message. + */ + + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } + catch(...) { return TRUE; } +} + +bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: return OnInit(); + case WM_COMMAND: return OnCommand(wParam, lParam); + case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam); + case WM_TIMER: return OnTimer(wParam, lParam); + case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_DESTROY: return OnDestroy(); + case WM_HELP: OnHelp(); return true; + /* + OnHelp( + #ifdef UNDER_CE + (void *) + #else + (LPHELPINFO) + #endif + lParam); + return true; + */ + default: return false; + } +} + +bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam) +{ + return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam); +} + +bool CDialog::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == BN_CLICKED) + return OnButtonClicked(itemID, (HWND)lParam); + return false; +} + +bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */) +{ + switch (buttonID) + { + case IDOK: OnOK(); break; + case IDCANCEL: OnCancel(); break; + case IDCLOSE: OnClose(); break; + case IDHELP: OnHelp(); break; + default: return false; + } + return true; +} + +static bool GetWorkAreaRect(RECT *rect) +{ + // use another function for multi-monitor. + return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0)); +} + +bool IsDialogSizeOK(int xSize, int ySize) +{ + // it returns for system font. Real font uses another values + LONG v = GetDialogBaseUnits(); + int x = LOWORD(v); + int y = HIWORD(v); + + RECT rect; + GetWorkAreaRect(&rect); + int wx = RECT_SIZE_X(rect); + int wy = RECT_SIZE_Y(rect); + return + xSize / 4 * x <= wx && + ySize / 8 * y <= wy; +} + +bool CDialog::GetMargins(int margin, int &x, int &y) +{ + x = margin; + y = margin; + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = margin; + rect.bottom = margin; + if (!MapRect(&rect)) + return false; + x = rect.right - rect.left; + y = rect.bottom - rect.top; + return true; +} + +int CDialog::Units_To_Pixels_X(int units) +{ + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = units; + rect.bottom = units; + if (!MapRect(&rect)) + return units * 3 / 2; + return rect.right - rect.left; +} + +bool CDialog::GetItemSizes(int id, int &x, int &y) +{ + RECT rect; + if (!::GetWindowRect(GetItem(id), &rect)) + return false; + x = RECT_SIZE_X(rect); + y = RECT_SIZE_Y(rect); + return true; +} + +void CDialog::GetClientRectOfItem(int id, RECT &rect) +{ + ::GetWindowRect(GetItem(id), &rect); + ScreenToClient(&rect); +} + +bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint) +{ + return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint))); +} + +void CDialog::NormalizeSize(bool fullNormalize) +{ + RECT workRect; + GetWorkAreaRect(&workRect); + int xSize = RECT_SIZE_X(workRect); + int ySize = RECT_SIZE_Y(workRect); + RECT rect; + GetWindowRect(&rect); + int xSize2 = RECT_SIZE_X(rect); + int ySize2 = RECT_SIZE_Y(rect); + bool needMove = (xSize2 > xSize || ySize2 > ySize); + if (xSize2 > xSize || (needMove && fullNormalize)) + { + rect.left = workRect.left; + rect.right = workRect.right; + xSize2 = xSize; + } + if (ySize2 > ySize || (needMove && fullNormalize)) + { + rect.top = workRect.top; + rect.bottom = workRect.bottom; + ySize2 = ySize; + } + if (needMove) + { + if (fullNormalize) + Show(SW_SHOWMAXIMIZED); + else + Move(rect.left, rect.top, xSize2, ySize2, true); + } +} + +void CDialog::NormalizePosition() +{ + RECT workRect, rect; + GetWorkAreaRect(&workRect); + GetWindowRect(&rect); + if (rect.bottom > workRect.bottom && rect.top > workRect.top) + Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true); +} + +bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow) +{ + HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + if (aHWND == 0) + return false; + Attach(aHWND); + return true; +} + +INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow) +{ + return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); +} + +#ifndef _UNICODE + +bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow) +{ + HWND aHWND; + if (g_IsNT) + aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + else + { + AString name; + LPCSTR templateNameA; + if (IS_INTRESOURCE(templateName)) + templateNameA = (LPCSTR)templateName; + else + { + name = GetSystemString(templateName); + templateNameA = name; + } + aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); + } + if (aHWND == 0) + return false; + Attach(aHWND); + return true; +} + +INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow) +{ + if (g_IsNT) + return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); + AString name; + LPCSTR templateNameA; + if (IS_INTRESOURCE(templateName)) + templateNameA = (LPCSTR)templateName; + else + { + name = GetSystemString(templateName); + templateNameA = name; + } + return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this); +} +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.h new file mode 100644 index 0000000..f804a9e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Dialog.h @@ -0,0 +1,190 @@ +// Windows/Control/Dialog.h + +#ifndef __WINDOWS_CONTROL_DIALOG_H +#define __WINDOWS_CONTROL_DIALOG_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CDialog: public CWindow +{ +public: + CDialog(HWND wnd = NULL): CWindow(wnd){}; + virtual ~CDialog() {}; + + HWND GetItem(int itemID) const + { return GetDlgItem(_window, itemID); } + + bool EnableItem(int itemID, bool enable) const + { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); } + + bool ShowItem(int itemID, int cmdShow) const + { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); } + + bool ShowItem_Bool(int itemID, bool show) const + { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); } + + bool HideItem(int itemID) const { return ShowItem(itemID, SW_HIDE); } + + bool SetItemText(int itemID, LPCTSTR s) + { return BOOLToBool(SetDlgItemText(_window, itemID, s)); } + + bool SetItemTextA(int itemID, LPCSTR s) + { return BOOLToBool(SetDlgItemTextA(_window, itemID, s)); } + + bool SetItemText_Empty(int itemID) + { return SetItemText(itemID, TEXT("")); } + + #ifndef _UNICODE + bool SetItemText(int itemID, LPCWSTR s) + { + CWindow window(GetItem(itemID)); + return window.SetText(s); + } + #endif + + UINT GetItemText(int itemID, LPTSTR string, int maxCount) + { return GetDlgItemText(_window, itemID, string, maxCount); } + #ifndef _UNICODE + /* + bool GetItemText(int itemID, LPWSTR string, int maxCount) + { + CWindow window(GetItem(itemID)); + return window.GetText(string, maxCount); + } + */ + #endif + + bool GetItemText(int itemID, UString &s) + { + CWindow window(GetItem(itemID)); + return window.GetText(s); + } + + bool SetItemInt(int itemID, UINT value, bool isSigned) + { return BOOLToBool(SetDlgItemInt(_window, itemID, value, BoolToBOOL(isSigned))); } + bool GetItemInt(int itemID, bool isSigned, UINT &value) + { + BOOL result; + value = GetDlgItemInt(_window, itemID, &result, BoolToBOOL(isSigned)); + return BOOLToBool(result); + } + + HWND GetNextGroupItem(HWND control, bool previous) + { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); } + HWND GetNextTabItem(HWND control, bool previous) + { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); } + + LRESULT SendMsg_NextDlgCtl(WPARAM wParam, LPARAM lParam) + { return SendMsg(WM_NEXTDLGCTL, wParam, lParam); } + LRESULT SendMsg_NextDlgCtl_HWND(HWND hwnd) { return SendMsg_NextDlgCtl((WPARAM)hwnd, TRUE); } + LRESULT SendMsg_NextDlgCtl_CtlId(int id) { return SendMsg_NextDlgCtl_HWND(GetItem(id)); } + LRESULT SendMsg_NextDlgCtl_Next() { return SendMsg_NextDlgCtl(0, FALSE); } + LRESULT SendMsg_NextDlgCtl_Prev() { return SendMsg_NextDlgCtl(1, FALSE); } + + bool MapRect(LPRECT rect) + { return BOOLToBool(MapDialogRect(_window, rect)); } + + bool IsMessage(LPMSG message) + { return BOOLToBool(IsDialogMessage(_window, message)); } + + LRESULT SendItemMessage(int itemID, UINT message, WPARAM wParam, LPARAM lParam) + { return SendDlgItemMessage(_window, itemID, message, wParam, lParam); } + + bool CheckButton(int buttonID, UINT checkState) + { return BOOLToBool(CheckDlgButton(_window, buttonID, checkState)); } + bool CheckButton(int buttonID, bool checkState) + { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); } + + UINT IsButtonChecked(int buttonID) const + { return IsDlgButtonChecked(_window, buttonID); } + bool IsButtonCheckedBool(int buttonID) const + { return (IsButtonChecked(buttonID) == BST_CHECKED); } + + bool CheckRadioButton(int firstButtonID, int lastButtonID, int checkButtonID) + { return BOOLToBool(::CheckRadioButton(_window, firstButtonID, lastButtonID, checkButtonID)); } + + virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnInit() { return true; } + virtual bool OnCommand(WPARAM wParam, LPARAM lParam); + virtual bool OnCommand(int code, int itemID, LPARAM lParam); + virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } + virtual bool OnDestroy() { return false; } + + /* + #ifdef UNDER_CE + virtual void OnHelp(void *) { OnHelp(); } + #else + virtual void OnHelp(LPHELPINFO) { OnHelp(); } + #endif + */ + virtual void OnHelp() {}; + + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK() {}; + virtual void OnCancel() {}; + virtual void OnClose() {} + virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; } + virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; } + + LONG_PTR SetMsgResult(LONG_PTR newLongPtr ) + { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } + LONG_PTR GetMsgResult() const + { return GetLongPtr(DWLP_MSGRESULT); } + + bool GetMargins(int margin, int &x, int &y); + int Units_To_Pixels_X(int units); + bool GetItemSizes(int id, int &x, int &y); + void GetClientRectOfItem(int id, RECT &rect); + bool MoveItem(int id, int x, int y, int width, int height, bool repaint = true); + + void NormalizeSize(bool fullNormalize = false); + void NormalizePosition(); +}; + +class CModelessDialog: public CDialog +{ +public: + bool Create(LPCTSTR templateName, HWND parentWindow); + bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } + #ifndef _UNICODE + bool Create(LPCWSTR templateName, HWND parentWindow); + #endif + virtual void OnOK() { Destroy(); } + virtual void OnCancel() { Destroy(); } + virtual void OnClose() { Destroy(); } +}; + +class CModalDialog: public CDialog +{ +public: + INT_PTR Create(LPCTSTR templateName, HWND parentWindow); + INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); } + #ifndef _UNICODE + INT_PTR Create(LPCWSTR templateName, HWND parentWindow); + #endif + + bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); } + virtual void OnOK() { End(IDOK); } + virtual void OnCancel() { End(IDCANCEL); } + virtual void OnClose() { End(IDCLOSE); } +}; + +class CDialogChildControl: public NWindows::CWindow +{ + int m_ID; +public: + void Init(const NWindows::NControl::CDialog &parentDialog, int id) + { + m_ID = id; + Attach(parentDialog.GetItem(id)); + } +}; + +bool IsDialogSizeOK(int xSize, int ySize); + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Edit.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Edit.h new file mode 100644 index 0000000..51a22c5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Edit.h @@ -0,0 +1,19 @@ +// Windows/Control/Edit.h + +#ifndef __WINDOWS_CONTROL_EDIT_H +#define __WINDOWS_CONTROL_EDIT_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CEdit: public CWindow +{ +public: + void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.cpp new file mode 100644 index 0000000..3e22b95 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.cpp @@ -0,0 +1,10 @@ +// Windows/Control/ImageList.cpp + +#include "StdAfx.h" + +#include "ImageList.h" + +namespace NWindows { +namespace NControl { + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.h new file mode 100644 index 0000000..19feb11 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ImageList.h @@ -0,0 +1,87 @@ +// Windows/Control/ImageList.h + +#ifndef __WINDOWS_CONTROL_IMAGE_LIST_H +#define __WINDOWS_CONTROL_IMAGE_LIST_H + +#include + +#include "../Defs.h" + +namespace NWindows { +namespace NControl { + +class CImageList +{ + HIMAGELIST m_Object; +public: + operator HIMAGELIST() const {return m_Object; } + CImageList(): m_Object(NULL) {} + bool Attach(HIMAGELIST imageList) + { + if (imageList == NULL) + return false; + m_Object = imageList; + return true; + } + + HIMAGELIST Detach() + { + HIMAGELIST imageList = m_Object; + m_Object = NULL; + return imageList; + } + + bool Create(int width, int height, UINT flags, int initialNumber, int grow) + { + HIMAGELIST a = ImageList_Create(width, height, flags, + initialNumber, grow); + if (a == NULL) + return false; + return Attach(a); + } + + bool Destroy() // DeleteImageList() in MFC + { + if (m_Object == NULL) + return false; + return BOOLToBool(ImageList_Destroy(Detach())); + } + + ~CImageList() + { Destroy(); } + + int GetImageCount() const + { return ImageList_GetImageCount(m_Object); } + + bool GetImageInfo(int index, IMAGEINFO* imageInfo) const + { return BOOLToBool(ImageList_GetImageInfo(m_Object, index, imageInfo)); } + + int Add(HBITMAP hbmImage, HBITMAP hbmMask = 0) + { return ImageList_Add(m_Object, hbmImage, hbmMask); } + int AddMasked(HBITMAP hbmImage, COLORREF mask) + { return ImageList_AddMasked(m_Object, hbmImage, mask); } + int AddIcon(HICON icon) + { return ImageList_AddIcon(m_Object, icon); } + int Replace(int index, HICON icon) + { return ImageList_ReplaceIcon(m_Object, index, icon); } + + // If index is -1, the function removes all images. + bool Remove(int index) + { return BOOLToBool(ImageList_Remove(m_Object, index)); } + bool RemoveAll() + { return BOOLToBool(ImageList_RemoveAll(m_Object)); } + + HICON ExtractIcon(int index) + { return ImageList_ExtractIcon(NULL, m_Object, index); } + HICON GetIcon(int index, UINT flags) + { return ImageList_GetIcon(m_Object, index, flags); } + + bool GetIconSize(int &width, int &height) const + { return BOOLToBool(ImageList_GetIconSize(m_Object, &width, &height)); } + bool SetIconSize(int width, int height) + { return BOOLToBool(ImageList_SetIconSize(m_Object, width, height)); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.cpp new file mode 100644 index 0000000..16cfd39 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.cpp @@ -0,0 +1,155 @@ +// Windows/Control/ListView.cpp + +#include "StdAfx.h" + +#include "ListView.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +bool CListView::CreateEx(DWORD exStyle, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(""), style, x, y, width, + height, parentWindow, idOrHMenu, instance, createParam); +} + +bool CListView::GetItemParam(int index, LPARAM ¶m) const +{ + LVITEM item; + item.iItem = index; + item.iSubItem = 0; + item.mask = LVIF_PARAM; + bool aResult = GetItem(&item); + param = item.lParam; + return aResult; +} + +int CListView::InsertColumn(int columnIndex, LPCTSTR text, int width) +{ + LVCOLUMN ci; + ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + ci.pszText = (LPTSTR)(void *)text; + ci.iSubItem = columnIndex; + ci.cx = width; + return InsertColumn(columnIndex, &ci); +} + +int CListView::InsertItem(int index, LPCTSTR text) +{ + LVITEM item; + item.mask = LVIF_TEXT | LVIF_PARAM; + item.iItem = index; + item.lParam = index; + item.pszText = (LPTSTR)(void *)text; + item.iSubItem = 0; + return InsertItem(&item); +} + +int CListView::SetSubItem(int index, int subIndex, LPCTSTR text) +{ + LVITEM item; + item.mask = LVIF_TEXT; + item.iItem = index; + item.pszText = (LPTSTR)(void *)text; + item.iSubItem = subIndex; + return SetItem(&item); +} + +#ifndef _UNICODE + +int CListView::InsertColumn(int columnIndex, LPCWSTR text, int width) +{ + LVCOLUMNW ci; + ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + ci.pszText = (LPWSTR)(void *)text; + ci.iSubItem = columnIndex; + ci.cx = width; + return InsertColumn(columnIndex, &ci); +} + +int CListView::InsertItem(int index, LPCWSTR text) +{ + LVITEMW item; + item.mask = LVIF_TEXT | LVIF_PARAM; + item.iItem = index; + item.lParam = index; + item.pszText = (LPWSTR)(void *)text; + item.iSubItem = 0; + return InsertItem(&item); +} + +int CListView::SetSubItem(int index, int subIndex, LPCWSTR text) +{ + LVITEMW item; + item.mask = LVIF_TEXT; + item.iItem = index; + item.pszText = (LPWSTR)(void *)text; + item.iSubItem = subIndex; + return SetItem(&item); +} + +#endif + +static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow window(hwnd); + CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr()); + if (w == NULL) + return 0; + return w->OnMessage(message, wParam, lParam); +} + +LRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + #ifndef _UNICODE + if (g_IsNT) + return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam); + else + #endif + return CallWindowProc(_origWindowProc, *this, message, wParam, lParam); +} + +void CListView2::SetWindowProc() +{ + SetUserDataLongPtr((LONG_PTR)this); + #ifndef _UNICODE + if (g_IsNT) + _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); + else + #endif + _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc); +} + +/* +LRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT res = CListView2::OnMessage(message, wParam, lParam); + if (message == WM_GETDLGCODE) + { + // when user presses RETURN, windows sends default (first) button command to parent dialog. + // we disable this: + MSG *msg = (MSG *)lParam; + WPARAM key = wParam; + bool change = false; + if (msg) + { + if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) + change = true; + } + else if (wParam == VK_RETURN) + change = true; + if (change) + res |= DLGC_WANTALLKEYS; + } + return res; +} +*/ + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.h new file mode 100644 index 0000000..a13b104 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ListView.h @@ -0,0 +1,147 @@ +// Windows/Control/ListView.h + +#ifndef __WINDOWS_CONTROL_LISTVIEW_H +#define __WINDOWS_CONTROL_LISTVIEW_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CListView: public NWindows::CWindow +{ +public: + bool CreateEx(DWORD exStyle, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + + void SetUnicodeFormat() + { + #ifndef UNDER_CE + ListView_SetUnicodeFormat(_window, TRUE); + #endif + } + + bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); } + bool DeleteColumn(int columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); } + + int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); } + int InsertColumn(int columnIndex, LPCTSTR text, int width); + bool SetColumnOrderArray(int count, const int *columns) + { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); } + + /* + int GetNumColumns() + { + HWND header = ListView_GetHeader(_window); + if (!header) + return -1; + return Header_GetItemCount(header); + } + */ + + int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); } + int InsertItem(int index, LPCTSTR text); + bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); } + int SetSubItem(int index, int subIndex, LPCTSTR text); + + #ifndef _UNICODE + + int InsertColumn(int columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); } + int InsertColumn(int columnIndex, LPCWSTR text, int width); + int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); } + int InsertItem(int index, LPCWSTR text); + bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); } + int SetSubItem(int index, int subIndex, LPCWSTR text); + + #endif + + bool DeleteItem(int itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); } + + UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); } + int GetItemCount() const { return ListView_GetItemCount(_window); } + + INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); } + + void SetItemCount(int numItems) { ListView_SetItemCount(_window, numItems); } + void SetItemCountEx(int numItems, DWORD flags) { ListView_SetItemCountEx(_window, numItems, flags); } + + int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); } + int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); } + int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); } + + bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); } + bool GetItemParam(int itemIndex, LPARAM ¶m) const; + void GetItemText(int itemIndex, int subItemIndex, LPTSTR text, int textSizeMax) const + { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax); } + bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam) + { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); } + + void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask); } + void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); } + void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); } + void SelectAll() { SetItemState_Selected(-1); } + void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); } + UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); } + bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; } + + bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const + { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); } + + HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType) + { return ListView_SetImageList(_window, imageList, imageListType); } + + // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3) + DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); } + void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); } + void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); } + + void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)); } + bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); } + + bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); } + + bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); } + + HWND GetEditControl() { return ListView_GetEditControl(_window) ; } + HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; } + + bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); } + bool RedrawAllItems() + { + if (GetItemCount() > 0) + return RedrawItems(0, GetItemCount() - 1); + return true; + } + bool RedrawItem(int index) { return RedrawItems(index, index); } + + int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); } + COLORREF GetBkColor() { return ListView_GetBkColor(_window); } + bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); } + bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); } +}; + +class CListView2: public CListView +{ + WNDPROC _origWindowProc; +public: + void SetWindowProc(); + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; + +/* +class CListView3: public CListView2 +{ +public: + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); +}; +*/ + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ProgressBar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ProgressBar.h new file mode 100644 index 0000000..0374306 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ProgressBar.h @@ -0,0 +1,35 @@ +// Windows/Control/ProgressBar.h + +#ifndef __WINDOWS_CONTROL_PROGRESSBAR_H +#define __WINDOWS_CONTROL_PROGRESSBAR_H + +#include "../../Common/MyWindows.h" + +#include + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CProgressBar: public CWindow +{ +public: + LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, pos, 0); } + LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); } + UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); } + LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); } + DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, minValue, maxValue); } + int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); } + LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); } + INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); } + + #ifndef UNDER_CE + COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, color); } + COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, color); } + #endif +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.cpp new file mode 100644 index 0000000..ce8696d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.cpp @@ -0,0 +1,143 @@ +// Windows/Control/PropertyPage.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "PropertyPage.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NControl { + +static INT_PTR APIENTRY MyProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempDialog(dialogHWND); + if (message == WM_INITDIALOG) + tempDialog.SetUserDataLongPtr(((PROPSHEETPAGE *)lParam)->lParam); + CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr()); + if (dialog == NULL) + return FALSE; + if (message == WM_INITDIALOG) + dialog->Attach(dialogHWND); + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } + catch(...) { return TRUE; } +} + +bool CPropertyPage::OnNotify(UINT /* controlID */, LPNMHDR lParam) +{ + switch (lParam->code) + { + case PSN_APPLY: SetMsgResult(OnApply(LPPSHNOTIFY(lParam))); break; + case PSN_KILLACTIVE: SetMsgResult(BoolToBOOL(OnKillActive(LPPSHNOTIFY(lParam)))); break; + case PSN_SETACTIVE: SetMsgResult(OnSetActive(LPPSHNOTIFY(lParam))); break; + case PSN_RESET: OnReset(LPPSHNOTIFY(lParam)); break; + case PSN_HELP: OnNotifyHelp(LPPSHNOTIFY(lParam)); break; + default: return false; + } + return true; +} + +INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title) +{ + #ifndef _UNICODE + AStringVector titles; + #endif + #ifndef _UNICODE + CRecordVector pagesA; + #endif + CRecordVector pagesW; + + unsigned i; + #ifndef _UNICODE + for (i = 0; i < pagesInfo.Size(); i++) + titles.Add(GetSystemString(pagesInfo[i].Title)); + #endif + + for (i = 0; i < pagesInfo.Size(); i++) + { + const CPageInfo &pageInfo = pagesInfo[i]; + #ifndef _UNICODE + { + PROPSHEETPAGE page; + page.dwSize = sizeof(page); + page.dwFlags = PSP_HASHELP; + page.hInstance = g_hInstance; + page.pszTemplate = MAKEINTRESOURCE(pageInfo.ID); + page.pszIcon = NULL; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; + + if (titles[i].IsEmpty()) + page.pszTitle = NULL; + else + { + page.dwFlags |= PSP_USETITLE; + page.pszTitle = titles[i]; + } + page.lParam = (LPARAM)pageInfo.Page; + page.pfnCallback = NULL; + pagesA.Add(page); + } + #endif + { + PROPSHEETPAGEW page; + page.dwSize = sizeof(page); + page.dwFlags = PSP_HASHELP; + page.hInstance = g_hInstance; + page.pszTemplate = MAKEINTRESOURCEW(pageInfo.ID); + page.pszIcon = NULL; + page.pfnDlgProc = NWindows::NControl::MyProperyPageProcedure; + + if (pageInfo.Title.IsEmpty()) + page.pszTitle = NULL; + else + { + page.dwFlags |= PSP_USETITLE; + page.pszTitle = pageInfo.Title; + } + page.lParam = (LPARAM)pageInfo.Page; + page.pfnCallback = NULL; + pagesW.Add(page); + } + } + + #ifndef _UNICODE + if (!g_IsNT) + { + PROPSHEETHEADER sheet; + sheet.dwSize = sizeof(sheet); + sheet.dwFlags = PSH_PROPSHEETPAGE; + sheet.hwndParent = hwndParent; + sheet.hInstance = g_hInstance; + AString titleA (GetSystemString(title)); + sheet.pszCaption = titleA; + sheet.nPages = pagesInfo.Size(); + sheet.nStartPage = 0; + sheet.ppsp = &pagesA.Front(); + sheet.pfnCallback = NULL; + return ::PropertySheetA(&sheet); + } + else + #endif + { + PROPSHEETHEADERW sheet; + sheet.dwSize = sizeof(sheet); + sheet.dwFlags = PSH_PROPSHEETPAGE; + sheet.hwndParent = hwndParent; + sheet.hInstance = g_hInstance; + sheet.pszCaption = title; + sheet.nPages = pagesInfo.Size(); + sheet.nStartPage = 0; + sheet.ppsp = &pagesW.Front(); + sheet.pfnCallback = NULL; + return ::PropertySheetW(&sheet); + } +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.h new file mode 100644 index 0000000..b68fd8f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/PropertyPage.h @@ -0,0 +1,50 @@ +// Windows/Control/PropertyPage.h + +#ifndef __WINDOWS_CONTROL_PROPERTYPAGE_H +#define __WINDOWS_CONTROL_PROPERTYPAGE_H + +#include "../../Common/MyWindows.h" + +#include + +#include "Dialog.h" + +namespace NWindows { +namespace NControl { + +INT_PTR APIENTRY ProperyPageProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam); + +class CPropertyPage: public CDialog +{ +public: + CPropertyPage(HWND window = NULL): CDialog(window){}; + + void Changed() { PropSheet_Changed(GetParent(), (HWND)*this); } + void UnChanged() { PropSheet_UnChanged(GetParent(), (HWND)*this); } + + virtual bool OnNotify(UINT controlID, LPNMHDR lParam); + + virtual bool OnKillActive() { return false; } // false = OK + virtual bool OnKillActive(const PSHNOTIFY *) { return OnKillActive(); } + virtual LONG OnSetActive() { return false; } // false = OK + virtual LONG OnSetActive(const PSHNOTIFY *) { return OnSetActive(); } + virtual LONG OnApply() { return PSNRET_NOERROR; } + virtual LONG OnApply(const PSHNOTIFY *) { return OnApply(); } + virtual void OnNotifyHelp() {} + virtual void OnNotifyHelp(const PSHNOTIFY *) { OnNotifyHelp(); } + virtual void OnReset() {} + virtual void OnReset(const PSHNOTIFY *) { OnReset(); } +}; + +struct CPageInfo +{ + CPropertyPage *Page; + UString Title; + UINT ID; +}; + +INT_PTR MyPropertySheet(const CObjectVector &pagesInfo, HWND hwndParent, const UString &title); + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ReBar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ReBar.h new file mode 100644 index 0000000..c2d58db --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ReBar.h @@ -0,0 +1,34 @@ +// Windows/Control/ReBar.h + +#ifndef __WINDOWS_CONTROL_REBAR_H +#define __WINDOWS_CONTROL_REBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CReBar: public NWindows::CWindow +{ +public: + bool SetBarInfo(LPREBARINFO barInfo) + { return LRESULTToBool(SendMsg(RB_SETBARINFO, 0, (LPARAM)barInfo)); } + bool InsertBand(int index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMsg(RB_INSERTBAND, index, (LPARAM)bandInfo)); } + bool SetBandInfo(unsigned index, LPREBARBANDINFO bandInfo) + { return LRESULTToBool(SendMsg(RB_SETBANDINFO, index, (LPARAM)bandInfo)); } + void MaximizeBand(unsigned index, bool ideal) + { SendMsg(RB_MAXIMIZEBAND, index, BoolToBOOL(ideal)); } + bool SizeToRect(LPRECT rect) + { return LRESULTToBool(SendMsg(RB_SIZETORECT, 0, (LPARAM)rect)); } + UINT GetHeight() + { return (UINT)SendMsg(RB_GETBARHEIGHT); } + UINT GetBandCount() + { return (UINT)SendMsg(RB_GETBANDCOUNT); } + bool DeleteBand(UINT index) + { return LRESULTToBool(SendMsg(RB_DELETEBAND, index)); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Static.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Static.h new file mode 100644 index 0000000..5523b2e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Static.h @@ -0,0 +1,28 @@ +// Windows/Control/Static.h + +#ifndef __WINDOWS_CONTROL_STATIC_H +#define __WINDOWS_CONTROL_STATIC_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CStatic: public CWindow +{ +public: + HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); } + HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); } + + #ifdef UNDER_CE + HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); } + HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); } + #else + HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); } + HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); } + #endif +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/StatusBar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/StatusBar.h new file mode 100644 index 0000000..988b847 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/StatusBar.h @@ -0,0 +1,42 @@ +// Windows/Control/StatusBar.h + +#ifndef __WINDOWS_CONTROL_STATUSBAR_H +#define __WINDOWS_CONTROL_STATUSBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CStatusBar: public NWindows::CWindow +{ +public: + bool Create(LONG style, LPCTSTR text, HWND hwndParent, UINT id) + { return (_window = ::CreateStatusWindow(style, text, hwndParent, id)) != 0; } + bool SetText(LPCTSTR text) + { return CWindow::SetText(text); } + bool SetText(unsigned index, LPCTSTR text, UINT type) + { return LRESULTToBool(SendMsg(SB_SETTEXT, index | type, (LPARAM)text)); } + bool SetText(unsigned index, LPCTSTR text) + { return SetText(index, text, 0); } + + #ifndef _UNICODE + bool Create(LONG style, LPCWSTR text, HWND hwndParent, UINT id) + { return (_window = ::CreateStatusWindowW(style, text, hwndParent, id)) != 0; } + bool SetText(LPCWSTR text) + { return CWindow::SetText(text); } + bool SetText(unsigned index, LPCWSTR text, UINT type) + { return LRESULTToBool(SendMsg(SB_SETTEXTW, index | type, (LPARAM)text)); } + bool SetText(unsigned index, LPCWSTR text) + { return SetText(index, text, 0); } + #endif + + bool SetParts(unsigned numParts, const int *edgePostions) + { return LRESULTToBool(SendMsg(SB_SETPARTS, numParts, (LPARAM)edgePostions)); } + void Simple(bool simple) + { SendMsg(SB_SIMPLE, BoolToBOOL(simple), 0); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/StdAfx.h new file mode 100644 index 0000000..1cbd7fe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/ToolBar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ToolBar.h new file mode 100644 index 0000000..7bc93a2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/ToolBar.h @@ -0,0 +1,43 @@ +// Windows/Control/ToolBar.h + +#ifndef __WINDOWS_CONTROL_TOOLBAR_H +#define __WINDOWS_CONTROL_TOOLBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CToolBar: public NWindows::CWindow +{ +public: + void AutoSize() { SendMsg(TB_AUTOSIZE, 0, 0); } + DWORD GetButtonSize() { return (DWORD)SendMsg(TB_GETBUTTONSIZE, 0, 0); } + + bool GetMaxSize(LPSIZE size) + #ifdef UNDER_CE + { + // maybe it must be fixed for more than 1 buttons + DWORD val = GetButtonSize(); + size->cx = LOWORD(val); + size->cy = HIWORD(val); + return true; + } + #else + { + return LRESULTToBool(SendMsg(TB_GETMAXSIZE, 0, (LPARAM)size)); + } + #endif + + bool EnableButton(UINT buttonID, bool enable) { return LRESULTToBool(SendMsg(TB_ENABLEBUTTON, buttonID, MAKELONG(BoolToBOOL(enable), 0))); } + void ButtonStructSize() { SendMsg(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON)); } + HIMAGELIST SetImageList(UINT listIndex, HIMAGELIST imageList) { return HIMAGELIST(SendMsg(TB_SETIMAGELIST, listIndex, (LPARAM)imageList)); } + bool AddButton(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONS, numButtons, (LPARAM)buttons)); } + #ifndef _UNICODE + bool AddButtonW(UINT numButtons, LPTBBUTTON buttons) { return LRESULTToBool(SendMsg(TB_ADDBUTTONSW, numButtons, (LPARAM)buttons)); } + #endif +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Trackbar.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Trackbar.h new file mode 100644 index 0000000..313e0c8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Trackbar.h @@ -0,0 +1,27 @@ +// Windows/Control/Trackbar.h + +#ifndef __WINDOWS_CONTROL_TRACKBAR_H +#define __WINDOWS_CONTROL_TRACKBAR_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CTrackbar: public CWindow +{ +public: + void SetRange(int minimum, int maximum, bool redraw = true) + { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } + void SetPos(int pos, bool redraw = true) + { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); } + void SetTicFreq(int freq) + { SendMsg(TBM_SETTICFREQ, freq); } + + int GetPos() + { return (int)SendMsg(TBM_GETPOS); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.cpp new file mode 100644 index 0000000..994d96e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.cpp @@ -0,0 +1,200 @@ +// Windows/Control/Window2.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../../Common/StringConvert.h" +#endif + +#include "Window2.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); +#endif + +namespace NControl { + +#ifdef UNDER_CE +#define MY_START_WM_CREATE WM_CREATE +#else +#define MY_START_WM_CREATE WM_NCCREATE +#endif + +static LRESULT CALLBACK WindowProcedure(HWND aHWND, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWindow tempWindow(aHWND); + if (message == MY_START_WM_CREATE) + tempWindow.SetUserDataLongPtr((LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams)); + CWindow2 *window = (CWindow2 *)(tempWindow.GetUserDataLongPtr()); + if (window != NULL && message == MY_START_WM_CREATE) + window->Attach(aHWND); + if (window == 0) + { + #ifndef _UNICODE + if (g_IsNT) + return DefWindowProcW(aHWND, message, wParam, lParam); + else + #endif + return DefWindowProc(aHWND, message, wParam, lParam); + } + return window->OnMessage(message, wParam, lParam); +} + +bool CWindow2::CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) +{ + WNDCLASS wc; + if (!::GetClassInfo(instance, className, &wc)) + { + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (::RegisterClass(&wc) == 0) + return false; + } + return CWindow::CreateEx(exStyle, className, windowName, style, + x, y, width, height, parentWindow, idOrHMenu, instance, this); +} + +#ifndef _UNICODE + +bool CWindow2::CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance) +{ + bool needRegister; + if (g_IsNT) + { + WNDCLASSW wc; + needRegister = ::GetClassInfoW(instance, className, &wc) == 0; + } + else + { + WNDCLASSA windowClassA; + AString classNameA; + LPCSTR classNameP; + if (IS_INTRESOURCE(className)) + classNameP = (LPCSTR)className; + else + { + classNameA = GetSystemString(className); + classNameP = classNameA; + } + needRegister = ::GetClassInfoA(instance, classNameP, &windowClassA) == 0; + } + if (needRegister) + { + WNDCLASSW wc; + // wc.style = CS_HREDRAW | CS_VREDRAW; + wc.style = 0; + wc.lpfnWndProc = WindowProcedure; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = className; + if (MyRegisterClass(&wc) == 0) + return false; + } + return CWindow::CreateEx(exStyle, className, windowName, style, + x, y, width, height, parentWindow, idOrHMenu, instance, this); +} + +#endif + +LRESULT CWindow2::DefProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + #ifndef _UNICODE + if (g_IsNT) + return DefWindowProcW(_window, message, wParam, lParam); + else + #endif + return DefWindowProc(_window, message, wParam, lParam); +} + +LRESULT CWindow2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT result; + switch (message) + { + case WM_CREATE: + if (!OnCreate((CREATESTRUCT *)lParam)) + return -1; + break; + case WM_COMMAND: + if (OnCommand(wParam, lParam, result)) + return result; + break; + case WM_NOTIFY: + if (OnNotify((UINT)wParam, (LPNMHDR) lParam, result)) + return result; + break; + case WM_DESTROY: + OnDestroy(); + break; + case WM_CLOSE: + OnClose(); + return 0; + case WM_SIZE: + if (OnSize(wParam, LOWORD(lParam), HIWORD(lParam))) + return 0; + } + return DefProc(message, wParam, lParam); +} + +bool CWindow2::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result) +{ + return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam, result); +} + +bool CWindow2::OnCommand(int /* code */, int /* itemID */, LPARAM /* lParam */, LRESULT & /* result */) +{ + return false; + // return DefProc(message, wParam, lParam); + /* + if (code == BN_CLICKED) + return OnButtonClicked(itemID, (HWND)lParam); + */ +} + +/* +bool CDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDOK: + OnOK(); + break; + case IDCANCEL: + OnCancel(); + break; + case IDHELP: + OnHelp(); + break; + default: + return false; + } + return true; +} + +*/ + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.h b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.h new file mode 100644 index 0000000..7ac580c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Control/Window2.h @@ -0,0 +1,51 @@ +// Windows/Control/Window2.h + +#ifndef __WINDOWS_CONTROL_WINDOW2_H +#define __WINDOWS_CONTROL_WINDOW2_H + +#include "../Window.h" + +namespace NWindows { +namespace NControl { + +class CWindow2: public CWindow +{ + LRESULT DefProc(UINT message, WPARAM wParam, LPARAM lParam); +public: + CWindow2(HWND newWindow = NULL): CWindow(newWindow){}; + virtual ~CWindow2() {}; + + bool CreateEx(DWORD exStyle, LPCTSTR className, LPCTSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); + + #ifndef _UNICODE + bool CreateEx(DWORD exStyle, LPCWSTR className, LPCWSTR windowName, + DWORD style, int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, HINSTANCE instance); + #endif + + virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual bool OnCreate(CREATESTRUCT * /* createStruct */) { return true; } + // virtual LRESULT OnCommand(WPARAM wParam, LPARAM lParam); + virtual bool OnCommand(WPARAM wParam, LPARAM lParam, LRESULT &result); + virtual bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result); + virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } + virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */, LRESULT & /* result */) { return false; } + virtual void OnDestroy() { PostQuitMessage(0); } + virtual void OnClose() { Destroy(); } + /* + virtual LRESULT OnHelp(LPHELPINFO helpInfo) { OnHelp(); } + virtual LRESULT OnHelp() {}; + virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); + virtual void OnOK() {}; + virtual void OnCancel() {}; + */ + + LONG_PTR SetMsgResult(LONG_PTR newLongPtr) { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); } + LONG_PTR GetMsgResult() const { return GetLongPtr(DWLP_MSGRESULT); } +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/DLL.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/DLL.cpp new file mode 100644 index 0000000..cf5d01a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/DLL.cpp @@ -0,0 +1,191 @@ +// Windows/DLL.cpp + +#include "StdAfx.h" + +#include "DLL.h" + +#ifdef _WIN32 + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +extern HINSTANCE g_hInstance; + +namespace NWindows { +namespace NDLL { + +bool CLibrary::Free() throw() +{ + if (_module == 0) + return true; + if (!::FreeLibrary(_module)) + return false; + _module = 0; + return true; +} + +bool CLibrary::LoadEx(CFSTR path, DWORD flags) throw() +{ + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibraryEx(fs2fas(path), NULL, flags); + } + else + #endif + { + _module = ::LoadLibraryExW(fs2us(path), NULL, flags); + } + return (_module != NULL); +} + +bool CLibrary::Load(CFSTR path) throw() +{ + if (!Free()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + _module = ::LoadLibrary(fs2fas(path)); + } + else + #endif + { + _module = ::LoadLibraryW(fs2us(path)); + } + return (_module != NULL); +} + +bool MyGetModuleFileName(FString &path) +{ + HMODULE hModule = g_hInstance; + path.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = fas2fs(s); + return true; + } + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1); + if (size <= MAX_PATH && size != 0) + { + path = us2fs(s); + return true; + } + } + return false; +} + +#ifndef _SFX + +FString GetModuleDirPrefix() +{ + FString s; + if (MyGetModuleFileName(s)) + { + int pos = s.ReverseFind_PathSepar(); + if (pos >= 0) + s.DeleteFrom((unsigned)(pos + 1)); + } + if (s.IsEmpty()) + s = "." STRING_PATH_SEPARATOR; + return s; +} + +#endif + +}} + +#else + +#include +#include + +namespace NWindows { +namespace NDLL { + +bool CLibrary::Free() throw() +{ + if (_module == NULL) + return true; + int ret = dlclose(_module); + if (ret != 0) + return false; + _module = NULL; + return true; +} + +static +// FARPROC +void * +local_GetProcAddress(HMODULE module, LPCSTR procName) +{ + void *ptr = NULL; + if (module) + { + ptr = dlsym(module, procName); + } + return ptr; +} + +bool CLibrary::Load(CFSTR path) throw() +{ + if (!Free()) + return false; + + int options = 0; + + #ifdef RTLD_LOCAL + options |= RTLD_LOCAL; + #endif + + #ifdef RTLD_NOW + options |= RTLD_NOW; + #endif + + #ifdef RTLD_GROUP + #if ! (defined(hpux) || defined(__hpux)) + options |= RTLD_GROUP; // mainly for solaris but not for HPUX + #endif + #endif + + void *handler = dlopen(path, options); + + if (handler) + { + // here we can transfer some settings to DLL + } + else + { + } + + _module = handler; + + return (_module != NULL); +} + +// FARPROC +void * CLibrary::GetProc(LPCSTR procName) const +{ + // return My_GetProcAddress(_module, procName); + return local_GetProcAddress(_module, procName); + // return NULL; +} + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/DLL.h b/3rdparty/lzma-21.03beta/CPP/Windows/DLL.h new file mode 100644 index 0000000..0c093ee --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/DLL.h @@ -0,0 +1,84 @@ +// Windows/DLL.h + +#ifndef __WINDOWS_DLL_H +#define __WINDOWS_DLL_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NDLL { + +#ifdef _WIN32 + +#ifdef UNDER_CE +#define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName) +#else +#define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName) +#endif + +/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another + FreeLibrary() code: detaching code in DLL entry-point or in + destructors of global objects in DLL module. */ + +class CLibrary +{ + HMODULE _module; + + // CLASS_NO_COPY(CLibrary); +public: + CLibrary(): _module(NULL) {}; + ~CLibrary() { Free(); } + + operator HMODULE() const { return _module; } + HMODULE* operator&() { return &_module; } + bool IsLoaded() const { return (_module != NULL); } + + void Attach(HMODULE m) + { + Free(); + _module = m; + } + HMODULE Detach() + { + HMODULE m = _module; + _module = NULL; + return m; + } + + bool Free() throw(); + bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw(); + bool Load(CFSTR path) throw(); + // FARPROC + void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); } +}; + +#else + +typedef void * HMODULE; +// typedef int (*FARPROC)(); +// typedef void *FARPROC; + +class CLibrary +{ + HMODULE _module; + + // CLASS_NO_COPY(CLibrary); +public: + CLibrary(): _module(NULL) {}; + ~CLibrary() { Free(); } + + bool Free() throw(); + bool Load(CFSTR path) throw(); + // FARPROC + void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); } +}; + +#endif + +bool MyGetModuleFileName(FString &path); + +FString GetModuleDirPrefix(); + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Defs.h b/3rdparty/lzma-21.03beta/CPP/Windows/Defs.h new file mode 100644 index 0000000..1d96078 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Defs.h @@ -0,0 +1,18 @@ +// Windows/Defs.h + +#ifndef __WINDOWS_DEFS_H +#define __WINDOWS_DEFS_H + +#include "../Common/MyWindows.h" + +#ifdef _WIN32 +inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); } +inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); } +#endif + +inline bool BOOLToBool(BOOL v) { return (v != FALSE); } + +inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); } +inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); } + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.cpp new file mode 100644 index 0000000..63fd792 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.cpp @@ -0,0 +1,133 @@ +// Windows/ErrorMsg.h + +#include "StdAfx.h" + +#if !defined(_UNICODE) || !defined(_WIN32) +#include "../Common/StringConvert.h" +#endif + +#include "ErrorMsg.h" + +#ifdef _WIN32 +#if !defined(_UNICODE) +extern bool g_IsNT; +#endif +#endif + +namespace NWindows { +namespace NError { + +static bool MyFormatMessage(DWORD errorCode, UString &message) +{ + #ifndef _SFX + if ((HRESULT)errorCode == MY_HRES_ERROR__INTERNAL_ERROR) + { + message = "Internal Error: The failure in hardware (RAM or CPU), OS or program"; + return true; + } + #endif + + #ifdef _WIN32 + + LPVOID msgBuf; + #ifndef _UNICODE + if (!g_IsNT) + { + if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0) + return false; + message = GetUnicodeString((LPCTSTR)msgBuf); + } + else + #endif + { + if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) + return false; + message = (LPCWSTR)msgBuf; + } + ::LocalFree(msgBuf); + return true; + + #else // _WIN32 + + AString m; + + const char *s = NULL; + + switch ((Int32)errorCode) + { + // case ERROR_NO_MORE_FILES : s = "No more files"; break; + // case ERROR_DIRECTORY : s = "Error Directory"; break; + case E_NOTIMPL : s = "E_NOTIMPL : Not implemented"; break; + case E_NOINTERFACE : s = "E_NOINTERFACE : No such interface supported"; break; + case E_ABORT : s = "E_ABORT : Operation aborted"; break; + case E_FAIL : s = "E_FAIL : Unspecified error"; break; + + case STG_E_INVALIDFUNCTION : s = "STG_E_INVALIDFUNCTION"; break; + case CLASS_E_CLASSNOTAVAILABLE : s = "CLASS_E_CLASSNOTAVAILABLE"; break; + + case E_OUTOFMEMORY : s = "E_OUTOFMEMORY : Can't allocate required memory"; break; + case E_INVALIDARG : s = "E_INVALIDARG : One or more arguments are invalid"; break; + + // case MY__E_ERROR_NEGATIVE_SEEK : s = "MY__E_ERROR_NEGATIVE_SEEK"; break; + default: + break; + } + + /* strerror() for unknow errors still shows message "Unknown error -12345678") + So we must trasfer error codes before strerror() */ + if (!s) + { + if ((errorCode & 0xFFFF0000) == (UInt32)((MY__FACILITY__WRes << 16) | 0x80000000)) + errorCode &= 0xFFFF; + else if ((errorCode & ((UInt32)1 << 31))) + return false; // we will show hex error later for that case + + s = strerror((int)errorCode); + + // if (!s) + { + m += "errno="; + m.Add_UInt32(errorCode); + if (s) + m += " : "; + } + } + + if (s) + m += s; + + MultiByteToUnicodeString2(message, m); + return true; + + #endif +} + + +UString MyFormatMessage(DWORD errorCode) +{ + UString m; + if (!MyFormatMessage(errorCode, m) || m.IsEmpty()) + { + char s[16]; + for (int i = 0; i < 8; i++) + { + unsigned t = errorCode & 0xF; + errorCode >>= 4; + s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[8] = 0; + m += "Error #"; + m += s; + } + else if (m.Len() >= 2 + && m[m.Len() - 1] == 0x0A + && m[m.Len() - 2] == 0x0D) + m.DeleteFrom(m.Len() - 2); + return m; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.h b/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.h new file mode 100644 index 0000000..01204eb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/ErrorMsg.h @@ -0,0 +1,16 @@ +// Windows/ErrorMsg.h + +#ifndef __WINDOWS_ERROR_MSG_H +#define __WINDOWS_ERROR_MSG_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NError { + +UString MyFormatMessage(DWORD errorCode); +inline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); } + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.cpp new file mode 100644 index 0000000..c06e7f3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.cpp @@ -0,0 +1,1078 @@ +// Windows/FileDir.cpp + +#include "StdAfx.h" + + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Common/StringConvert.h" +#include "../Common/C_FileIO.h" +#include "TimeUtils.h" +#endif + +#include "FileDir.h" +#include "FileFind.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +namespace NWindows { +namespace NFile { +namespace NDir { + +#ifdef _WIN32 + +#ifndef UNDER_CE + +bool GetWindowsDir(FString &path) +{ + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +bool GetSystemDir(FString &path) +{ + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} +#endif // UNDER_CE + + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + #endif + + HANDLE hDir = INVALID_HANDLE_VALUE; + IF_USE_MAIN_PATH + hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + #ifdef WIN_LONG_PATH + if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + } + #endif + + bool res = false; + if (hDir != INVALID_HANDLE_VALUE) + { + res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); + ::CloseHandle(hDir); + } + return res; +} + + + +bool SetFileAttrib(CFSTR path, DWORD attrib) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::SetFileAttributes(fs2fas(path), attrib)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::SetFileAttributesW(fs2us(path), attrib)) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::SetFileAttributesW(superPath, attrib)); + } + #endif + } + return false; +} + + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) +{ + #ifdef _WIN32 + if ((attrib & 0xF0000000) != 0) + attrib &= 0x3FFF; + #endif + return SetFileAttrib(path, attrib); +} + + +bool RemoveDir(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::RemoveDirectory(fs2fas(path))) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::RemoveDirectoryW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::RemoveDirectoryW(superPath)); + } + #endif + } + return false; +} + + +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::MoveFile(fs2fas(oldFile), fs2fas(newFile))) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH_2(oldFile, newFile) + { + if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) + return true; + } + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(::MoveFileW(d1, d2)); + } + #endif + } + return false; +} + +#ifndef UNDER_CE +EXTERN_C_BEGIN +typedef BOOL (WINAPI *Func_CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); +EXTERN_C_END +#endif // UNDER_CE + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + /* + if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL)) + return true; + */ + } + else + #endif + { + Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) + (void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + if (!my_CreateHardLinkW) + return false; + IF_USE_MAIN_PATH_2(newFileName, existFileName) + { + if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) + return true; + } + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH_2) + { + UString d1, d2; + if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2)) + return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL)); + } + #endif + } + return false; +} + + +/* +WinXP-64 CreateDir(): + "" - ERROR_PATH_NOT_FOUND + \ - ERROR_ACCESS_DENIED + C:\ - ERROR_ACCESS_DENIED, if there is such drive, + + D:\folder - ERROR_PATH_NOT_FOUND, if there is no such drive, + C:\nonExistent\folder - ERROR_PATH_NOT_FOUND + + C:\existFolder - ERROR_ALREADY_EXISTS + C:\existFolder\ - ERROR_ALREADY_EXISTS + + C:\folder - OK + C:\folder\ - OK + + \\Server\nonExistent - ERROR_BAD_NETPATH + \\Server\Share_Readonly - ERROR_ACCESS_DENIED + \\Server\Share - ERROR_ALREADY_EXISTS + + \\Server\Share_NTFS_drive - ERROR_ACCESS_DENIED + \\Server\Share_FAT_drive - ERROR_ALREADY_EXISTS +*/ + +bool CreateDir(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::CreateDirectory(fs2fas(path), NULL)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::CreateDirectoryW(superPath, NULL)); + } + #endif + } + return false; +} + +/* + CreateDir2 returns true, if directory can contain files after the call (two cases): + 1) the directory already exists + 2) the directory was created + path must be WITHOUT trailing path separator. + + We need CreateDir2, since fileInfo.Find() for reserved names like "com8" + returns FILE instead of DIRECTORY. And we need to use SuperPath */ + +static bool CreateDir2(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + if (::CreateDirectory(fs2fas(path), NULL)) + return true; + } + else + #endif + { + IF_USE_MAIN_PATH + if (::CreateDirectoryW(fs2us(path), NULL)) + return true; + #ifdef WIN_LONG_PATH + if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + { + if (::CreateDirectoryW(superPath, NULL)) + return true; + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + NFind::CFileInfo fi; + if (!fi.Find(us2fs(superPath))) + return false; + return fi.IsDir(); + } + } + #endif + } + if (::GetLastError() != ERROR_ALREADY_EXISTS) + return false; + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + return fi.IsDir(); +} + +#endif // _WIN32 + +static bool CreateDir2(CFSTR path); + +bool CreateComplexDir(CFSTR _path) +{ + #ifdef _WIN32 + + { + DWORD attrib = NFind::GetFileAttrib(_path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + return true; + } + + #ifndef UNDER_CE + + if (IsDriveRootPath_SuperAllowed(_path)) + return false; + + const unsigned prefixSize = GetRootPrefixSize(_path); + + #endif // UNDER_CE + + #else // _WIN32 + + // Posix + NFind::CFileInfo fi; + if (fi.Find(_path)) + { + if (fi.IsDir()) + return true; + } + + #endif // _WIN32 + + FString path (_path); + + int pos = path.ReverseFind_PathSepar(); + if (pos >= 0 && (unsigned)pos == path.Len() - 1) + { + if (path.Len() == 1) + return true; + path.DeleteBack(); + } + + const FString path2 (path); + pos = (int)path.Len(); + + for (;;) + { + if (CreateDir2(path)) + break; + if (::GetLastError() == ERROR_ALREADY_EXISTS) + return false; + pos = path.ReverseFind_PathSepar(); + if (pos < 0 || pos == 0) + return false; + + #if defined(_WIN32) && !defined(UNDER_CE) + if (pos == 1 && IS_PATH_SEPAR(path[0])) + return false; + if (prefixSize >= (unsigned)pos + 1) + return false; + #endif + + path.DeleteFrom((unsigned)pos); + } + + while (pos < (int)path2.Len()) + { + int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1)); + if (pos2 < 0) + pos = (int)path2.Len(); + else + pos += 1 + pos2; + path.SetFrom(path2, (unsigned)pos); + if (!CreateDir(path)) + return false; + } + + return true; +} + + +#ifdef _WIN32 + +bool DeleteFileAlways(CFSTR path) +{ + /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete. + SetFileAttrib("name:stream", ) changes attributes of main file. */ + { + DWORD attrib = NFind::GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES + && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0 + && (attrib & FILE_ATTRIBUTE_READONLY) != 0) + { + if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY)) + return false; + } + } + + #ifndef _UNICODE + if (!g_IsNT) + { + if (::DeleteFile(fs2fas(path))) + return true; + } + else + #endif + { + /* DeleteFile("name::$DATA") deletes all alt streams (same as delete DeleteFile("name")). + Maybe it's better to open "name::$DATA" and clear data for unnamed stream? */ + IF_USE_MAIN_PATH + if (::DeleteFileW(fs2us(path))) + return true; + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return BOOLToBool(::DeleteFileW(superPath)); + } + #endif + } + return false; +} + + + +bool RemoveDirWithSubItems(const FString &path) +{ + bool needRemoveSubItems = true; + { + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; + } + + if (needRemoveSubItems) + { + FString s (path); + s.Add_PathSepar(); + const unsigned prefixSize = s.Len(); + NFind::CEnumerator enumerator; + enumerator.SetDirPrefix(s); + NFind::CDirEntry fi; + bool isError = false; + DWORD lastError = 0; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + { + lastError = GetLastError(); + isError = true; + } + } + else if (!DeleteFileAlways(s)) + { + lastError = GetLastError(); + isError = false; + } + } + if (isError) + { + SetLastError(lastError); + return false; + } + } + + // we clear read-only attrib to remove read-only dir + if (!SetFileAttrib(path, 0)) + return false; + return RemoveDir(path); +} + +#endif // _WIN32 + +#ifdef UNDER_CE + +bool MyGetFullPathName(CFSTR path, FString &resFullPath) +{ + resFullPath = path; + return true; +} + +#else + +bool MyGetFullPathName(CFSTR path, FString &resFullPath) +{ + return GetFullPath(path, resFullPath); +} + +#ifdef _WIN32 + +bool SetCurrentDir(CFSTR path) +{ + // SetCurrentDirectory doesn't support \\?\ prefix + #ifndef _UNICODE + if (!g_IsNT) + { + return BOOLToBool(::SetCurrentDirectory(fs2fas(path))); + } + else + #endif + { + return BOOLToBool(::SetCurrentDirectoryW(fs2us(path))); + } +} + + +bool GetCurrentDir(FString &path) +{ + path.Empty(); + + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); +} + +#endif // _WIN32 +#endif // UNDER_CE + + +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) +{ + bool res = MyGetFullPathName(path, resDirPrefix); + if (!res) + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind_PathSepar(); + pos++; + resFileName = resDirPrefix.Ptr((unsigned)pos); + resDirPrefix.DeleteFrom((unsigned)pos); + return res; +} + +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) +{ + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); +} + +bool MyGetTempPath(FString &path) +{ + #ifdef _WIN32 + path.Empty(); + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPath(MAX_PATH + 1, s); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetTempPathW(MAX_PATH + 1, s);; + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); + + #else + + // FIXME: improve that code + path = "/tmp/"; + if (!NFind::DoesDirExist_FollowLink(path)) + path = "./"; + return true; + #endif +} + + +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) +{ + UInt32 d = + #ifdef _WIN32 + (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + #else + (UInt32)(time(NULL) << 12) ^ ((UInt32)getppid() << 14) ^ (UInt32)(getpid()); + #endif + + for (unsigned i = 0; i < 100; i++) + { + path = prefix; + if (addRandom) + { + char s[16]; + UInt32 val = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = val & 0xF; + val >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += '.'; + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += ".tmp"; + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (CreateDir(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; + } + path.Empty(); + return false; +} + +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) +{ + if (!Remove()) + return false; + if (!CreateTempFile(prefix, false, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) +{ + if (!Remove()) + return false; + FString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempFile::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !DeleteFileAlways(_path); + return !_mustBeDeleted; +} + +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) +{ + // DWORD attrib = 0; + if (deleteDestBefore) + { + if (NFind::DoesFileExist_Raw(name)) + { + // attrib = NFind::GetFileAttrib(name); + if (!DeleteFileAlways(name)) + return false; + } + } + DisableDeleting(); + return MyMoveFile(_path, name); + + /* + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) + { + DWORD attrib2 = NFind::GetFileAttrib(name); + if (attrib2 != INVALID_FILE_ATTRIBUTES) + SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY); + } + */ +} + +#ifdef _WIN32 +bool CTempDir::Create(CFSTR prefix) +{ + if (!Remove()) + return false; + FString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) + return false; + _mustBeDeleted = true; + return true; +} + +bool CTempDir::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !RemoveDirWithSubItems(_path); + return !_mustBeDeleted; +} +#endif + + + +#ifndef _WIN32 + +bool RemoveDir(CFSTR path) +{ + return (rmdir(path) == 0); +} + + +static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile) +{ + NWindows::NFile::NIO::COutFile outFile; + if (!outFile.Create(newFile, false)) + return FALSE; + + NWindows::NFile::NIO::CInFile inFile; + if (!inFile.Open(oldFile)) + return FALSE; + + char buf[1 << 14]; + + for (;;) + { + const ssize_t num = inFile.read_part(buf, sizeof(buf)); + if (num == 0) + return TRUE; + if (num < 0) + return FALSE; + size_t processed; + const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); + if (num2 != num || processed != (size_t)num) + return FALSE; + } +} + + +bool MyMoveFile(CFSTR oldFile, CFSTR newFile) +{ + int res = rename(oldFile, newFile); + if (res == 0) + return true; + if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) + return false; + + if (My__CopyFile(oldFile, newFile) == FALSE) + return false; + + struct stat info_file; + res = stat(oldFile, &info_file); + if (res != 0) + return false; + + /* + ret = chmod(dst,info_file.st_mode & g_umask.mask); + */ + return (unlink(oldFile) == 0); +} + + +bool CreateDir(CFSTR path) +{ + return (mkdir(path, 0777) == 0); // change it +} + +static bool CreateDir2(CFSTR path) +{ + return (mkdir(path, 0777) == 0); // change it +} + + +bool DeleteFileAlways(CFSTR path) +{ + return (remove(path) == 0); +} + +bool SetCurrentDir(CFSTR path) +{ + return (chdir(path) == 0); +} + + +bool GetCurrentDir(FString &path) +{ + path.Empty(); + + #define MY__PATH_MAX PATH_MAX + // #define MY__PATH_MAX 1024 + + char s[MY__PATH_MAX + 1]; + char *res = getcwd(s, MY__PATH_MAX); + if (!res) + { + // if (errno != ERANGE) + return false; + } + path = fas2fs(s); + return true; +} + + +static void FILETME_To_timespec(const FILETIME *ft, timespec &ts) +{ + if (ft) + { + const Int64 sec = NTime::FileTimeToUnixTime64(*ft); + // time_t is long + const time_t sec2 = (time_t)sec; + if (sec2 == sec) + { + ts.tv_sec = sec2; + const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime; + ts.tv_nsec = (long)((winTime % 10000000) * 100); + return; + } + } + // else + { + ts.tv_sec = 0; + // ts.tv_nsec = UTIME_NOW; // set to the current time + ts.tv_nsec = UTIME_OMIT; // keep old timesptamp + } +} + + + + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) +{ + // need testing + /* + struct utimbuf buf; + struct stat st; + UNUSED_VAR(cTime) + + printf("\nstat = %s\n", path); + int ret = stat(path, &st); + + if (ret == 0) + { + buf.actime = st.st_atime; + buf.modtime = st.st_mtime; + } + else + { + time_t cur_time = time(0); + buf.actime = cur_time; + buf.modtime = cur_time; + } + + if (aTime) + { + UInt32 ut; + if (NTime::FileTimeToUnixTime(*aTime, ut)) + buf.actime = ut; + } + + if (mTime) + { + UInt32 ut; + if (NTime::FileTimeToUnixTime(*mTime, ut)) + buf.modtime = ut; + } + + return utime(path, &buf) == 0; + */ + + // if (!aTime && !mTime) return true; + + struct timespec times[2]; + UNUSED_VAR(cTime) + + FILETME_To_timespec(aTime, times[0]); + FILETME_To_timespec(mTime, times[1]); + + const int flags = 0; // follow link + // = AT_SYMLINK_NOFOLLOW; // don't follow link + return utimensat(AT_FDCWD, path, times, flags) == 0; +} + + + +struct C_umask +{ + mode_t mask; + + C_umask() + { + /* by security reasons we restrict attributes according + with process's file mode creation mask (umask) */ + const mode_t um = umask(0); // octal :0022 is expected + mask = 0777 & (~um); // octal: 0755 is expected + umask(um); // restore the umask + // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); + + // mask = 0777; // debug we can disable the restriction: + } +}; + +static C_umask g_umask; + +// #define PRF(x) x; +#define PRF(x) + +#define TRACE_SetFileAttrib(msg) \ + PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg)); + +#define TRACE_chmod(s, mode) \ + PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); + + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) +{ + TRACE_SetFileAttrib(""); + + struct stat st; + + bool use_lstat = true; + if (use_lstat) + { + if (lstat(path, &st) != 0) + { + TRACE_SetFileAttrib("bad lstat()"); + return false; + } + } + else + { + if (stat(path, &st) != 0) + { + TRACE_SetFileAttrib("bad stat()"); + return false; + } + } + + if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) + { + st.st_mode = attrib >> 16; + if (S_ISDIR(st.st_mode)) + { + // user/7z must be able to create files in this directory + st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); + } + else if (!S_ISREG(st.st_mode)) + return true; + } + else if (S_ISLNK(st.st_mode)) + { + // change it + SetLastError(ENOSYS); + return false; + } + else + { + // Only Windows Attributes + if (S_ISDIR(st.st_mode) + || (attrib & FILE_ATTRIBUTE_READONLY) == 0) + return true; + st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions + } + + TRACE_chmod(path, (st.st_mode) & g_umask.mask); + int res = chmod(path, (st.st_mode) & g_umask.mask); + + // TRACE_SetFileAttrib("OK") + return (res == 0); +} + + +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) +{ + PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName)); + return (link(existFileName, newFileName) == 0); +} + +#endif // !_WIN32 + +// #endif + +}}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.h new file mode 100644 index 0000000..6d6ddea --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileDir.h @@ -0,0 +1,125 @@ +// Windows/FileDir.h + +#ifndef __WINDOWS_FILE_DIR_H +#define __WINDOWS_FILE_DIR_H + +#include "../Common/MyString.h" + +#include "FileIO.h" + +namespace NWindows { +namespace NFile { +namespace NDir { + +bool GetWindowsDir(FString &path); +bool GetSystemDir(FString &path); + +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); + + +#ifdef _WIN32 + +bool SetFileAttrib(CFSTR path, DWORD attrib); + +/* + Some programs store posix attributes in high 16 bits of windows attributes field. + Also some programs use additional flag markers: 0x8000 or 0x4000. + SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute + bits that are related to current system only. +*/ + +#endif + +bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); + + +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); + +#ifndef UNDER_CE +bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); +#endif + +bool RemoveDir(CFSTR path); +bool CreateDir(CFSTR path); + +/* CreateComplexDir returns true, if directory can contain files after the call (two cases): + 1) the directory already exists (network shares and drive paths are supported) + 2) the directory was created + path can be WITH or WITHOUT trailing path separator. */ + +bool CreateComplexDir(CFSTR path); + +bool DeleteFileAlways(CFSTR name); +bool RemoveDirWithSubItems(const FString &path); + +bool MyGetFullPathName(CFSTR path, FString &resFullPath); +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName); +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix); + +#ifndef UNDER_CE + +bool SetCurrentDir(CFSTR path); +bool GetCurrentDir(FString &resultPath); + +#endif + +bool MyGetTempPath(FString &resultPath); + +class CTempFile MY_UNCOPYABLE +{ + bool _mustBeDeleted; + FString _path; + void DisableDeleting() { _mustBeDeleted = false; } +public: + CTempFile(): _mustBeDeleted(false) {} + ~CTempFile() { Remove(); } + const FString &GetPath() const { return _path; } + bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix + bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); + bool Remove(); + bool MoveTo(CFSTR name, bool deleteDestBefore); +}; + + +#ifdef _WIN32 +class CTempDir MY_UNCOPYABLE +{ + bool _mustBeDeleted; + FString _path; +public: + CTempDir(): _mustBeDeleted(false) {} + ~CTempDir() { Remove(); } + const FString &GetPath() const { return _path; } + void DisableDeleting() { _mustBeDeleted = false; } + bool Create(CFSTR namePrefix) ; + bool Remove(); +}; +#endif + + +#if !defined(UNDER_CE) +class CCurrentDirRestorer MY_UNCOPYABLE +{ + FString _path; +public: + bool NeedRestore; + + CCurrentDirRestorer(): NeedRestore(true) + { + GetCurrentDir(_path); + } + ~CCurrentDirRestorer() + { + if (!NeedRestore) + return; + FString s; + if (GetCurrentDir(s)) + if (s != _path) + SetCurrentDir(_path); + } +}; +#endif + +}}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.cpp new file mode 100644 index 0000000..8ef0f7b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.cpp @@ -0,0 +1,1216 @@ +// Windows/FileFind.cpp + +#include "StdAfx.h" + +// #include + +#ifndef _WIN32 +#include /* Definition of AT_* constants */ +#include "TimeUtils.h" +#endif + +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +#if defined(_WIN32) && !defined(UNDER_CE) + +EXTERN_C_BEGIN + +typedef enum +{ + My_FindStreamInfoStandard, + My_FindStreamInfoMaxInfoLevel +} MY_STREAM_INFO_LEVELS; + +typedef struct +{ + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA; + +typedef HANDLE (WINAPI *FindFirstStreamW_Ptr)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel, + LPVOID findStreamData, DWORD flags); + +typedef BOOL (APIENTRY *FindNextStreamW_Ptr)(HANDLE findStream, LPVOID findStreamData); + +EXTERN_C_END + +#endif // defined(_WIN32) && !defined(UNDER_CE) + + +namespace NWindows { +namespace NFile { + + +#ifdef _WIN32 +#ifdef SUPPORT_DEVICE_FILE +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif +#endif + +namespace NFind { + +#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; + +void CFileInfoBase::ClearBase() throw() +{ + Size = 0; + MY_CLEAR_FILETIME(CTime); + MY_CLEAR_FILETIME(ATime); + MY_CLEAR_FILETIME(MTime); + Attrib = 0; + // ReparseTag = 0; + IsAltStream = false; + IsDevice = false; + + #ifndef _WIN32 + ino = 0; + nlink = 0; + mode = 0; + #endif +} + +bool CFileInfo::IsDots() const throw() +{ + if (!IsDir() || Name.IsEmpty()) + return false; + if (Name[0] != '.') + return false; + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); +} + + +#ifdef _WIN32 + + +#define WIN_FD_TO_MY_FI(fi, fd) \ + fi.Attrib = fd.dwFileAttributes; \ + fi.CTime = fd.ftCreationTime; \ + fi.ATime = fd.ftLastAccessTime; \ + fi.MTime = fd.ftLastWriteTime; \ + fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \ + /* fi.ReparseTag = fd.dwReserved0; */ \ + fi.IsAltStream = false; \ + fi.IsDevice = false; + + /* + #ifdef UNDER_CE + fi.ObjectID = fd.dwOID; + #else + fi.ReparseTag = fd.dwReserved0; + #endif + */ + +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = us2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = us2fs(fd.cAlternateFileName); + #endif +} + +#ifndef _UNICODE +static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) +{ + WIN_FD_TO_MY_FI(fi, fd); + fi.Name = fas2fs(fd.cFileName); + #if defined(_WIN32) && !defined(UNDER_CE) + // fi.ShortName = fas2fs(fd.cAlternateFileName); + #endif +} +#endif + +//////////////////////////////// +// CFindFile + +bool CFindFileBase::Close() throw() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::FindClose(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +/* +WinXP-64 FindFirstFile(): + "" - ERROR_PATH_NOT_FOUND + folder\ - ERROR_FILE_NOT_FOUND + \ - ERROR_FILE_NOT_FOUND + c:\ - ERROR_FILE_NOT_FOUND + c: - ERROR_FILE_NOT_FOUND, if current dir is ROOT ( c:\ ) + c: - OK, if current dir is NOT ROOT ( c:\folder ) + folder - OK + + \\ - ERROR_INVALID_NAME + \\Server - ERROR_INVALID_NAME + \\Server\ - ERROR_INVALID_NAME + + \\Server\Share - ERROR_BAD_NETPATH + \\Server\Share - ERROR_BAD_NET_NAME (Win7). + !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon), + when we call it for "\\Server\Share" + + \\Server\Share\ - ERROR_FILE_NOT_FOUND + + \\?\UNC\Server\Share - ERROR_INVALID_NAME + \\?\UNC\Server\Share - ERROR_BAD_PATHNAME (Win7) + \\?\UNC\Server\Share\ - ERROR_FILE_NOT_FOUND + + \\Server\Share_RootDrive - ERROR_INVALID_NAME + \\Server\Share_RootDrive\ - ERROR_INVALID_NAME + + e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder + w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w: +*/ + +bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi) +{ + if (!Close()) + return false; + #ifndef _UNICODE + if (!g_IsNT) + { + WIN32_FIND_DATAA fd; + _handle = ::FindFirstFileA(fs2fas(path), &fd); + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + else + #endif + { + WIN32_FIND_DATAW fd; + + IF_USE_MAIN_PATH + _handle = ::FindFirstFileW(fs2us(path), &fd); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::FindFirstFileW(superPath, &fd); + } + #endif + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; +} + +bool CFindFile::FindNext(CFileInfo &fi) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + WIN32_FIND_DATAA fd; + if (!::FindNextFileA(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + else + #endif + { + WIN32_FIND_DATAW fd; + if (!::FindNextFileW(_handle, &fd)) + return false; + Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi); + } + return true; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +//////////////////////////////// +// AltStreams + +static FindFirstStreamW_Ptr g_FindFirstStreamW; +static FindNextStreamW_Ptr g_FindNextStreamW; + +static struct CFindStreamLoader +{ + CFindStreamLoader() + { + HMODULE hm = ::GetModuleHandleA("kernel32.dll"); + g_FindFirstStreamW = (FindFirstStreamW_Ptr)(void *)::GetProcAddress(hm, "FindFirstStreamW"); + g_FindNextStreamW = (FindNextStreamW_Ptr)(void *)::GetProcAddress(hm, "FindNextStreamW"); + } +} g_FindStreamLoader; + +bool CStreamInfo::IsMainStream() const throw() +{ + return StringsAreEqualNoCase_Ascii(Name, "::$DATA"); +}; + +UString CStreamInfo::GetReducedName() const +{ + // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA" + UString s (Name); + if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA")) + s.DeleteFrom(s.Len() - 6); + return s; +} + +/* +UString CStreamInfo::GetReducedName2() const +{ + UString s = GetReducedName(); + if (!s.IsEmpty() && s[0] == ':') + s.Delete(0); + return s; +} +*/ + +static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si) +{ + si.Size = (UInt64)sd.StreamSize.QuadPart; + si.Name = sd.cStreamName; +} + +/* + WinXP-64 FindFirstStream(): + "" - ERROR_PATH_NOT_FOUND + folder\ - OK + folder - OK + \ - OK + c:\ - OK + c: - OK, if current dir is ROOT ( c:\ ) + c: - OK, if current dir is NOT ROOT ( c:\folder ) + \\Server\Share - OK + \\Server\Share\ - OK + + \\ - ERROR_INVALID_NAME + \\Server - ERROR_INVALID_NAME + \\Server\ - ERROR_INVALID_NAME +*/ + +bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si) +{ + if (!Close()) + return false; + if (!g_FindFirstStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + SetLastError(0); + IF_USE_MAIN_PATH + _handle = g_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0); + if (_handle == INVALID_HANDLE_VALUE) + { + if (::GetLastError() == ERROR_HANDLE_EOF) + return false; + // long name can be tricky for path like ".\dirName". + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = g_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0); + } + #endif + } + if (_handle == INVALID_HANDLE_VALUE) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); + } + return true; +} + +bool CFindStream::FindNext(CStreamInfo &si) +{ + if (!g_FindNextStreamW) + { + ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; + } + { + MY_WIN32_FIND_STREAM_DATA sd; + if (!g_FindNextStreamW(_handle, &sd)) + return false; + Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si); + } + return true; +} + +bool CStreamEnumerator::Next(CStreamInfo &si, bool &found) +{ + bool res; + if (_find.IsHandleAllocated()) + res = _find.FindNext(si); + else + res = _find.FindFirst(_filePath, si); + if (res) + { + found = true; + return true; + } + found = false; + return (::GetLastError() == ERROR_HANDLE_EOF); +} + +#endif + + +/* +WinXP-64 GetFileAttributes(): + If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code + + \ - OK + C:\ - OK, if there is such drive, + D:\ - ERROR_PATH_NOT_FOUND, if there is no such drive, + + C:\folder - OK + C:\folder\ - OK + C:\folderBad - ERROR_FILE_NOT_FOUND + + \\Server\BadShare - ERROR_BAD_NETPATH + \\Server\Share - WORKS OK, but MSDN says: + GetFileAttributes for a network share, the function fails, and GetLastError + returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share. +*/ + +DWORD GetFileAttrib(CFSTR path) +{ + #ifndef _UNICODE + if (!g_IsNT) + return ::GetFileAttributes(fs2fas(path)); + else + #endif + { + IF_USE_MAIN_PATH + { + DWORD dw = ::GetFileAttributesW(fs2us(path)); + if (dw != INVALID_FILE_ATTRIBUTES) + return dw; + } + #ifdef WIN_LONG_PATH + if (USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + return ::GetFileAttributesW(superPath); + } + #endif + return INVALID_FILE_ATTRIBUTES; + } +} + +/* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk + so instead of absolute path we have relative path in Name. That is not good in some calls */ + +/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */ + +/* CFileInfo::Find() +We alow the following paths (as FindFirstFile): + C:\folder + c: - if current dir is NOT ROOT ( c:\folder ) + +also we support paths that are not supported by FindFirstFile: + \ + \\.\c: + c:\ - Name will be without tail slash ( c: ) + \\?\c:\ - Name will be without tail slash ( c: ) + \\Server\Share + \\?\UNC\Server\Share + + c:\folder:stream - Name = folder:stream + c:\:stream - Name = :stream + c::stream - Name = c::stream +*/ + +bool CFileInfo::Find(CFSTR path, bool followLink) +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDevicePath(path)) + { + ClearBase(); + Name = path + 4; + IsDevice = true; + + if (NName::IsDrivePath2(path + 4) && path[6] == 0) + { + FChar drive[4] = { path[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize)) + { + Size = totalSize; + return true; + } + } + + NIO::CInFile inFile; + // ::OutputDebugStringW(path); + if (!inFile.Open(path)) + return false; + // ::OutputDebugStringW(L"---"); + if (inFile.SizeDefined) + Size = inFile.Size; + return true; + } + #endif + + #if defined(_WIN32) && !defined(UNDER_CE) + + int colonPos = FindAltStreamColon(path); + if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) + { + UString streamName = fs2us(path + (unsigned)colonPos); + FString filePath (path); + filePath.DeleteFrom((unsigned)colonPos); + /* we allow both cases: + name:stream + name:stream:$DATA + */ + const unsigned kPostfixSize = 6; + if (streamName.Len() <= kPostfixSize + || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA")) + streamName += ":$DATA"; + + bool isOk = true; + + if (IsDrivePath2(filePath) && + (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\'))) + { + // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT) + ClearBase(); + Name.Empty(); + if (colonPos == 2) + Name = filePath; + } + else + isOk = Find(filePath, followLink); // check it (followLink) + + if (isOk) + { + Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT); + Size = 0; + CStreamEnumerator enumerator(filePath); + for (;;) + { + CStreamInfo si; + bool found; + if (!enumerator.Next(si, found)) + return false; + if (!found) + { + ::SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } + if (si.Name.IsEqualTo_NoCase(streamName)) + { + // we delete postfix, if alt stream name is not "::$DATA" + if (si.Name.Len() > kPostfixSize + 1) + si.Name.DeleteFrom(si.Name.Len() - kPostfixSize); + Name += us2fs(si.Name); + Size = si.Size; + IsAltStream = true; + return true; + } + } + } + } + + #endif + + CFindFile finder; + + #if defined(_WIN32) && !defined(UNDER_CE) + { + /* + DWORD lastError = GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND + || lastError == ERROR_BAD_NETPATH // XP64: "\\Server\Share" + || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share" + || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share" + || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share" + ) + */ + + unsigned rootSize = 0; + if (IsSuperPath(path)) + rootSize = kSuperPathPrefixSize; + + if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0) + { + DWORD attrib = GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + ClearBase(); + Attrib = attrib; + Name = path + rootSize; + Name.DeleteFrom(2); + if (!Fill_From_ByHandleFileInfo(path)) + { + } + return true; + } + } + else if (IS_PATH_SEPAR(path[0])) + { + if (path[1] == 0) + { + DWORD attrib = GetFileAttrib(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + ClearBase(); + Name.Empty(); + Attrib = attrib; + return true; + } + } + else + { + const unsigned prefixSize = GetNetworkServerPrefixSize(path); + if (prefixSize > 0 && path[prefixSize] != 0) + { + if (NName::FindSepar(path + prefixSize) < 0) + { + if (Fill_From_ByHandleFileInfo(path)) + { + Name = path + prefixSize; + return true; + } + + FString s (path); + s.Add_PathSepar(); + s += '*'; // CHAR_ANY_MASK + bool isOK = false; + if (finder.FindFirst(s, *this)) + { + if (Name == FTEXT(".")) + { + Name = path + prefixSize; + return true; + } + isOK = true; + /* if "\\server\share" maps to root folder "d:\", there is no "." item. + But it's possible that there are another items */ + } + { + DWORD attrib = GetFileAttrib(path); + if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)) + { + ClearBase(); + if (attrib != INVALID_FILE_ATTRIBUTES) + Attrib = attrib; + else + SetAsDir(); + Name = path + prefixSize; + return true; + } + } + // ::SetLastError(lastError); + } + } + } + } + } + #endif + + bool res = finder.FindFirst(path, *this); + if (!followLink + || !res + || !HasReparsePoint()) + return res; + + // return FollowReparse(path, IsDir()); + return Fill_From_ByHandleFileInfo(path); +} + +bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path) +{ + BY_HANDLE_FILE_INFORMATION info; + if (!NIO::CFileBase::GetFileInformation(path, &info)) + return false; + { + Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + CTime = info.ftCreationTime; + ATime = info.ftLastAccessTime; + MTime = info.ftLastWriteTime; + Attrib = info.dwFileAttributes; + return true; + } +} + +/* +bool CFileInfo::FollowReparse(CFSTR path, bool isDir) +{ + if (isDir) + { + FString prefix = path; + prefix.Add_PathSepar(); + + // "folder/." refers to folder itself. So we can't use that path + // we must use enumerator and search "." item + CEnumerator enumerator; + enumerator.SetDirPrefix(prefix); + for (;;) + { + CFileInfo fi; + if (!enumerator.NextAny(fi)) + break; + if (fi.Name.IsEqualTo_Ascii_NoCase(".")) + { + // we can copy preperies; + CTime = fi.CTime; + ATime = fi.ATime; + MTime = fi.MTime; + Attrib = fi.Attrib; + Size = fi.Size; + return true; + } + break; + } + // LastError(lastError); + return false; + } + + { + NIO::CInFile inFile; + if (inFile.Open(path)) + { + BY_HANDLE_FILE_INFORMATION info; + if (inFile.GetFileInformation(&info)) + { + ClearBase(); + Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + CTime = info.ftCreationTime; + ATime = info.ftLastAccessTime; + MTime = info.ftLastWriteTime; + Attrib = info.dwFileAttributes; + return true; + } + } + return false; + } +} +*/ + +bool DoesFileExist_Raw(CFSTR name) +{ + CFileInfo fi; + return fi.Find(name) && !fi.IsDir(); +} + +bool DoesFileExist_FollowLink(CFSTR name) +{ + CFileInfo fi; + return fi.Find_FollowLink(name) && !fi.IsDir(); +} + +bool DoesDirExist(CFSTR name, bool followLink) +{ + CFileInfo fi; + return fi.Find(name, followLink) && fi.IsDir(); +} + +bool DoesFileOrDirExist(CFSTR name) +{ + CFileInfo fi; + return fi.Find(name); +} + + +void CEnumerator::SetDirPrefix(const FString &dirPrefix) +{ + _wildcard = dirPrefix; + _wildcard += '*'; +} + +bool CEnumerator::NextAny(CFileInfo &fi) +{ + if (_findFile.IsHandleAllocated()) + return _findFile.FindNext(fi); + else + return _findFile.FindFirst(_wildcard, fi); +} + +bool CEnumerator::Next(CFileInfo &fi) +{ + for (;;) + { + if (!NextAny(fi)) + return false; + if (!fi.IsDots()) + return true; + } +} + +bool CEnumerator::Next(CFileInfo &fi, bool &found) +{ + /* + for (;;) + { + if (!NextAny(fi)) + break; + if (!fi.IsDots()) + { + found = true; + return true; + } + } + */ + + if (Next(fi)) + { + found = true; + return true; + } + + found = false; + DWORD lastError = ::GetLastError(); + if (_findFile.IsHandleAllocated()) + return (lastError == ERROR_NO_MORE_FILES); + // we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND + if (lastError == ERROR_FILE_NOT_FOUND) + return true; + if (lastError == ERROR_ACCESS_DENIED) + { + // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings + const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*"; + const int len = (int)strlen(s); + const int delta = (int)_wildcard.Len() - len; + if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1]))) + if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s)) + return true; + } + return false; +} + + +//////////////////////////////// +// CFindChangeNotification +// FindFirstChangeNotification can return 0. MSDN doesn't tell about it. + +bool CFindChangeNotification::Close() throw() +{ + if (!IsHandleAllocated()) + return true; + if (!::FindCloseChangeNotification(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter) +{ + #ifndef _UNICODE + if (!g_IsNT) + _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter); + else + #endif + { + IF_USE_MAIN_PATH + _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter); + #ifdef WIN_LONG_PATH + if (!IsHandleAllocated()) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter); + } + #endif + } + return _handle; +} + +#ifndef UNDER_CE + +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings) +{ + driveStrings.Clear(); + #ifndef _UNICODE + if (!g_IsNT) + { + driveStrings.Clear(); + UINT32 size = GetLogicalDriveStrings(0, NULL); + if (size == 0) + return false; + CObjArray buf(size); + UINT32 newSize = GetLogicalDriveStrings(size, buf); + if (newSize == 0 || newSize > size) + return false; + AString s; + UINT32 prev = 0; + for (UINT32 i = 0; i < newSize; i++) + { + if (buf[i] == 0) + { + s = buf + prev; + prev = i + 1; + driveStrings.Add(fas2fs(s)); + } + } + return prev == newSize; + } + else + #endif + { + UINT32 size = GetLogicalDriveStringsW(0, NULL); + if (size == 0) + return false; + CObjArray buf(size); + UINT32 newSize = GetLogicalDriveStringsW(size, buf); + if (newSize == 0 || newSize > size) + return false; + UString s; + UINT32 prev = 0; + for (UINT32 i = 0; i < newSize; i++) + { + if (buf[i] == 0) + { + s = buf + prev; + prev = i + 1; + driveStrings.Add(us2fs(s)); + } + } + return prev == newSize; + } +} + +#endif // UNDER_CE + + + +#else // _WIN32 + +// ---------- POSIX ---------- + +static int MY__lstat(CFSTR path, struct stat *st, bool followLink) +{ + memset(st, 0, sizeof(*st)); + int res; + // #ifdef ENV_HAVE_LSTAT + if (/* global_use_lstat && */ !followLink) + { + // printf("\nlstat\n"); + res = lstat(path, st); + } + else + // #endif + { + // printf("\nstat\n"); + res = stat(path, st); + } + /* + printf("\nres = %d\n", res); + printf("\n st_dev = %lld \n", (long long)(st->st_dev)); + printf("\n st_ino = %lld \n", (long long)(st->st_ino)); + printf("\n st_mode = %lld \n", (long long)(st->st_mode)); + printf("\n st_nlink = %lld \n", (long long)(st->st_nlink)); + printf("\n st_uid = %lld \n", (long long)(st->st_uid)); + printf("\n st_gid = %lld \n", (long long)(st->st_gid)); + printf("\n st_size = %lld \n", (long long)(st->st_size)); + printf("\n st_blksize = %lld \n", (long long)(st->st_blksize)); + printf("\n st_blocks = %lld \n", (long long)(st->st_blocks)); + */ + + return res; +} + + +static const char *Get_Name_from_Path(CFSTR path) throw() +{ + size_t len = strlen(path); + if (len == 0) + return path; + const char *p = path + len - 1; + { + if (p == path) + return path; + p--; + } + for (;;) + { + char c = *p; + if (IS_PATH_SEPAR(c)) + return p + 1; + if (p == path) + return path; + p--; + } +} + + +void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft) +{ + UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) +{ + UInt32 attrib = S_ISDIR(mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((mode & 0222) == 0) // S_IWUSR in p7zip + attrib |= FILE_ATTRIBUTE_READONLY; + return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16); +} + +/* +UInt32 Get_WinAttrib_From_stat(const struct stat &st) +{ + UInt32 attrib = S_ISDIR(st.st_mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + + if ((st.st_mode & 0222) == 0) // check it !!! + attrib |= FILE_ATTRIBUTE_READONLY; + + attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16); + return attrib; +} +*/ + +void CFileInfo::SetFrom_stat(const struct stat &st) +{ + IsDevice = false; + + if (S_ISDIR(st.st_mode)) + { + Size = 0; + } + else + { + Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename + } + + Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); + + // NTime::UnixTimeToFileTime(st.st_ctime, CTime); + // NTime::UnixTimeToFileTime(st.st_mtime, MTime); + // NTime::UnixTimeToFileTime(st.st_atime, ATime); + #ifdef __APPLE__ + timespec_To_FILETIME(st.st_ctimespec, CTime); + timespec_To_FILETIME(st.st_mtimespec, MTime); + timespec_To_FILETIME(st.st_atimespec, ATime); + #else + timespec_To_FILETIME(st.st_ctim, CTime); + timespec_To_FILETIME(st.st_mtim, MTime); + timespec_To_FILETIME(st.st_atim, ATime); + #endif + + dev = st.st_dev; + ino = st.st_ino; + nlink = st.st_nlink; + mode = st.st_mode; +} + +bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) +{ + struct stat st; + if (MY__lstat(path, &st, followLink) != 0) + return false; + SetFrom_stat(st); + return true; +} + + +bool CFileInfo::Find(CFSTR path, bool followLink) +{ + // printf("\nCEnumerator::Find() name = %s\n", path); + if (!Find_DontFill_Name(path, followLink)) + return false; + + // printf("\nOK\n"); + + Name = Get_Name_from_Path(path); + if (!Name.IsEmpty()) + { + char c = Name.Back(); + if (IS_PATH_SEPAR(c)) + Name.DeleteBack(); + } + return true; +} + + +bool DoesFileExist_Raw(CFSTR name) +{ + // FIXME for symbolic links. + struct stat st; + if (MY__lstat(name, &st, false) != 0) + return false; + return !S_ISDIR(st.st_mode); +} + +bool DoesFileExist_FollowLink(CFSTR name) +{ + // FIXME for symbolic links. + struct stat st; + if (MY__lstat(name, &st, true) != 0) + return false; + return !S_ISDIR(st.st_mode); +} + +bool DoesDirExist(CFSTR name, bool followLink) +{ + struct stat st; + if (MY__lstat(name, &st, followLink) != 0) + return false; + return S_ISDIR(st.st_mode); +} + +bool DoesFileOrDirExist(CFSTR name) +{ + struct stat st; + if (MY__lstat(name, &st, false) != 0) + return false; + return true; +} + + +CEnumerator::~CEnumerator() +{ + if (_dir) + closedir(_dir); +} + +void CEnumerator::SetDirPrefix(const FString &dirPrefix) +{ + _wildcard = dirPrefix; +} + +bool CDirEntry::IsDots() const throw() +{ + if ( + #if !defined(_AIX) + !IsDir() || + #endif + Name.IsEmpty()) + return false; + if (Name[0] != '.') + return false; + return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.'); +} + + +bool CEnumerator::NextAny(CDirEntry &fi, bool &found) +{ + found = false; + + if (!_dir) + { + const char *w = "./"; + if (!_wildcard.IsEmpty()) + w = _wildcard.Ptr(); + _dir = ::opendir((const char *)w); + if (_dir == NULL) + return false; + } + + // To distinguish end of stream from an error, we must set errno to zero before readdir() + errno = 0; + + struct dirent *de = readdir(_dir); + if (!de) + { + if (errno == 0) + return true; // it's end of stream, and we report it with (found = false) + // it's real error + return false; + } + + fi.iNode = de->d_ino; + + #if !defined(_AIX) + fi.Type = de->d_type; + #endif + + /* + if (de->d_type == DT_DIR) + fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16); + else if (de->d_type < 16) + fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12)); + */ + fi.Name = de->d_name; + + /* + printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr()); + for (unsigned i = 0; i < fi.Name.Len(); i++) + printf (" %02x", (unsigned)(Byte)de->d_name[i]); + printf("\n"); + */ + + found = true; + return true; +} + + +bool CEnumerator::Next(CDirEntry &fi, bool &found) +{ + // printf("\nCEnumerator::Next()\n"); + // PrintName("Next", ""); + for (;;) + { + if (!NextAny(fi, found)) + return false; + if (!found) + return true; + if (!fi.IsDots()) + { + /* + if (!NeedFullStat) + return true; + // we silently skip error file here - it can be wrong link item + if (fi.Find_DontFill_Name(path)) + return true; + */ + return true; + } + } +} + +/* +bool CEnumerator::Next(CDirEntry &fileInfo, bool &found) +{ + bool found; + if (!Next(fi, found)) + return false; + return found; +} +*/ + +bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) +{ + // printf("\nCEnumerator::Fill_FileInfo()\n"); + struct stat st; + // probably it's OK to use fstatat() even if it changes file position dirfd(_dir) + int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW); + // if fstatat() is not supported, we can use stat() / lstat() + + /* + const FString path = _wildcard + s; + int res = MY__lstat(path, &st, followLink); + */ + + if (res != 0) + return false; + fileInfo.SetFrom_stat(st); + fileInfo.Name = de.Name; + return true; +} + +#endif // _WIN32 + +}}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.h new file mode 100644 index 0000000..009e84e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileFind.h @@ -0,0 +1,279 @@ +// Windows/FileFind.h + +#ifndef __WINDOWS_FILE_FIND_H +#define __WINDOWS_FILE_FIND_H + +#ifndef _WIN32 +#include +#include +#include +#endif + +#include "../Common/MyString.h" +#include "../Common/MyWindows.h" +#include "Defs.h" + +namespace NWindows { +namespace NFile { +namespace NFind { + +// bool DoesFileExist(CFSTR name, bool followLink); +bool DoesFileExist_Raw(CFSTR name); +bool DoesFileExist_FollowLink(CFSTR name); +bool DoesDirExist(CFSTR name, bool followLink); + +inline bool DoesDirExist(CFSTR name) + { return DoesDirExist(name, false); } +inline bool DoesDirExist_FollowLink(CFSTR name) + { return DoesDirExist(name, true); } + +// it's always _Raw +bool DoesFileOrDirExist(CFSTR name); + +DWORD GetFileAttrib(CFSTR path); + + +namespace NAttributes +{ + inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } + inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } + inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } + inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } + inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } + inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } + inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } +} + +class CFileInfoBase +{ + bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } +public: + UInt64 Size; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + DWORD Attrib; + bool IsAltStream; + bool IsDevice; + + #ifdef _WIN32 + /* + #ifdef UNDER_CE + DWORD ObjectID; + #else + UINT32 ReparseTag; + #endif + */ + #else + dev_t dev; + ino_t ino; + nlink_t nlink; + mode_t mode; + // bool Use_lstat; + #endif + + CFileInfoBase() { ClearBase(); } + void ClearBase() throw(); + + void SetAsDir() + { + Attrib = FILE_ATTRIBUTE_DIRECTORY; + #ifndef _WIN32 + Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); + #endif + } + + bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } + bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } + bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } + bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } + bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } + bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } + bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } + bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } + bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } + bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } + bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } + bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } + + #ifndef _WIN32 + bool IsPosixLink() const + { + const UInt32 mod = Attrib >> 16; + return S_ISLNK(mod); + } + #endif +}; + +struct CFileInfo: public CFileInfoBase +{ + FString Name; + #if defined(_WIN32) && !defined(UNDER_CE) + // FString ShortName; + #endif + + bool IsDots() const throw(); + bool Find(CFSTR path, bool followLink = false); + bool Find_FollowLink(CFSTR path) { return Find(path, true); } + + #ifdef _WIN32 + bool Fill_From_ByHandleFileInfo(CFSTR path); + // bool FollowReparse(CFSTR path, bool isDir); + #else + bool Find_DontFill_Name(CFSTR path, bool followLink = false); + void SetFrom_stat(const struct stat &st); + #endif +}; + + +#ifdef _WIN32 + +class CFindFileBase MY_UNCOPYABLE +{ +protected: + HANDLE _handle; +public: + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } + CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindFileBase() { Close(); } + bool Close() throw(); +}; + +class CFindFile: public CFindFileBase +{ +public: + bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo); + bool FindNext(CFileInfo &fileInfo); +}; + +#if defined(_WIN32) && !defined(UNDER_CE) + +struct CStreamInfo +{ + UString Name; + UInt64 Size; + + UString GetReducedName() const; // returns ":Name" + // UString GetReducedName2() const; // returns "Name" + bool IsMainStream() const throw(); +}; + +class CFindStream: public CFindFileBase +{ +public: + bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo); + bool FindNext(CStreamInfo &streamInfo); +}; + +class CStreamEnumerator MY_UNCOPYABLE +{ + CFindStream _find; + FString _filePath; + + bool NextAny(CFileInfo &fileInfo, bool &found); +public: + CStreamEnumerator(const FString &filePath): _filePath(filePath) {} + bool Next(CStreamInfo &streamInfo, bool &found); +}; + +#endif // defined(_WIN32) && !defined(UNDER_CE) + + +class CEnumerator MY_UNCOPYABLE +{ + CFindFile _findFile; + FString _wildcard; + + bool NextAny(CFileInfo &fileInfo); +public: + void SetDirPrefix(const FString &dirPrefix); + bool Next(CFileInfo &fileInfo); + bool Next(CFileInfo &fileInfo, bool &found); +}; + + +class CFindChangeNotification MY_UNCOPYABLE +{ + HANDLE _handle; +public: + operator HANDLE () { return _handle; } + bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } + CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} + ~CFindChangeNotification() { Close(); } + bool Close() throw(); + HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter); + bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } +}; + +#ifndef UNDER_CE +bool MyGetLogicalDriveStrings(CObjectVector &driveStrings); +#endif + +typedef CFileInfo CDirEntry; + + +#else // WIN32 + + +struct CDirEntry +{ + ino_t iNode; + #if !defined(_AIX) + Byte Type; + #endif + FString Name; + + #if !defined(_AIX) + bool IsDir() const + { + // DT_DIR is + return Type == DT_DIR; + } + #endif + + bool IsDots() const throw(); +}; + +class CEnumerator MY_UNCOPYABLE +{ + DIR *_dir; + FString _wildcard; + + bool NextAny(CDirEntry &fileInfo, bool &found); +public: + CEnumerator(): _dir(NULL) {} + ~CEnumerator(); + void SetDirPrefix(const FString &dirPrefix); + + bool Next(CDirEntry &fileInfo, bool &found); + bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink); +}; + +/* +inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode) +{ + UInt32 attrib = S_ISDIR(mode) ? + FILE_ATTRIBUTE_DIRECTORY : + FILE_ATTRIBUTE_ARCHIVE; + if ((st.st_mode & 0222) == 0) // check it !!! + attrib |= FILE_ATTRIBUTE_READONLY; + return attrib; +} +*/ + +UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode); + +// UInt32 Get_WinAttrib_From_stat(const struct stat &st); +#if defined(_AIX) + #define MY_ST_TIMESPEC st_timespec +#else + #define MY_ST_TIMESPEC timespec +#endif + +void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft); + +#endif // WIN32 + +}}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.cpp new file mode 100644 index 0000000..b6f2f26 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.cpp @@ -0,0 +1,730 @@ +// Windows/FileIO.cpp + +#include "StdAfx.h" + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +// #include + +#include "FileIO.h" +#include "FileName.h" + +HRESULT GetLastError_noZero_HRESULT() +{ + DWORD res = ::GetLastError(); + if (res == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(res); +} + +#ifdef _WIN32 + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +namespace NWindows { +namespace NFile { + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif + +namespace NIO { + +/* +WinXP-64 CreateFile(): + "" - ERROR_PATH_NOT_FOUND + :stream - OK + .:stream - ERROR_PATH_NOT_FOUND + .\:stream - OK + + folder\:stream - ERROR_INVALID_NAME + folder:stream - OK + + c:\:stream - OK + + c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 ) + c::stream - OK, if current dir is ROOT ( c:\ ) +*/ + +bool CFileBase::Create(CFSTR path, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + if (!Close()) + return false; + + #ifdef SUPPORT_DEVICE_FILE + IsDeviceFile = false; + #endif + + #ifndef _UNICODE + if (!g_IsNT) + { + _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + else + #endif + { + IF_USE_MAIN_PATH + _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + #ifdef WIN_LONG_PATH + if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH) + { + UString superPath; + if (GetSuperPath(path, superPath, USE_MAIN_PATH)) + _handle = ::CreateFileW(superPath, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); + } + #endif + } + + /* + #ifndef UNDER_CE + #ifndef _SFX + if (_handle == INVALID_HANDLE_VALUE) + { + // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10 + DWORD lastError = GetLastError(); + if (lastError == ERROR_CANT_ACCESS_FILE) + { + CByteBuffer buf; + if (NIO::GetReparseData(path, buf, NULL)) + { + CReparseAttr attr; + if (attr.Parse(buf, buf.Size())) + { + FString dirPrefix, fileName; + if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName)) + { + FString fullPath; + if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath)) + { + // FIX IT: recursion levels must be restricted + return Create(fullPath, desiredAccess, + shareMode, creationDisposition, flagsAndAttributes); + } + } + } + } + SetLastError(lastError); + } + } + #endif + #endif + */ + + return (_handle != INVALID_HANDLE_VALUE); +} + +bool CFileBase::Close() throw() +{ + if (_handle == INVALID_HANDLE_VALUE) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = INVALID_HANDLE_VALUE; + return true; +} + +bool CFileBase::GetPosition(UInt64 &position) const throw() +{ + return Seek(0, FILE_CURRENT, position); +} + +bool CFileBase::GetLength(UInt64 &length) const throw() +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && SizeDefined) + { + length = Size; + return true; + } + #endif + + DWORD sizeHigh; + DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + if (::GetLastError() != NO_ERROR) + return false; + length = (((UInt64)sizeHigh) << 32) + sizeLow; + return true; +} + +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw() +{ + #ifdef SUPPORT_DEVICE_FILE + if (IsDeviceFile && SizeDefined && moveMethod == FILE_END) + { + distanceToMove += Size; + moveMethod = FILE_BEGIN; + } + #endif + + LONG high = (LONG)(distanceToMove >> 32); + DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod); + if (low == 0xFFFFFFFF) + if (::GetLastError() != NO_ERROR) + return false; + newPosition = (((UInt64)(UInt32)high) << 32) + low; + return true; +} + +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw() +{ + return Seek((Int64)position, FILE_BEGIN, newPosition); +} + +bool CFileBase::SeekToBegin() const throw() +{ + UInt64 newPosition; + return Seek(0, newPosition); +} + +bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw() +{ + return Seek(0, FILE_END, newPosition); +} + +// ---------- CInFile --------- + +#ifdef SUPPORT_DEVICE_FILE + +void CInFile::CorrectDeviceSize() +{ + // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail + static const UInt32 kClusterSize = 1 << 14; + UInt64 pos = Size & ~(UInt64)(kClusterSize - 1); + UInt64 realNewPosition; + if (!Seek(pos, realNewPosition)) + return; + Byte *buf = (Byte *)MidAlloc(kClusterSize); + + bool needbackward = true; + + for (;;) + { + UInt32 processed = 0; + // up test is slow for "PhysicalDrive". + // processed size for latest block for "PhysicalDrive0" is 0. + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed == 0) + break; + needbackward = false; + Size = pos + processed; + if (processed != kClusterSize) + break; + pos += kClusterSize; + } + + if (needbackward && pos != 0) + { + pos -= kClusterSize; + for (;;) + { + // break; + if (!Seek(pos, realNewPosition)) + break; + if (!buf) + { + buf = (Byte *)MidAlloc(kClusterSize); + if (!buf) + break; + } + UInt32 processed = 0; + // that code doesn't work for "PhysicalDrive0" + if (!Read1(buf, kClusterSize, processed)) + break; + if (processed != 0) + { + Size = pos + processed; + break; + } + if (pos == 0) + break; + pos -= kClusterSize; + } + } + MidFree(buf); +} + + +void CInFile::CalcDeviceSize(CFSTR s) +{ + SizeDefined = false; + Size = 0; + if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile) + return; + #ifdef UNDER_CE + + SizeDefined = true; + Size = 128 << 20; + + #else + + PARTITION_INFORMATION partInfo; + bool needCorrectSize = true; + + /* + WinXP 64-bit: + + HDD \\.\PhysicalDrive0 (MBR): + GetPartitionInfo == GeometryEx : corrrect size? (includes tail) + Geometry : smaller than GeometryEx (no tail, maybe correct too?) + MyGetDiskFreeSpace : FAIL + Size correction is slow and block size (kClusterSize) must be small? + + HDD partition \\.\N: (NTFS): + MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction + GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS + Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition) + + CD-ROM drive (ISO): + MyGetDiskFreeSpace : correct size. Same size can be calculated after correction + Geometry == CdRomGeometry : smaller than corrrect size + GetPartitionInfo == GeometryEx : larger than corrrect size + + Floppy \\.\a: (FAT): + Geometry : correct size. + CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL + correction works OK for FAT. + correction works OK for non-FAT, if kClusterSize = 512. + */ + + if (GetPartitionInfo(&partInfo)) + { + Size = (UInt64)partInfo.PartitionLength.QuadPart; + SizeDefined = true; + needCorrectSize = false; + if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0) + { + FChar path[4] = { s[4], ':', '\\', 0 }; + UInt64 clusterSize, totalSize, freeSize; + if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize)) + Size = totalSize; + else + needCorrectSize = true; + } + } + + if (!SizeDefined) + { + my_DISK_GEOMETRY_EX geomEx; + SizeDefined = GetGeometryEx(&geomEx); + if (SizeDefined) + Size = (UInt64)geomEx.DiskSize.QuadPart; + else + { + DISK_GEOMETRY geom; + SizeDefined = GetGeometry(&geom); + if (!SizeDefined) + SizeDefined = GetCdRomGeometry(&geom); + if (SizeDefined) + Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector; + } + } + + if (needCorrectSize && SizeDefined && Size != 0) + { + CorrectDeviceSize(); + SeekToBegin(); + } + + // SeekToBegin(); + #endif +} + +// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 && + +#define MY_DEVICE_EXTRA_CODE \ + IsDeviceFile = IsDevicePath(fileName); \ + CalcDeviceSize(fileName); +#else +#define MY_DEVICE_EXTRA_CODE +#endif + +bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + DWORD desiredAccess = GENERIC_READ; + + #ifdef _WIN32 + if (PreserveATime) + desiredAccess |= FILE_WRITE_ATTRIBUTES; + #endif + + bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes); + + #ifdef _WIN32 + if (res && PreserveATime) + { + FILETIME ft; + ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF; + ::SetFileTime(_handle, NULL, &ft, NULL); + } + #endif + + MY_DEVICE_EXTRA_CODE + return res; +} + +bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite) +{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } + +bool CInFile::Open(CFSTR fileName) + { return OpenShared(fileName, false); } + +// ReadFile and WriteFile functions in Windows have BUG: +// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) +// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES +// (Insufficient system resources exist to complete the requested service). + +// Probably in some version of Windows there are problems with other sizes: +// for 32 MB (maybe also for 16 MB). +// And message can be "Network connection was lost" + +static const UInt32 kChunkSizeMax = (1 << 22); + +bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + DWORD processedLoc = 0; + bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return Read1(data, size, processedSize); +} + +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = ReadPart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (void *)((unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size); + const bool res = Read1(data, sizeLoc, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (void *)((unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +// ---------- COutFile --------- + +static inline DWORD GetCreationDisposition(bool createAlways) + { return createAlways? CREATE_ALWAYS: CREATE_NEW; } + +bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +bool COutFile::Open(CFSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(CFSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +bool COutFile::CreateAlways(CFSTR fileName, DWORD flagsAndAttributes) + { return Open(fileName, FILE_SHARE_READ, GetCreationDisposition(true), flagsAndAttributes); } + +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() + { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } + +bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); } + +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + DWORD processedLoc = 0; + bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw() +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = WritePart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (const void *)((const unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); } + +bool COutFile::SetLength(UInt64 length) throw() +{ + UInt64 newPosition; + if (!Seek(length, newPosition)) + return false; + if (newPosition != length) + return false; + return SetEndOfFile(); +} + +}}} + +#else // _WIN32 + + +// POSIX + +#include +#include + +namespace NWindows { +namespace NFile { + +namespace NDir { +bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); +} + +namespace NIO { + +bool CFileBase::OpenBinary(const char *name, int flags) +{ + #ifdef O_BINARY + flags |= O_BINARY; + #endif + + Close(); + _handle = ::open(name, flags, 0666); + return _handle != -1; +} + +bool CFileBase::Close() +{ + if (_handle == -1) + return true; + if (close(_handle) != 0) + return false; + _handle = -1; + return true; +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + const off_t curPos = seek(0, SEEK_CUR); + if (curPos == -1) + return false; + const off_t lengthTemp = seek(0, SEEK_END); + seek(curPos, SEEK_SET); + length = (UInt64)lengthTemp; + return (lengthTemp != -1); +} + +off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const +{ + // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); + // off_t res = ::lseek(_handle, distanceToMove, moveMethod); + return ::lseek(_handle, distanceToMove, moveMethod); + // printf(" res = %lld", (long long)res); + // return res; +} + +off_t CFileBase::seekToBegin() const throw() +{ + return seek(0, SEEK_SET); +} + +/* +bool CFileBase::SeekToBegin() const throw() +{ + return (::seek(0, SEEK_SET) != -1); +} +*/ + + +///////////////////////// +// CInFile + +bool CInFile::Open(const char *name) +{ + return CFileBase::OpenBinary(name, O_RDONLY); +} + +bool CInFile::OpenShared(const char *name, bool) +{ + return Open(name); +} + +/* +On Linux (32-bit and 64-bit): +read(), write() (and similar system calls) will transfer at most +0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred. +*/ + +static const size_t kChunkSizeMax = ((size_t)1 << 22); + +ssize_t CInFile::read_part(void *data, size_t size) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return ::read(_handle, data, size); +} + +bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw() +{ + processed = 0; + do + { + const ssize_t res = read_part(data, size); + if (res < 0) + return false; + if (res == 0) + break; + data = (void *)((unsigned char *)data + (size_t)res); + size -= (size_t)res; + processed += (size_t)res; + } + while (size > 0); + return true; +} + + +///////////////////////// +// COutFile + +bool COutFile::Create(const char *name, bool createAlways) +{ + Path = name; // change it : set it only if open is success. + if (createAlways) + { + Close(); + _handle = ::creat(name, 0666); + return _handle != -1; + } + return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); +} + +bool COutFile::Open(const char *name, DWORD creationDisposition) +{ + UNUSED_VAR(creationDisposition) // FIXME + return Create(name, false); +} + +ssize_t COutFile::write_part(const void *data, size_t size) throw() +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + return ::write(_handle, data, size); +} + +ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw() +{ + processed = 0; + do + { + const ssize_t res = write_part(data, size); + if (res < 0) + return res; + if (res == 0) + break; + data = (const void *)((const unsigned char *)data + (size_t)res); + size -= (size_t)res; + processed += (size_t)res; + } + while (size > 0); + return (ssize_t)processed; +} + +bool COutFile::SetLength(UInt64 length) throw() +{ + const off_t len2 = (off_t)length; + if ((Int64)length != len2) + { + SetLastError(EFBIG); + return false; + } + int iret = ftruncate(_handle, len2); + return (iret == 0); +} + +bool COutFile::Close() +{ + bool res = CFileBase::Close(); + if (!res) + return res; + if (CTime_defined || ATime_defined || MTime_defined) + { + /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, + CTime_defined ? &CTime : NULL, + ATime_defined ? &ATime : NULL, + MTime_defined ? &MTime : NULL); + } + return res; +} + +bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() +{ + // On some OS (cygwin, MacOSX ...), you must close the file before updating times + // return true; + + if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false; + if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; + if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; + return true; +} + +bool COutFile::SetMTime(const FILETIME *mTime) throw() +{ + if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; + return true; +} + +}}} + + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.h new file mode 100644 index 0000000..276e595 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileIO.h @@ -0,0 +1,330 @@ +// Windows/FileIO.h + +#ifndef __WINDOWS_FILE_IO_H +#define __WINDOWS_FILE_IO_H + +#include "../Common/MyWindows.h" + +#define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) +#define _my_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL) + +#define _my_SYMLINK_FLAG_RELATIVE 1 + +// what the meaning of that FLAG or field (2)? +#define _my_LX_SYMLINK_FLAG 2 + +#ifdef _WIN32 + +#if defined(_WIN32) && !defined(UNDER_CE) +#include +#endif + +#else + +#include +#include + +#endif + +#include "../Common/MyString.h" +#include "../Common/MyBuffer.h" + +#include "Defs.h" + +HRESULT GetLastError_noZero_HRESULT(); + +#define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER +#define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER + +namespace NWindows { +namespace NFile { + +#if defined(_WIN32) && !defined(UNDER_CE) +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL); +#endif + +struct CReparseShortInfo +{ + unsigned Offset; + unsigned Size; + + bool Parse(const Byte *p, size_t size); +}; + +struct CReparseAttr +{ + UInt32 Tag; + UInt32 Flags; + UString SubsName; + UString PrintName; + + AString WslName; + + bool HeaderError; + bool TagIsUnknown; + bool MinorError; + DWORD ErrorCode; + + CReparseAttr(): Tag(0), Flags(0) {} + + // Parse() + // returns (true) and (ErrorCode = 0), if (it'a correct known link) + // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag + bool Parse(const Byte *p, size_t size); + + bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction + bool IsSymLink_Win() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } + bool IsSymLink_WSL() const { return Tag == _my_IO_REPARSE_TAG_LX_SYMLINK; } + + bool IsRelative_Win() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } + + bool IsRelative_WSL() const + { + if (WslName.IsEmpty()) + return true; + char c = WslName[0]; + return !IS_PATH_SEPAR(c); + } + + // bool IsVolume() const; + + bool IsOkNamePair() const; + UString GetPath() const; +}; + + +#ifdef _WIN32 + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); +bool DeleteReparseData(CFSTR path); + +class CFileBase MY_UNCOPYABLE +{ +protected: + HANDLE _handle; + + bool Create(CFSTR path, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + +public: + + bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, + LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const + { + return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, + outBuffer, outSize, bytesReturned, overlapped)); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const + { + return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); + } + + bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const + { + DWORD bytesReturned; + return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); + } + +public: + bool PreserveATime; + #ifdef SUPPORT_DEVICE_FILE + bool IsDeviceFile; + bool SizeDefined; + UInt64 Size; // it can be larger than real available size + #endif + + CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; + ~CFileBase() { Close(); } + + bool Close() throw(); + + bool GetPosition(UInt64 &position) const throw(); + bool GetLength(UInt64 &length) const throw(); + + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); + bool Seek(UInt64 position, UInt64 &newPosition) const throw(); + bool SeekToBegin() const throw(); + bool SeekToEnd(UInt64 &newPosition) const throw(); + + bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const + { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } + + static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) + { + // probably it can work for complex paths: unsupported by another things + NIO::CFileBase file; + if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) + return false; + return file.GetFileInformation(info); + } +}; + +#ifndef UNDER_CE +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) +// #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) + +// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP +#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) + +struct my_DISK_GEOMETRY_EX +{ + DISK_GEOMETRY Geometry; + LARGE_INTEGER DiskSize; + BYTE Data[1]; +}; +#endif + +class CInFile: public CFileBase +{ + #ifdef SUPPORT_DEVICE_FILE + + #ifndef UNDER_CE + + bool GetGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const + { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } + + bool GetCdRomGeometry(DISK_GEOMETRY *res) const + { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } + + bool GetPartitionInfo(PARTITION_INFORMATION *res) + { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } + + #endif + + void CorrectDeviceSize(); + void CalcDeviceSize(CFSTR name); + + #endif + +public: + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool OpenShared(CFSTR fileName, bool shareForWrite); + bool Open(CFSTR fileName); + + #ifndef UNDER_CE + + bool OpenReparse(CFSTR fileName) + { + // 17.02 fix: to support Windows XP compatibility junctions: + // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ + return + Create(fileName, 0, + // Open(fileName, + FILE_SHARE_READ, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); + } + + #endif + + bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); + bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); +}; + +class COutFile: public CFileBase +{ +public: + bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(CFSTR fileName, DWORD creationDisposition); + bool Create(CFSTR fileName, bool createAlways); + bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); + + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); + bool SetEndOfFile() throw(); + bool SetLength(UInt64 length) throw(); +}; + +} + + +#else // _WIN32 + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData); +// bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); + +// parameters are in reverse order of symlink() function !!! +bool SetSymLink(CFSTR from, CFSTR to); +bool SetSymLink_UString(CFSTR from, const UString &to); + + +class CFileBase +{ +protected: + int _handle; + + bool OpenBinary(const char *name, int flags); +public: + bool PreserveATime; + + CFileBase(): _handle(-1), PreserveATime(false) {}; + ~CFileBase() { Close(); } + bool Close(); + bool GetLength(UInt64 &length) const; + off_t seek(off_t distanceToMove, int moveMethod) const; + off_t seekToBegin() const throw(); + // bool SeekToBegin() throw(); + int my_fstat(struct stat *st) const { return fstat(_handle, st); } +}; + +class CInFile: public CFileBase +{ +public: + bool Open(const char *name); + bool OpenShared(const char *name, bool shareForWrite); + ssize_t read_part(void *data, size_t size) throw(); + // ssize_t read_full(void *data, size_t size, size_t &processed); + bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); +}; + +class COutFile: public CFileBase +{ + bool CTime_defined; + bool ATime_defined; + bool MTime_defined; + + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + + AString Path; + ssize_t write_part(const void *data, size_t size) throw(); +public: + COutFile(): + CTime_defined(false), + ATime_defined(false), + MTime_defined(false) + {} + + bool Close(); + bool Create(const char *name, bool createAlways); + bool Open(const char *name, DWORD creationDisposition); + ssize_t write_full(const void *data, size_t size, size_t &processed) throw(); + bool SetLength(UInt64 length) throw(); + bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); + bool SetMTime(const FILETIME *mTime) throw(); +}; + +} + +#endif // _WIN32 + +}} + + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileLink.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileLink.cpp new file mode 100644 index 0000000..8ce634f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileLink.cpp @@ -0,0 +1,613 @@ +// Windows/FileLink.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#ifndef _WIN32 +#include +#endif + +#ifdef SUPPORT_DEVICE_FILE +#include "../../C/Alloc.h" +#endif + +#include "../Common/UTFConvert.h" +#include "../Common/StringConvert.h" + +#include "FileDir.h" +#include "FileFind.h" +#include "FileIO.h" +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { + +using namespace NName; + +/* + Reparse Points (Junctions and Symbolic Links): + struct + { + UInt32 Tag; + UInt16 Size; // not including starting 8 bytes + UInt16 Reserved; // = 0 + + UInt16 SubstituteOffset; // offset in bytes from start of namesChars + UInt16 SubstituteLen; // size in bytes, it doesn't include tailed NUL + UInt16 PrintOffset; // offset in bytes from start of namesChars + UInt16 PrintLen; // size in bytes, it doesn't include tailed NUL + + [UInt32] Flags; // for Symbolic Links only. + + UInt16 namesChars[] + } + + MOUNT_POINT (Junction point): + 1) there is NUL wchar after path + 2) Default Order in table: + Substitute Path + Print Path + 3) pathnames can not contain dot directory names + + SYMLINK: + 1) there is no NUL wchar after path + 2) Default Order in table: + Print Path + Substitute Path +*/ + +/* +Win10 WSL2: +admin rights + sudo: it creates normal windows symbolic link. +in another cases : it creates IO_REPARSE_TAG_LX_SYMLINK repare point. +*/ + +/* +static const UInt32 kReparseFlags_Alias = (1 << 29); +static const UInt32 kReparseFlags_HighLatency = (1 << 30); +static const UInt32 kReparseFlags_Microsoft = ((UInt32)1 << 31); + +#define _my_IO_REPARSE_TAG_HSM (0xC0000004L) +#define _my_IO_REPARSE_TAG_HSM2 (0x80000006L) +#define _my_IO_REPARSE_TAG_SIS (0x80000007L) +#define _my_IO_REPARSE_TAG_WIM (0x80000008L) +#define _my_IO_REPARSE_TAG_CSV (0x80000009L) +#define _my_IO_REPARSE_TAG_DFS (0x8000000AL) +#define _my_IO_REPARSE_TAG_DFSR (0x80000012L) +*/ + +#define Get16(p) GetUi16(p) +#define Get32(p) GetUi32(p) + +static const wchar_t * const k_LinkPrefix = L"\\??\\"; +static const unsigned k_LinkPrefix_Size = 4; + +static bool IsLinkPrefix(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_LinkPrefix); +} + +/* +static const wchar_t * const k_VolumePrefix = L"Volume{"; +static const bool IsVolumeName(const wchar_t *s) +{ + return IsString1PrefixedByString2(s, k_VolumePrefix); +} +*/ + +#if defined(_WIN32) && !defined(UNDER_CE) + +#define Set16(p, v) SetUi16(p, v) +#define Set32(p, v) SetUi32(p, v) + +static void WriteString(Byte *dest, const wchar_t *path) +{ + for (;;) + { + wchar_t c = *path++; + if (c == 0) + return; + Set16(dest, (UInt16)c); + dest += 2; + } +} + +bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL) +{ + bool isAbs = IsAbsolutePath(path); + if (!isAbs && !isSymLink) + return false; + + if (isWSL) + { + // unsupported characters probably use Replacement Character UTF-16 0xFFFD + AString utf; + ConvertUnicodeToUTF8(path, utf); + const size_t size = 4 + utf.Len(); + if (size != (UInt16)size) + return false; + dest.Alloc(8 + size); + Byte *p = dest; + Set32(p, _my_IO_REPARSE_TAG_LX_SYMLINK); + Set16(p + 4, (UInt16)(size)); + Set16(p + 6, 0); + Set32(p + 8, _my_LX_SYMLINK_FLAG); + memcpy(p + 12, utf.Ptr(), utf.Len()); + return true; + } + + // usual symbolic LINK (NOT WSL) + + bool needPrintName = true; + + if (IsSuperPath(path)) + { + path += kSuperPathPrefixSize; + if (!IsDrivePath(path)) + needPrintName = false; + } + + const unsigned add_Prefix_Len = isAbs ? k_LinkPrefix_Size : 0; + + size_t len2 = (size_t)MyStringLen(path) * 2; + const size_t len1 = len2 + add_Prefix_Len * 2; + if (!needPrintName) + len2 = 0; + + size_t totalNamesSize = (len1 + len2); + + /* some WIM imagex software uses old scheme for symbolic links. + so we can old scheme for byte to byte compatibility */ + + bool newOrderScheme = isSymLink; + // newOrderScheme = false; + + if (!newOrderScheme) + totalNamesSize += 2 * 2; + + const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize; + if (size != (UInt16)size) + return false; + dest.Alloc(size); + memset(dest, 0, size); + const UInt32 tag = isSymLink ? + _my_IO_REPARSE_TAG_SYMLINK : + _my_IO_REPARSE_TAG_MOUNT_POINT; + Byte *p = dest; + Set32(p, tag); + Set16(p + 4, (UInt16)(size - 8)); + Set16(p + 6, 0); + p += 8; + + unsigned subOffs = 0; + unsigned printOffs = 0; + if (newOrderScheme) + subOffs = (unsigned)len2; + else + printOffs = (unsigned)len1 + 2; + + Set16(p + 0, (UInt16)subOffs); + Set16(p + 2, (UInt16)len1); + Set16(p + 4, (UInt16)printOffs); + Set16(p + 6, (UInt16)len2); + + p += 8; + if (isSymLink) + { + UInt32 flags = isAbs ? 0 : _my_SYMLINK_FLAG_RELATIVE; + Set32(p, flags); + p += 4; + } + + if (add_Prefix_Len != 0) + WriteString(p + subOffs, k_LinkPrefix); + WriteString(p + subOffs + add_Prefix_Len * 2, path); + if (needPrintName) + WriteString(p + printOffs, path); + return true; +} + +#endif // defined(_WIN32) && !defined(UNDER_CE) + + +static void GetString(const Byte *p, unsigned len, UString &res) +{ + wchar_t *s = res.GetBuf(len); + unsigned i; + for (i = 0; i < len; i++) + { + wchar_t c = Get16(p + i * 2); + if (c == 0) + break; + s[i] = c; + } + s[i] = 0; + res.ReleaseBuf_SetLen(i); +} + +bool CReparseAttr::Parse(const Byte *p, size_t size) +{ + ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA; + HeaderError = true; + TagIsUnknown = true; + MinorError = false; + + if (size < 8) + return false; + Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 != size) + // if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + + if (Get16(p + 6) != 0) // padding + return false; + + HeaderError = false; + + if ( Tag != _my_IO_REPARSE_TAG_MOUNT_POINT + && Tag != _my_IO_REPARSE_TAG_SYMLINK + && Tag != _my_IO_REPARSE_TAG_LX_SYMLINK) + { + // for unsupported reparse points + ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH + // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID + return false; + } + + TagIsUnknown = false; + + p += 8; + size -= 8; + + if (Tag == _my_IO_REPARSE_TAG_LX_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); // maybe it's not Flags + if (Flags != _my_LX_SYMLINK_FLAG) + return false; + len -= 4; + p += 4; + char *s = WslName.GetBuf(len); + unsigned i; + for (i = 0; i < len; i++) + { + char c = (char)p[i]; + s[i] = c; + if (c == 0) + break; + } + WslName.ReleaseBuf_SetEnd(i); + MinorError = (i != len); + ErrorCode = 0; + return true; + } + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + GetString(p + subOffs, subLen >> 1, SubsName); + GetString(p + printOffs, printLen >> 1, PrintName); + + ErrorCode = 0; + return true; +} + + +bool CReparseShortInfo::Parse(const Byte *p, size_t size) +{ + const Byte *start = p; + Offset= 0; + Size = 0; + if (size < 8) + return false; + UInt32 Tag = Get32(p); + UInt32 len = Get16(p + 4); + if (len + 8 > size) + return false; + /* + if ((type & kReparseFlags_Alias) == 0 || + (type & kReparseFlags_Microsoft) == 0 || + (type & 0xFFFF) != 3) + */ + if (Tag != _my_IO_REPARSE_TAG_MOUNT_POINT && + Tag != _my_IO_REPARSE_TAG_SYMLINK) + // return true; + return false; + + if (Get16(p + 6) != 0) // padding + return false; + + p += 8; + size -= 8; + + if (len != size) // do we need that check? + return false; + + if (len < 8) + return false; + unsigned subOffs = Get16(p); + unsigned subLen = Get16(p + 2); + unsigned printOffs = Get16(p + 4); + unsigned printLen = Get16(p + 6); + len -= 8; + p += 8; + + // UInt32 Flags = 0; + if (Tag == _my_IO_REPARSE_TAG_SYMLINK) + { + if (len < 4) + return false; + // Flags = Get32(p); + len -= 4; + p += 4; + } + + if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen) + return false; + if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen) + return false; + + Offset = (unsigned)(p - start) + subOffs; + Size = subLen; + return true; +} + +bool CReparseAttr::IsOkNamePair() const +{ + if (IsLinkPrefix(SubsName)) + { + if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size))) + return PrintName.IsEmpty(); + if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0) + return true; + } + return wcscmp(SubsName, PrintName) == 0; +} + +/* +bool CReparseAttr::IsVolume() const +{ + if (!IsLinkPrefix(SubsName)) + return false; + return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size)); +} +*/ + +UString CReparseAttr::GetPath() const +{ + if (IsSymLink_WSL()) + { + UString u; + // if (CheckUTF8(attr.WslName) + if (!ConvertUTF8ToUnicode(WslName, u)) + MultiByteToUnicodeString2(u, WslName); + return u; + } + + UString s (SubsName); + if (IsLinkPrefix(s)) + { + s.ReplaceOneCharAtPos(1, '\\'); // we normalize prefix from "\??\" to "\\?\" + if (IsDrivePath(s.Ptr(k_LinkPrefix_Size))) + s.DeleteFrontal(k_LinkPrefix_Size); + } + return s; +} + +#ifdef SUPPORT_DEVICE_FILE + +namespace NSystem +{ +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); +} +#endif // SUPPORT_DEVICE_FILE + +#if defined(_WIN32) && !defined(UNDER_CE) + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo) +{ + reparseData.Free(); + CInFile file; + if (!file.OpenReparse(path)) + return false; + + if (fileInfo) + file.GetFileInformation(fileInfo); + + const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + CByteArr buf(kBufSize); + DWORD returnedSize; + if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) + return false; + reparseData.CopyFrom(buf, returnedSize); + return true; +} + +static bool CreatePrefixDirOfFile(CFSTR path) +{ + FString path2 (path); + int pos = path2.ReverseFind_PathSepar(); + if (pos < 0) + return true; + #ifdef _WIN32 + if (pos == 2 && path2[1] == L':') + return true; // we don't create Disk folder; + #endif + path2.DeleteFrom((unsigned)pos); + return NDir::CreateComplexDir(path2); +} + + +static bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size) +{ + COutFile file; + if (!file.Open(path, + FILE_SHARE_WRITE, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) + return false; + + DWORD returnedSize; + return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize); +} + + +// If there is Reparse data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + NFile::NFind::CFileInfo fi; + if (fi.Find(path)) + { + if (fi.IsDir() != isDir) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + } + else + { + if (isDir) + { + if (!NDir::CreateComplexDir(path)) + return false; + } + else + { + CreatePrefixDirOfFile(path); + COutFile file; + if (!file.Create(path, CREATE_NEW)) + return false; + } + } + + return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size); +} + + +bool DeleteReparseData(CFSTR path) +{ + CByteBuffer reparseData; + if (!GetReparseData(path, reparseData, NULL)) + return false; + /* MSDN: The tag specified in the ReparseTag member of this structure + must match the tag of the reparse point to be deleted, + and the ReparseDataLength member must be zero */ + #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8 + if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE) + { + SetLastError(ERROR_INVALID_REPARSE_DATA); + return false; + } + BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE]; + memset(buf, 0, sizeof(buf)); + memcpy(buf, reparseData, 4); // tag + return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, buf, sizeof(buf)); +} + +} + +#endif // defined(_WIN32) && !defined(UNDER_CE) + + +#ifndef _WIN32 + +namespace NIO { + +bool GetReparseData(CFSTR path, CByteBuffer &reparseData) +{ + reparseData.Free(); + + #define MAX_PATHNAME_LEN 1024 + char buf[MAX_PATHNAME_LEN + 2]; + const size_t request = sizeof(buf) - 1; + + // printf("\nreadlink() path = %s \n", path); + const ssize_t size = readlink(path, buf, request); + // there is no tail zero + + if (size < 0) + return false; + if ((size_t)size >= request) + { + SetLastError(EINVAL); // check it: ENAMETOOLONG + return false; + } + + // printf("\nreadlink() res = %s size = %d \n", buf, (int)size); + reparseData.CopyFrom((const Byte *)buf, (size_t)size); + return true; +} + + +/* +// If there is Reparse data already, it still writes new Reparse data +bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size) +{ + // AString s; + // s.SetFrom_CalcLen(data, size); + // return (symlink(s, path) == 0); + UNUSED_VAR(path) + UNUSED_VAR(isDir) + UNUSED_VAR(data) + UNUSED_VAR(size) + SetLastError(ENOSYS); + return false; +} +*/ + +bool SetSymLink(CFSTR from, CFSTR to) +{ + // printf("\nsymlink() %s -> %s\n", from, to); + int ir; + // ir = unlink(path); + // if (ir == 0) + ir = symlink(to, from); + return (ir == 0); +} + +bool SetSymLink_UString(CFSTR from, const UString &to) +{ + AString utf; + ConvertUnicodeToUTF8(to, utf); + return SetSymLink(from, utf); +} + +} + +#endif // !_WIN32 + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.cpp new file mode 100644 index 0000000..1933f7c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.cpp @@ -0,0 +1,12 @@ +// Windows/FileMapping.cpp + +#include "StdAfx.h" + +#include "FileMapping.h" + +namespace NWindows { +namespace NFile { +namespace NMapping { + + +}}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.h new file mode 100644 index 0000000..f90c429 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileMapping.h @@ -0,0 +1,66 @@ +// Windows/FileMapping.h + +#ifndef __WINDOWS_FILEMAPPING_H +#define __WINDOWS_FILEMAPPING_H + +#include "../Common/MyTypes.h" + +#include "Handle.h" + +namespace NWindows { + +class CFileMapping: public CHandle +{ +public: + WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name) + { + _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name); + return ::GetLastError(); + } + + WRes Open(DWORD + #ifndef UNDER_CE + desiredAccess + #endif + , LPCTSTR name) + { + #ifdef UNDER_CE + WRes res = Create(PAGE_READONLY, 0, name); + if (res == ERROR_ALREADY_EXISTS) + return 0; + Close(); + if (res == 0) + res = ERROR_FILE_NOT_FOUND; + return res; + #else + _handle = ::OpenFileMapping(desiredAccess, FALSE, name); + if (_handle != 0) + return 0; + return ::GetLastError(); + #endif + } + + LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap) + { + return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap); + } + + #ifndef UNDER_CE + LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) + { + return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress); + } + #endif +}; + +class CFileUnmapper +{ + const void *_data; +public: + CFileUnmapper(const void *data) : _data(data) {} + ~CFileUnmapper() { ::UnmapViewOfFile(_data); } +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileName.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileName.cpp new file mode 100644 index 0000000..4ee9457 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileName.cpp @@ -0,0 +1,885 @@ +// Windows/FileName.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#include +#include "../Common/StringConvert.h" +#endif + +#include "FileName.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NName { + +#define IS_SEPAR(c) IS_PATH_SEPAR(c) + +int FindSepar(const wchar_t *s) throw() +{ + for (const wchar_t *p = s;; p++) + { + const wchar_t c = *p; + if (c == 0) + return -1; + if (IS_SEPAR(c)) + return (int)(p - s); + } +} + +#ifndef USE_UNICODE_FSTRING +int FindSepar(const FChar *s) throw() +{ + for (const FChar *p = s;; p++) + { + const FChar c = *p; + if (c == 0) + return -1; + if (IS_SEPAR(c)) + return (int)(p - s); + } +} +#endif + +#ifndef USE_UNICODE_FSTRING +void NormalizeDirPathPrefix(FString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (!IsPathSepar(dirPath.Back())) + dirPath.Add_PathSepar(); +} +#endif + +void NormalizeDirPathPrefix(UString &dirPath) +{ + if (dirPath.IsEmpty()) + return; + if (!IsPathSepar(dirPath.Back())) + dirPath.Add_PathSepar(); +} + +#ifdef _WIN32 +void NormalizeDirSeparators(FString &s) +{ + const unsigned len = s.Len(); + for (unsigned i = 0; i < len; i++) + if (s[i] == '/') + s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR); +} +#endif + + +#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) + +bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } + +bool IsAltPathPrefix(CFSTR s) throw() +{ + unsigned len = MyStringLen(s); + if (len == 0) + return false; + if (s[len - 1] != ':') + return false; + + #if defined(_WIN32) && !defined(UNDER_CE) + if (IsDevicePath(s)) + return false; + if (IsSuperPath(s)) + { + s += kSuperPathPrefixSize; + len -= kSuperPathPrefixSize; + } + if (len == 2 && IsDrivePath2(s)) + return false; + #endif + + return true; +} + +#if defined(_WIN32) && !defined(UNDER_CE) + +const char * const kSuperPathPrefix = "\\\\?\\"; +#ifdef WIN_LONG_PATH +static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; +#endif + +#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3])) +#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3])) +#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3])) + +#define IS_UNC_WITH_SLASH(s) ( \ + ((s)[0] == 'U' || (s)[0] == 'u') \ + && ((s)[1] == 'N' || (s)[1] == 'n') \ + && ((s)[2] == 'C' || (s)[2] == 'c') \ + && IS_SEPAR((s)[3])) + +bool IsDevicePath(CFSTR s) throw() +{ + #ifdef UNDER_CE + + s = s; + return false; + /* + // actually we don't know the way to open device file in WinCE. + unsigned len = MyStringLen(s); + if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, "DSK")) + return false; + if (s[4] != ':') + return false; + // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); + */ + + #else + + if (!IS_DEVICE_PATH(s)) + return false; + unsigned len = MyStringLen(s); + if (len == 6 && s[5] == ':') + return true; + if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, "PhysicalDrive")) + return false; + for (unsigned i = 17; i < len; i++) + if (s[i] < '0' || s[i] > '9') + return false; + return true; + + #endif +} + +bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } +bool IsNetworkPath(CFSTR s) throw() +{ + if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) + return false; + if (IsSuperUncPath(s)) + return true; + FChar c = s[2]; + return (c != '.' && c != '?'); +} + +unsigned GetNetworkServerPrefixSize(CFSTR s) throw() +{ + if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1])) + return 0; + unsigned prefixSize = 2; + if (IsSuperUncPath(s)) + prefixSize = kSuperUncPathPrefixSize; + else + { + FChar c = s[2]; + if (c == '.' || c == '?') + return 0; + } + int pos = FindSepar(s + prefixSize); + if (pos < 0) + return 0; + return prefixSize + (unsigned)(pos + 1); +} + +bool IsNetworkShareRootPath(CFSTR s) throw() +{ + unsigned prefixSize = GetNetworkServerPrefixSize(s); + if (prefixSize == 0) + return false; + s += prefixSize; + int pos = FindSepar(s); + if (pos < 0) + return true; + return s[(unsigned)pos + 1] == 0; +} + +static const unsigned kDrivePrefixSize = 3; /* c:\ */ + +bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } +// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } +bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } +// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } +bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } +bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } +bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } +#endif // USE_UNICODE_FSTRING + +bool IsDrivePath_SuperAllowed(CFSTR s) throw() +{ + if (IsSuperPath(s)) + s += kSuperPathPrefixSize; + return IsDrivePath(s); +} + +bool IsDriveRootPath_SuperAllowed(CFSTR s) throw() +{ + if (IsSuperPath(s)) + s += kSuperPathPrefixSize; + return IsDrivePath(s) && s[kDrivePrefixSize] == 0; +} + +bool IsAbsolutePath(const wchar_t *s) throw() +{ + return IS_SEPAR(s[0]) || IsDrivePath2(s); +} + +int FindAltStreamColon(CFSTR path) throw() +{ + unsigned i = 0; + if (IsDrivePath2(path)) + i = 2; + int colonPos = -1; + for (;; i++) + { + FChar c = path[i]; + if (c == 0) + return colonPos; + if (c == ':') + { + if (colonPos < 0) + colonPos = (int)i; + continue; + } + if (IS_SEPAR(c)) + colonPos = -1; + } +} + +#ifndef USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) +{ + // Network path: we look "server\path\" as root prefix + int pos = FindSepar(s); + if (pos < 0) + return 0; + int pos2 = FindSepar(s + (unsigned)pos + 1); + if (pos2 < 0) + return 0; + return pos + pos2 + 2; +} + +static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (!IS_SEPAR(s[0])) + return 0; + if (s[1] == 0 || !IS_SEPAR(s[1])) + return 1; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindSepar(s + kSuperPathPrefixSize); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + pos + 1; +} + +unsigned GetRootPrefixSize(CFSTR s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#endif // USE_UNICODE_FSTRING + +static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() +{ + // Network path: we look "server\path\" as root prefix + int pos = FindSepar(s); + if (pos < 0) + return 0; + int pos2 = FindSepar(s + (unsigned)pos + 1); + if (pos2 < 0) + return 0; + return (unsigned)(pos + pos2 + 2); +} + +static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() +{ + if (IsDrivePath(s)) + return kDrivePrefixSize; + if (!IS_SEPAR(s[0])) + return 0; + if (s[1] == 0 || !IS_SEPAR(s[1])) + return 1; + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); + return (size == 0) ? 0 : 2 + size; +} + +static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() +{ + if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) + { + unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); + return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; + } + // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" + int pos = FindSepar(s + kSuperPathPrefixSize); + if (pos < 0) + return 0; + return kSuperPathPrefixSize + (unsigned)(pos + 1); +} + +unsigned GetRootPrefixSize(const wchar_t *s) throw() +{ + if (IS_DEVICE_PATH(s)) + return kDevicePathPrefixSize; + if (IsSuperPath(s)) + return GetRootPrefixSize_Of_SuperPath(s); + return GetRootPrefixSize_Of_SimplePath(s); +} + +#else // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); } + +#ifndef USE_UNICODE_FSTRING +unsigned GetRootPrefixSize(CFSTR s) throw(); +unsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } +#endif +unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; } + +#endif // _WIN32 + + +#ifndef UNDER_CE + +static bool GetCurDir(UString &path) +{ + path.Empty(); + + #ifdef _WIN32 + + DWORD needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + path = fs2us(fas2fs(s)); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); + path = s; + } + return (needLength > 0 && needLength <= MAX_PATH); + + #else + + #define MY__PATH_MAX PATH_MAX + // #define MY__PATH_MAX 1024 + + char s[MY__PATH_MAX + 1]; + char *res = getcwd(s, MY__PATH_MAX); + if (!res) + { + // if (errno != ERANGE) + return false; + } + path = GetUnicodeString(s); + return true; + + #endif +} + +static bool ResolveDotsFolders(UString &s) +{ + #ifdef _WIN32 + // s.Replace(L'/', WCHAR_PATH_SEPARATOR); + #endif + + for (unsigned i = 0;;) + { + const wchar_t c = s[i]; + if (c == 0) + return true; + if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) + { + const wchar_t c1 = s[i + 1]; + if (c1 == '.') + { + const wchar_t c2 = s[i + 2]; + if (IS_SEPAR(c2) || c2 == 0) + { + if (i == 0) + return false; + int k = (int)i - 2; + i += 2; + + for (;; k--) + { + if (k < 0) + return false; + if (!IS_SEPAR(s[(unsigned)k])) + break; + } + + do + k--; + while (k >= 0 && !IS_SEPAR(s[(unsigned)k])); + + unsigned num; + + if (k >= 0) + { + num = i - (unsigned)k; + i = (unsigned)k; + } + else + { + num = (c2 == 0 ? i : (i + 1)); + i = 0; + } + + s.Delete(i, num); + continue; + } + } + else if (IS_SEPAR(c1) || c1 == 0) + { + unsigned num = 2; + if (i != 0) + i--; + else if (c1 == 0) + num = 1; + s.Delete(i, num); + continue; + } + } + + i++; + } +} + +#endif // UNDER_CE + +#define LONG_PATH_DOTS_FOLDERS_PARSING + + +/* +Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ +To solve that problem we check such path: + - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper + - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain +*/ +#ifdef LONG_PATH_DOTS_FOLDERS_PARSING +#ifndef UNDER_CE +static bool AreThereDotsFolders(CFSTR s) +{ + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return false; + if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1]))) + { + FChar c1 = s[i + 1]; + if (c1 == 0 || IS_SEPAR(c1) || + (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2])))) + return true; + } + } +} +#endif +#endif // LONG_PATH_DOTS_FOLDERS_PARSING + +#ifdef WIN_LONG_PATH + +/* +Most of Windows versions have problems, if some file or dir name +contains '.' or ' ' at the end of name (Bad Path). +To solve that problem, we always use Super Path ("\\?\" prefix and full path) +in such cases. Note that "." and ".." are not bad names. + +There are 3 cases: + 1) If the path is already Super Path, we use that path + 2) If the path is not Super Path : + 2.1) Bad Path; we use only Super Path. + 2.2) Good Path; we use Main Path. If it fails, we use Super Path. + + NeedToUseOriginalPath returns: + kSuperPathType_UseOnlyMain : Super already + kSuperPathType_UseOnlySuper : not Super, Bad Path + kSuperPathType_UseMainAndSuper : not Super, Good Path +*/ + +int GetUseSuperPathType(CFSTR s) throw() +{ + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + if ((s)[2] != '.') + if (AreThereDotsFolders(s + kSuperPathPrefixSize)) + return kSuperPathType_UseOnlySuper; + #endif + return kSuperPathType_UseOnlyMain; + } + + for (unsigned i = 0;; i++) + { + FChar c = s[i]; + if (c == 0) + return kSuperPathType_UseMainAndSuper; + if (c == '.' || c == ' ') + { + FChar c2 = s[i + 1]; + if (c2 == 0 || IS_SEPAR(c2)) + { + // if it's "." or "..", it's not bad name. + if (c == '.') + { + if (i == 0 || IS_SEPAR(s[i - 1])) + continue; + if (s[i - 1] == '.') + { + if (i - 1 == 0 || IS_SEPAR(s[i - 2])) + continue; + } + } + return kSuperPathType_UseOnlySuper; + } + } + } +} + + + +/* + returns false in two cases: + - if GetCurDir was used, and GetCurDir returned error. + - if we can't resolve ".." name. + if path is ".", "..", res is empty. + if it's Super Path already, res is empty. + for \**** , and if GetCurDir is not drive (c:\), res is empty + for absolute paths, returns true, res is Super path. +*/ + +static bool GetSuperPathBase(CFSTR s, UString &res) +{ + res.Empty(); + + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + + if (IsSuperOrDevicePath(s)) + { + #ifdef LONG_PATH_DOTS_FOLDERS_PARSING + + if ((s)[2] == '.') + return true; + + // we will return true here, so we will try to use these problem paths. + + if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) + return true; + + UString temp = fs2us(s); + unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); + if (fixedSize == 0) + return true; + + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return true; + + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + + #endif + + return true; + } + + if (IS_SEPAR(c)) + { + if (IS_SEPAR(s[1])) + { + UString temp = fs2us(s + 2); + unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); + // we ignore that error to allow short network paths server\share? + /* + if (fixedSize == 0) + return false; + */ + UString rem = &temp[fixedSize]; + if (!ResolveDotsFolders(rem)) + return false; + res += kSuperUncPrefix; + temp.DeleteFrom(fixedSize); + res += temp; + res += rem; + return true; + } + } + else + { + if (IsDrivePath2(s)) + { + UString temp = fs2us(s); + unsigned prefixSize = 2; + if (IsDrivePath(s)) + prefixSize = kDrivePrefixSize; + UString rem = temp.Ptr(prefixSize); + if (!ResolveDotsFolders(rem)) + return true; + res += kSuperPathPrefix; + temp.DeleteFrom(prefixSize); + res += temp; + res += rem; + return true; + } + } + + UString curDir; + if (!GetCurDir(curDir)) + return false; + NormalizeDirPathPrefix(curDir); + + unsigned fixedSizeStart = 0; + unsigned fixedSize = 0; + const char *superMarker = NULL; + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + { + superMarker = kSuperPathPrefix; + fixedSize = kDrivePrefixSize; + } + else + { + if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) + return false; + fixedSizeStart = 2; + fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); + if (fixedSize == 0) + return false; + superMarker = kSuperUncPrefix; + } + } + + UString temp; + if (IS_SEPAR(c)) + { + temp = fs2us(s + 1); + } + else + { + temp += &curDir[fixedSizeStart + fixedSize]; + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + if (superMarker) + res += superMarker; + res += curDir.Mid(fixedSizeStart, fixedSize); + res += temp; + return true; +} + + +/* + In that case if GetSuperPathBase doesn't return new path, we don't need + to use same path that was used as main path + + GetSuperPathBase superPath.IsEmpty() onlyIfNew + false * * GetCurDir Error + true false * use Super path + true true true don't use any path, we already used mainPath + true true false use main path as Super Path, we don't try mainMath + That case is possible now if GetCurDir returns unknow + type of path (not drive and not network) + + We can change that code if we want to try mainPath, if GetSuperPathBase returns error, + and we didn't try mainPath still. + If we want to work that way, we don't need to use GetSuperPathBase return code. +*/ + +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) +{ + if (GetSuperPathBase(path, superPath)) + { + if (superPath.IsEmpty()) + { + // actually the only possible when onlyIfNew == true and superPath is empty + // is case when + + if (onlyIfNew) + return false; + superPath = fs2us(path); + } + + NormalizeDirSeparators(superPath); + return true; + } + return false; +} + +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) +{ + if (!GetSuperPathBase(s1, d1) || + !GetSuperPathBase(s2, d2)) + return false; + + NormalizeDirSeparators(d1); + NormalizeDirSeparators(d2); + + if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; +} + + +/* +// returns true, if we need additional use with New Super path. +bool GetSuperPath(CFSTR path, UString &superPath) +{ + if (GetSuperPathBase(path, superPath)) + return !superPath.IsEmpty(); + return false; +} +*/ +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) +{ + res = s; + + #ifdef UNDER_CE + + if (!IS_SEPAR(s[0])) + { + if (!dirPrefix) + return false; + res = dirPrefix; + res += s; + } + + #else + + unsigned prefixSize = GetRootPrefixSize(s); + if (prefixSize != 0) + { + if (!AreThereDotsFolders(s + prefixSize)) + return true; + + UString rem = fs2us(s + prefixSize); + if (!ResolveDotsFolders(rem)) + return true; // maybe false; + res.DeleteFrom(prefixSize); + res += us2fs(rem); + return true; + } + + /* + FChar c = s[0]; + if (c == 0) + return true; + if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) + return true; + if (IS_SEPAR(c) && IS_SEPAR(s[1])) + return true; + if (IsDrivePath(s)) + return true; + */ + + UString curDir; + if (dirPrefix) + curDir = fs2us(dirPrefix); + else + { + if (!GetCurDir(curDir)) + return false; + } + NormalizeDirPathPrefix(curDir); + + unsigned fixedSize = 0; + + #ifdef _WIN32 + + if (IsSuperPath(curDir)) + { + fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); + if (fixedSize == 0) + return false; + } + else + { + if (IsDrivePath(curDir)) + fixedSize = kDrivePrefixSize; + else + { + if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) + return false; + fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); + if (fixedSize == 0) + return false; + fixedSize += 2; + } + } + + #endif // _WIN32 + + UString temp; + if (IS_SEPAR(s[0])) + { + temp = fs2us(s + 1); + } + else + { + temp += curDir.Ptr(fixedSize); + temp += fs2us(s); + } + if (!ResolveDotsFolders(temp)) + return false; + curDir.DeleteFrom(fixedSize); + res = us2fs(curDir); + res += us2fs(temp); + + #endif // UNDER_CE + + return true; +} + +bool GetFullPath(CFSTR path, FString &fullPath) +{ + return GetFullPath(NULL, path, fullPath); +} + +}}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileName.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileName.h new file mode 100644 index 0000000..de8bd13 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileName.h @@ -0,0 +1,119 @@ +// Windows/FileName.h + +#ifndef __WINDOWS_FILE_NAME_H +#define __WINDOWS_FILE_NAME_H + +#include "../Common/MyString.h" + +namespace NWindows { +namespace NFile { +namespace NName { + +int FindSepar(const wchar_t *s) throw(); +#ifndef USE_UNICODE_FSTRING +int FindSepar(const FChar *s) throw(); +#endif + +void NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\', if dirPath is not epmty +void NormalizeDirPathPrefix(UString &dirPath); + +#ifdef _WIN32 +void NormalizeDirSeparators(FString &s); +#endif + +bool IsDrivePath(const wchar_t *s) throw(); // first 3 chars are drive chars like "a:\\" + +bool IsAltPathPrefix(CFSTR s) throw(); /* name: */ + +#if defined(_WIN32) && !defined(UNDER_CE) + +extern const char * const kSuperPathPrefix; /* \\?\ */ +const unsigned kDevicePathPrefixSize = 4; +const unsigned kSuperPathPrefixSize = 4; +const unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4; + +bool IsDevicePath(CFSTR s) throw(); /* \\.\ */ +bool IsSuperUncPath(CFSTR s) throw(); /* \\?\UNC\ */ +bool IsNetworkPath(CFSTR s) throw(); /* \\?\UNC\ or \\SERVER */ + +/* GetNetworkServerPrefixSize() returns size of server prefix: + \\?\UNC\SERVER\ + \\SERVER\ + in another cases it returns 0 +*/ + +unsigned GetNetworkServerPrefixSize(CFSTR s) throw(); + +bool IsNetworkShareRootPath(CFSTR s) throw(); /* \\?\UNC\SERVER\share or \\SERVER\share or with slash */ + +bool IsDrivePath_SuperAllowed(CFSTR s) throw(); // first chars are drive chars like "a:\" or "\\?\a:\" +bool IsDriveRootPath_SuperAllowed(CFSTR s) throw(); // exact drive root path "a:\" or "\\?\a:\" + +bool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like "a:" +// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like "a:" +bool IsSuperPath(const wchar_t *s) throw(); +bool IsSuperOrDevicePath(const wchar_t *s) throw(); + +#ifndef USE_UNICODE_FSTRING +bool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like "a:" +// bool IsDriveName2(CFSTR s) throw(); // is drive name like "a:" +bool IsDrivePath(CFSTR s) throw(); +bool IsSuperPath(CFSTR s) throw(); +bool IsSuperOrDevicePath(CFSTR s) throw(); + +/* GetRootPrefixSize() returns size of ROOT PREFIX for cases: + \ + \\.\ + C:\ + \\?\C:\ + \\?\UNC\SERVER\Shared\ + \\SERVER\Shared\ + in another cases it returns 0 +*/ + +unsigned GetRootPrefixSize(CFSTR s) throw(); + +#endif + +int FindAltStreamColon(CFSTR path) throw(); + +#endif // _WIN32 + +bool IsAbsolutePath(const wchar_t *s) throw(); +unsigned GetRootPrefixSize(const wchar_t *s) throw(); + +#ifdef WIN_LONG_PATH + +const int kSuperPathType_UseOnlyMain = 0; +const int kSuperPathType_UseOnlySuper = 1; +const int kSuperPathType_UseMainAndSuper = 2; + +int GetUseSuperPathType(CFSTR s) throw(); +bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew); +bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew); + +#define USE_MAIN_PATH (__useSuperPathType != kSuperPathType_UseOnlySuper) +#define USE_MAIN_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlySuper && __useSuperPathType2 != kSuperPathType_UseOnlySuper) + +#define USE_SUPER_PATH (__useSuperPathType != kSuperPathType_UseOnlyMain) +#define USE_SUPER_PATH_2 (__useSuperPathType1 != kSuperPathType_UseOnlyMain || __useSuperPathType2 != kSuperPathType_UseOnlyMain) + +#define IF_USE_MAIN_PATH int __useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH) +#define IF_USE_MAIN_PATH_2(x1, x2) \ + int __useSuperPathType1 = GetUseSuperPathType(x1); \ + int __useSuperPathType2 = GetUseSuperPathType(x2); \ + if (USE_MAIN_PATH_2) + +#else + +#define IF_USE_MAIN_PATH +#define IF_USE_MAIN_PATH_2(x1, x2) + +#endif // WIN_LONG_PATH + +bool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath); +bool GetFullPath(CFSTR path, FString &fullPath); + +}}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.cpp new file mode 100644 index 0000000..6259453 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.cpp @@ -0,0 +1,135 @@ +// Windows/FileSystem.cpp + +#include "StdAfx.h" + +#ifndef UNDER_CE + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "FileSystem.h" +#include "Defs.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NSystem { + +#ifdef _WIN32 + +bool MyGetVolumeInformation( + CFSTR rootPath, + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName) +{ + BOOL res; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR v[MAX_PATH + 2]; v[0] = 0; + TCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformation(fs2fas(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = MultiByteToUnicodeString(v); + fileSystemName = MultiByteToUnicodeString(f); + } + else + #endif + { + WCHAR v[MAX_PATH + 2]; v[0] = 0; + WCHAR f[MAX_PATH + 2]; f[0] = 0; + res = GetVolumeInformationW(fs2us(rootPath), + v, MAX_PATH, + volumeSerialNumber, maximumComponentLength, fileSystemFlags, + f, MAX_PATH); + volumeName = v; + fileSystemName = f; + } + return BOOLToBool(res); +} + +UINT MyGetDriveType(CFSTR pathName) +{ + #ifndef _UNICODE + if (!g_IsNT) + { + return GetDriveType(fs2fas(pathName)); + } + else + #endif + { + return GetDriveTypeW(fs2us(pathName)); + } +} + +typedef BOOL (WINAPI * GetDiskFreeSpaceExA_Pointer)( + LPCSTR lpDirectoryName, // directory name + PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller + PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk + PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk +); + +typedef BOOL (WINAPI * GetDiskFreeSpaceExW_Pointer)( + LPCWSTR lpDirectoryName, // directory name + PULARGE_INTEGER lpFreeBytesAvailable, // bytes available to caller + PULARGE_INTEGER lpTotalNumberOfBytes, // bytes on disk + PULARGE_INTEGER lpTotalNumberOfFreeBytes // free bytes on disk +); + +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize) +{ + DWORD numSectorsPerCluster, bytesPerSector, numFreeClusters, numClusters; + bool sizeIsDetected = false; + #ifndef _UNICODE + if (!g_IsNT) + { + GetDiskFreeSpaceExA_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExA_Pointer)(void *)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExA"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2fas(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + if (!::GetDiskFreeSpace(fs2fas(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; + } + else + #endif + { + GetDiskFreeSpaceExW_Pointer pGetDiskFreeSpaceEx = (GetDiskFreeSpaceExW_Pointer)(void *)GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "GetDiskFreeSpaceExW"); + if (pGetDiskFreeSpaceEx) + { + ULARGE_INTEGER freeBytesToCaller2, totalSize2, freeSize2; + sizeIsDetected = BOOLToBool(pGetDiskFreeSpaceEx(fs2us(rootPath), &freeBytesToCaller2, &totalSize2, &freeSize2)); + totalSize = totalSize2.QuadPart; + freeSize = freeSize2.QuadPart; + } + if (!::GetDiskFreeSpaceW(fs2us(rootPath), &numSectorsPerCluster, &bytesPerSector, &numFreeClusters, &numClusters)) + return false; + } + clusterSize = (UInt64)bytesPerSector * (UInt64)numSectorsPerCluster; + if (!sizeIsDetected) + { + totalSize = clusterSize * (UInt64)numClusters; + freeSize = clusterSize * (UInt64)numFreeClusters; + } + return true; +} + +#endif + +}}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.h b/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.h new file mode 100644 index 0000000..9b49a02 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/FileSystem.h @@ -0,0 +1,31 @@ +// Windows/FileSystem.h + +#ifndef __WINDOWS_FILE_SYSTEM_H +#define __WINDOWS_FILE_SYSTEM_H + +#include "../Common/MyString.h" +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NFile { +namespace NSystem { + +#ifdef _WIN32 + +bool MyGetVolumeInformation( + CFSTR rootPath , + UString &volumeName, + LPDWORD volumeSerialNumber, + LPDWORD maximumComponentLength, + LPDWORD fileSystemFlags, + UString &fileSystemName); + +UINT MyGetDriveType(CFSTR pathName); + +bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize); + +#endif + +}}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Handle.h b/3rdparty/lzma-21.03beta/CPP/Windows/Handle.h new file mode 100644 index 0000000..5878c83 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Handle.h @@ -0,0 +1,39 @@ +// Windows/Handle.h + +#ifndef __WINDOWS_HANDLE_H +#define __WINDOWS_HANDLE_H + +#include "../Common/MyTypes.h" + +namespace NWindows { + +class CHandle MY_UNCOPYABLE +{ +protected: + HANDLE _handle; +public: + operator HANDLE() { return _handle; } + CHandle(): _handle(NULL) {} + ~CHandle() { Close(); } + bool IsCreated() const { return (_handle != NULL); } + bool Close() + { + if (_handle == NULL) + return true; + if (!::CloseHandle(_handle)) + return false; + _handle = NULL; + return true; + } + void Attach(HANDLE handle) { _handle = handle; } + HANDLE Detach() + { + HANDLE handle = _handle; + _handle = NULL; + return handle; + } +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.cpp new file mode 100644 index 0000000..fdfbeb9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.cpp @@ -0,0 +1,112 @@ +// Windows/MemoryLock.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "MemoryLock.h" + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE + +#ifdef _UNICODE +#define MY_FUNC_SELECT(f) :: f +#else +#define MY_FUNC_SELECT(f) my_ ## f +extern "C" { +typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); +typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); +typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); +} +#define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff)GetProcAddress(hModule, name) +#endif + +bool EnablePrivilege(LPCTSTR privilegeName, bool enable) +{ + bool res = false; + + #ifndef _UNICODE + + HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll")); + if (hModule == NULL) + return false; + + GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken"); + GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA"); + GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges"); + + if (my_OpenProcessToken && + my_AdjustTokenPrivileges && + my_LookupPrivilegeValue) + + #endif + + { + HANDLE token; + if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) + { + TOKEN_PRIVILEGES tp; + if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid))) + { + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); + if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL)) + res = (GetLastError() == ERROR_SUCCESS); + } + ::CloseHandle(token); + } + } + + #ifndef _UNICODE + + ::FreeLibrary(hModule); + + #endif + + return res; +} + + + +typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); + +/* + We suppose that Window 10 works incorrectly with "Large Pages" at: + - Windows 10 1703 (15063) : incorrect allocating after VirtualFree() + - Windows 10 1709 (16299) : incorrect allocating after VirtualFree() + - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger, + if CPU doesn't support 1 GB pages. + Windows 10 1903 (18362) probably works correctly. +*/ + +unsigned Get_LargePages_RiskLevel() +{ + OSVERSIONINFOEXW vi; + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + if (!ntdll) + return 0; + Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion"); + if (!func) + return 0; + func(&vi); + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return 0; + if (vi.dwMajorVersion + vi.dwMinorVersion != 10) + return 0; + if (vi.dwBuildNumber <= 16299) + return 1; + + #ifdef MY_CPU_X86_OR_AMD64 + if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB()) + return 1; + #endif + + return 0; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.h b/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.h new file mode 100644 index 0000000..dcaf182 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/MemoryLock.h @@ -0,0 +1,40 @@ +// Windows/MemoryLock.h + +#ifndef __WINDOWS_MEMORY_LOCK_H +#define __WINDOWS_MEMORY_LOCK_H + +#include "../Common/MyWindows.h" + +namespace NWindows { +namespace NSecurity { + +#ifndef UNDER_CE + +bool EnablePrivilege(LPCTSTR privilegeName, bool enable = true); + +inline bool EnablePrivilege_LockMemory(bool enable = true) +{ + return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable); +} + +inline void EnablePrivilege_SymLink() +{ + /* Probably we do not to set any Privilege for junction points. + But we need them for Symbolic links */ + NSecurity::EnablePrivilege(SE_RESTORE_NAME); + + /* Probably we need only SE_RESTORE_NAME, but there is also + SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */ + + NSecurity::EnablePrivilege(TEXT("SeCreateSymbolicLinkPrivilege")); // SE_CREATE_SYMBOLIC_LINK_NAME + + // Do we need to set SE_BACKUP_NAME ? +} + +unsigned Get_LargePages_RiskLevel(); + +#endif + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/NtCheck.h b/3rdparty/lzma-21.03beta/CPP/Windows/NtCheck.h new file mode 100644 index 0000000..0af3291 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/NtCheck.h @@ -0,0 +1,48 @@ +// Windows/NtCheck.h + +#ifndef __WINDOWS_NT_CHECK_H +#define __WINDOWS_NT_CHECK_H + +#ifdef _WIN32 + +#include "../Common/MyWindows.h" + +#if !defined(_WIN64) && !defined(UNDER_CE) +static inline bool IsItWindowsNT() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif + +#ifndef _UNICODE + extern + bool g_IsNT; + #if defined(_WIN64) || defined(UNDER_CE) + bool g_IsNT = true; + #define SET_IS_NT + #else + bool g_IsNT = false; + #define SET_IS_NT g_IsNT = IsItWindowsNT(); + #endif + #define NT_CHECK_ACTION + // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION } +#else + #if !defined(_WIN64) && !defined(UNDER_CE) + #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION } + #else + #define NT_CHECK_ACTION + #endif + #define SET_IS_NT +#endif + +#define NT_CHECK NT_CHECK_ACTION SET_IS_NT + +#else + +#define NT_CHECK + +#endif + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.cpp new file mode 100644 index 0000000..8cc89a3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.cpp @@ -0,0 +1,349 @@ +// Windows/PropVariant.cpp + +#include "StdAfx.h" + +#include "../Common/Defs.h" + +#include "PropVariant.h" + +namespace NWindows { +namespace NCOM { + +BSTR AllocBstrFromAscii(const char *s) throw() +{ + if (!s) + return NULL; + UINT len = (UINT)strlen(s); + BSTR p = ::SysAllocStringLen(NULL, len); + if (p) + { + for (UINT i = 0; i <= len; i++) + p[i] = (Byte)s[i]; + } + return p; +} + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() +{ + p->bstrVal = ::SysAllocStringLen(NULL, numChars); + if (!p->bstrVal) + { + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } + p->vt = VT_BSTR; + return S_OK; +} + +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() +{ + p->bstrVal = AllocBstrFromAscii(s); + if (p->bstrVal) + { + p->vt = VT_BSTR; + return S_OK; + } + p->vt = VT_ERROR; + p->scode = E_OUTOFMEMORY; + return E_OUTOFMEMORY; +} + +CPropVariant::CPropVariant(const PROPVARIANT &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(const CPropVariant &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(BSTR bstrSrc) +{ + vt = VT_EMPTY; + *this = bstrSrc; +} + +CPropVariant::CPropVariant(LPCOLESTR lpszSrc) +{ + vt = VT_EMPTY; + *this = lpszSrc; +} + +CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} + +CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} + +CPropVariant& CPropVariant::operator=(BSTR bstrSrc) +{ + *this = (LPCOLESTR)bstrSrc; + return *this; +} + +static const char * const kMemException = "out of memory"; + +CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocString(lpszSrc); + if (!bstrVal && lpszSrc) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(const UString &s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(s, s.Len()); + if (!bstrVal) + throw kMemException; + return *this; +} + +CPropVariant& CPropVariant::operator=(const UString2 &s) +{ + /* + if (s.IsEmpty()) + *this = L""; + else + */ + { + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len()); + if (!bstrVal) + throw kMemException; + /* SysAllocStringLen probably appends a null-terminating character for NULL string. + But it doesn't specified in MSDN. + But we suppose that it works + + if (!s.GetRawPtr()) + { + *bstrVal = 0; + } + */ + + /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL) + pointers to this function causes an unexpected termination of the application. + Is it safe? Maybe we must chamnge the code for that case ? */ + } + return *this; +} + +CPropVariant& CPropVariant::operator=(const char *s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = AllocBstrFromAscii(s); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(bool bSrc) throw() +{ + if (vt != VT_BOOL) + { + InternalClear(); + vt = VT_BOOL; + } + boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; + return *this; +} + +BSTR CPropVariant::AllocBstr(unsigned numChars) +{ + if (vt != VT_EMPTY) + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocStringLen(NULL, numChars); + if (!bstrVal) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return bstrVal; +} + +#define SET_PROP_FUNC(type, id, dest) \ + CPropVariant& CPropVariant::operator=(type value) throw() \ + { if (vt != id) { InternalClear(); vt = id; } \ + dest = value; return *this; } + +SET_PROP_FUNC(Byte, VT_UI1, bVal) +// SET_PROP_FUNC(Int16, VT_I2, iVal) +SET_PROP_FUNC(Int32, VT_I4, lVal) +SET_PROP_FUNC(UInt32, VT_UI4, ulVal) +SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) +SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) + +HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() +{ + switch (prop->vt) + { + case VT_EMPTY: + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + prop->vt = VT_EMPTY; + prop->wReserved1 = 0; + prop->wReserved2 = 0; + prop->wReserved3 = 0; + prop->uhVal.QuadPart = 0; + return S_OK; + } + return ::VariantClear((VARIANTARG *)prop); + // return ::PropVariantClear(prop); + // PropVariantClear can clear VT_BLOB. +} + +HRESULT CPropVariant::Clear() throw() +{ + if (vt == VT_EMPTY) + return S_OK; + return PropVariant_Clear(this); +} + +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() +{ + ::VariantClear((tagVARIANT *)this); + switch (pSrc->vt) + { + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); + return S_OK; + } + return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast(pSrc)); +} + + +HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() +{ + HRESULT hr = Clear(); + if (FAILED(hr)) + return hr; + // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); + *(PROPVARIANT *)this = *pSrc; + pSrc->vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() +{ + if (pDest->vt != VT_EMPTY) + { + HRESULT hr = PropVariant_Clear(pDest); + if (FAILED(hr)) + return hr; + } + // memcpy(pDest, this, sizeof(PROPVARIANT)); + *pDest = *(PROPVARIANT *)this; + vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::InternalClear() throw() +{ + if (vt == VT_EMPTY) + return S_OK; + HRESULT hr = Clear(); + if (FAILED(hr)) + { + vt = VT_ERROR; + scode = hr; + } + return hr; +} + +void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) +{ + HRESULT hr = Copy(pSrc); + if (FAILED(hr)) + { + if (hr == E_OUTOFMEMORY) + throw kMemException; + vt = VT_ERROR; + scode = hr; + } +} + +int CPropVariant::Compare(const CPropVariant &a) throw() +{ + if (vt != a.vt) + return MyCompare(vt, a.vt); + switch (vt) + { + case VT_EMPTY: return 0; + // case VT_I1: return MyCompare(cVal, a.cVal); + case VT_UI1: return MyCompare(bVal, a.bVal); + case VT_I2: return MyCompare(iVal, a.iVal); + case VT_UI2: return MyCompare(uiVal, a.uiVal); + case VT_I4: return MyCompare(lVal, a.lVal); + case VT_UI4: return MyCompare(ulVal, a.ulVal); + // case VT_UINT: return MyCompare(uintVal, a.uintVal); + case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); + case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); + case VT_BOOL: return -MyCompare(boolVal, a.boolVal); + case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); + case VT_BSTR: return 0; // Not implemented + default: return 0; + } +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.h b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.h new file mode 100644 index 0000000..58e8a0c --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariant.h @@ -0,0 +1,114 @@ +// Windows/PropVariant.h + +#ifndef __WINDOWS_PROP_VARIANT_H +#define __WINDOWS_PROP_VARIANT_H + +#include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" +#include "../Common/MyString.h" + +namespace NWindows { +namespace NCOM { + +BSTR AllocBstrFromAscii(const char *s) throw(); + +HRESULT PropVariant_Clear(PROPVARIANT *p) throw(); + +HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw(); +HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw(); + +inline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw() +{ + p->vt = VT_UI4; + p->ulVal = v; +} + +inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_UI8; + p->uhVal.QuadPart = v; +} + +inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() +{ + p->vt = VT_FILETIME; + p->filetime.dwLowDateTime = (DWORD)v; + p->filetime.dwHighDateTime = (DWORD)(v >> 32); +} + +inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() +{ + p->vt = VT_BOOL; + p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE); +} + + +class CPropVariant : public tagPROPVARIANT +{ +public: + CPropVariant() + { + vt = VT_EMPTY; + wReserved1 = 0; + // wReserved2 = 0; + // wReserved3 = 0; + // uhVal.QuadPart = 0; + bstrVal = 0; + } + ~CPropVariant() throw() { Clear(); } + CPropVariant(const PROPVARIANT &varSrc); + CPropVariant(const CPropVariant &varSrc); + CPropVariant(BSTR bstrSrc); + CPropVariant(LPCOLESTR lpszSrc); + CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); } + CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } + +private: + CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; } + +public: + CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } + CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(Int64 value) { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; } + CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } + + CPropVariant& operator=(const CPropVariant &varSrc); + CPropVariant& operator=(const PROPVARIANT &varSrc); + CPropVariant& operator=(BSTR bstrSrc); + CPropVariant& operator=(LPCOLESTR lpszSrc); + CPropVariant& operator=(const UString &s); + CPropVariant& operator=(const UString2 &s); + CPropVariant& operator=(const char *s); + CPropVariant& operator=(const AString &s) + { return (*this)=(const char *)s; } + + CPropVariant& operator=(bool bSrc) throw(); + CPropVariant& operator=(Byte value) throw(); + +private: + CPropVariant& operator=(Int16 value) throw(); + +public: + CPropVariant& operator=(Int32 value) throw(); + CPropVariant& operator=(UInt32 value) throw(); + CPropVariant& operator=(UInt64 value) throw(); + CPropVariant& operator=(Int64 value) throw(); + CPropVariant& operator=(const FILETIME &value) throw(); + + BSTR AllocBstr(unsigned numChars); + + HRESULT Clear() throw(); + HRESULT Copy(const PROPVARIANT *pSrc) throw(); + HRESULT Attach(PROPVARIANT *pSrc) throw(); + HRESULT Detach(PROPVARIANT *pDest) throw(); + + HRESULT InternalClear() throw(); + void InternalCopy(const PROPVARIANT *pSrc); + + int Compare(const CPropVariant &a) throw(); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.cpp new file mode 100644 index 0000000..b58d37e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.cpp @@ -0,0 +1,138 @@ +// PropVariantConv.cpp + +#include "StdAfx.h" + +#include "../Common/IntToString.h" + +#include "Defs.h" +#include "PropVariantConv.h" + +#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } + +bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() +{ + *s = 0; + FILETIME ft; + if (!FileTimeToLocalFileTime(&utc, &ft)) + return false; + + SYSTEMTIME st; + if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) + return false; + + { + unsigned val = st.wYear; + if (val >= 10000) + { + *s++ = (char)('0' + val / 10000); + val %= 10000; + } + s[3] = (char)('0' + val % 10); val /= 10; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 4; + } + UINT_TO_STR_2('-', st.wMonth); + UINT_TO_STR_2('-', st.wDay); + + if (level > kTimestampPrintLevel_DAY) + { + UINT_TO_STR_2(' ', st.wHour); + UINT_TO_STR_2(':', st.wMinute); + + if (level >= kTimestampPrintLevel_SEC) + { + UINT_TO_STR_2(':', st.wSecond); + + if (level > kTimestampPrintLevel_SEC) + { + *s++ = '.'; + /* + { + unsigned val = st.wMilliseconds; + s[2] = (char)('0' + val % 10); val /= 10; + s[1] = (char)('0' + val % 10); + s[0] = (char)('0' + val / 10); + s += 3; + } + *s++ = ' '; + */ + + { + unsigned numDigits = 7; + UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000); + for (unsigned i = numDigits; i != 0;) + { + i--; + s[i] = (char)('0' + val % 10); val /= 10; + } + if (numDigits > (unsigned)level) + numDigits = (unsigned)level; + s += numDigits; + } + } + } + } + + *s = 0; + return true; +} + + +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() +{ + char s[32]; + bool res = ConvertUtcFileTimeToString(ft, s, level); + for (unsigned i = 0;; i++) + { + Byte c = (Byte)s[i]; + dest[i] = c; + if (c == 0) + break; + } + return res; +} + + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2); + } +} + +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw() +{ + *dest = 0; + switch (prop.vt) + { + case VT_EMPTY: return; + case VT_BSTR: dest[0] = '?'; dest[1] = 0; return; + case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return; + case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; + case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; + case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; + case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; + // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; + case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; + case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; + case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return; + case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return; + default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2); + } +} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.h b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.h new file mode 100644 index 0000000..390e0b8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/PropVariantConv.h @@ -0,0 +1,37 @@ +// Windows/PropVariantConv.h + +#ifndef __PROP_VARIANT_CONV_H +#define __PROP_VARIANT_CONV_H + +#include "../Common/MyTypes.h" + +// provide at least 32 bytes for buffer including zero-end + +#define kTimestampPrintLevel_DAY -3 +// #define kTimestampPrintLevel_HOUR -2 +#define kTimestampPrintLevel_MIN -1 +#define kTimestampPrintLevel_SEC 0 +#define kTimestampPrintLevel_NTFS 7 + +bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); +bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); + +// provide at least 32 bytes for buffer including zero-end +// don't send VT_BSTR to these functions +void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(); +void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw(); + +inline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value) +{ + switch (prop.vt) + { + case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true; + case VT_UI4: value = prop.ulVal; return true; + case VT_UI2: value = prop.uiVal; return true; + case VT_UI1: value = prop.bVal; return true; + case VT_EMPTY: return false; + default: throw 151199; + } +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Registry.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Registry.cpp new file mode 100644 index 0000000..b20157d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Registry.cpp @@ -0,0 +1,406 @@ +// Windows/Registry.cpp + +#include "StdAfx.h" + +#include +// #include + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif +#include "Registry.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NRegistry { + +#define MYASSERT(expr) // _ASSERTE(expr) +#define MY_ASSUME(expr) + +/* +static void Error() +{ + #ifdef _CONSOLE + printf("\nregistry error\n"); + #else + MessageBoxW(0, L"registry error", L"", 0); + // exit(1); + #endif +} + +#define MY_ASSUME(expr) { if (!(expr)) Error(); } +*/ + +LONG CKey::Create(HKEY parentKey, LPCTSTR keyName, + LPTSTR keyClass, DWORD options, REGSAM accessMask, + LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw() +{ + MY_ASSUME(parentKey != NULL); + DWORD dispositionReal; + HKEY key = NULL; + LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass, + options, accessMask, securityAttributes, &key, &dispositionReal); + if (disposition != NULL) + *disposition = dispositionReal; + if (res == ERROR_SUCCESS) + { + res = Close(); + _object = key; + } + return res; +} + +LONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw() +{ + MY_ASSUME(parentKey != NULL); + HKEY key = NULL; + LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key); + if (res == ERROR_SUCCESS) + { + res = Close(); + MYASSERT(res == ERROR_SUCCESS); + _object = key; + } + return res; +} + +LONG CKey::Close() throw() +{ + LONG res = ERROR_SUCCESS; + if (_object != NULL) + { + res = RegCloseKey(_object); + _object = NULL; + } + return res; +} + +// win95, win98: deletes sunkey and all its subkeys +// winNT to be deleted must not have subkeys +LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() +{ + MY_ASSUME(_object != NULL); + return RegDeleteKey(_object, subKeyName); +} + +LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() +{ + CKey key; + LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); + if (res != ERROR_SUCCESS) + return res; + FILETIME fileTime; + const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL + DWORD size = kBufSize; + TCHAR buffer[kBufSize]; + while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) + { + res = key.RecurseDeleteKey(buffer); + if (res != ERROR_SUCCESS) + return res; + size = kBufSize; + } + key.Close(); + return DeleteSubKey(subKeyName); +} + + +///////////////////////// +// Value Functions + +static inline UInt32 BoolToUINT32(bool value) { return (value ? 1: 0); } +static inline bool UINT32ToBool(UInt32 value) { return (value != 0); } + + +LONG CKey::DeleteValue(LPCTSTR name) throw() +{ + MY_ASSUME(_object != NULL); + return ::RegDeleteValue(_object, name); +} + +#ifndef _UNICODE +LONG CKey::DeleteValue(LPCWSTR name) +{ + MY_ASSUME(_object != NULL); + if (g_IsNT) + return ::RegDeleteValueW(_object, name); + return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); +} +#endif + +LONG CKey::SetValue(LPCTSTR name, UInt32 value) throw() +{ + MY_ASSUME(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_DWORD, + (const BYTE *)&value, sizeof(UInt32)); +} + +LONG CKey::SetValue(LPCTSTR name, bool value) throw() +{ + return SetValue(name, BoolToUINT32(value)); +} + +LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() +{ + MYASSERT(value != NULL); + MY_ASSUME(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_SZ, + (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)); +} + +/* +LONG CKey::SetValue(LPCTSTR name, const CSysString &value) +{ + MYASSERT(value != NULL); + MY_ASSUME(_object != NULL); + return RegSetValueEx(_object, name, NULL, REG_SZ, + (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); +} +*/ + +#ifndef _UNICODE + +LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) +{ + MYASSERT(value != NULL); + MY_ASSUME(_object != NULL); + if (g_IsNT) + return RegSetValueExW(_object, name, 0, REG_SZ, + (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); + return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), + value == 0 ? 0 : (LPCSTR)GetSystemString(value)); +} + +#endif + + +LONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw() +{ + MYASSERT(value != NULL); + MY_ASSUME(_object != NULL); + return RegSetValueEx(_object, name, 0, REG_BINARY, + (const BYTE *)value, size); +} + +LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) +{ + MYASSERT(value != NULL); + CKey key; + LONG res = key.Create(parentKey, keyName); + if (res == ERROR_SUCCESS) + res = key.SetValue(valueName, value); + return res; +} + +LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw() +{ + MYASSERT(value != NULL); + CKey key; + LONG res = key.Create(_object, keyName); + if (res == ERROR_SUCCESS) + res = key.SetValue(valueName, value); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() +{ + DWORD type = 0; + DWORD count = sizeof(DWORD); + LONG res = RegQueryValueEx(_object, name, NULL, &type, + (LPBYTE)&value, &count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); + MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() +{ + UInt32 uintValue = BoolToUINT32(value); + LONG res = QueryValue(name, uintValue); + value = UINT32ToBool(uintValue); + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() +{ + UInt32 newVal; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() +{ + bool newVal = false; + LONG res = QueryValue(name, newVal); + if (res == ERROR_SUCCESS) + value = newVal; + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() +{ + DWORD type = 0; + LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); + return res; +} + +LONG CKey::QueryValue(LPCTSTR name, CSysString &value) +{ + value.Empty(); + DWORD type = 0; + UInt32 curSize = 0; + LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&curSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + UInt32 curSize2 = curSize; + res = QueryValue(name, value.GetBuf(curSize), curSize2); + if (curSize > curSize2) + curSize = curSize2; + value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); + return res; +} + + +#ifndef _UNICODE + +LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) +{ + DWORD type = 0; + LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); + return res; +} + +LONG CKey::QueryValue(LPCWSTR name, UString &value) +{ + value.Empty(); + DWORD type = 0; + UInt32 curSize = 0; + + LONG res; + + if (g_IsNT) + { + res = RegQueryValueExW(_object, name, NULL, &type, NULL, (DWORD *)&curSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + UInt32 curSize2 = curSize; + res = QueryValue(name, value.GetBuf(curSize), curSize2); + if (curSize > curSize2) + curSize = curSize2; + value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); + } + else + { + AString vTemp; + res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); + value = GetUnicodeString(vTemp); + } + + return res; +} + +#endif + + +LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() +{ + DWORD type = 0; + LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); + MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); + return res; +} + + +LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) +{ + DWORD type = 0; + dataSize = 0; + LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + return res; + value.Alloc(dataSize); + return QueryValue(name, (BYTE *)value, dataSize); +} + +LONG CKey::EnumKeys(CSysStringVector &keyNames) +{ + keyNames.Clear(); + CSysString keyName; + for (DWORD index = 0; ; index++) + { + const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL + FILETIME lastWriteTime; + UInt32 nameSize = kBufSize; + LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), + (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); + keyName.ReleaseBuf_CalcLen(kBufSize); + if (result == ERROR_NO_MORE_ITEMS) + break; + if (result != ERROR_SUCCESS) + return result; + keyNames.Add(keyName); + } + return ERROR_SUCCESS; +} + +LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) +{ + size_t numChars = 0; + + unsigned i; + + for (i = 0; i < strings.Size(); i++) + numChars += strings[i].Len() + 1; + + CObjArray buffer(numChars); + size_t pos = 0; + + for (i = 0; i < strings.Size(); i++) + { + const UString &s = strings[i]; + size_t size = s.Len() + 1; + wmemcpy(buffer + pos, s, size); + pos += size; + } + return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); +} + +LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) +{ + strings.Clear(); + CByteBuffer buffer; + UInt32 dataSize = 0; + LONG res = QueryValue(valueName, buffer, dataSize); + if (res != ERROR_SUCCESS) + return res; + if (dataSize > buffer.Size()) + return E_FAIL; + if (dataSize % sizeof(wchar_t) != 0) + return E_FAIL; + + const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; + size_t numChars = dataSize / sizeof(wchar_t); + size_t prev = 0; + UString s; + + for (size_t i = 0; i < numChars; i++) + { + if (data[i] == 0) + { + s = data + prev; + strings.Add(s); + prev = i + 1; + } + } + + return res; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Registry.h b/3rdparty/lzma-21.03beta/CPP/Windows/Registry.h new file mode 100644 index 0000000..ca79dfe --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Registry.h @@ -0,0 +1,84 @@ +// Windows/Registry.h + +#ifndef __WINDOWS_REGISTRY_H +#define __WINDOWS_REGISTRY_H + +#include "../Common/MyBuffer.h" +#include "../Common/MyString.h" + +namespace NWindows { +namespace NRegistry { + +LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value); + +class CKey +{ + HKEY _object; +public: + CKey(): _object(NULL) {} + ~CKey() { Close(); } + + operator HKEY() const { return _object; } + void Attach(HKEY key) { _object = key; } + HKEY Detach() + { + HKEY key = _object; + _object = NULL; + return key; + } + + LONG Create(HKEY parentKey, LPCTSTR keyName, + LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, + REGSAM accessMask = KEY_ALL_ACCESS, + LPSECURITY_ATTRIBUTES securityAttributes = NULL, + LPDWORD disposition = NULL) throw(); + LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw(); + + LONG Close() throw(); + + LONG DeleteSubKey(LPCTSTR subKeyName) throw(); + LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); + + LONG DeleteValue(LPCTSTR name) throw(); + #ifndef _UNICODE + LONG DeleteValue(LPCWSTR name); + #endif + + LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); + LONG SetValue(LPCTSTR valueName, bool value) throw(); + LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); + // LONG SetValue(LPCTSTR valueName, const CSysString &value); + #ifndef _UNICODE + LONG SetValue(LPCWSTR name, LPCWSTR value); + // LONG SetValue(LPCWSTR name, const UString &value); + #endif + + LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); + + LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings); + LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings); + + LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); + + LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); + LONG QueryValue(LPCTSTR name, bool &value) throw(); + LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); + LONG QueryValue(LPCTSTR name, CSysString &value); + + LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); + LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); + + #ifndef _UNICODE + LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); + LONG QueryValue(LPCWSTR name, UString &value); + #endif + + LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); + LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); + + LONG EnumKeys(CSysStringVector &keyNames); +}; + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.cpp new file mode 100644 index 0000000..ae8182e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.cpp @@ -0,0 +1,103 @@ +// Windows/ResourceString.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "ResourceString.h" + +extern HINSTANCE g_hInstance; +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE + +static CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID) +{ + CSysString s; + int size = 128; + int len; + do + { + size <<= 1; + len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuf_CalcLen((unsigned)len); + return s; +} + +#endif + +static const int kStartSize = 256; + +static void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s) +{ + int size = kStartSize; + int len; + do + { + size <<= 1; + len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size); + } + while (size - len <= 1); + s.ReleaseBuf_CalcLen((unsigned)len); +} + +// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it. + +UString MyLoadString(UINT resourceID) +{ + #ifndef _UNICODE + if (!g_IsNT) + return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID)); + else + #endif + { + { + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + return s; + } + UString dest; + MyLoadString2(g_hInstance, resourceID, dest); + return dest; + } +} + +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest) +{ + dest.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID)); + else + #endif + { + { + wchar_t s[kStartSize]; + s[0] = 0; + int len = ::LoadStringW(hInstance, resourceID, s, kStartSize); + if (kStartSize - len > 1) + { + dest = s; + return; + } + } + MyLoadString2(hInstance, resourceID, dest); + } +} + +void MyLoadString(UINT resourceID, UString &dest) +{ + MyLoadString(g_hInstance, resourceID, dest); +} + +} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.h b/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.h new file mode 100644 index 0000000..f0bdabf --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/ResourceString.h @@ -0,0 +1,16 @@ +// Windows/ResourceString.h + +#ifndef __WINDOWS_RESOURCE_STRING_H +#define __WINDOWS_RESOURCE_STRING_H + +#include "../Common/MyString.h" + +namespace NWindows { + +UString MyLoadString(UINT resourceID); +void MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest); +void MyLoadString(UINT resourceID, UString &dest); + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.cpp new file mode 100644 index 0000000..640c90d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.cpp @@ -0,0 +1,181 @@ +// Windows/SecurityUtils.cpp + +#include "StdAfx.h" + +#include "../Common/MyString.h" + +#include "SecurityUtils.h" + +namespace NWindows { +namespace NSecurity { + +/* +bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, + CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) +{ + DWORD accountNameSize = 0, domainNameSize = 0; + + if (!::LookupAccountSid(systemName, sid, + accountName.GetBuf(0), &accountNameSize, + domainName.GetBuf(0), &domainNameSize, sidNameUse)) + { + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return false; + } + DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize; + bool result = BOOLToBool(::LookupAccountSid(systemName, sid, + accountName.GetBuf(accountNameSize), &accountNameSize2, + domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse)); + accountName.ReleaseBuf_CalcLen(accountNameSize); + domainName.ReleaseBuf_CalcLen(domainNameSize); + return result; +} +*/ + +static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) +{ + size_t len = (size_t)wcslen(src); + dest->Length = (USHORT)(len * sizeof(WCHAR)); + dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); + dest->Buffer = src; +} + +/* +static void MyLookupSids(CPolicy &policy, PSID ps) +{ + LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; + LSA_TRANSLATED_NAME *names = NULL; + NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); + int res = LsaNtStatusToWinError(nts); + LsaFreeMemory(referencedDomains); + LsaFreeMemory(names); +} +*/ + +#ifndef _UNICODE +typedef BOOL (WINAPI * LookupAccountNameWP)( + LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR ReferencedDomainName, + LPDWORD cchReferencedDomainName, + PSID_NAME_USE peUse + ); +#endif + +static PSID GetSid(LPWSTR accountName) +{ + #ifndef _UNICODE + HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); + if (hModule == NULL) + return NULL; + LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); + if (lookupAccountNameW == NULL) + return NULL; + #endif + + DWORD sidLen = 0, domainLen = 0; + SID_NAME_USE sidNameUse; + if (! + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) + { + if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); + LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); + BOOL res = + #ifdef _UNICODE + ::LookupAccountNameW + #else + lookupAccountNameW + #endif + (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); + ::HeapFree(GetProcessHeap(), 0, domainName); + if (res) + return pSid; + } + } + return NULL; +} + +#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" + +bool AddLockMemoryPrivilege() +{ + CPolicy policy; + LSA_OBJECT_ATTRIBUTES attr; + attr.Length = sizeof(attr); + attr.RootDirectory = NULL; + attr.ObjectName = NULL; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (policy.Open(NULL, &attr, + // GENERIC_WRITE) + POLICY_ALL_ACCESS) + // STANDARD_RIGHTS_REQUIRED, + // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) + != 0) + return false; + LSA_UNICODE_STRING userRights; + wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; + SetLsaString(s, &userRights); + WCHAR userName[256 + 2]; + DWORD size = 256; + if (!GetUserNameW(userName, &size)) + return false; + PSID psid = GetSid(userName); + if (psid == NULL) + return false; + bool res = false; + + /* + PLSA_UNICODE_STRING userRightsArray; + ULONG countOfRights; + NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); + if (status != 0) + return false; + bool finded = false; + for (ULONG i = 0; i < countOfRights; i++) + { + LSA_UNICODE_STRING &ur = userRightsArray[i]; + if (ur.Length != s.Length() * sizeof(WCHAR)) + continue; + if (wcsncmp(ur.Buffer, s, s.Length()) != 0) + continue; + finded = true; + res = true; + break; + } + if (!finded) + */ + { + /* + LSA_ENUMERATION_INFORMATION *enums; + ULONG countReturned; + NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); + if (status == 0) + { + for (ULONG i = 0; i < countReturned; i++) + MyLookupSids(policy, enums[i].Sid); + if (enums) + ::LsaFreeMemory(enums); + res = true; + } + */ + NTSTATUS status = policy.AddAccountRights(psid, &userRights); + if (status == 0) + res = true; + // ULONG res = LsaNtStatusToWinError(status); + } + HeapFree(GetProcessHeap(), 0, psid); + return res; +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.h b/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.h new file mode 100644 index 0000000..8966dfd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/SecurityUtils.h @@ -0,0 +1,167 @@ +// Windows/SecurityUtils.h + +#ifndef __WINDOWS_SECURITY_UTILS_H +#define __WINDOWS_SECURITY_UTILS_H + +#include + +#include "Defs.h" + +namespace NWindows { +namespace NSecurity { + +class CAccessToken +{ + HANDLE _handle; +public: + CAccessToken(): _handle(NULL) {}; + ~CAccessToken() { Close(); } + bool Close() + { + if (_handle == NULL) + return true; + bool res = BOOLToBool(::CloseHandle(_handle)); + if (res) + _handle = NULL; + return res; + } + + bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess) + { + Close(); + return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle)); + } + + /* + bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf) + { + Close(); + return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle)); + } + */ + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState, + DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength) + { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges), + newState, bufferLength, previousState, returnLength)); } + + bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); } + + bool AdjustPrivileges(PTOKEN_PRIVILEGES newState) + { return AdjustPrivileges(false, newState); } + +}; + +#ifndef _UNICODE +typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, + PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); +typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); +typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, + PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); +#define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#endif + +struct CPolicy +{ +protected: + LSA_HANDLE _handle; + #ifndef _UNICODE + HMODULE hModule; + #endif +public: + operator LSA_HANDLE() const { return _handle; } + CPolicy(): _handle(NULL) + { + #ifndef _UNICODE + hModule = GetModuleHandle(TEXT("Advapi32.dll")); + #endif + }; + ~CPolicy() { Close(); } + + NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, + ACCESS_MASK desiredAccess) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); + if (lsaOpenPolicy == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + Close(); + return + #ifdef _UNICODE + ::LsaOpenPolicy + #else + lsaOpenPolicy + #endif + (systemName, objectAttributes, desiredAccess, &_handle); + } + + NTSTATUS Close() + { + if (_handle == NULL) + return 0; + + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); + if (lsaClose == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + NTSTATUS res = + #ifdef _UNICODE + ::LsaClose + #else + lsaClose + #endif + (_handle); + _handle = NULL; + return res; + } + + NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights, + PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned) + { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); } + + NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights) + { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); } + + NTSTATUS LookupSids(ULONG count, PSID* sids, + PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names) + { return LsaLookupSids(_handle, count, sids, referencedDomains, names); } + + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { + #ifndef _UNICODE + if (hModule == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); + if (lsaAddAccountRights == NULL) + return MY_STATUS_NOT_IMPLEMENTED; + #endif + + return + #ifdef _UNICODE + ::LsaAddAccountRights + #else + lsaAddAccountRights + #endif + (_handle, accountSid, userRights, countOfRights); + } + NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) + { return AddAccountRights(accountSid, userRights, 1); } + + NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights) + { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); } +}; + +bool AddLockMemoryPrivilege(); + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Shell.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Shell.cpp new file mode 100644 index 0000000..d0f9032 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Shell.cpp @@ -0,0 +1,358 @@ +// Windows/Shell.cpp + +#include "StdAfx.h" + +/* +#include +#include +*/ + +#include "../Common/MyCom.h" +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#include "COM.h" +#include "Shell.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NShell { + +#ifndef UNDER_CE + +// SHGetMalloc is unsupported in Windows Mobile? + +void CItemIDList::Free() +{ + if (m_Object == NULL) + return; + CMyComPtr shellMalloc; + if (::SHGetMalloc(&shellMalloc) != NOERROR) + throw 41099; + shellMalloc->Free(m_Object); + m_Object = NULL; +} + +/* +CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) + { *this = itemIDList; } +CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) + { *this = itemIDList; } + +CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) +{ + Free(); + if (object != 0) + { + UINT32 size = GetSize(object); + m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); + if (m_Object != NULL) + MoveMemory(m_Object, object, size); + } + return *this; +} + +CItemIDList& CItemIDList::operator=(const CItemIDList &object) +{ + Free(); + if (object.m_Object != NULL) + { + UINT32 size = GetSize(object.m_Object); + m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); + if (m_Object != NULL) + MoveMemory(m_Object, object.m_Object, size); + } + return *this; +} +*/ + +///////////////////////////// +// CDrop + +void CDrop::Attach(HDROP object) +{ + Free(); + m_Object = object; + m_Assigned = true; +} + +void CDrop::Free() +{ + if (m_MustBeFinished && m_Assigned) + Finish(); + m_Assigned = false; +} + +UINT CDrop::QueryCountOfFiles() +{ + return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); +} + +UString CDrop::QueryFileName(UINT fileIndex) +{ + UString fileName; + #ifndef _UNICODE + if (!g_IsNT) + { + AString fileNameA; + UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0); + const unsigned len = bufferSize + 2; + QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1); + fileNameA.ReleaseBuf_CalcLen(len); + fileName = GetUnicodeString(fileNameA); + } + else + #endif + { + UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); + const unsigned len = bufferSize + 2; + QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1); + fileName.ReleaseBuf_CalcLen(len); + } + return fileName; +} + +void CDrop::QueryFileNames(UStringVector &fileNames) +{ + UINT numFiles = QueryCountOfFiles(); + /* + char s[100]; + sprintf(s, "QueryFileNames: %d files", numFiles); + OutputDebugStringA(s); + */ + fileNames.ClearAndReserve(numFiles); + for (UINT i = 0; i < numFiles; i++) + { + const UString s2 = QueryFileName(i); + if (!s2.IsEmpty()) + fileNames.AddInReserved(s2); + /* + OutputDebugStringW(L"file ---"); + OutputDebugStringW(s2); + */ + } +} + + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) +{ + const unsigned len = MAX_PATH * 2; + bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); + path.ReleaseBuf_CalcLen(len); + return result; +} + +#endif + +#ifdef UNDER_CE + +bool BrowseForFolder(LPBROWSEINFO, CSysString) +{ + return false; +} + +bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) +{ + return false; +} + +bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, + LPCTSTR /* initialFolder */, CSysString & /* resultPath */) +{ + /* + // SHBrowseForFolder doesn't work before CE 6.0 ? + if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) + MessageBoxW(0, L"no", L"", 0); + else + MessageBoxW(0, L"yes", L"", 0); + */ + /* + UString s = "all files"; + s += " (*.*)"; + return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); + */ + return false; +} + +#else + +bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) +{ + NWindows::NCOM::CComInitializer comInitializer; + LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); + if (itemIDList == NULL) + return false; + CItemIDList itemIDListHolder; + itemIDListHolder.Attach(itemIDList); + return GetPathFromIDList(itemIDList, resultPath); +} + + +static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) +{ + #ifndef UNDER_CE + switch (uMsg) + { + case BFFM_INITIALIZED: + { + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); + break; + } + /* + case BFFM_SELCHANGED: + { + TCHAR dir[MAX_PATH]; + if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); + else + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); + break; + } + */ + default: + break; + } + #endif + return 0; +} + + +static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, + LPCTSTR initialFolder, CSysString &resultPath) +{ + CSysString displayName; + BROWSEINFO browseInfo; + browseInfo.hwndOwner = owner; + browseInfo.pidlRoot = NULL; + + // there are Unicode/Astring problems in some WinCE SDK ? + /* + #ifdef UNDER_CE + browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = (LPCSTR)title; + #else + */ + browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = title; + // #endif + browseInfo.ulFlags = ulFlags; + browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL; + browseInfo.lParam = (LPARAM)initialFolder; + return BrowseForFolder(&browseInfo, resultPath); +} + +bool BrowseForFolder(HWND owner, LPCTSTR title, + LPCTSTR initialFolder, CSysString &resultPath) +{ + return BrowseForFolder(owner, title, + #ifndef UNDER_CE + BIF_NEWDIALOGSTYLE | + #endif + BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); + // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) +} + +#ifndef _UNICODE + +typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) +{ + path.Empty(); + SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); + if (shGetPathFromIDListW == 0) + return false; + const unsigned len = MAX_PATH * 2; + bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); + path.ReleaseBuf_CalcLen(len); + return result; +} + +typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); + +static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) +{ + NWindows::NCOM::CComInitializer comInitializer; + SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); + if (shBrowseForFolderW == 0) + return false; + LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); + if (itemIDList == NULL) + return false; + CItemIDList itemIDListHolder; + itemIDListHolder.Attach(itemIDList); + return GetPathFromIDList(itemIDList, resultPath); +} + +static +int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) +{ + switch (uMsg) + { + case BFFM_INITIALIZED: + { + SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); + break; + } + /* + case BFFM_SELCHANGED: + { + wchar_t dir[MAX_PATH * 2]; + + if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) + SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); + else + SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); + break; + } + */ + default: + break; + } + return 0; +} + + +static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, + LPCWSTR initialFolder, UString &resultPath) +{ + UString displayName; + BROWSEINFOW browseInfo; + browseInfo.hwndOwner = owner; + browseInfo.pidlRoot = NULL; + browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); + browseInfo.lpszTitle = title; + browseInfo.ulFlags = ulFlags; + browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL; + browseInfo.lParam = (LPARAM)initialFolder; + return BrowseForFolder(&browseInfo, resultPath); +} + +bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) +{ + if (g_IsNT) + return BrowseForFolder(owner, title, + BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS + // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. + , initialFolder, resultPath); + // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) + CSysString s; + bool res = BrowseForFolder(owner, GetSystemString(title), + BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS + // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. + , GetSystemString(initialFolder), s); + resultPath = GetUnicodeString(s); + return res; +} + +#endif + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Shell.h b/3rdparty/lzma-21.03beta/CPP/Windows/Shell.h new file mode 100644 index 0000000..de91d3f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Shell.h @@ -0,0 +1,94 @@ +// Windows/Shell.h + +#ifndef __WINDOWS_SHELL_H +#define __WINDOWS_SHELL_H + +#include "../Common/MyWindows.h" +#include + +#include "../Common/MyString.h" + +#include "Defs.h" + +namespace NWindows{ +namespace NShell{ + +///////////////////////// +// CItemIDList +#ifndef UNDER_CE + +class CItemIDList +{ + LPITEMIDLIST m_Object; +public: + CItemIDList(): m_Object(NULL) {} + // CItemIDList(LPCITEMIDLIST itemIDList); + // CItemIDList(const CItemIDList& itemIDList); + ~CItemIDList() { Free(); } + void Free(); + void Attach(LPITEMIDLIST object) + { + Free(); + m_Object = object; + } + LPITEMIDLIST Detach() + { + LPITEMIDLIST object = m_Object; + m_Object = NULL; + return object; + } + operator LPITEMIDLIST() { return m_Object;} + operator LPCITEMIDLIST() const { return m_Object;} + LPITEMIDLIST* operator&() { return &m_Object; } + LPITEMIDLIST operator->() { return m_Object; } + + // CItemIDList& operator=(LPCITEMIDLIST object); + // CItemIDList& operator=(const CItemIDList &object); +}; + +///////////////////////////// +// CDrop + +class CDrop +{ + HDROP m_Object; + bool m_MustBeFinished; + bool m_Assigned; + void Free(); +public: + CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {} + ~CDrop() { Free(); } + + void Attach(HDROP object); + operator HDROP() { return m_Object;} + bool QueryPoint(LPPOINT point) + { return BOOLToBool(::DragQueryPoint(m_Object, point)); } + void Finish() { ::DragFinish(m_Object); } + UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT fileNameSize) + { return ::DragQueryFile(m_Object, fileIndex, fileName, fileNameSize); } + #ifndef _UNICODE + UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT fileNameSize) + { return ::DragQueryFileW(m_Object, fileIndex, fileName, fileNameSize); } + #endif + UINT QueryCountOfFiles(); + UString QueryFileName(UINT fileIndex); + void QueryFileNames(UStringVector &fileNames); +}; + +#endif + +///////////////////////////// +// Functions + +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path); +bool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath); +bool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath); + +#ifndef _UNICODE +bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path); +bool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath); +bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath); +#endif +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/StdAfx.h b/3rdparty/lzma-21.03beta/CPP/Windows/StdAfx.h new file mode 100644 index 0000000..1766dfa --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../Common/Common.h" + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.cpp new file mode 100644 index 0000000..fbf919d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.cpp @@ -0,0 +1,63 @@ +// Windows/Synchronization.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include "Synchronization.h" + +namespace NWindows { +namespace NSynchronization { + +/* +#define INFINITE 0xFFFFFFFF +#define MAXIMUM_WAIT_OBJECTS 64 +#define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L) +#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 ) +// WINAPI +DWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout); +*/ + +DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) +{ + if (count < 1) + { + // abort(); + SetLastError(EINVAL); + return WAIT_FAILED; + } + + CSynchro *synchro = handles[0]->_sync; + synchro->Enter(); + + // #ifdef DEBUG_SYNCHRO + for (DWORD i = 1; i < count; i++) + { + if (synchro != handles[i]->_sync) + { + // abort(); + synchro->Leave(); + SetLastError(EINVAL); + return WAIT_FAILED; + } + } + // #endif + + for (;;) + { + for (DWORD i = 0; i < count; i++) + { + if (handles[i]->IsSignaledAndUpdate()) + { + synchro->Leave(); + return WAIT_OBJECT_0 + i; + } + } + synchro->WaitCond(); + } +} + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.h b/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.h new file mode 100644 index 0000000..7d2e8d2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Synchronization.h @@ -0,0 +1,393 @@ +// Windows/Synchronization.h + +#ifndef __WINDOWS_SYNCHRONIZATION_H +#define __WINDOWS_SYNCHRONIZATION_H + +#include "../../C/Threads.h" + +#include "../Common/MyTypes.h" + +#include "Defs.h" + +#ifdef _WIN32 +#include "Handle.h" +#endif + +namespace NWindows { +namespace NSynchronization { + +class CBaseEvent MY_UNCOPYABLE +{ +protected: + ::CEvent _object; +public: + bool IsCreated() { return Event_IsCreated(&_object) != 0; } + + CBaseEvent() { Event_Construct(&_object); } + ~CBaseEvent() { Close(); } + WRes Close() { return Event_Close(&_object); } + + #ifdef _WIN32 + operator HANDLE() { return _object; } + WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) + { + _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); + if (name == NULL && _object != 0) + return 0; + return ::GetLastError(); + } + WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) + { + _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); + if (_object != 0) + return 0; + return ::GetLastError(); + } + #endif + + WRes Set() { return Event_Set(&_object); } + // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } + WRes Reset() { return Event_Reset(&_object); } + WRes Lock() { return Event_Wait(&_object); } +}; + +class CManualResetEvent: public CBaseEvent +{ +public: + WRes Create(bool initiallyOwn = false) + { + return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); + } + WRes CreateIfNotCreated_Reset() + { + if (IsCreated()) + return Reset(); + return ManualResetEvent_CreateNotSignaled(&_object); + } + #ifdef _WIN32 + WRes CreateWithName(bool initiallyOwn, LPCTSTR name) + { + return CBaseEvent::Create(true, initiallyOwn, name); + } + #endif +}; + +class CAutoResetEvent: public CBaseEvent +{ +public: + WRes Create() + { + return AutoResetEvent_CreateNotSignaled(&_object); + } + WRes CreateIfNotCreated_Reset() + { + if (IsCreated()) + return Reset(); + return AutoResetEvent_CreateNotSignaled(&_object); + } +}; + + +/* +#ifdef _WIN32 + +class CObject: public CHandle +{ +public: + WRes Lock(DWORD timeoutInterval = INFINITE) + { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } +}; + +class CMutex: public CObject +{ +public: + WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) + { + _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name); + if (name == NULL && _handle != 0) + return 0; + return ::GetLastError(); + } + #ifndef UNDER_CE + WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) + { + _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); + if (_handle != 0) + return 0; + return ::GetLastError(); + } + #endif + WRes Release() + { + return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); + } +}; + +class CMutexLock MY_UNCOPYABLE +{ + CMutex *_object; +public: + CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } + ~CMutexLock() { _object->Release(); } +}; + +#endif // _WIN32 +*/ + + +class CSemaphore MY_UNCOPYABLE +{ + ::CSemaphore _object; +public: + CSemaphore() { Semaphore_Construct(&_object); } + ~CSemaphore() { Close(); } + WRes Close() { return Semaphore_Close(&_object); } + + #ifdef _WIN32 + operator HANDLE() { return _object; } + #endif + + // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; } + + WRes Create(UInt32 initCount, UInt32 maxCount) + { + return Semaphore_Create(&_object, initCount, maxCount); + } + WRes OptCreateInit(UInt32 initCount, UInt32 maxCount) + { + return Semaphore_OptCreateInit(&_object, initCount, maxCount); + } + WRes Release() { return Semaphore_Release1(&_object); } + WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } + WRes Lock() { return Semaphore_Wait(&_object); } +}; + +class CCriticalSection MY_UNCOPYABLE +{ + ::CCriticalSection _object; +public: + CCriticalSection() { CriticalSection_Init(&_object); } + ~CCriticalSection() { CriticalSection_Delete(&_object); } + void Enter() { CriticalSection_Enter(&_object); } + void Leave() { CriticalSection_Leave(&_object); } +}; + +class CCriticalSectionLock MY_UNCOPYABLE +{ + CCriticalSection *_object; + void Unlock() { _object->Leave(); } +public: + CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } + ~CCriticalSectionLock() { Unlock(); } +}; + + +#ifdef _WIN32 + +typedef HANDLE CHandle_WFMO; +typedef CSemaphore CSemaphore_WFMO; +typedef CAutoResetEvent CAutoResetEvent_WFMO; +typedef CManualResetEvent CManualResetEvent_WFMO; + +inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) +{ + return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); +} + +#define SYNC_OBJ_DECL(obj) +#define SYNC_WFMO(x) +#define SYNC_PARAM(x) +#define SYNC_PARAM_DECL(x) + +#else // _WIN32 + +// POSIX sync objects for WaitForMultipleObjects + +#define SYNC_WFMO(x) x +#define SYNC_PARAM(x) x, +#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x +#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x; + +class CSynchro MY_UNCOPYABLE +{ + pthread_mutex_t _mutex; + pthread_cond_t _cond; + bool _isValid; + +public: + CSynchro() { _isValid = false; } + ~CSynchro() + { + if (_isValid) + { + ::pthread_mutex_destroy(&_mutex); + ::pthread_cond_destroy(&_cond); + } + _isValid = false; + } + WRes Create() + { + RINOK(::pthread_mutex_init(&_mutex, 0)); + WRes ret = ::pthread_cond_init(&_cond, 0); + _isValid = 1; + return ret; + } + WRes Enter() + { + return ::pthread_mutex_lock(&_mutex); + } + WRes Leave() + { + return ::pthread_mutex_unlock(&_mutex); + } + WRes WaitCond() + { + return ::pthread_cond_wait(&_cond, &_mutex); + } + WRes LeaveAndSignal() + { + WRes res1 = ::pthread_cond_broadcast(&_cond); + WRes res2 = ::pthread_mutex_unlock(&_mutex); + return (res2 ? res2 : res1); + } +}; + + +struct CBaseHandle_WFMO; +typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO; + +// these constants are from Windows +#define WAIT_OBJECT_0 0 +#define WAIT_FAILED ((DWORD)0xFFFFFFFF) + +DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles); + + +struct CBaseHandle_WFMO MY_UNCOPYABLE +{ + CSynchro *_sync; + + CBaseHandle_WFMO(): _sync(NULL) {} + + operator CHandle_WFMO() { return this; } + virtual bool IsSignaledAndUpdate() = 0; +}; + + +class CBaseEvent_WFMO : public CBaseHandle_WFMO +{ + bool _manual_reset; + bool _state; + +public: + + // bool IsCreated() { return (this->_sync != NULL); } + // CBaseEvent_WFMO() { ; } + ~CBaseEvent_WFMO() { Close(); } + + WRes Close() { this->_sync = NULL; return 0; } + + WRes Create( + CSynchro *sync, + bool manualReset, bool initiallyOwn) + { + this->_sync = sync; + this->_manual_reset = manualReset; + this->_state = initiallyOwn; + return 0; + } + + WRes Set() + { + RINOK(this->_sync->Enter()); + this->_state = true; + return this->_sync->LeaveAndSignal(); + } + + WRes Reset() + { + RINOK(this->_sync->Enter()); + this->_state = false; + return this->_sync->Leave(); + } + + virtual bool IsSignaledAndUpdate() + { + if (this->_state == false) + return false; + if (this->_manual_reset == false) + this->_state = false; + return true; + } +}; + + +class CManualResetEvent_WFMO: public CBaseEvent_WFMO +{ +public: + WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } +}; + + +class CAutoResetEvent_WFMO: public CBaseEvent_WFMO +{ +public: + WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } + WRes CreateIfNotCreated_Reset(CSynchro *sync) + { + return Create(sync); + } +}; + + +class CSemaphore_WFMO : public CBaseHandle_WFMO +{ + UInt32 _count; + UInt32 _maxCount; + +public: + CSemaphore_WFMO() : _count(0), _maxCount(0) {} + + WRes Close() { this->_sync = NULL; return 0; } + + WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) + { + if (initCount > maxCount || maxCount < 1) + return EINVAL; + this->_sync = sync; + this->_count = initCount; + this->_maxCount = maxCount; + return 0; + } + + WRes Release(UInt32 releaseCount = 1) + { + if (releaseCount < 1) + return EINVAL; + + RINOK(this->_sync->Enter()); + UInt32 newCount = this->_count + releaseCount; + if (newCount > this->_maxCount) + { + RINOK(this->_sync->Leave()); + return ERROR_TOO_MANY_POSTS; // EINVAL + } + this->_count = newCount; + + return this->_sync->LeaveAndSignal(); + } + + virtual bool IsSignaledAndUpdate() + { + if (this->_count == 0) + return false; + this->_count--; + return true; + } +}; + +#endif // _WIN32 + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/System.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/System.cpp new file mode 100644 index 0000000..099407e --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/System.cpp @@ -0,0 +1,231 @@ +// Windows/System.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#ifdef __APPLE__ +#include +#else +#include +#endif +#endif + +#include "../Common/Defs.h" +// #include "../Common/MyWindows.h" + +// #include "../../C/CpuArch.h" + +#include "System.h" + +namespace NWindows { +namespace NSystem { + +#ifdef _WIN32 + +UInt32 CountAffinity(DWORD_PTR mask) +{ + UInt32 num = 0; + for (unsigned i = 0; i < sizeof(mask) * 8; i++) + num += (UInt32)((mask >> i) & 1); + return num; +} + +BOOL CProcessAffinity::Get() +{ + #ifndef UNDER_CE + return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask); + #else + return FALSE; + #endif +} + + +UInt32 GetNumberOfProcessors() +{ + // We need to know how many threads we can use. + // By default the process is assigned to one group. + // So we get the number of logical processors (threads) + // assigned to current process in the current group. + // Group size can be smaller than total number logical processors, for exammple, 2x36 + + CProcessAffinity pa; + + if (pa.Get() && pa.processAffinityMask != 0) + return pa.GetNumProcessThreads(); + + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + // the number of logical processors in the current group + return (UInt32)systemInfo.dwNumberOfProcessors; +} + +#else + + +BOOL CProcessAffinity::Get() +{ + numSysThreads = GetNumberOfProcessors(); + + /* + numSysThreads = 8; + for (unsigned i = 0; i < numSysThreads; i++) + CpuSet_Set(&cpu_set, i); + return TRUE; + */ + + #ifdef _7ZIP_AFFINITY_SUPPORTED + + // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online + if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0) + return FALSE; + return TRUE; + + #else + + // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1; + return TRUE; + // errno = ENOSYS; + // return FALSE; + + #endif +} + +UInt32 GetNumberOfProcessors() +{ + #ifndef _7ZIP_ST + long n = sysconf(_SC_NPROCESSORS_CONF); // The number of processors configured + if (n < 1) + n = 1; + return (UInt32)n; + #else + return 1; + #endif +} + +#endif + + +#ifdef _WIN32 + +#ifndef UNDER_CE + +#if !defined(_WIN64) && defined(__GNUC__) + +typedef struct _MY_MEMORYSTATUSEX { + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; + +#else + +#define MY_MEMORYSTATUSEX MEMORYSTATUSEX +#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX + +#endif + +typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); + +#endif // !UNDER_CE + + +bool GetRamSize(UInt64 &size) +{ + size = (UInt64)(sizeof(size_t)) << 29; + + #ifndef UNDER_CE + MY_MEMORYSTATUSEX stat; + stat.dwLength = sizeof(stat); + #endif + + #ifdef _WIN64 + + if (!::GlobalMemoryStatusEx(&stat)) + return false; + size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + return true; + + #else + + #ifndef UNDER_CE + GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) + (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx"); + if (globalMemoryStatusEx && globalMemoryStatusEx(&stat)) + { + size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); + return true; + } + #endif + + { + MEMORYSTATUS stat2; + stat2.dwLength = sizeof(stat2); + ::GlobalMemoryStatus(&stat2); + size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys); + return true; + } + #endif +} + +#else + +// POSIX +// #include + +bool GetRamSize(UInt64 &size) +{ + size = (UInt64)(sizeof(size_t)) << 29; + + #ifdef __APPLE__ + + #ifdef HW_MEMSIZE + uint64_t val = 0; // support 2Gb+ RAM + int mib[2] = { CTL_HW, HW_MEMSIZE }; + #elif defined(HW_PHYSMEM64) + uint64_t val = 0; // support 2Gb+ RAM + int mib[2] = { CTL_HW, HW_PHYSMEM64 }; + #else + unsigned int val = 0; // For old system + int mib[2] = { CTL_HW, HW_PHYSMEM }; + #endif // HW_MEMSIZE + size_t size_sys = sizeof(val); + + sysctl(mib, 2, &val, &size_sys, NULL, 0); + if (val) + size = val; + + #elif defined(_AIX) + + // fixme + + #else + + struct sysinfo info; + if (::sysinfo(&info) != 0) + return false; + size = (UInt64)info.mem_unit * info.totalram; + const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); + if (size > kLimit) + size = kLimit; + + /* + printf("\n mem_unit = %lld", (UInt64)info.mem_unit); + printf("\n totalram = %lld", (UInt64)info.totalram); + printf("\n freeram = %lld", (UInt64)info.freeram); + */ + + #endif + + return true; +} + +#endif + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/System.h b/3rdparty/lzma-21.03beta/CPP/Windows/System.h new file mode 100644 index 0000000..23cb0da --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/System.h @@ -0,0 +1,129 @@ +// Windows/System.h + +#ifndef __WINDOWS_SYSTEM_H +#define __WINDOWS_SYSTEM_H + +#ifndef _WIN32 +// #include +#include "../../C/Threads.h" +#endif + +#include "../Common/MyTypes.h" + +namespace NWindows { +namespace NSystem { + + +#ifdef _WIN32 + +UInt32 CountAffinity(DWORD_PTR mask); + +struct CProcessAffinity +{ + // UInt32 numProcessThreads; + // UInt32 numSysThreads; + DWORD_PTR processAffinityMask; + DWORD_PTR systemAffinityMask; + + void InitST() + { + // numProcessThreads = 1; + // numSysThreads = 1; + processAffinityMask = 1; + systemAffinityMask = 1; + } + + void CpuZero() + { + processAffinityMask = 0; + } + + void CpuSet(unsigned cpuIndex) + { + processAffinityMask |= ((DWORD_PTR)1 << cpuIndex); + } + + UInt32 GetNumProcessThreads() const { return CountAffinity(processAffinityMask); } + UInt32 GetNumSystemThreads() const { return CountAffinity(systemAffinityMask); } + + BOOL Get(); + + BOOL SetProcAffinity() const + { + return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask); + } +}; + + +#else // WIN32 + +struct CProcessAffinity +{ + UInt32 numSysThreads; + + UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; } + BOOL Get(); + + #ifdef _7ZIP_AFFINITY_SUPPORTED + + CCpuSet cpu_set; + + void InitST() + { + numSysThreads = 1; + CpuSet_Zero(&cpu_set); + CpuSet_Set(&cpu_set, 0); + } + + UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); } + void CpuZero() { CpuSet_Zero(&cpu_set); } + void CpuSet(unsigned cpuIndex) { CpuSet_Set(&cpu_set, cpuIndex); } + int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); } + // void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); } + + BOOL SetProcAffinity() const + { + return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0; + } + + #else + + void InitST() + { + numSysThreads = 1; + } + + UInt32 GetNumProcessThreads() const + { + return numSysThreads; + /* + UInt32 num = 0; + for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++) + num += (UInt32)((cpu_set >> i) & 1); + return num; + */ + } + + void CpuZero() { } + void CpuSet(unsigned cpuIndex) { UNUSED_VAR(cpuIndex); } + int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; } + + BOOL SetProcAffinity() const + { + errno = ENOSYS; + return FALSE; + } + + #endif +}; + +#endif + + +UInt32 GetNumberOfProcessors(); + +bool GetRamSize(UInt64 &size); // returns false, if unknown ram size + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.cpp new file mode 100644 index 0000000..9346afd --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.cpp @@ -0,0 +1,897 @@ +// Windows/SystemInfo.cpp + +#include "StdAfx.h" + +#include "../../C/CpuArch.h" + +#include "../Common/IntToString.h" + +#ifdef _WIN32 + +#include "Registry.h" + +#else + +#include +#include +#ifdef __APPLE__ +#include +#elif !defined(_AIX) + +#include + +#ifdef MY_CPU_ARM_OR_ARM64 +#include +#endif +#endif + +#ifdef __linux__ +#include "../Windows/FileIO.h" +#endif + +#endif // WIN32 + +#include "SystemInfo.h" +#include "System.h" + +using namespace NWindows; + +#ifdef __linux__ + +static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf) +{ + NWindows::NFile::NIO::CInFile file; + if (!file.Open(fileName)) + return false; + /* + UInt64 size; + if (!file.GetLength(size)) + { + // GetLength() doesn't work "/proc/cpuinfo" + return false; + } + if (size >= ((UInt32)1 << 29)) + return false; + */ + size_t size = 0; + size_t addSize = ((size_t)1 << 12); + for (;;) + { + // printf("\nsize = %d\n", (unsigned)size); + buf.ChangeSize_KeepData(size + addSize, size); + size_t processed; + if (!file.ReadFull(buf + size, addSize, processed)) + return false; + if (processed == 0) + { + buf.ChangeSize_KeepData(size, size); + return true; + } + size += processed; + addSize *= 2; + } +} + +#endif + + +#ifndef __APPLE__ +static void PrintHex(AString &s, UInt64 v) +{ + char temp[32]; + ConvertUInt64ToHex(v, temp); + s += temp; +} +#endif + +#ifdef MY_CPU_X86_OR_AMD64 + +static void PrintCpuChars(AString &s, UInt32 v) +{ + for (int j = 0; j < 4; j++) + { + Byte b = (Byte)(v & 0xFF); + v >>= 8; + if (b == 0) + break; + s += (char)b; + } +} + + +static void x86cpuid_to_String(const Cx86cpuid &c, AString &s, AString &ver) +{ + s.Empty(); + + UInt32 maxFunc2 = 0; + UInt32 t[3]; + + MyCPUID(0x80000000, &maxFunc2, &t[0], &t[1], &t[2]); + + bool fullNameIsAvail = (maxFunc2 >= 0x80000004); + + if (fullNameIsAvail) + { + for (unsigned i = 0; i < 3; i++) + { + UInt32 d[4] = { 0 }; + MyCPUID(0x80000002 + i, &d[0], &d[1], &d[2], &d[3]); + for (unsigned j = 0; j < 4; j++) + PrintCpuChars(s, d[j]); + } + } + + s.Trim(); + + if (s.IsEmpty()) + { + for (int i = 0; i < 3; i++) + PrintCpuChars(s, c.vendor[i]); + s.Trim(); + } + + { + char temp[32]; + ConvertUInt32ToHex(c.ver, temp); + ver += temp; + } +} + +/* +static void x86cpuid_all_to_String(AString &s) +{ + Cx86cpuid p; + if (!x86cpuid_CheckAndRead(&p)) + return; + s += "x86cpuid maxFunc = "; + s.Add_UInt32(p.maxFunc); + for (unsigned j = 0; j <= p.maxFunc; j++) + { + s.Add_LF(); + // s.Add_UInt32(j); // align + { + char temp[32]; + ConvertUInt32ToString(j, temp); + unsigned len = (unsigned)strlen(temp); + while (len < 8) + { + len++; + s.Add_Space(); + } + s += temp; + } + + s += ":"; + UInt32 d[4] = { 0 }; + MyCPUID(j, &d[0], &d[1], &d[2], &d[3]); + for (unsigned i = 0; i < 4; i++) + { + char temp[32]; + ConvertUInt32ToHex8Digits(d[i], temp); + s += " "; + s += temp; + } + } +} +*/ + +#endif + + + +#ifdef _WIN32 + +static const char * const k_PROCESSOR_ARCHITECTURE[] = +{ + "x86" // "INTEL" + , "MIPS" + , "ALPHA" + , "PPC" + , "SHX" + , "ARM" + , "IA64" + , "ALPHA64" + , "MSIL" + , "x64" // "AMD64" + , "IA32_ON_WIN64" + , "NEUTRAL" + , "ARM64" + , "ARM32_ON_WIN64" +}; + +#define MY__PROCESSOR_ARCHITECTURE_INTEL 0 +#define MY__PROCESSOR_ARCHITECTURE_AMD64 9 + + +#define MY__PROCESSOR_INTEL_PENTIUM 586 +#define MY__PROCESSOR_AMD_X8664 8664 + +/* +static const CUInt32PCharPair k_PROCESSOR[] = +{ + { 2200, "IA64" }, + { 8664, "x64" } +}; + +#define PROCESSOR_INTEL_386 386 +#define PROCESSOR_INTEL_486 486 +#define PROCESSOR_INTEL_PENTIUM 586 +#define PROCESSOR_INTEL_860 860 +#define PROCESSOR_INTEL_IA64 2200 +#define PROCESSOR_AMD_X8664 8664 +#define PROCESSOR_MIPS_R2000 2000 +#define PROCESSOR_MIPS_R3000 3000 +#define PROCESSOR_MIPS_R4000 4000 +#define PROCESSOR_ALPHA_21064 21064 +#define PROCESSOR_PPC_601 601 +#define PROCESSOR_PPC_603 603 +#define PROCESSOR_PPC_604 604 +#define PROCESSOR_PPC_620 620 +#define PROCESSOR_HITACHI_SH3 10003 +#define PROCESSOR_HITACHI_SH3E 10004 +#define PROCESSOR_HITACHI_SH4 10005 +#define PROCESSOR_MOTOROLA_821 821 +#define PROCESSOR_SHx_SH3 103 +#define PROCESSOR_SHx_SH4 104 +#define PROCESSOR_STRONGARM 2577 // 0xA11 +#define PROCESSOR_ARM720 1824 // 0x720 +#define PROCESSOR_ARM820 2080 // 0x820 +#define PROCESSOR_ARM920 2336 // 0x920 +#define PROCESSOR_ARM_7TDMI 70001 +#define PROCESSOR_OPTIL 18767 // 0x494f +*/ + + +/* +static const char * const k_PF[] = +{ + "FP_ERRATA" + , "FP_EMU" + , "CMPXCHG" + , "MMX" + , "PPC_MOVEMEM_64BIT" + , "ALPHA_BYTE" + , "SSE" + , "3DNOW" + , "RDTSC" + , "PAE" + , "SSE2" + , "SSE_DAZ" + , "NX" + , "SSE3" + , "CMPXCHG16B" + , "CMP8XCHG16" + , "CHANNELS" + , "XSAVE" + , "ARM_VFP_32" + , "ARM_NEON" + , "L2AT" + , "VIRT_FIRMWARE" + , "RDWRFSGSBASE" + , "FASTFAIL" + , "ARM_DIVIDE" + , "ARM_64BIT_LOADSTORE_ATOMIC" + , "ARM_EXTERNAL_CACHE" + , "ARM_FMAC" + , "RDRAND" + , "ARM_V8" + , "ARM_V8_CRYPTO" + , "ARM_V8_CRC32" + , "RDTSCP" + , "RDPID" + , "ARM_V81_ATOMIC" + , "MONITORX" +}; +*/ + +#endif + + +#ifdef _WIN32 + +static void PrintPage(AString &s, UInt32 v) +{ + if ((v & 0x3FF) == 0) + { + s.Add_UInt32(v >> 10); + s += "K"; + } + else + s.Add_UInt32(v >> 10); +} + +static AString TypeToString2(const char * const table[], unsigned num, UInt32 value) +{ + char sz[16]; + const char *p = NULL; + if (value < num) + p = table[value]; + if (!p) + { + ConvertUInt32ToString(value, sz); + p = sz; + } + return (AString)p; +} + +// #if defined(_7ZIP_LARGE_PAGES) || defined(_WIN32) +// #ifdef _WIN32 +void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v) +{ + char c = 0; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'M'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'G'; + if ((v & 0x3FF) == 0) { v >>= 10; c = 'T'; + }}}} + else + { + PrintHex(s, v); + return; + } + char temp[32]; + ConvertUInt64ToString(v, temp); + s += temp; + if (c) + s += c; +} +// #endif +// #endif + +static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si) +{ + s += TypeToString2(k_PROCESSOR_ARCHITECTURE, ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture); + + if (!( (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == MY__PROCESSOR_INTEL_PENTIUM) + || (si.wProcessorArchitecture == MY__PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == MY__PROCESSOR_AMD_X8664))) + { + s += " "; + // s += TypePairToString(k_PROCESSOR, ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType); + s.Add_UInt32(si.dwProcessorType); + } + s += " "; + PrintHex(s, si.wProcessorLevel); + s += "."; + PrintHex(s, si.wProcessorRevision); + if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors)) + if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8) + { + s += " act:"; + PrintHex(s, si.dwActiveProcessorMask); + } + s += " cpus:"; + s.Add_UInt32(si.dwNumberOfProcessors); + if (si.dwPageSize != 1 << 12) + { + s += " page:"; + PrintPage(s, si.dwPageSize); + } + if (si.dwAllocationGranularity != 1 << 16) + { + s += " gran:"; + PrintPage(s, si.dwAllocationGranularity); + } + s += " "; + + DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress; + UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1; + const UInt32 kReserveSize = ((UInt32)1 << 16); + if (minAdd != kReserveSize) + { + PrintSize_KMGT_Or_Hex(s, minAdd); + s += "-"; + } + else + { + if ((maxSize & (kReserveSize - 1)) == 0) + maxSize += kReserveSize; + } + PrintSize_KMGT_Or_Hex(s, maxSize); +} + +#ifndef _WIN64 +EXTERN_C_BEGIN +typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo); +EXTERN_C_END +#endif + +#endif + +#ifdef __APPLE__ +#ifndef MY_CPU_X86_OR_AMD64 +static void Add_sysctlbyname_to_String(const char *name, AString &s) +{ + size_t bufSize = 256; + char buf[256]; + if (My_sysctlbyname_Get(name, &buf, &bufSize) == 0) + s += buf; +} +#endif +#endif + +void GetSysInfo(AString &s1, AString &s2); +void GetSysInfo(AString &s1, AString &s2) +{ + s1.Empty(); + s2.Empty(); + + #ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + { + SysInfo_To_String(s1, si); + // s += " : "; + } + + #if !defined(_WIN64) && !defined(UNDER_CE) + Func_GetNativeSystemInfo fn_GetNativeSystemInfo = (Func_GetNativeSystemInfo)(void *)GetProcAddress( + GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); + if (fn_GetNativeSystemInfo) + { + SYSTEM_INFO si2; + fn_GetNativeSystemInfo(&si2); + // if (memcmp(&si, &si2, sizeof(si)) != 0) + { + // s += " - "; + SysInfo_To_String(s2, si2); + } + } + #endif + #endif +} + + +void GetCpuName(AString &s); + +static void AddBracedString(AString &dest, AString &src) +{ + if (!src.IsEmpty()) + { + AString s; + s += '('; + s += src; + s += ')'; + dest.Add_OptSpaced(s); + } +} + +struct CCpuName +{ + AString CpuName; + AString Revision; + AString Microcode; + AString LargePages; + + void Fill(); + + void Get_Revision_Microcode_LargePages(AString &s) + { + s.Empty(); + AddBracedString(s, Revision); + AddBracedString(s, Microcode); + s.Add_OptSpaced(LargePages); + } +}; + +void CCpuName::Fill() +{ + CpuName.Empty(); + Revision.Empty(); + Microcode.Empty(); + LargePages.Empty(); + + AString &s = CpuName; + + #ifdef MY_CPU_X86_OR_AMD64 + { + Cx86cpuid cpuid; + if (x86cpuid_CheckAndRead(&cpuid)) + { + x86cpuid_to_String(cpuid, s, Revision); + } + else + { + #ifdef MY_CPU_AMD64 + s += "x64"; + #else + s += "x86"; + #endif + } + } + #elif defined(__APPLE__) + { + Add_sysctlbyname_to_String("machdep.cpu.brand_string", s); + } + #endif + + + if (s.IsEmpty()) + { + #ifdef MY_CPU_LE + s += "LE"; + #elif defined(MY_CPU_BE) + s += "BE"; + #endif + } + + #ifdef __APPLE__ + { + AString s2; + UInt32 v = 0; + if (My_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0) + { + s2.Add_UInt32(v); + s2 += 'C'; + } + if (My_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0) + { + s2.Add_UInt32(v); + s2 += 'T'; + } + if (!s2.IsEmpty()) + { + s.Add_Space_if_NotEmpty(); + s += s2; + } + } + #endif + + + #ifdef _WIN32 + { + NRegistry::CKey key; + if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS) + { + LONG res[2]; + CByteBuffer bufs[2]; + { + for (int i = 0; i < 2; i++) + { + UInt32 size = 0; + res[i] = key.QueryValue(i == 0 ? + TEXT("Previous Update Revision") : + TEXT("Update Revision"), bufs[i], size); + if (res[i] == ERROR_SUCCESS) + if (size != bufs[i].Size()) + res[i] = ERROR_SUCCESS + 1; + } + } + if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) + { + for (int i = 0; i < 2; i++) + { + if (i == 1) + Microcode += "->"; + if (res[i] != ERROR_SUCCESS) + continue; + const CByteBuffer &buf = bufs[i]; + if (buf.Size() == 8) + { + UInt32 high = GetUi32(buf); + if (high != 0) + { + PrintHex(Microcode, high); + Microcode += "."; + } + PrintHex(Microcode, GetUi32(buf + 4)); + } + } + } + } + } + #endif + + + #ifdef _7ZIP_LARGE_PAGES + Add_LargePages_String(LargePages); + #endif +} + +void AddCpuFeatures(AString &s); +void AddCpuFeatures(AString &s) +{ + #ifdef _WIN32 + // const unsigned kNumFeatures_Extra = 32; // we check also for unknown features + // const unsigned kNumFeatures = ARRAY_SIZE(k_PF) + kNumFeatures_Extra; + const unsigned kNumFeatures = 64; + UInt64 flags = 0; + for (unsigned i = 0; i < kNumFeatures; i++) + { + if (IsProcessorFeaturePresent(i)) + { + flags += (UInt64)1 << i; + // s.Add_Space_if_NotEmpty(); + // s += TypeToString2(k_PF, ARRAY_SIZE(k_PF), i); + } + } + s.Add_OptSpaced("f:"); + PrintHex(s, flags); + + #elif defined(__APPLE__) + { + UInt32 v = 0; + if (My_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0) + { + s += "PageSize:"; + s.Add_UInt32(v >> 10); + s += "KB"; + } + } + + #else + + const long v = sysconf(_SC_PAGESIZE); + if (v != -1) + { + s.Add_Space_if_NotEmpty(); + s += "PageSize:"; + s.Add_UInt32((UInt32)(v >> 10)); + s += "KB"; + } + + #if !defined(_AIX) + + #ifdef __linux__ + + CByteBuffer buf; + if (ReadFile_to_Buffer("/sys/kernel/mm/transparent_hugepage/enabled", buf)) + // if (ReadFile_to_Buffer("/proc/cpuinfo", buf)) + { + s.Add_OptSpaced("THP:"); + AString s2; + s2.SetFrom_CalcLen((const char *)(const void *)(const Byte *)buf, (unsigned)buf.Size()); + const int pos = s2.Find('['); + if (pos >= 0) + { + const int pos2 = s2.Find(']', pos + 1); + if (pos2 >= 0) + { + s2.DeleteFrom(pos2); + s2.DeleteFrontal(pos + 1); + } + } + s += s2; + } + // else throw CSystemException(MY_SRes_HRESULT_FROM_WRes(errno)); + + #endif + + + s.Add_OptSpaced("hwcap:"); + { + unsigned long h = getauxval(AT_HWCAP); + PrintHex(s, h); + #ifdef MY_CPU_ARM64 + if (h & HWCAP_CRC32) s += ":CRC32"; + if (h & HWCAP_SHA1) s += ":SHA1"; + if (h & HWCAP_SHA2) s += ":SHA2"; + if (h & HWCAP_AES) s += ":AES"; + if (h & HWCAP_ASIMD) s += ":ASIMD"; + #elif defined(MY_CPU_ARM) + if (h & HWCAP_NEON) s += ":NEON"; + #endif + } + + { + unsigned long h = getauxval(AT_HWCAP2); + #ifndef MY_CPU_ARM + if (h != 0) + #endif + { + s += " hwcap2:"; + PrintHex(s, h); + #ifdef MY_CPU_ARM + if (h & HWCAP2_CRC32) s += ":CRC32"; + if (h & HWCAP2_SHA1) s += ":SHA1"; + if (h & HWCAP2_SHA2) s += ":SHA2"; + if (h & HWCAP2_AES) s += ":AES"; + #endif + } + } + #endif // _AIX + #endif // _WIN32 +} + + +#ifdef _WIN32 +#ifndef UNDER_CE + +EXTERN_C_BEGIN +typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *); +EXTERN_C_END + +static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi) +{ + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + if (!ntdll) + return FALSE; + Func_RtlGetVersion func = (Func_RtlGetVersion)(void *)GetProcAddress(ntdll, "RtlGetVersion"); + if (!func) + return FALSE; + func(vi); + return TRUE; +} + +#endif +#endif + + +void GetOsInfoText(AString &sRes) +{ + sRes.Empty(); + AString s; + + #ifdef _WIN32 + #ifndef UNDER_CE + // OSVERSIONINFO vi; + OSVERSIONINFOEXW vi; + vi.dwOSVersionInfoSize = sizeof(vi); + // if (::GetVersionEx(&vi)) + if (My_RtlGetVersion(&vi)) + { + s += "Windows"; + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) + s.Add_UInt32(vi.dwPlatformId); + s += " "; s.Add_UInt32(vi.dwMajorVersion); + s += "."; s.Add_UInt32(vi.dwMinorVersion); + s += " "; s.Add_UInt32(vi.dwBuildNumber); + + if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0) + { + s += " SP:"; s.Add_UInt32(vi.wServicePackMajor); + s += "."; s.Add_UInt32(vi.wServicePackMinor); + } + // s += " Suite:"; PrintHex(s, vi.wSuiteMask); + // s += " Type:"; s.Add_UInt32(vi.wProductType); + // s += " "; s += GetOemString(vi.szCSDVersion); + } + /* + { + s += " OEMCP:"; s.Add_UInt32(GetOEMCP()); + s += " ACP:"; s.Add_UInt32(GetACP()); + } + */ + #endif + #else // _WIN32 + + if (!s.IsEmpty()) + s.Add_LF(); + struct utsname un; + if (uname(&un) == 0) + { + s += un.sysname; + // s += " : "; s += un.nodename; // we don't want to show name of computer + s += " : "; s += un.release; + s += " : "; s += un.version; + s += " : "; s += un.machine; + + #ifdef __APPLE__ + // Add_sysctlbyname_to_String("kern.version", s); + // it's same as "utsname.version" + #endif + } + #endif // _WIN32 + + sRes += s; +} + + + +void GetSystemInfoText(AString &sRes) +{ + GetOsInfoText(sRes); + sRes.Add_LF(); + + { + AString s, s1, s2; + GetSysInfo(s1, s2); + if (!s1.IsEmpty() || !s2.IsEmpty()) + { + s = s1; + if (s1 != s2 && !s2.IsEmpty()) + { + s += " - "; + s += s2; + } + } + { + AddCpuFeatures(s); + if (!s.IsEmpty()) + { + sRes += s; + sRes.Add_LF(); + } + } + } + { + AString s; + GetCpuName(s); + if (!s.IsEmpty()) + { + sRes += s; + sRes.Add_LF(); + } + } + /* + #ifdef MY_CPU_X86_OR_AMD64 + { + AString s; + x86cpuid_all_to_String(s); + if (!s.IsEmpty()) + { + printCallback->Print(s); + printCallback->NewLine(); + } + } + #endif + */ +} + + +void GetCpuName(AString &s); +void GetCpuName(AString &s) +{ + CCpuName cpuName; + cpuName.Fill(); + s = cpuName.CpuName; + AString s2; + cpuName.Get_Revision_Microcode_LargePages(s2); + s.Add_OptSpaced(s2); +} + + +void GetCpuName_MultiLine(AString &s); +void GetCpuName_MultiLine(AString &s) +{ + CCpuName cpuName; + cpuName.Fill(); + s = cpuName.CpuName; + AString s2; + cpuName.Get_Revision_Microcode_LargePages(s2); + if (!s2.IsEmpty()) + { + s.Add_LF(); + s += s2; + } +} + +void GetCompiler(AString &s) +{ + #ifdef __VERSION__ + s += __VERSION__; + #endif + + #ifdef __GNUC__ + s += " GCC "; + s.Add_UInt32(__GNUC__); + s += '.'; + s.Add_UInt32(__GNUC_MINOR__); + s += '.'; + s.Add_UInt32(__GNUC_PATCHLEVEL__); + #endif + + #ifdef __clang__ + s += " CLANG "; + s.Add_UInt32(__clang_major__); + s += '.'; + s.Add_UInt32(__clang_minor__); + #endif + + #ifdef __xlC__ + s += " XLC "; + s.Add_UInt32(__xlC__ >> 8); + s += '.'; + s.Add_UInt32(__xlC__ & 0xFF); + #ifdef __xlC_ver__ + s += '.'; + s.Add_UInt32(__xlC_ver__ >> 8); + s += '.'; + s.Add_UInt32(__xlC_ver__ & 0xFF); + #endif + #endif + + #ifdef _MSC_VER + s += " MSC "; + s.Add_UInt32(_MSC_VER); + #endif +} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.h b/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.h new file mode 100644 index 0000000..e941d0a --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/SystemInfo.h @@ -0,0 +1,18 @@ +// Windows/SystemInfo.h + +#ifndef __WINDOWS_SYSTEM_INFO_H +#define __WINDOWS_SYSTEM_INFO_H + +#include "../Common/MyString.h" + + +void GetCpuName_MultiLine(AString &s); + +void GetOsInfoText(AString &sRes); +void GetSystemInfoText(AString &s); +void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v); +void Add_LargePages_String(AString &s); + +void GetCompiler(AString &s); + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Thread.h b/3rdparty/lzma-21.03beta/CPP/Windows/Thread.h new file mode 100644 index 0000000..c957146 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Thread.h @@ -0,0 +1,44 @@ +// Windows/Thread.h + +#ifndef __WINDOWS_THREAD_H +#define __WINDOWS_THREAD_H + +#include "../../C/Threads.h" + +#include "Defs.h" + +namespace NWindows { + +class CThread MY_UNCOPYABLE +{ + ::CThread thread; +public: + CThread() { Thread_Construct(&thread); } + ~CThread() { Close(); } + bool IsCreated() { return Thread_WasCreated(&thread) != 0; } + WRes Close() { return Thread_Close(&thread); } + // WRes Wait() { return Thread_Wait(&thread); } + WRes Wait_Close() { return Thread_Wait_Close(&thread); } + + WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param) + { return Thread_Create(&thread, startAddress, param); } + WRes Create_With_Affinity(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, CAffinityMask affinity) + { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); } + WRes Create_With_CpuSet(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID param, const CCpuSet *cpuSet) + { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); } + + #ifdef _WIN32 + operator HANDLE() { return thread; } + void Attach(HANDLE handle) { thread = handle; } + HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; } + DWORD Resume() { return ::ResumeThread(thread); } + DWORD Suspend() { return ::SuspendThread(thread); } + bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); } + int GetPriority() { return ::GetThreadPriority(thread); } + bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); } + #endif +}; + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.cpp new file mode 100644 index 0000000..1f1335f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.cpp @@ -0,0 +1,234 @@ +// Windows/TimeUtils.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#endif + +#include "Defs.h" +#include "TimeUtils.h" + +namespace NWindows { +namespace NTime { + +static const UInt32 kNumTimeQuantumsInSecond = 10000000; +static const UInt32 kFileTimeStartYear = 1601; +#if !defined(_WIN32) || defined(UNDER_CE) +static const UInt32 kDosTimeStartYear = 1980; +#endif +static const UInt32 kUnixTimeStartYear = 1970; +static const UInt64 kUnixTimeOffset = + (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); +static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); + #else + ft.dwLowDateTime = 0; + ft.dwHighDateTime = 0; + UInt64 res; + if (!GetSecondsSince1601(kDosTimeStartYear + (dosTime >> 25), (dosTime >> 21) & 0xF, (dosTime >> 16) & 0x1F, + (dosTime >> 11) & 0x1F, (dosTime >> 5) & 0x3F, (dosTime & 0x1F) * 2, res)) + return false; + res *= kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (UInt32)res; + ft.dwHighDateTime = (UInt32)(res >> 32); + return true; + #endif +} + +static const UInt32 kHighDosTime = 0xFF9FBF7D; +static const UInt32 kLowDosTime = 0x210000; + +bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() +{ + #if defined(_WIN32) && !defined(UNDER_CE) + + WORD datePart, timePart; + if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart)) + { + dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; + return false; + } + dosTime = (((UInt32)datePart) << 16) + timePart; + + #else + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + + unsigned year, mon, day, hour, min, sec; + UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned temp; + UInt32 v; + v64 += (kNumTimeQuantumsInSecond * 2 - 1); + v64 /= kNumTimeQuantumsInSecond; + sec = (unsigned)(v64 % 60); + v64 /= 60; + min = (unsigned)(v64 % 60); + v64 /= 60; + hour = (unsigned)(v64 % 24); + v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(kFileTimeStartYear + v / PERIOD_400 * 400); + v %= PERIOD_400; + + temp = (unsigned)(v / PERIOD_100); + if (temp == 4) + temp = 3; + year += temp * 100; + v -= temp * PERIOD_100; + + temp = v / PERIOD_4; + if (temp == 25) + temp = 24; + year += temp * 4; + v -= temp * PERIOD_4; + + temp = v / 365; + if (temp == 4) + temp = 3; + year += temp; + v -= temp * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 1; mon <= 12; mon++) + { + unsigned s = ms[mon - 1]; + if (v < s) + break; + v -= s; + } + day = (unsigned)v + 1; + + dosTime = kLowDosTime; + if (year < kDosTimeStartYear) + return false; + year -= kDosTimeStartYear; + dosTime = kHighDosTime; + if (year >= 128) + return false; + dosTime = (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1); + #endif + return true; +} + +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() +{ + return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; +} + +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() +{ + UInt64 v = UnixTimeToFileTime64(unixTime); + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() +{ + return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; +} + +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() +{ + if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) + { + ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; + return false; + } + Int64 v = (Int64)kUnixTimeOffset + unixTime; + if (v < 0) + { + ft.dwLowDateTime = ft.dwHighDateTime = 0; + return false; + } + UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; + ft.dwLowDateTime = (DWORD)v2; + ft.dwHighDateTime = (DWORD)(v2 >> 32); + return true; +} + +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; +} + +bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() +{ + UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + winTime /= kNumTimeQuantumsInSecond; + if (winTime < kUnixTimeOffset) + { + unixTime = 0; + return false; + } + winTime -= kUnixTimeOffset; + if (winTime > 0xFFFFFFFF) + { + unixTime = 0xFFFFFFFF; + return false; + } + unixTime = (UInt32)winTime; + return true; +} + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw() +{ + resSeconds = 0; + if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) + return false; + UInt32 numYears = year - kFileTimeStartYear; + UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + month--; + for (unsigned i = 0; i < month; i++) + numDays += ms[i]; + numDays += day - 1; + resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; + return true; +} + +void GetCurUtcFileTime(FILETIME &ft) throw() +{ + // Both variants provide same low resolution on WinXP: about 15 ms. + // But GetSystemTimeAsFileTime is much faster. + #ifdef _WIN32 + + #ifdef UNDER_CE + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + #else + GetSystemTimeAsFileTime(&ft); + #endif + + #else + + UInt64 v = 0; + struct timeval now; + if (gettimeofday(&now, 0 ) == 0) + { + v = ((UInt64)now.tv_sec + kUnixTimeOffset) * + kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10; + } + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); + + #endif +} + +}} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.h b/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.h new file mode 100644 index 0000000..d1d8c15 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/TimeUtils.h @@ -0,0 +1,32 @@ +// Windows/TimeUtils.h + +#ifndef __WINDOWS_TIME_UTILS_H +#define __WINDOWS_TIME_UTILS_H + +#include "../Common/MyTypes.h" +#include "../Common/MyWindows.h" + +namespace NWindows { +namespace NTime { + +bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); +bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); + +// UInt32 Unix Time : for dates 1970-2106 +UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw(); +void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); + +// Int64 Unix Time : negative values for dates before 1970 +UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw(); +bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); + +bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); +Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); + +bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, + unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); +void GetCurUtcFileTime(FILETIME &ft) throw(); + +}} + +#endif diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Window.cpp b/3rdparty/lzma-21.03beta/CPP/Windows/Window.cpp new file mode 100644 index 0000000..32af4aa --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Window.cpp @@ -0,0 +1,179 @@ +// Windows/Window.cpp + +#include "StdAfx.h" + +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif +#include "Window.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass) +{ + if (g_IsNT) + return RegisterClassW(wndClass); + WNDCLASSA wndClassA; + wndClassA.style = wndClass->style; + wndClassA.lpfnWndProc = wndClass->lpfnWndProc; + wndClassA.cbClsExtra = wndClass->cbClsExtra; + wndClassA.cbWndExtra = wndClass->cbWndExtra; + wndClassA.hInstance = wndClass->hInstance; + wndClassA.hIcon = wndClass->hIcon; + wndClassA.hCursor = wndClass->hCursor; + wndClassA.hbrBackground = wndClass->hbrBackground; + AString menuName; + AString className; + if (IS_INTRESOURCE(wndClass->lpszMenuName)) + wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName; + else + { + menuName = GetSystemString(wndClass->lpszMenuName); + wndClassA.lpszMenuName = menuName; + } + if (IS_INTRESOURCE(wndClass->lpszClassName)) + wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName; + else + { + className = GetSystemString(wndClass->lpszClassName); + wndClassA.lpszClassName = className; + } + return RegisterClassA(&wndClassA); +} + +bool CWindow::Create(LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + if (g_IsNT) + { + _window = ::CreateWindowW(className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + return Create(GetSystemString(className), GetSystemString(windowName), + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); +} + +bool CWindow::CreateEx(DWORD exStyle, LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) +{ + if (g_IsNT) + { + _window = ::CreateWindowExW(exStyle, className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + AString classNameA; + LPCSTR classNameP; + if (IS_INTRESOURCE(className)) + classNameP = (LPCSTR)className; + else + { + classNameA = GetSystemString(className); + classNameP = classNameA; + } + AString windowNameA; + LPCSTR windowNameP; + if (IS_INTRESOURCE(windowName)) + windowNameP = (LPCSTR)windowName; + else + { + windowNameA = GetSystemString(windowName); + windowNameP = windowNameA; + } + return CreateEx(exStyle, classNameP, windowNameP, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); +} + +#endif + +#ifndef _UNICODE +bool MySetWindowText(HWND wnd, LPCWSTR s) +{ + if (g_IsNT) + return BOOLToBool(::SetWindowTextW(wnd, s)); + return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s))); +} +#endif + +bool CWindow::GetText(CSysString &s) +{ + s.Empty(); + unsigned len = (unsigned)GetTextLength(); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + TCHAR *p = s.GetBuf(len); + { + unsigned len2 = (unsigned)GetText(p, (int)(len + 1)); + if (len > len2) + len = len2; + } + s.ReleaseBuf_CalcLen(len); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + return true; +} + +#ifndef _UNICODE +bool CWindow::GetText(UString &s) +{ + if (g_IsNT) + { + s.Empty(); + unsigned len = (unsigned)GetWindowTextLengthW(_window); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + wchar_t *p = s.GetBuf(len); + { + unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1)); + if (len > len2) + len = len2; + } + s.ReleaseBuf_CalcLen(len); + if (len == 0) + return (::GetLastError() == ERROR_SUCCESS); + return true; + } + CSysString sysString; + bool result = GetText(sysString); + MultiByteToUnicodeString2(s, sysString); + return result; +} +#endif + + +/* +bool CWindow::ModifyStyleBase(int styleOffset, + DWORD remove, DWORD add, UINT flags) +{ + DWORD style = GetWindowLong(styleOffset); + DWORD newStyle = (style & ~remove) | add; + if (style == newStyle) + return false; // it is not good + + SetWindowLong(styleOffset, newStyle); + if (flags != 0) + { + ::SetWindowPos(_window, NULL, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags); + } + return TRUE; +} +*/ + +} diff --git a/3rdparty/lzma-21.03beta/CPP/Windows/Window.h b/3rdparty/lzma-21.03beta/CPP/Windows/Window.h new file mode 100644 index 0000000..83726c7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CPP/Windows/Window.h @@ -0,0 +1,284 @@ +// Windows/Window.h + +#ifndef __WINDOWS_WINDOW_H +#define __WINDOWS_WINDOW_H + +#include "../Common/MyWindows.h" +#include "../Common/MyString.h" + +#include "Defs.h" + +#ifndef UNDER_CE + +#define MY__WM_CHANGEUISTATE 0x0127 +#define MY__WM_UPDATEUISTATE 0x0128 +#define MY__WM_QUERYUISTATE 0x0129 + +// LOWORD(wParam) values in WM_*UISTATE +#define MY__UIS_SET 1 +#define MY__UIS_CLEAR 2 +#define MY__UIS_INITIALIZE 3 + +// HIWORD(wParam) values in WM_*UISTATE +#define MY__UISF_HIDEFOCUS 0x1 +#define MY__UISF_HIDEACCEL 0x2 +#define MY__UISF_ACTIVE 0x4 + +#endif + +namespace NWindows { + +inline ATOM MyRegisterClass(CONST WNDCLASS *wndClass) + { return ::RegisterClass(wndClass); } + +#ifndef _UNICODE +ATOM MyRegisterClass(CONST WNDCLASSW *wndClass); +#endif + +#ifdef _UNICODE +inline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); } +#else +bool MySetWindowText(HWND wnd, LPCWSTR s); +#endif + + +#ifdef UNDER_CE +#define GWLP_USERDATA GWL_USERDATA +#define GWLP_WNDPROC GWL_WNDPROC +#define BTNS_BUTTON TBSTYLE_BUTTON +#define WC_COMBOBOXW L"ComboBox" +#define DWLP_MSGRESULT DWL_MSGRESULT +#endif + +class CWindow +{ +private: + // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags); +protected: + HWND _window; +public: + CWindow(HWND newWindow = NULL): _window(newWindow){}; + CWindow& operator=(HWND newWindow) + { + _window = newWindow; + return *this; + } + operator HWND() const { return _window; } + void Attach(HWND newWindow) { _window = newWindow; } + HWND Detach() + { + HWND window = _window; + _window = NULL; + return window; + } + + bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); } + + HWND GetParent() const { return ::GetParent(_window); } + bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); } + #ifndef UNDER_CE + bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); } + #endif + bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); } + bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); } + + bool CreateEx(DWORD exStyle, LPCTSTR className, + LPCTSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) + { + _window = ::CreateWindowEx(exStyle, className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + + bool Create(LPCTSTR className, + LPCTSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam) + { + _window = ::CreateWindow(className, windowName, + style, x, y, width, height, parentWindow, + idOrHMenu, instance, createParam); + return (_window != NULL); + } + + #ifndef _UNICODE + bool Create(LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + bool CreateEx(DWORD exStyle, LPCWSTR className, + LPCWSTR windowName, DWORD style, + int x, int y, int width, int height, + HWND parentWindow, HMENU idOrHMenu, + HINSTANCE instance, LPVOID createParam); + #endif + + + bool Destroy() + { + if (_window == NULL) + return true; + bool result = BOOLToBool(::DestroyWindow(_window)); + if (result) + _window = NULL; + return result; + } + bool IsWindow() { return BOOLToBool(::IsWindow(_window)); } + bool Move(int x, int y, int width, int height, bool repaint = true) + { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); } + + bool ChangeSubWindowSizeX(HWND hwnd, int xSize) + { + RECT rect; + ::GetWindowRect(hwnd, &rect); + POINT p1; + p1.x = rect.left; + p1.y = rect.top; + ScreenToClient(&p1); + return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE)); + } + + void ScreenToClient(RECT *rect) + { + POINT p1, p2; + p1.x = rect->left; + p1.y = rect->top; + p2.x = rect->right; + p2.y = rect->bottom; + ScreenToClient(&p1); + ScreenToClient(&p2); + + rect->left = p1.x; + rect->top = p1.y; + rect->right = p2.x; + rect->bottom = p2.y; + } + + bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); } + bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); } + bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); } + + #ifndef UNDER_CE + bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); } + bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); } + #endif + bool Update() { return BOOLToBool(::UpdateWindow(_window)); } + bool InvalidateRect(LPCRECT rect, bool backgroundErase = true) + { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); } + void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); } + + LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); } + LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); } + // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); } + + LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); } + LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); } + LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); } + LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); } + + + #ifdef UNDER_CE + + LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); } + LONG_PTR GetLongPtr(int index) const { return GetLong(index); } + + LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); } + LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); } + + #else + + LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) + { return ::SetWindowLongPtr(_window, index, + #ifndef _WIN64 + (LONG) + #endif + newLongPtr); } + #ifndef _UNICODE + LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr) + { return ::SetWindowLongPtrW(_window, index, + #ifndef _WIN64 + (LONG) + #endif + newLongPtr); } + #endif + + LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); } + LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); } + LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); } + + #endif + + /* + bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) + { return ModifyStyleBase(GWL_STYLE, remove, add, flags); } + bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0) + { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); } + */ + + HWND SetFocus() { return ::SetFocus(_window); } + + LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessage(_window, message, wParam, lParam); } + #ifndef _UNICODE + LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return ::SendMessageW(_window, message, wParam, lParam); } + #endif + + bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); } + #ifndef _UNICODE + bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); } + #endif + + bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); } + #ifndef _UNICODE + bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); } + #endif + + int GetTextLength() const + { return GetWindowTextLength(_window); } + int GetText(LPTSTR string, int maxCount) const + { return GetWindowText(_window, string, maxCount); } + bool GetText(CSysString &s); + #ifndef _UNICODE + /* + UINT GetText(LPWSTR string, int maxCount) const + { return GetWindowTextW(_window, string, maxCount); } + */ + bool GetText(UString &s); + #endif + + bool Enable(bool enable) + { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); } + + bool IsEnabled() + { return BOOLToBool(::IsWindowEnabled(_window)); } + + #ifndef UNDER_CE + HMENU GetSystemMenu(bool revert) + { return ::GetSystemMenu(_window, BoolToBOOL(revert)); } + #endif + + UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = 0) + { return ::SetTimer(_window, idEvent, elapse, timerFunc); } + bool KillTimer(UINT_PTR idEvent) + {return BOOLToBool(::KillTimer(_window, idEvent)); } + + HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); } +}; + +#define RECT_SIZE_X(r) ((r).right - (r).left) +#define RECT_SIZE_Y(r) ((r).bottom - (r).top) + +inline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; } + +} + +#endif diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Common/CRC.cs b/3rdparty/lzma-21.03beta/CS/7zip/Common/CRC.cs new file mode 100644 index 0000000..82cc857 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Common/CRC.cs @@ -0,0 +1,55 @@ +// Common/CRC.cs + +namespace SevenZip +{ + class CRC + { + public static readonly uint[] Table; + + static CRC() + { + Table = new uint[256]; + const uint kPoly = 0xEDB88320; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >> 1) ^ kPoly; + else + r >>= 1; + Table[i] = r; + } + } + + uint _value = 0xFFFFFFFF; + + public void Init() { _value = 0xFFFFFFFF; } + + public void UpdateByte(byte b) + { + _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); + } + + public void Update(byte[] data, uint offset, uint size) + { + for (uint i = 0; i < size; i++) + _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); + } + + public uint GetDigest() { return _value ^ 0xFFFFFFFF; } + + static uint CalculateDigest(byte[] data, uint offset, uint size) + { + CRC crc = new CRC(); + // crc.Init(); + crc.Update(data, offset, size); + return crc.GetDigest(); + } + + static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) + { + return (CalculateDigest(data, offset, size) == digest); + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Common/CommandLineParser.cs b/3rdparty/lzma-21.03beta/CS/7zip/Common/CommandLineParser.cs new file mode 100644 index 0000000..8eabf59 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Common/CommandLineParser.cs @@ -0,0 +1,274 @@ +// CommandLineParser.cs + +using System; +using System.Collections; + +namespace SevenZip.CommandLineParser +{ + public enum SwitchType + { + Simple, + PostMinus, + LimitedPostString, + UnLimitedPostString, + PostChar + } + + public class SwitchForm + { + public string IDString; + public SwitchType Type; + public bool Multi; + public int MinLen; + public int MaxLen; + public string PostCharSet; + + public SwitchForm(string idString, SwitchType type, bool multi, + int minLen, int maxLen, string postCharSet) + { + IDString = idString; + Type = type; + Multi = multi; + MinLen = minLen; + MaxLen = maxLen; + PostCharSet = postCharSet; + } + public SwitchForm(string idString, SwitchType type, bool multi, int minLen): + this(idString, type, multi, minLen, 0, "") + { + } + public SwitchForm(string idString, SwitchType type, bool multi): + this(idString, type, multi, 0) + { + } + } + + public class SwitchResult + { + public bool ThereIs; + public bool WithMinus; + public ArrayList PostStrings = new ArrayList(); + public int PostCharIndex; + public SwitchResult() + { + ThereIs = false; + } + } + + public class Parser + { + public ArrayList NonSwitchStrings = new ArrayList(); + SwitchResult[] _switches; + + public Parser(int numSwitches) + { + _switches = new SwitchResult[numSwitches]; + for (int i = 0; i < numSwitches; i++) + _switches[i] = new SwitchResult(); + } + + bool ParseString(string srcString, SwitchForm[] switchForms) + { + int len = srcString.Length; + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(srcString[pos])) + return false; + while (pos < len) + { + if (IsItSwitchChar(srcString[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; + int maxLen = kNoLen; + for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) + { + int switchLen = switchForms[switchIndex].IDString.Length; + if (switchLen <= maxLen || pos + switchLen > len) + continue; + if (String.Compare(switchForms[switchIndex].IDString, 0, + srcString, pos, switchLen, true) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw new Exception("maxLen == kNoLen"); + SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; + SwitchForm switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw new Exception("switch must be single"); + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + SwitchType type = switchForm.Type; + switch (type) + { + case SwitchType.PostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case SwitchType.PostChar: + { + if (tailSize < switchForm.MinLen) + throw new Exception("switch is not full"); + string charSet = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = charSet.IndexOf(srcString[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case SwitchType.LimitedPostString: + case SwitchType.UnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw new Exception("switch is not full"); + if (type == SwitchType.UnLimitedPostString) + { + matchedSwitch.PostStrings.Add(srcString.Substring(pos)); + return true; + } + String stringSwitch = srcString.Substring(pos, minLen); + pos += minLen; + for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) + { + char c = srcString[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + } + } + return true; + + } + + public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) + { + int numCommandStrings = commandStrings.Length; + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + string s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } + } + + public SwitchResult this[int index] { get { return _switches[index]; } } + + public static int ParseCommand(CommandForm[] commandForms, string commandString, + out string postString) + { + for (int i = 0; i < commandForms.Length; i++) + { + string id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if (commandString.IndexOf(id) == 0) + { + postString = commandString.Substring(id.Length); + return i; + } + } + else + if (commandString == id) + { + postString = ""; + return i; + } + } + postString = ""; + return -1; + } + + static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, + string commandString, ArrayList indices) + { + indices.Clear(); + int numUsedChars = 0; + for (int i = 0; i < numForms; i++) + { + CommandSubCharsSet charsSet = forms[i]; + int currentIndex = -1; + int len = charsSet.Chars.Length; + for (int j = 0; j < len; j++) + { + char c = charsSet.Chars[j]; + int newIndex = commandString.IndexOf(c); + if (newIndex >= 0) + { + if (currentIndex >= 0) + return false; + if (commandString.IndexOf(c, newIndex + 1) >= 0) + return false; + currentIndex = j; + numUsedChars++; + } + } + if (currentIndex == -1 && !charsSet.EmptyAllowed) + return false; + indices.Add(currentIndex); + } + return (numUsedChars == commandString.Length); + } + const char kSwitchID1 = '-'; + const char kSwitchID2 = '/'; + + const char kSwitchMinus = '-'; + const string kStopSwitchParsing = "--"; + + static bool IsItSwitchChar(char c) + { + return (c == kSwitchID1 || c == kSwitchID2); + } + } + + public class CommandForm + { + public string IDString = ""; + public bool PostStringMode = false; + public CommandForm(string idString, bool postStringMode) + { + IDString = idString; + PostStringMode = postStringMode; + } + } + + class CommandSubCharsSet + { + public string Chars = ""; + public bool EmptyAllowed = false; + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Common/InBuffer.cs b/3rdparty/lzma-21.03beta/CS/7zip/Common/InBuffer.cs new file mode 100644 index 0000000..7c51f0b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Common/InBuffer.cs @@ -0,0 +1,72 @@ +// InBuffer.cs + +namespace SevenZip.Buffer +{ + public class InBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_Limit; + uint m_BufferSize; + System.IO.Stream m_Stream; + bool m_StreamWasExhausted; + ulong m_ProcessedSize; + + public InBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void Init(System.IO.Stream stream) + { + m_Stream = stream; + m_ProcessedSize = 0; + m_Limit = 0; + m_Pos = 0; + m_StreamWasExhausted = false; + } + + public bool ReadBlock() + { + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += m_Pos; + int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); + m_Pos = 0; + m_Limit = (uint)aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); + } + + + public void ReleaseStream() + { + // m_Stream.Close(); + m_Stream = null; + } + + public bool ReadByte(byte b) // check it + { + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return false; + b = m_Buffer[m_Pos++]; + return true; + } + + public byte ReadByte() + { + // return (byte)m_Stream.ReadByte(); + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return 0xFF; + return m_Buffer[m_Pos++]; + } + + public ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Common/OutBuffer.cs b/3rdparty/lzma-21.03beta/CS/7zip/Common/OutBuffer.cs new file mode 100644 index 0000000..2da16e1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Common/OutBuffer.cs @@ -0,0 +1,47 @@ +// OutBuffer.cs + +namespace SevenZip.Buffer +{ + public class OutBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_BufferSize; + System.IO.Stream m_Stream; + ulong m_ProcessedSize; + + public OutBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void SetStream(System.IO.Stream stream) { m_Stream = stream; } + public void FlushStream() { m_Stream.Flush(); } + public void CloseStream() { m_Stream.Close(); } + public void ReleaseStream() { m_Stream = null; } + + public void Init() + { + m_ProcessedSize = 0; + m_Pos = 0; + } + + public void WriteByte(byte b) + { + m_Buffer[m_Pos++] = b; + if (m_Pos >= m_BufferSize) + FlushData(); + } + + public void FlushData() + { + if (m_Pos == 0) + return; + m_Stream.Write(m_Buffer, 0, (int)m_Pos); + m_Pos = 0; + } + + public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/IMatchFinder.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/IMatchFinder.cs new file mode 100644 index 0000000..10ca2b3 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/IMatchFinder.cs @@ -0,0 +1,24 @@ +// IMatchFinder.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + interface IInWindowStream + { + void SetStream(System.IO.Stream inStream); + void Init(); + void ReleaseStream(); + Byte GetIndexByte(Int32 index); + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); + UInt32 GetNumAvailableBytes(); + } + + interface IMatchFinder : IInWindowStream + { + void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + UInt32 GetMatches(UInt32[] distances); + void Skip(UInt32 num); + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzBinTree.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzBinTree.cs new file mode 100644 index 0000000..c1c006b --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzBinTree.cs @@ -0,0 +1,367 @@ +// LzBinTree.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class BinTree : InWindow, IMatchFinder + { + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize = 0; + UInt32 _matchMaxLen; + + UInt32[] _son; + UInt32[] _hash; + + UInt32 _cutValue = 0xFF; + UInt32 _hashMask; + UInt32 _hashSizeSum = 0; + + bool HASH_ARRAY = true; + + const UInt32 kHash2Size = 1 << 10; + const UInt32 kHash3Size = 1 << 16; + const UInt32 kBT2HashSize = 1 << 16; + const UInt32 kStartMaxLen = 1; + const UInt32 kHash3Offset = kHash2Size; + const UInt32 kEmptyHashValue = 0; + const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; + + UInt32 kNumHashDirectBytes = 0; + UInt32 kMinMatchCheck = 4; + UInt32 kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } + public new void ReleaseStream() { base.ReleaseStream(); } + + public new void Init() + { + base.Init(); + for (UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public new void MovePos() + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + base.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } + + public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { return base.GetMatchLen(index, distance, limit); } + + public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } + + public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + throw new Exception(); + _cutValue = 16 + (matchMaxLen >> 1); + + UInt32 windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + UInt32 cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + UInt32 hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new UInt32[_hashSizeSum = hs]; + } + + public UInt32 GetMatches(UInt32[] distances) + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + UInt32 offset = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + UInt32 hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + hash2Value = temp & (kHash2Size - 1); + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + UInt32 curMatch2 = _hash[hash2Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + UInt32 count = _cutValue; + + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(UInt32 num) + { + do + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + + UInt32 hashValue; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + UInt32 hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + UInt32 hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + UInt32 count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) + { + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + UInt32 subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets((Int32)subValue); + } + + public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzInWindow.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzInWindow.cs new file mode 100644 index 0000000..52d23ce --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzInWindow.cs @@ -0,0 +1,132 @@ +// LzInWindow.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class InWindow + { + public Byte[] _bufferBase = null; // pointer to buffer with data + System.IO.Stream _stream; + UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + UInt32 _pointerToLastSafePosition; + + public UInt32 _bufferOffset; + + public UInt32 _blockSize; // Size of Allocated memory block + public UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; + + // check negative offset ???? + for (UInt32 i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public virtual void ReadBlock() + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); + if (size == 0) + return; + int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); + if (numReadBytes == 0) + { + _posLimit = _streamPos; + UInt32 pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); + + _streamEndWasReached = true; + return; + } + _streamPos += (UInt32)numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new Byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(System.IO.Stream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() + { + _pos++; + if (_pos > _posLimit) + { + UInt32 pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (UInt32)(_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + UInt32 pby = _bufferOffset + _pos + (UInt32)index; + + UInt32 i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(Int32 subValue) + { + _bufferOffset += (UInt32)subValue; + _posLimit -= (UInt32)subValue; + _pos -= (UInt32)subValue; + _streamPos -= (UInt32)subValue; + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzOutWindow.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzOutWindow.cs new file mode 100644 index 0000000..c998584 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZ/LzOutWindow.cs @@ -0,0 +1,110 @@ +// LzOutWindow.cs + +namespace SevenZip.Compression.LZ +{ + public class OutWindow + { + byte[] _buffer = null; + uint _pos; + uint _windowSize = 0; + uint _streamPos; + System.IO.Stream _stream; + + public uint TrainSize = 0; + + public void Create(uint windowSize) + { + if (_windowSize != windowSize) + { + // System.GC.Collect(); + _buffer = new byte[windowSize]; + } + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void Init(System.IO.Stream stream, bool solid) + { + ReleaseStream(); + _stream = stream; + if (!solid) + { + _streamPos = 0; + _pos = 0; + TrainSize = 0; + } + } + + public bool Train(System.IO.Stream stream) + { + long len = stream.Length; + uint size = (len < _windowSize) ? (uint)len : _windowSize; + TrainSize = size; + stream.Position = len - size; + _streamPos = _pos = 0; + while (size > 0) + { + uint curSize = _windowSize - _pos; + if (size < curSize) + curSize = size; + int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); + if (numReadBytes == 0) + return false; + size -= (uint)numReadBytes; + _pos += (uint)numReadBytes; + _streamPos += (uint)numReadBytes; + if (_pos == _windowSize) + _streamPos = _pos = 0; + } + return true; + } + + public void ReleaseStream() + { + Flush(); + _stream = null; + } + + public void Flush() + { + uint size = _pos - _streamPos; + if (size == 0) + return; + _stream.Write(_buffer, (int)_streamPos, (int)size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(uint distance, uint len) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for (; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(uint distance) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaBase.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaBase.cs new file mode 100644 index 0000000..c7bca86 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaBase.cs @@ -0,0 +1,76 @@ +// LzmaBase.cs + +namespace SevenZip.Compression.LZMA +{ + internal abstract class Base + { + public const uint kNumRepDistances = 4; + public const uint kNumStates = 12; + + // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; + // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; + // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; + // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + + public struct State + { + public uint Index; + public void Init() { Index = 0; } + public void UpdateChar() + { + if (Index < 4) Index = 0; + else if (Index < 10) Index -= 3; + else Index -= 6; + } + public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } + public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } + public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } + public bool IsCharState() { return Index < 7; } + } + + public const int kNumPosSlotBits = 6; + public const int kDicLogSizeMin = 0; + // public const int kDicLogSizeMax = 30; + // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; + + public const int kNumLenToPosStatesBits = 2; // it's for speed optimization + public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public const uint kMatchMinLen = 2; + + public static uint GetLenToPosState(uint len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (uint)(kNumLenToPosStates - 1); + } + + public const int kNumAlignBits = 4; + public const uint kAlignTableSize = 1 << kNumAlignBits; + public const uint kAlignMask = (kAlignTableSize - 1); + + public const uint kStartPosModelIndex = 4; + public const uint kEndPosModelIndex = 14; + public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); + + public const uint kNumLitPosStatesBitsEncodingMax = 4; + public const uint kNumLitContextBitsMax = 8; + + public const int kNumPosStatesBitsMax = 4; + public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public const int kNumPosStatesBitsEncodingMax = 4; + public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public const int kNumLowLenBits = 3; + public const int kNumMidLenBits = 3; + public const int kNumHighLenBits = 8; + public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; + public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaDecoder.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaDecoder.cs new file mode 100644 index 0000000..a9be39f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaDecoder.cs @@ -0,0 +1,398 @@ +// LzmaDecoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream + { + class LenDecoder + { + BitDecoder m_Choice = new BitDecoder(); + BitDecoder m_Choice2 = new BitDecoder(); + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + uint m_NumPosStates = 0; + + public void Create(uint numPosStates) + { + for (uint posState = m_NumPosStates; posState < numPosStates; posState++) + { + m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); + } + m_NumPosStates = numPosStates; + } + + public void Init() + { + m_Choice.Init(); + for (uint posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) + { + if (m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + else + { + uint symbol = Base.kNumLowLenSymbols; + if (m_Choice2.Decode(rangeDecoder) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + { + symbol += Base.kNumMidLenSymbols; + symbol += m_HighCoder.Decode(rangeDecoder); + } + return symbol; + } + } + } + + class LiteralDecoder + { + struct Decoder2 + { + BitDecoder[] m_Decoders; + public void Create() { m_Decoders = new BitDecoder[0x300]; } + public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) + { + uint symbol = 1; + do + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) + { + uint symbol = 1; + do + { + uint matchBit = (uint)(matchByte >> 7) & 1; + matchByte <<= 1; + uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && + m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + uint GetState(uint pos, byte prevByte) + { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) + { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) + { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } + }; + + LZ.OutWindow m_OutWindow = new LZ.OutWindow(); + RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); + + BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + uint m_DictionarySize; + uint m_DictionarySizeCheck; + + uint m_PosStateMask; + + public Decoder() + { + m_DictionarySize = 0xFFFFFFFF; + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + void SetDictionarySize(uint dictionarySize) + { + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); + uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); + m_OutWindow.Create(blockSize); + } + } + + void SetLiteralProperties(int lp, int lc) + { + if (lp > 8) + throw new InvalidParamException(); + if (lc > 8) + throw new InvalidParamException(); + m_LiteralDecoder.Create(lp, lc); + } + + void SetPosBitsProperties(int pb) + { + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + uint numPosStates = (uint)1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + } + + bool _solid = false; + void Init(System.IO.Stream inStream, System.IO.Stream outStream) + { + m_RangeDecoder.Init(inStream); + m_OutWindow.Init(outStream, _solid); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= m_PosStateMask; j++) + { + uint index = (i << Base.kNumPosStatesBitsMax) + j; + m_IsMatchDecoders[index].Init(); + m_IsRep0LongDecoders[index].Init(); + } + m_IsRepDecoders[i].Init(); + m_IsRepG0Decoders[i].Init(); + m_IsRepG1Decoders[i].Init(); + m_IsRepG2Decoders[i].Init(); + } + + m_LiteralDecoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + // m_PosSpecDecoder.Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + } + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + Init(inStream, outStream); + + Base.State state = new Base.State(); + state.Init(); + uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + UInt64 nowPos64 = 0; + UInt64 outSize64 = (UInt64)outSize; + if (nowPos64 < outSize64) + { + if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) + throw new DataErrorException(); + state.UpdateChar(); + byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); + m_OutWindow.PutByte(b); + nowPos64++; + } + while (nowPos64 < outSize64) + { + // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); + // while(nowPos64 < next) + { + uint posState = (uint)nowPos64 & m_PosStateMask; + if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + byte b; + byte prevByte = m_OutWindow.GetByte(0); + if (!state.IsCharState()) + b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, + (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); + else + b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); + m_OutWindow.PutByte(b); + state.UpdateChar(); + nowPos64++; + } + else + { + uint len; + if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) + { + if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); + nowPos64++; + continue; + } + } + else + { + UInt32 distance; + if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + distance = rep1; + } + else + { + if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state.UpdateRep(); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state.UpdateMatch(); + uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (int)((posSlot >> 1) - 1); + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + } + } + else + rep0 = posSlot; + } + if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) + { + if (rep0 == 0xFFFFFFFF) + break; + throw new DataErrorException(); + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + } + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + } + + public void SetDecoderProperties(byte[] properties) + { + if (properties.Length < 5) + throw new InvalidParamException(); + int lc = properties[0] % 9; + int remainder = properties[0] / 9; + int lp = remainder % 5; + int pb = remainder / 5; + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); + SetDictionarySize(dictionarySize); + SetLiteralProperties(lp, lc); + SetPosBitsProperties(pb); + } + + public bool Train(System.IO.Stream stream) + { + _solid = true; + return m_OutWindow.Train(stream); + } + + /* + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return true; }} + public override bool CanSeek { get { return true; }} + public override long Length { get { return 0; }} + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + public override void Write(byte[] buffer, int offset, int count) + { + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return 0; + } + public override void SetLength(long value) {} + */ + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaEncoder.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaEncoder.cs new file mode 100644 index 0000000..0237c51 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LZMA/LzmaEncoder.cs @@ -0,0 +1,1480 @@ +// LzmaEncoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + { + enum EMatchFinderType + { + BT2, + BT4, + }; + + const UInt32 kIfinityPrice = 0xFFFFFFF; + + static Byte[] g_FastPos = new Byte[1 << 11]; + + static Encoder() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } + + static UInt32 GetPosSlot(UInt32 pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (UInt32)(g_FastPos[pos >> 10] + 20); + return (UInt32)(g_FastPos[pos >> 20] + 40); + } + + static UInt32 GetPosSlot2(UInt32 pos) + { + if (pos < (1 << 17)) + return (UInt32)(g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (UInt32)(g_FastPos[pos >> 16] + 32); + return (UInt32)(g_FastPos[pos >> 26] + 52); + } + + Base.State _state = new Base.State(); + Byte _previousByte; + UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; + + void BaseInit() + { + _state.Init(); + _previousByte = 0; + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + const int kDefaultDictionaryLogSize = 22; + const UInt32 kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + public struct Encoder2 + { + BitEncoder[] m_Encoders; + + public void Create() { m_Encoders = new BitEncoder[0x300]; } + + public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } + + public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) + { + uint context = 1; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + m_Encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) + { + uint context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + uint state = context; + if (same) + { + uint matchBit = (uint)((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + m_Encoders[state].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public uint GetPrice(bool matchMode, byte matchByte, byte symbol) + { + uint price = 0; + uint context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + uint matchBit = (uint)(matchByte >> i) & 1; + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); + RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); + RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); + + public LenEncoder() + { + for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + if (symbol < Base.kNumLowLenSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + _choice.Encode(rangeEncoder, 1); + if (symbol < Base.kNumMidLenSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) + { + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder : LenEncoder + { + UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; + UInt32 _tableSize; + UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; + + public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + + public UInt32 GetPrice(UInt32 symbol, UInt32 posState) + { + return _prices[posState * Base.kNumLenSymbols + symbol]; + } + + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); + _counters[posState] = _tableSize; + } + + public void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + + public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + base.Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } + } + + const UInt32 kNumOpts = 1 << 12; + class Optimal + { + public Base.State State; + + public bool Prev1IsChar; + public bool Prev2; + + public UInt32 PosPrev2; + public UInt32 BackPrev2; + + public UInt32 Price; + public UInt32 PosPrev; + public UInt32 BackPrev; + + public UInt32 Backs0; + public UInt32 Backs1; + public UInt32 Backs2; + public UInt32 Backs3; + + public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } + public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + public bool IsShortRep() { return (BackPrev == 0); } + }; + Optimal[] _optimum = new Optimal[kNumOpts]; + LZ.IMatchFinder _matchFinder = null; + RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); + + RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; + + RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); + + LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + + LiteralEncoder _literalEncoder = new LiteralEncoder(); + + UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; + + UInt32 _numFastBytes = kNumFastBytesDefault; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; + UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; + UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); + + int _posStateBits = 2; + UInt32 _posStateMask = (4 - 1); + int _numLiteralPosStateBits = 0; + int _numLiteralContextBits = 3; + + UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); + UInt32 _dictionarySizePrev = 0xFFFFFFFF; + UInt32 _numFastBytesPrev = 0xFFFFFFFF; + + Int64 nowPos64; + bool _finished; + System.IO.Stream _inStream; + + EMatchFinderType _matchFinderType = EMatchFinderType.BT4; + bool _writeEndMark = false; + + bool _needReleaseMFStream; + + void Create() + { + if (_matchFinder == null) + { + LZ.BinTree bt = new LZ.BinTree(); + int numHashBytes = 4; + if (_matchFinderType == EMatchFinderType.BT2) + numHashBytes = 2; + bt.SetType(numHashBytes); + _matchFinder = bt; + } + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return; + _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + } + + public Encoder() + { + for (int i = 0; i < kNumOpts; i++) + _optimum[i] = new Optimal(); + for (int i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); + } + + void SetWriteEndMarkerMode(bool writeEndMarker) + { + _writeEndMark = writeEndMarker; + } + + void Init() + { + BaseInit(); + _rangeEncoder.Init(); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= _posStateMask; j++) + { + uint complexState = (i << Base.kNumPosStatesBitsMax) + j; + _isMatch[complexState].Init(); + _isRep0Long[complexState].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + _literalEncoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init((UInt32)1 << _posStateBits); + _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + } + + void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) + { + lenRes = 0; + numDistancePairs = _matchFinder.GetMatches(_matchDistances); + if (numDistancePairs > 0) + { + lenRes = _matchDistances[numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + } + + + void MovePos(UInt32 num) + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + UInt32 GetRepLen1Price(Base.State state, UInt32 posState) + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) + { + UInt32 price; + if (repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) + { + UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) + { + UInt32 price; + UInt32 lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + UInt32 Backward(out UInt32 backRes, UInt32 cur) + { + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + UInt32[] reps = new UInt32[Base.kNumRepDistances]; + UInt32[] repLens = new UInt32[Base.kNumRepDistances]; + + + UInt32 GetOptimum(UInt32 position, out UInt32 backRes) + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + ReadMatchDistances(out lenMain, out numDistancePairs); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + UInt32 repMaxIndex = 0; + UInt32 i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + UInt32 lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + Byte currentByte = _matchFinder.GetIndexByte(0 - 1); + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)0xFFFFFFFF; + return 1; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + UInt32 distance = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(out backRes, cur); + UInt32 newLen; + ReadMatchDistances(out newLen, out numDistancePairs); + if (newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(out backRes, cur); + } + position++; + UInt32 posPrev = _optimum[cur].PosPrev; + Base.State state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + UInt32 curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); + + posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!state.IsCharState(), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + { + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + + for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + UInt32 lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (UInt32 lenTest = startLen; ; lenTest++) + { + UInt32 curBack = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + bool ChangePair(UInt32 smallDist, UInt32 bigDist) + { + const int kDif = 7; + return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(UInt32 posState) + { + if (!_writeEndMark) + return; + + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + UInt32 posReduced = (((UInt32)1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(UInt32 nowPos) + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) + { + inSize = 0; + outSize = 0; + finished = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + if (_trainSize > 0) + _matchFinder.Skip(_trainSize); + } + + if (_finished) + return; + _finished = true; + + + Int64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + UInt32 len, numDistancePairs; // it's not used + ReadMatchDistances(out len, out numDistancePairs); + UInt32 posState = (UInt32)(nowPos64) & _posStateMask; + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + while (true) + { + UInt32 pos; + UInt32 len = GetOptimum((UInt32)nowPos64, out pos); + + UInt32 posState = ((UInt32)nowPos64) & _posStateMask; + UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[complexState].Encode(_rangeEncoder, 0); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); + if (!_state.IsCharState()) + { + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state.UpdateChar(); + } + else + { + _isMatch[complexState].Encode(_rangeEncoder, 1); + if (pos < Base.kNumRepDistances) + { + _isRep[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 0) + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 0); + if (len == 1) + _isRep0Long[complexState].Encode(_rangeEncoder, 0); + else + _isRep0Long[complexState].Encode(_rangeEncoder, 1); + } + else + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state.UpdateRep(); + } + UInt32 distance = _repDistances[pos]; + if (pos != 0) + { + for (UInt32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + UInt32 distance = pos; + for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize = nowPos64; + outSize = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); + + nowPos64 = 0; + } + + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + Int64 processedInSize; + Int64 processedOutSize; + bool finished; + CodeOneBlock(out processedInSize, out processedOutSize, out finished); + if (finished) + return; + if (progress != null) + { + progress.SetProgress(processedInSize, processedOutSize); + } + } + } + finally + { + ReleaseStreams(); + } + } + + const int kPropSize = 5; + Byte[] properties = new Byte[kPropSize]; + + public void WriteCoderProperties(System.IO.Stream outStream) + { + properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF); + outStream.Write(properties, 0, kPropSize); + } + + UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; + UInt32 _matchPriceCount; + + void FillDistancesPrices() + { + for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + UInt32 st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); + + UInt32 st2 = lenToPosState * Base.kNumFullDistances; + UInt32 i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (UInt32 i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + static string[] kMatchFinderIDs = + { + "BT2", + "BT4", + }; + + static int FindMatchFinder(string s) + { + for (int m = 0; m < kMatchFinderIDs.Length; m++) + if (s == kMatchFinderIDs[m]) + return m; + return -1; + } + + public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) + { + for (UInt32 i = 0; i < properties.Length; i++) + { + object prop = properties[i]; + switch (propIDs[i]) + { + case CoderPropID.NumFastBytes: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 numFastBytes = (Int32)prop; + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + throw new InvalidParamException(); + _numFastBytes = (UInt32)numFastBytes; + break; + } + case CoderPropID.Algorithm: + { + /* + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 maximize = (Int32)prop; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + */ + break; + } + case CoderPropID.MatchFinder: + { + if (!(prop is String)) + throw new InvalidParamException(); + EMatchFinderType matchFinderIndexPrev = _matchFinderType; + int m = FindMatchFinder(((string)prop).ToUpper()); + if (m < 0) + throw new InvalidParamException(); + _matchFinderType = (EMatchFinderType)m; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = 0xFFFFFFFF; + _matchFinder = null; + } + break; + } + case CoderPropID.DictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (!(prop is Int32)) + throw new InvalidParamException(); ; + Int32 dictionarySize = (Int32)prop; + if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || + dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) + throw new InvalidParamException(); + _dictionarySize = (UInt32)dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= ((UInt32)(1) << dicLogSize)) + break; + _distTableSize = (UInt32)dicLogSize * 2; + break; + } + case CoderPropID.PosStateBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _posStateBits = (int)v; + _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; + break; + } + case CoderPropID.LitPosBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _numLiteralPosStateBits = (int)v; + break; + } + case CoderPropID.LitContextBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) + throw new InvalidParamException(); ; + _numLiteralContextBits = (int)v; + break; + } + case CoderPropID.EndMarker: + { + if (!(prop is Boolean)) + throw new InvalidParamException(); + SetWriteEndMarkerMode((Boolean)prop); + break; + } + default: + throw new InvalidParamException(); + } + } + } + + uint _trainSize = 0; + public void SetTrainSize(uint trainSize) + { + _trainSize = trainSize; + } + + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs new file mode 100644 index 0000000..7e22450 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs @@ -0,0 +1,364 @@ +using System; +using System.IO; +namespace SevenZip +{ + using CommandLineParser; + + public class CDoubleStream: Stream + { + public System.IO.Stream s1; + public System.IO.Stream s2; + public int fileIndex; + public long skipSize; + + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return false; }} + public override bool CanSeek { get { return false; }} + public override long Length { get { return s1.Length + s2.Length - skipSize; } } + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + int numTotal = 0; + while (count > 0) + { + if (fileIndex == 0) + { + int num = s1.Read(buffer, offset, count); + offset += num; + count -= num; + numTotal += num; + if (num == 0) + fileIndex++; + } + if (fileIndex == 1) + { + numTotal += s2.Read(buffer, offset, count); + return numTotal; + } + } + return numTotal; + } + public override void Write(byte[] buffer, int offset, int count) + { + throw (new Exception("can't Write")); + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + throw (new Exception("can't Seek")); + } + public override void SetLength(long value) + { + throw (new Exception("can't SetLength")); + } + } + + class LzmaAlone + { + enum Key + { + Help1 = 0, + Help2, + Mode, + Dictionary, + FastBytes, + LitContext, + LitPos, + PosBits, + MatchFinder, + EOS, + StdIn, + StdOut, + Train + }; + + static void PrintHelp() + { + System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + + " e: encode file\n" + + " d: decode file\n" + + " b: Benchmark\n" + + "\n" + + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + + " -eos: write End Of Stream marker\n" + // + " -si: read data from stdin\n" + // + " -so: write data to stdout\n" + ); + } + + static bool GetNumber(string s, out Int32 v) + { + v = 0; + for (int i = 0; i < s.Length; i++) + { + char c = s[i]; + if (c < '0' || c > '9') + return false; + v *= 10; + v += (Int32)(c - '0'); + } + return true; + } + + static int IncorrectCommand() + { + throw (new Exception("Command line error")); + // System.Console.WriteLine("\nCommand line error\n"); + // return 1; + } + static int Main2(string[] args) + { + System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); + + if (args.Length == 0) + { + PrintHelp(); + return 0; + } + + SwitchForm[] kSwitchForms = new SwitchForm[13]; + int sw = 0; + kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); + kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); + kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); + + + Parser parser = new Parser(sw); + try + { + parser.ParseStrings(kSwitchForms, args); + } + catch + { + return IncorrectCommand(); + } + + if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) + { + PrintHelp(); + return 0; + } + + System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; + + int paramIndex = 0; + if (paramIndex >= nonSwitchStrings.Count) + return IncorrectCommand(); + string command = (string)nonSwitchStrings[paramIndex++]; + command = command.ToLower(); + + bool dictionaryIsDefined = false; + Int32 dictionary = 1 << 21; + if (parser[(int)Key.Dictionary].ThereIs) + { + Int32 dicLog; + if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) + IncorrectCommand(); + dictionary = (Int32)1 << dicLog; + dictionaryIsDefined = true; + } + string mf = "bt4"; + if (parser[(int)Key.MatchFinder].ThereIs) + mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; + mf = mf.ToLower(); + + if (command == "b") + { + const Int32 kNumDefaultItereations = 10; + Int32 numIterations = kNumDefaultItereations; + if (paramIndex < nonSwitchStrings.Count) + if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) + numIterations = kNumDefaultItereations; + return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); + } + + string train = ""; + if (parser[(int)Key.Train].ThereIs) + train = (string)parser[(int)Key.Train].PostStrings[0]; + + bool encodeMode = false; + if (command == "e") + encodeMode = true; + else if (command == "d") + encodeMode = false; + else + IncorrectCommand(); + + bool stdInMode = parser[(int)Key.StdIn].ThereIs; + bool stdOutMode = parser[(int)Key.StdOut].ThereIs; + + Stream inStream = null; + if (stdInMode) + { + throw (new Exception("Not implemeted")); + } + else + { + if (paramIndex >= nonSwitchStrings.Count) + IncorrectCommand(); + string inputName = (string)nonSwitchStrings[paramIndex++]; + inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); + } + + FileStream outStream = null; + if (stdOutMode) + { + throw (new Exception("Not implemeted")); + } + else + { + if (paramIndex >= nonSwitchStrings.Count) + IncorrectCommand(); + string outputName = (string)nonSwitchStrings[paramIndex++]; + outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); + } + + FileStream trainStream = null; + if (train.Length != 0) + trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); + + if (encodeMode) + { + if (!dictionaryIsDefined) + dictionary = 1 << 23; + + Int32 posStateBits = 2; + Int32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + Int32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + Int32 algorithm = 2; + Int32 numFastBytes = 128; + + bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; + + if (parser[(int)Key.Mode].ThereIs) + if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) + IncorrectCommand(); + + if (parser[(int)Key.FastBytes].ThereIs) + if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) + IncorrectCommand(); + if (parser[(int)Key.LitContext].ThereIs) + if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) + IncorrectCommand(); + if (parser[(int)Key.LitPos].ThereIs) + if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) + IncorrectCommand(); + if (parser[(int)Key.PosBits].ThereIs) + if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) + IncorrectCommand(); + + CoderPropID[] propIDs = + { + CoderPropID.DictionarySize, + CoderPropID.PosStateBits, + CoderPropID.LitContextBits, + CoderPropID.LitPosBits, + CoderPropID.Algorithm, + CoderPropID.NumFastBytes, + CoderPropID.MatchFinder, + CoderPropID.EndMarker + }; + object[] properties = + { + (Int32)(dictionary), + (Int32)(posStateBits), + (Int32)(litContextBits), + (Int32)(litPosBits), + (Int32)(algorithm), + (Int32)(numFastBytes), + mf, + eos + }; + + Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); + encoder.SetCoderProperties(propIDs, properties); + encoder.WriteCoderProperties(outStream); + Int64 fileSize; + if (eos || stdInMode) + fileSize = -1; + else + fileSize = inStream.Length; + for (int i = 0; i < 8; i++) + outStream.WriteByte((Byte)(fileSize >> (8 * i))); + if (trainStream != null) + { + CDoubleStream doubleStream = new CDoubleStream(); + doubleStream.s1 = trainStream; + doubleStream.s2 = inStream; + doubleStream.fileIndex = 0; + inStream = doubleStream; + long trainFileSize = trainStream.Length; + doubleStream.skipSize = 0; + if (trainFileSize > dictionary) + doubleStream.skipSize = trainFileSize - dictionary; + trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); + encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); + } + encoder.Code(inStream, outStream, -1, -1, null); + } + else if (command == "d") + { + byte[] properties = new byte[5]; + if (inStream.Read(properties, 0, 5) != 5) + throw (new Exception("input .lzma is too short")); + Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); + decoder.SetDecoderProperties(properties); + if (trainStream != null) + { + if (!decoder.Train(trainStream)) + throw (new Exception("can't train")); + } + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = inStream.ReadByte(); + if (v < 0) + throw (new Exception("Can't Read 1")); + outSize |= ((long)(byte)v) << (8 * i); + } + long compressedSize = inStream.Length - inStream.Position; + decoder.Code(inStream, outStream, compressedSize, outSize, null); + } + else + throw (new Exception("Command Error")); + return 0; + } + + [STAThread] + static int Main(string[] args) + { + try + { + return Main2(args); + } + catch (Exception e) + { + Console.WriteLine("{0} Caught exception #1.", e); + // throw e; + return 1; + } + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln new file mode 100644 index 0000000..376cd27 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C# Express 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaBench.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaBench.cs new file mode 100644 index 0000000..f7b6bd0 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/LzmaBench.cs @@ -0,0 +1,340 @@ +// LzmaBench.cs + +using System; +using System.IO; + +namespace SevenZip +{ + /// + /// LZMA Benchmark + /// + internal abstract class LzmaBench + { + const UInt32 kAdditionalSize = (6 << 20); + const UInt32 kCompressedAdditionalSize = (1 << 10); + const UInt32 kMaxLzmaPropSize = 10; + + class CRandomGenerator + { + UInt32 A1; + UInt32 A2; + public CRandomGenerator() { Init(); } + public void Init() { A1 = 362436069; A2 = 521288629; } + public UInt32 GetRnd() + { + return + ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); + } + }; + + class CBitRandomGenerator + { + CRandomGenerator RG = new CRandomGenerator(); + UInt32 Value; + int NumBits; + public void Init() + { + Value = 0; + NumBits = 0; + } + public UInt32 GetRnd(int numBits) + { + UInt32 result; + if (NumBits > numBits) + { + result = Value & (((UInt32)1 << numBits) - 1); + Value >>= numBits; + NumBits -= numBits; + return result; + } + numBits -= NumBits; + result = (Value << numBits); + Value = RG.GetRnd(); + result |= Value & (((UInt32)1 << numBits) - 1); + Value >>= numBits; + NumBits = 32 - numBits; + return result; + } + }; + + class CBenchRandomGenerator + { + CBitRandomGenerator RG = new CBitRandomGenerator(); + UInt32 Pos; + UInt32 Rep0; + + public UInt32 BufferSize; + public Byte[] Buffer = null; + + public CBenchRandomGenerator() { } + + public void Set(UInt32 bufferSize) + { + Buffer = new Byte[bufferSize]; + Pos = 0; + BufferSize = bufferSize; + } + UInt32 GetRndBit() { return RG.GetRnd(1); } + UInt32 GetLogRandBits(int numBits) + { + UInt32 len = RG.GetRnd(numBits); + return RG.GetRnd((int)len); + } + UInt32 GetOffset() + { + if (GetRndBit() == 0) + return GetLogRandBits(4); + return (GetLogRandBits(4) << 10) | RG.GetRnd(10); + } + UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } + UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } + public void Generate() + { + RG.Init(); + Rep0 = 1; + while (Pos < BufferSize) + { + if (GetRndBit() == 0 || Pos < 1) + Buffer[Pos++] = (Byte)RG.GetRnd(8); + else + { + UInt32 len; + if (RG.GetRnd(3) == 0) + len = 1 + GetLen1(); + else + { + do + Rep0 = GetOffset(); + while (Rep0 >= Pos); + Rep0++; + len = 2 + GetLen2(); + } + for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) + Buffer[Pos] = Buffer[Pos - Rep0]; + } + } + } + }; + + class CrcOutStream : System.IO.Stream + { + public CRC CRC = new CRC(); + public void Init() { CRC.Init(); } + public UInt32 GetDigest() { return CRC.GetDigest(); } + + public override bool CanRead { get { return false; } } + public override bool CanSeek { get { return false; } } + public override bool CanWrite { get { return true; } } + public override Int64 Length { get { return 0; } } + public override Int64 Position { get { return 0; } set { } } + public override void Flush() { } + public override long Seek(long offset, SeekOrigin origin) { return 0; } + public override void SetLength(long value) { } + public override int Read(byte[] buffer, int offset, int count) { return 0; } + + public override void WriteByte(byte b) + { + CRC.UpdateByte(b); + } + public override void Write(byte[] buffer, int offset, int count) + { + CRC.Update(buffer, (uint)offset, (uint)count); + } + }; + + class CProgressInfo : ICodeProgress + { + public Int64 ApprovedStart; + public Int64 InSize; + public System.DateTime Time; + public void Init() { InSize = 0; } + public void SetProgress(Int64 inSize, Int64 outSize) + { + if (inSize >= ApprovedStart && InSize == 0) + { + Time = DateTime.UtcNow; + InSize = inSize; + } + } + } + const int kSubBits = 8; + + static UInt32 GetLogSize(UInt32 size) + { + for (int i = kSubBits; i < 32; i++) + for (UInt32 j = 0; j < (1 << kSubBits); j++) + if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) + return (UInt32)(i << kSubBits) + j; + return (32 << kSubBits); + } + + static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) + { + UInt64 freq = TimeSpan.TicksPerSecond; + UInt64 elTime = elapsedTime; + while (freq > 1000000) + { + freq >>= 1; + elTime >>= 1; + } + if (elTime == 0) + elTime = 1; + return value * freq / elTime; + } + + static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) + { + UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); + UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); + UInt64 numCommands = (UInt64)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime); + } + + static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) + { + UInt64 numCommands = inSize * 220 + outSize * 20; + return MyMultDiv64(numCommands, elapsedTime); + } + + static UInt64 GetTotalRating( + UInt32 dictionarySize, + UInt64 elapsedTimeEn, UInt64 sizeEn, + UInt64 elapsedTimeDe, + UInt64 inSizeDe, UInt64 outSizeDe) + { + return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; + } + + static void PrintValue(UInt64 v) + { + string s = v.ToString(); + for (int i = 0; i + s.Length < 6; i++) + System.Console.Write(" "); + System.Console.Write(s); + } + + static void PrintRating(UInt64 rating) + { + PrintValue(rating / 1000000); + System.Console.Write(" MIPS"); + } + + static void PrintResults( + UInt32 dictionarySize, + UInt64 elapsedTime, + UInt64 size, + bool decompressMode, UInt64 secondSize) + { + UInt64 speed = MyMultDiv64(size, elapsedTime); + PrintValue(speed / 1024); + System.Console.Write(" KB/s "); + UInt64 rating; + if (decompressMode) + rating = GetDecompressRating(elapsedTime, size, secondSize); + else + rating = GetCompressRating(dictionarySize, elapsedTime, size); + PrintRating(rating); + } + + static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) + { + if (numIterations <= 0) + return 0; + if (dictionarySize < (1 << 18)) + { + System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); + return 1; + } + System.Console.Write("\n Compressing Decompressing\n\n"); + + Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); + Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); + + + CoderPropID[] propIDs = + { + CoderPropID.DictionarySize, + }; + object[] properties = + { + (Int32)(dictionarySize), + }; + + UInt32 kBufferSize = dictionarySize + kAdditionalSize; + UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + + encoder.SetCoderProperties(propIDs, properties); + System.IO.MemoryStream propStream = new System.IO.MemoryStream(); + encoder.WriteCoderProperties(propStream); + byte[] propArray = propStream.ToArray(); + + CBenchRandomGenerator rg = new CBenchRandomGenerator(); + + rg.Set(kBufferSize); + rg.Generate(); + CRC crc = new CRC(); + crc.Init(); + crc.Update(rg.Buffer, 0, rg.BufferSize); + + CProgressInfo progressInfo = new CProgressInfo(); + progressInfo.ApprovedStart = dictionarySize; + + UInt64 totalBenchSize = 0; + UInt64 totalEncodeTime = 0; + UInt64 totalDecodeTime = 0; + UInt64 totalCompressedSize = 0; + + MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); + MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); + CrcOutStream crcOutStream = new CrcOutStream(); + for (Int32 i = 0; i < numIterations; i++) + { + progressInfo.Init(); + inStream.Seek(0, SeekOrigin.Begin); + compressedStream.Seek(0, SeekOrigin.Begin); + encoder.Code(inStream, compressedStream, -1, -1, progressInfo); + TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; + UInt64 encodeTime = (UInt64)sp2.Ticks; + + long compressedSize = compressedStream.Position; + if (progressInfo.InSize == 0) + throw (new Exception("Internal ERROR 1282")); + + UInt64 decodeTime = 0; + for (int j = 0; j < 2; j++) + { + compressedStream.Seek(0, SeekOrigin.Begin); + crcOutStream.Init(); + + decoder.SetDecoderProperties(propArray); + UInt64 outSize = kBufferSize; + System.DateTime startTime = DateTime.UtcNow; + decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); + TimeSpan sp = (DateTime.UtcNow - startTime); + decodeTime = (ulong)sp.Ticks; + if (crcOutStream.GetDigest() != crc.GetDigest()) + throw (new Exception("CRC Error")); + } + UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; + PrintResults(dictionarySize, encodeTime, benchSize, false, 0); + System.Console.Write(" "); + PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); + System.Console.WriteLine(); + + totalBenchSize += benchSize; + totalEncodeTime += encodeTime; + totalDecodeTime += decodeTime; + totalCompressedSize += (ulong)compressedSize; + } + System.Console.WriteLine("---------------------------------------------------"); + PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); + System.Console.Write(" "); + PrintResults(dictionarySize, totalDecodeTime, + kBufferSize * (UInt64)numIterations, true, totalCompressedSize); + System.Console.WriteLine(" Average"); + return 0; + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9614884 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Using directives + +using System.Reflection; +using System.Runtime.CompilerServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LZMA#")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Igor Pavlov")] +[assembly: AssemblyProduct("LZMA# SDK")] +[assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("4.12.*")] diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs new file mode 100644 index 0000000..1170cf1 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.40607.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LzmaAlone.Properties +{ + using System; + using System.IO; + using System.Resources; + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the Strongly Typed Resource Builder + // class via a tool like ResGen or Visual Studio.NET. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + class Resources + { + + private static System.Resources.ResourceManager _resMgr; + + private static System.Globalization.CultureInfo _resCulture; + + /*FamANDAssem*/ + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Resources.ResourceManager ResourceManager + { + get + { + if ((_resMgr == null)) + { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); + _resMgr = temp; + } + return _resMgr; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Globalization.CultureInfo Culture + { + get + { + return _resCulture; + } + set + { + _resCulture = value; + } + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs new file mode 100644 index 0000000..ccfed77 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.40607.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LzmaAlone.Properties +{ + public partial class Settings : System.Configuration.ApplicationSettingsBase + { + private static Settings m_Value; + + private static object m_SyncObject = new object(); + + public static Settings Value + { + get + { + if ((Settings.m_Value == null)) + { + System.Threading.Monitor.Enter(Settings.m_SyncObject); + if ((Settings.m_Value == null)) + { + try + { + Settings.m_Value = new Settings(); + } + finally + { + System.Threading.Monitor.Exit(Settings.m_SyncObject); + } + } + } + return Settings.m_Value; + } + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoder.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoder.cs new file mode 100644 index 0000000..949c6bb --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoder.cs @@ -0,0 +1,234 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + class Encoder + { + public const uint kTopValue = (1 << 24); + + System.IO.Stream Stream; + + public UInt64 Low; + public uint Range; + uint _cacheSize; + byte _cache; + + long StartPosition; + + public void SetStream(System.IO.Stream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + StartPosition = Stream.Position; + + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() + { + Stream.Flush(); + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Encode(uint start, uint size, uint total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public void ShiftLow() + { + if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) + { + byte temp = _cache; + do + { + Stream.WriteByte((byte)(temp + (Low >> 32))); + temp = 0xFF; + } + while (--_cacheSize != 0); + _cache = (byte)(((uint)Low) >> 24); + } + _cacheSize++; + Low = ((uint)Low) << 8; + } + + public void EncodeDirectBits(uint v, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((v >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + public void EncodeBit(uint size0, int numTotalBits, uint symbol) + { + uint newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public long GetProcessedSizeAdd() + { + return _cacheSize + + Stream.Position - StartPosition + 4; + // (long)Stream.GetProcessedSize(); + } + } + + class Decoder + { + public const uint kTopValue = (1 << 24); + public uint Range; + public uint Code; + // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); + public System.IO.Stream Stream; + + public void Init(System.IO.Stream stream) + { + // Stream.Init(stream); + Stream = stream; + + Code = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | (byte)Stream.ReadByte(); + } + + public void ReleaseStream() + { + // Stream.ReleaseStream(); + Stream = null; + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public void Normalize2() + { + if (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public uint GetThreshold(uint total) + { + return Code / (Range /= total); + } + + public void Decode(uint start, uint size, uint total) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + public uint DecodeDirectBits(int numTotalBits) + { + uint range = Range; + uint code = Code; + uint result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + uint t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | (byte)Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + public uint DecodeBit(uint size0, int numTotalBits) + { + uint newBound = (Range >> numTotalBits) * size0; + uint symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs new file mode 100644 index 0000000..4f0346d --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs @@ -0,0 +1,117 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitEncoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + const int kNumMoveReducingBits = 2; + public const int kNumBitPriceShiftBits = 6; + + uint Prob; + + public void Init() { Prob = kBitModelTotal >> 1; } + + public void UpdateModel(uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + else + Prob -= (Prob) >> kNumMoveBits; + } + + public void Encode(Encoder encoder, uint symbol) + { + // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); + // UpdateModel(symbol); + uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; + if (symbol == 0) + { + encoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + } + else + { + encoder.Low += newBound; + encoder.Range -= newBound; + Prob -= (Prob) >> kNumMoveBits; + } + if (encoder.Range < Encoder.kTopValue) + { + encoder.Range <<= 8; + encoder.ShiftLow(); + } + } + + private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; + + static BitEncoder() + { + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = (UInt32)1 << (kNumBits - i - 1); + UInt32 end = (UInt32)1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + } + + public uint GetPrice(uint symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } + public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } + } + + struct BitDecoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + + uint Prob; + + public void UpdateModel(int numMoveBits, uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } + + public void Init() { Prob = kBitModelTotal >> 1; } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; + if (rangeDecoder.Code < newBound) + { + rangeDecoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 0; + } + else + { + rangeDecoder.Range -= newBound; + rangeDecoder.Code -= newBound; + Prob -= (Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 1; + } + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs new file mode 100644 index 0000000..4b4506f --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs @@ -0,0 +1,157 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitTreeEncoder + { + BitEncoder[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitEncoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public void Encode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (UInt32 i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public UInt32 GetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + price += Models[m].GetPrice(bit); + m = (m << 1) + bit; + } + return price; + } + + public UInt32 ReverseGetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, + int NumBitLevels, UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[startIndex + m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, + Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) + { + UInt32 m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[startIndex + m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + } + + struct BitTreeDecoder + { + BitDecoder[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitDecoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + m = (m << 1) + Models[m].Decode(rangeDecoder); + return m - ((uint)1 << NumBitLevels); + } + + public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, + RangeCoder.Decoder rangeDecoder, int NumBitLevels) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[startIndex + m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + } +} diff --git a/3rdparty/lzma-21.03beta/CS/7zip/ICoder.cs b/3rdparty/lzma-21.03beta/CS/7zip/ICoder.cs new file mode 100644 index 0000000..c8b95c8 --- /dev/null +++ b/3rdparty/lzma-21.03beta/CS/7zip/ICoder.cs @@ -0,0 +1,157 @@ +// ICoder.h + +using System; + +namespace SevenZip +{ + /// + /// The exception that is thrown when an error in input stream occurs during decoding. + /// + class DataErrorException : ApplicationException + { + public DataErrorException(): base("Data Error") { } + } + + /// + /// The exception that is thrown when the value of an argument is outside the allowable range. + /// + class InvalidParamException : ApplicationException + { + public InvalidParamException(): base("Invalid Parameter") { } + } + + public interface ICodeProgress + { + /// + /// Callback progress. + /// + /// + /// input size. -1 if unknown. + /// + /// + /// output size. -1 if unknown. + /// + void SetProgress(Int64 inSize, Int64 outSize); + }; + + public interface ICoder + { + /// + /// Codes streams. + /// + /// + /// input Stream. + /// + /// + /// output Stream. + /// + /// + /// input Size. -1 if unknown. + /// + /// + /// output Size. -1 if unknown. + /// + /// + /// callback progress reference. + /// + /// + /// if input stream is not valid + /// + void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress); + }; + + /* + public interface ICoder2 + { + void Code(ISequentialInStream []inStreams, + const UInt64 []inSizes, + ISequentialOutStream []outStreams, + UInt64 []outSizes, + ICodeProgress progress); + }; + */ + + /// + /// Provides the fields that represent properties idenitifiers for compressing. + /// + public enum CoderPropID + { + /// + /// Specifies default property. + /// + DefaultProp = 0, + /// + /// Specifies size of dictionary. + /// + DictionarySize, + /// + /// Specifies size of memory for PPM*. + /// + UsedMemorySize, + /// + /// Specifies order for PPM methods. + /// + Order, + /// + /// Specifies Block Size. + /// + BlockSize, + /// + /// Specifies number of postion state bits for LZMA (0 <= x <= 4). + /// + PosStateBits, + /// + /// Specifies number of literal context bits for LZMA (0 <= x <= 8). + /// + LitContextBits, + /// + /// Specifies number of literal position bits for LZMA (0 <= x <= 4). + /// + LitPosBits, + /// + /// Specifies number of fast bytes for LZ*. + /// + NumFastBytes, + /// + /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". + /// + MatchFinder, + /// + /// Specifies the number of match finder cyckes. + /// + MatchFinderCycles, + /// + /// Specifies number of passes. + /// + NumPasses, + /// + /// Specifies number of algorithm. + /// + Algorithm, + /// + /// Specifies the number of threads. + /// + NumThreads, + /// + /// Specifies mode with end marker. + /// + EndMarker + }; + + + public interface ISetCoderProperties + { + void SetCoderProperties(CoderPropID[] propIDs, object[] properties); + }; + + public interface IWriteCoderProperties + { + void WriteCoderProperties(System.IO.Stream outStream); + } + + public interface ISetDecoderProperties + { + void SetDecoderProperties(byte[] properties); + } +} diff --git a/3rdparty/lzma-21.03beta/DOC/7zC.txt b/3rdparty/lzma-21.03beta/DOC/7zC.txt new file mode 100644 index 0000000..939b720 --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/7zC.txt @@ -0,0 +1,187 @@ +7z ANSI-C Decoder 9.35 +---------------------- + +7z ANSI-C provides 7z/LZMA decoding. +7z ANSI-C version is simplified version ported from C++ code. + +LZMA is default and general compression method of 7z format +in 7-Zip compression program (www.7-zip.org). LZMA provides high +compression ratio and very fast decompression. + + +LICENSE +------- + +7z ANSI-C Decoder is part of the LZMA SDK. +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +Files +--------------------- + +7zDecode.* - Low level 7z decoding +7zExtract.* - High level 7z decoding +7zHeader.* - .7z format constants +7zIn.* - .7z archive opening +7zItem.* - .7z structures +7zMain.c - Test application + + +How To Use +---------- + +You can create .7z archive with 7z.exe, 7za.exe or 7zr.exe: + + 7z.exe a archive.7z *.htm -r -mx -m0fb=255 + +If you have big number of files in archive, and you need fast extracting, +you can use partly-solid archives: + + 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K + +In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only +512KB for extracting one file from such archive. + + +Limitations of current version of 7z ANSI-C Decoder +--------------------------------------------------- + + - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. + - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. + - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. + +These limitations will be fixed in future versions. + + +Using 7z ANSI-C Decoder Test application: +----------------------------------------- + +Usage: 7zDec + +: + e: Extract files from archive + l: List contents of archive + t: Test integrity of archive + +Example: + + 7zDec l archive.7z + +lists contents of archive.7z + + 7zDec e archive.7z + +extracts files from archive.7z to current folder. + + +How to use .7z Decoder +---------------------- + +Memory allocation +~~~~~~~~~~~~~~~~~ + +7z Decoder uses two memory pools: +1) Temporary pool +2) Main pool +Such scheme can allow you to avoid fragmentation of allocated blocks. + + +Steps for using 7z decoder +-------------------------- + +Use code at 7zMain.c as example. + +1) Declare variables: + inStream /* implements ILookInStream interface */ + CSzArEx db; /* 7z archive database structure */ + ISzAlloc allocImp; /* memory functions for main pool */ + ISzAlloc allocTempImp; /* memory functions for temporary pool */ + +2) call CrcGenerateTable(); function to initialize CRC structures. + +3) call SzArEx_Init(&db); function to initialize db structures. + +4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive + +This function opens archive "inStream" and reads headers to "db". +All items in "db" will be allocated with "allocMain" functions. +SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. + +5) List items or Extract items + + Listing code: + ~~~~~~~~~~~~~ + + Use SzArEx_GetFileNameUtf16 function. Look example code in C\Util\7z\7zMain.c file. + + + Extracting code: + ~~~~~~~~~~~~~~~~ + + SZ_RESULT SzAr_Extract( + CArchiveDatabaseEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + If you need to decompress more than one file, you can send these values from previous call: + blockIndex, + outBuffer, + outBufferSize, + You can consider "outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + After decompressing you must free "outBuffer": + allocImp.Free(outBuffer); + +6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". + + + + +Memory requirements for .7z decoding +------------------------------------ + +Memory usage for Archive opening: + - Temporary pool: + - Memory for uncompressed .7z headers + - some other temporary blocks + - Main pool: + - Memory for database: + Estimated size of one file structures in solid archive: + - Size (4 or 8 Bytes) + - CRC32 (4 bytes) + - LastWriteTime (8 bytes) + - Some file information (4 bytes) + - File Name (variable length) + pointer + allocation structures + +Memory usage for archive Decompressing: + - Temporary pool: + - Memory for LZMA decompressing structures + - Main pool: + - Memory for decompressed solid block + - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these + temprorary buffers can be about 15% of solid block size. + + +7z Decoder doesn't allocate memory for compressed blocks. +Instead of this, you must allocate buffer with desired +size before calling 7z Decoder. Use 7zMain.c as example. + + +Defines +------- + +_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. + + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/3rdparty/lzma-21.03beta/DOC/7zFormat.txt b/3rdparty/lzma-21.03beta/DOC/7zFormat.txt new file mode 100644 index 0000000..74cdfa4 --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/7zFormat.txt @@ -0,0 +1,469 @@ +7z Format description (18.06) +---------------------------- + +This file contains description of 7z archive format. +7z archive can contain files compressed with any method. +See "Methods.txt" for description for defined compressing methods. + + +Format structure Overview +------------------------- + +Some fields can be optional. + +Archive structure +~~~~~~~~~~~~~~~~~ +SignatureHeader +[PackedStreams] +[PackedStreamsForHeaders] +[ + Header + or + { + Packed Header + HeaderInfo + } +] + + + +Header structure +~~~~~~~~~~~~~~~~ +{ + ArchiveProperties + AdditionalStreams + { + PackInfo + { + PackPos + NumPackStreams + Sizes[NumPackStreams] + CRCs[NumPackStreams] + } + CodersInfo + { + NumFolders + Folders[NumFolders] + { + NumCoders + CodersInfo[NumCoders] + { + ID + NumInStreams; + NumOutStreams; + PropertiesSize + Properties[PropertiesSize] + } + NumBindPairs + BindPairsInfo[NumBindPairs] + { + InIndex; + OutIndex; + } + PackedIndices + } + UnPackSize[Folders][Folders.NumOutstreams] + CRCs[NumFolders] + } + SubStreamsInfo + { + NumUnPackStreamsInFolders[NumFolders]; + UnPackSizes[] + CRCs[] + } + } + MainStreamsInfo + { + (Same as in AdditionalStreams) + } + FilesInfo + { + NumFiles + Properties[] + { + ID + Size + Data + } + } +} + +HeaderInfo structure +~~~~~~~~~~~~~~~~~~~~ +{ + (Same as in AdditionalStreams) +} + + + +Notes about Notation and encoding +--------------------------------- + +7z uses little endian encoding. + +7z archive format has optional headers that are marked as +[] +Header +[] + +REAL_UINT64 means real UINT64. + +UINT64 means real UINT64 encoded with the following scheme: + + Size of encoding sequence depends from first byte: + First_Byte Extra_Bytes Value + (binary) + 0xxxxxxx : ( xxxxxxx ) + 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y + 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y + ... + 1111110x BYTE y[6] : ( x << (8 * 6)) + y + 11111110 BYTE y[7] : y + 11111111 BYTE y[8] : y + + + +Property IDs +------------ + +0x00 = kEnd + +0x01 = kHeader + +0x02 = kArchiveProperties + +0x03 = kAdditionalStreamsInfo +0x04 = kMainStreamsInfo +0x05 = kFilesInfo + +0x06 = kPackInfo +0x07 = kUnPackInfo +0x08 = kSubStreamsInfo + +0x09 = kSize +0x0A = kCRC + +0x0B = kFolder + +0x0C = kCodersUnPackSize +0x0D = kNumUnPackStream + +0x0E = kEmptyStream +0x0F = kEmptyFile +0x10 = kAnti + +0x11 = kName +0x12 = kCTime +0x13 = kATime +0x14 = kMTime +0x15 = kWinAttributes +0x16 = kComment + +0x17 = kEncodedHeader + +0x18 = kStartPos +0x19 = kDummy + + +7z format headers +----------------- + +SignatureHeader +~~~~~~~~~~~~~~~ + BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + + ArchiveVersion + { + BYTE Major; // now = 0 + BYTE Minor; // now = 4 + }; + + UINT32 StartHeaderCRC; + + StartHeader + { + REAL_UINT64 NextHeaderOffset + REAL_UINT64 NextHeaderSize + UINT32 NextHeaderCRC + } + + +........................... + + +ArchiveProperties +~~~~~~~~~~~~~~~~~ +BYTE NID::kArchiveProperties (0x02) +for (;;) +{ + BYTE PropertyType; + if (aType == 0) + break; + UINT64 PropertySize; + BYTE PropertyData[PropertySize]; +} + + +Digests (NumStreams) +~~~~~~~~~~~~~~~~~~~~~ + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumStreams) + BIT Defined + } + UINT32 CRCs[NumDefined] + + +PackInfo +~~~~~~~~~~~~ + BYTE NID::kPackInfo (0x06) + UINT64 PackPos + UINT64 NumPackStreams + + [] + BYTE NID::kSize (0x09) + UINT64 PackSizes[NumPackStreams] + [] + + [] + BYTE NID::kCRC (0x0A) + PackStreamDigests[NumPackStreams] + [] + + BYTE NID::kEnd + + +Folder +~~~~~~ + UINT64 NumCoders; + for (NumCoders) + { + BYTE + { + 0:3 CodecIdSize + 4: Is Complex Coder + 5: There Are Attributes + 6: Reserved + 7: There are more alternative methods. (Not used anymore, must be 0). + } + BYTE CodecId[CodecIdSize] + if (Is Complex Coder) + { + UINT64 NumInStreams; + UINT64 NumOutStreams; + } + if (There Are Attributes) + { + UINT64 PropertiesSize + BYTE Properties[PropertiesSize] + } + } + + NumBindPairs = NumOutStreamsTotal - 1; + + for (NumBindPairs) + { + UINT64 InIndex; + UINT64 OutIndex; + } + + NumPackedStreams = NumInStreamsTotal - NumBindPairs; + if (NumPackedStreams > 1) + for(NumPackedStreams) + { + UINT64 Index; + }; + + + + +Coders Info +~~~~~~~~~~~ + + BYTE NID::kUnPackInfo (0x07) + + + BYTE NID::kFolder (0x0B) + UINT64 NumFolders + BYTE External + switch(External) + { + case 0: + Folders[NumFolders] + case 1: + UINT64 DataStreamIndex + } + + + BYTE ID::kCodersUnPackSize (0x0C) + for(Folders) + for(Folder.NumOutStreams) + UINT64 UnPackSize; + + + [] + BYTE NID::kCRC (0x0A) + UnPackDigests[NumFolders] + [] + + + + BYTE NID::kEnd + + + +SubStreams Info +~~~~~~~~~~~~~~ + BYTE NID::kSubStreamsInfo; (0x08) + + [] + BYTE NID::kNumUnPackStream; (0x0D) + UINT64 NumUnPackStreamsInFolders[NumFolders]; + [] + + + [] + BYTE NID::kSize (0x09) + UINT64 UnPackSizes[] + [] + + + [] + BYTE NID::kCRC (0x0A) + Digests[Number of streams with unknown CRC] + [] + + + BYTE NID::kEnd + + +Streams Info +~~~~~~~~~~~~ + + [] + PackInfo + [] + + + [] + CodersInfo + [] + + + [] + SubStreamsInfo + [] + + BYTE NID::kEnd + + +FilesInfo +~~~~~~~~~ + BYTE NID::kFilesInfo; (0x05) + UINT64 NumFiles + + for (;;) + { + BYTE PropertyType; + if (aType == 0) + break; + + UINT64 Size; + + switch(PropertyType) + { + kEmptyStream: (0x0E) + for(NumFiles) + BIT IsEmptyStream + + kEmptyFile: (0x0F) + for(EmptyStreams) + BIT IsEmptyFile + + kAnti: (0x10) + for(EmptyStreams) + BIT IsAntiFile + + case kCTime: (0x12) + case kATime: (0x13) + case kMTime: (0x14) + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumFiles) + BIT TimeDefined + } + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Definded Items) + REAL_UINT64 Time + [] + + kNames: (0x11) + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Files) + { + wchar_t Names[NameSize]; + wchar_t 0; + } + [] + + kAttributes: (0x15) + BYTE AllAreDefined + if (AllAreDefined == 0) + { + for(NumFiles) + BIT AttributesAreDefined + } + BYTE External; + if(External != 0) + UINT64 DataIndex + [] + for(Definded Attributes) + UINT32 Attributes + [] + } + } + + +Header +~~~~~~ + BYTE NID::kHeader (0x01) + + [] + ArchiveProperties + [] + + [] + BYTE NID::kAdditionalStreamsInfo; (0x03) + StreamsInfo + [] + + [] + BYTE NID::kMainStreamsInfo; (0x04) + StreamsInfo + [] + + [] + FilesInfo + [] + + BYTE NID::kEnd + + +HeaderInfo +~~~~~~~~~~ + [] + BYTE NID::kEncodedHeader; (0x17) + StreamsInfo for Encoded Header + [] + + +--- +End of document diff --git a/3rdparty/lzma-21.03beta/DOC/Methods.txt b/3rdparty/lzma-21.03beta/DOC/Methods.txt new file mode 100644 index 0000000..d4a1b1d --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/Methods.txt @@ -0,0 +1,173 @@ +7-Zip method IDs for 7z and xz archives +--------------------------------------- + +Version: 18.06 +Date: 2018-06-30 + +Each compression or crypto method in 7z is associated with unique binary value (ID). +The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). + +xz and 7z formats use same ID map. + +If you want to add some new ID, you have two ways: + 1) Write request for allocating IDs to 7-Zip developers. + 2) Generate 8-bytes ID: + + 3F ZZ ZZ ZZ ZZ ZZ MM MM + + 3F - Prefix for random IDs (1 byte) + ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. + + MM MM - Method ID (2 bytes) + + You can notify 7-Zip developers about your Developer ID / Method ID. + + Note: Use new ID, if old codec can not decode data encoded with new version. + + +List of defined IDs +------------------- + +00 - Copy + +03 - Delta +04 - BCJ (x86) +05 - PPC (big-endian) +06 - IA64 +07 - ARM (little-endian) +08 - ARMT (little-endian) +09 - SPARC + +21 - LZMA2 + +02.. - Common + 03 [Swap] + - 2 Swap2 + - 4 Swap4 + +03.. - 7z + 01 - + 01 - LZMA + + 03 - [Branch Codecs] + 01 - [x86 Codecs] + 03 - BCJ + 1B - BCJ2 (4 packed streams) + 02 - + 05 - PPC (big-endian) + 03 - + 01 - Alpha + 04 - + 01 - IA64 + 05 - + 01 - ARM (little-endian) + 06 - + 05 - M68 (big-endian) + 07 - + 01 - ARMT (little-endian) + 08 - + 05 - SPARC + + 04 - + 01 - PPMD + + 7F - + 01 - experimental method. + + +04.. - Misc codecs + + 00 - Reserved + + 01 - [Zip] + 00 - Copy (not used. Use {00} instead) + 01 - Shrink + 06 - Implode + 08 - Deflate + 09 - Deflate64 + 0A - Imploding + 0C - BZip2 (not used. Use {040202} instead) + 0E - LZMA (LZMA-zip) + 5F - xz + 60 - Jpeg + 61 - WavPack + 62 - PPMd (PPMd-zip) + 63 - wzAES + + 02 - + 02 - BZip2 + + 03 - [Rar] + 01 - Rar1 + 02 - Rar2 + 03 - Rar3 + 05 - Rar5 + + 04 - [Arj] + 01 - Arj(1,2,3) + 02 - Arj4 + + 05 - [Z] + + 06 - [Lzh] + + 07 - Reserved for 7z + + 08 - [Cab] + + 09 - [NSIS] + 01 - DeflateNSIS + 02 - BZip2NSIS + + F7 - External codecs (that are not included to 7-Zip) + + 0x xx - reserved + + 10 xx - reserved (LZHAM) + 01 - LZHAM + + 11 xx - reserved (Tino Reichardt) + 01 - ZSTD + 02 - BROTLI + 04 - LZ4 + 05 - LZ5 + 06 - LIZARD + + 12 xx - reserverd (Denis Anisimov) + + 01 - WavPack2 + FE - eSplitter + FF - RawSplitter + + +06.. - Crypto + + F0 - Ciphers without hashing algo + + 01 - [AES] + 0x - AES-128 + 4x - AES-192 + 8x - AES-256 + Cx - AES + + x0 - ECB + x1 - CBC + x2 - CFB + x3 - OFB + x4 - CTR + + F1 - Combine Ciphers + + 01 - [Zip] + 01 - ZipCrypto (Main Zip crypto algo) + + 03 - [RAR] + 02 - + 03 - Rar29AES (AES-128 + modified SHA-1) + + 07 - [7z] + 01 - 7zAES (AES-256 + SHA-256) + + +--- +End of document diff --git a/3rdparty/lzma-21.03beta/DOC/installer.txt b/3rdparty/lzma-21.03beta/DOC/installer.txt new file mode 100644 index 0000000..b99d21d --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/installer.txt @@ -0,0 +1,166 @@ +7-Zip for installers 9.38 +------------------------- + +7-Zip is a file archiver for Windows NT/2000/2003/2008/XP/Vista/7/8/10. + +7-Zip for installers is part of LZMA SDK. +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +It's allowed to join 7-Zip SFX module with another software. +It's allowed to change resources of 7-Zip's SFX modules. + + +HOW to use +----------- + +7zr.exe is reduced version of 7za.exe of 7-Zip. +7zr.exe supports only format with these codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, Copy. + +Example of compressing command for installation packages: + +7zr a archive.7z files + +7zSD.sfx is SFX module for installers. 7zSD.sfx uses msvcrt.dll. + +SFX modules for installers allow to create installation program. +Such module extracts archive to temp folder and then runs specified program and removes +temp files after program finishing. Self-extract archive for installers must be created +as joining 3 files: SFX_Module, Installer_Config, 7z_Archive. +Installer_Config is optional file. You can use the following command to create installer +self-extract archive: + +copy /b 7zSD.sfx + config.txt + archive.7z archive.exe + +The smallest installation package size can be achieved, if installation files was +uncompressed before including to 7z archive. + +-y switch for installer module (at runtime) specifies quiet mode for extracting. + +Installer Config file format +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Config file contains commands for Installer. File begins from string +;!@Install@!UTF-8! and ends with ;!@InstallEnd@!. File must be written +in UTF-8 encoding. File contains string pairs: + +ID_String="Value" + +ID_String Description + +Title Title for messages +BeginPrompt Begin Prompt message +Progress Value can be "yes" or "no". Default value is "yes". +RunProgram Command for executing. Default value is "setup.exe". + Substring %%T will be replaced with path to temporary + folder, where files were extracted +Directory Directory prefix for "RunProgram". Default value is ".\\" +ExecuteFile Name of file for executing +ExecuteParameters Parameters for "ExecuteFile" + + +You can omit any string pair. + +There are two ways to run program: RunProgram and ExecuteFile. +Use RunProgram, if you want to run some program from .7z archive. +Use ExecuteFile, if you want to open some document from .7z archive or +if you want to execute some command from Windows. + +If you use RunProgram and if you specify empty directory prefix: Directory="", +the system searches for the executable file in the following sequence: + +1. The directory from which the application (installer) loaded. +2. The temporary folder, where files were extracted. +3. The Windows system directory. + + +Config file Examples +~~~~~~~~~~~~~~~~~~~~ + +;!@Install@!UTF-8! +Title="7-Zip 4.00" +BeginPrompt="Do you want to install the 7-Zip 4.00?" +RunProgram="setup.exe" +;!@InstallEnd@! + + + +;!@Install@!UTF-8! +Title="7-Zip 4.00" +BeginPrompt="Do you want to install the 7-Zip 4.00?" +ExecuteFile="7zip.msi" +;!@InstallEnd@! + + + +;!@Install@!UTF-8! +Title="7-Zip 4.01 Update" +BeginPrompt="Do you want to install the 7-Zip 4.01 Update?" +ExecuteFile="msiexec.exe" +ExecuteParameters="/i 7zip.msi REINSTALL=ALL REINSTALLMODE=vomus" +;!@InstallEnd@! + + + +Small SFX modules for installers +-------------------------------- + +7zS2.sfx - small SFX module (GUI version) +7zS2con.sfx - small SFX module (Console version) + +Small SFX modules support this codecs: LZMA, LZMA2, BCJ, BCJ2, ARM, COPY + +Small SFX module is similar to common SFX module for installers. +The difference (what's new in small version): + - Smaller size (30 KB vs 100 KB) + - C source code instead of Ñ++ + - No installer Configuration file + - No extracting progress window + - It decompresses solid 7z blocks (it can be whole 7z archive) to RAM. + So user that calls SFX installer must have free RAM of size of largest + solid 7z block (size of 7z archive at simplest case). + +How to use +---------- + +copy /b 7zS2.sfx + archive.7z sfx.exe + +When you run installer sfx module (sfx.exe) +1) It creates "7zNNNNNNNN" temp folder in system temp folder. +2) It extracts .7z archive to that folder +3) It executes one file from "7zNNNNNNNN" temp folder. +4) It removes "7zNNNNNNNN" temp folder + +You can send parameters to installer, and installer will transfer them to extracted .exe file. + +Small SFX uses 3 levels of priorities to select file to execute: + + 1) Files in root folder have higher priority than files in subfolders. + 2) File extension priorities (from high to low priority order): + bat, cmd, exe, inf, msi, cab (under Windows CE), html, htm + 3) File name priorities (from high to low priority order): + setup, install, run, start + +Windows CE (ARM) version of 7zS2.sfx is included to 7-Zip for Windows Mobile package. + + +Examples +-------- + +1) To create compressed console 7-Zip: + +7zr a c.7z 7z.exe 7z.dll -mx +copy /b 7zS2con.sfx + c.7z 7zCompr.exe +7zCompr.exe b -md22 + + +2) To create compressed GUI 7-Zip: + +7zr a g.7z 7zg.exe 7z.dll -mx +copy /b 7zS2.sfx + g.7z 7zgCompr.exe +7zgCompr.exe b -md22 + + +3) To open some file: + +7zr a h.7z readme.txt -mx +copy /b 7zS2.sfx + h.7z 7zTxt.exe +7zTxt.exe diff --git a/3rdparty/lzma-21.03beta/DOC/lzma-history.txt b/3rdparty/lzma-21.03beta/DOC/lzma-history.txt new file mode 100644 index 0000000..84fb1c2 --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/lzma-history.txt @@ -0,0 +1,490 @@ +HISTORY of the LZMA SDK +----------------------- + +21.03 beta 2021-07-20 +------------------------- +- The maximum dictionary size for LZMA/LZMA2 compressing was increased to 4 GB (3840 MiB). +- Minor speed optimizations in LZMA/LZMA2 compressing. + + +21.02 alpha 2021-05-06 +------------------------- +- The command line version of 7-Zip for macOS was released. +- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux + was increased by 20%-60%. + + +21.01 alpha 2021-03-09 +------------------------- +- The command line version of 7-Zip for Linux was released. +- The improvements for speed of ARM64 version using hardware CPU instructions + for AES, CRC-32, SHA-1 and SHA-256. +- Some bugs were fixed. + + +20.02 alpha 2020-08-08 +------------------------- +- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. + It allows to increase the compression speed for big 7z archives, if there is a big number + of CPU cores and threads. +- The speed of PPMd compressing/decompressing was increased for 7z archives. +- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system + to modify "Last Access Time" property of source files for archiving and hashing operations. +- Some bugs were fixed. + + +20.00 alpha 2020-02-06 +------------------------- +- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, + that can work faster than bt4 and hc4 match finders for the data with big redundancy. +- The compression ratio was improved for Fast and Fastest compression levels with the + following default settings: + - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. + - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. +- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra + compression levels. + + +19.00 2019-02-21 +------------------------- +- Encryption strength for 7z archives was increased: + the size of random initialization vector was increased from 64-bit to 128-bit, + and the pseudo-random number generator was improved. +- The bug in 7zIn.c code was fixed. + + +18.06 2018-12-30 +------------------------- +- The speed for LZMA/LZMA2 compressing was increased by 3-10%, + and there are minor changes in compression ratio. +- Some bugs were fixed. +- The bug in 7-Zip 18.02-18.05 was fixed: + There was memory leak in multithreading xz decoder - XzDecMt_Decode(), + if xz stream contains only one block. +- The changes for MSVS compiler makefiles: + - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64) + instead of "CPU" macroname with values (AMD64, ARM64). + - the makefiles by default now use static version of the run-time library. + + +18.05 2018-04-30 +------------------------- +- The speed for LZMA/LZMA2 compressing was increased + by 8% for fastest/fast compression levels and + by 3% for normal/maximum compression levels. +- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in + Windows 10 because of some BUG with "Large Pages" in Windows 10. + Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). +- The BUG was fixed in Lzma2Enc.c + Lzma2Enc_Encode2() function worked incorretly, + if (inStream == NULL) and the number of block threads is more than 1. + + +18.03 beta 2018-03-04 +------------------------- +- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm + for x64 with about 30% higher speed than main version of LZMA decoder written in C. +- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. +- 7-Zip now can use multi-threading for 7z/LZMA2 decoding, + if there are multiple independent data chunks in LZMA2 stream. +- 7-Zip now can use multi-threading for xz decoding, + if there are multiple blocks in xz stream. + + +18.01 2019-01-28 +------------------------- +- The BUG in 17.01 - 18.00 beta was fixed: + XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished() + didn't work correctly for xz archives without checksum (CRC). + + +18.00 beta 2019-01-10 +------------------------- +- The BUG in xz encoder was fixed: + There was memory leak of 16 KB for each file compressed with + xz compression method, if additional filter was used. + + +17.01 beta 2017-08-28 +------------------------- +- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression. + 7-Zip now uses additional memory buffers for multi-block LZMA2 compression. + CPU utilization was slightly improved. +- 7-zip now creates multi-block xz archives by default. Block size can be + specified with -ms[Size]{m|g} switch. +- xz decoder now can unpack random block from multi-block xz archives. +- 7-Zip command line: @listfile now doesn't work after -- switch. + Use -i@listfile before -- switch instead. +- The BUGs were fixed: + 7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive. + + +17.00 beta 2017-04-29 +------------------------- +- NewHandler.h / NewHandler.cpp: + now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). +- C/7zTypes.h : the names of variables in interface structures were changed (vt). +- Some bugs were fixed. 7-Zip could crash in some cases. +- Some internal changes in code. + + +16.04 2016-10-04 +------------------------- +- The bug was fixed in DllSecur.c. + + +16.03 2016-09-28 +------------------------- +- SFX modules now use some protection against DLL preloading attack. +- Some bugs in 7z code were fixed. + + +16.02 2016-05-21 +------------------------- +- The BUG in 16.00 - 16.01 was fixed: + Split Handler (SplitHandler.cpp) returned incorrect + total size value (kpidSize) for split archives. + + +16.01 2016-05-19 +------------------------- +- Some internal changes to reduce the number of compiler warnings. + + +16.00 2016-05-10 +------------------------- +- Some bugs were fixed. + + +15.12 2015-11-19 +------------------------- +- The BUG in C version of 7z decoder was fixed: + 7zDec.c : SzDecodeLzma2() + 7z decoder could mistakenly report about decoding error for some 7z archives + that use LZMA2 compression method. + The probability to get that mistaken decoding error report was about + one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). +- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: + 7zArcIn.c : SzReadHeader2() + 7z decoder worked incorrectly for 7z archives that contain + empty solid blocks, that can be placed to 7z archive, if some file is + unavailable for reading during archive creation. + + +15.09 beta 2015-10-16 +------------------------- +- The BUG in LZMA / LZMA2 encoding code was fixed. + The BUG in LzFind.c::MatchFinder_ReadBlock() function. + If input data size is larger than (4 GiB - dictionary_size), + the following code worked incorrectly: + - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions + for compressing from memory to memory. + That BUG is not related to LZMA encoder version that works via streams. + - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if + default value of chunk size (CLzma2EncProps::blockSize) is changed + to value larger than (4 GiB - dictionary_size). + + +9.38 beta 2015-01-03 +------------------------- +- The BUG in 9.31-9.37 was fixed: + IArchiveGetRawProps interface was disabled for 7z archives. +- The BUG in 9.26-9.36 was fixed: + Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows. + + +9.36 beta 2014-12-26 +------------------------- +- The BUG in command line version was fixed: + 7-Zip created temporary archive in current folder during update archive + operation, if -w{Path} switch was not specified. + The fixed 7-Zip creates temporary archive in folder that contains updated archive. +- The BUG in 9.33-9.35 was fixed: + 7-Zip silently ignored file reading errors during 7z or gz archive creation, + and the created archive contained only part of file that was read before error. + The fixed 7-Zip stops archive creation and it reports about error. + + +9.35 beta 2014-12-07 +------------------------- +- 7zr.exe now support AES encryption. +- SFX mudules were added to LZMA SDK +- Some bugs were fixed. + + +9.21 beta 2011-04-11 +------------------------- +- New class FString for file names at file systems. +- Speed optimization in CRC code for big-endian CPUs. +- The BUG in Lzma2Dec.c was fixed: + Lzma2Decode function didn't work. + + +9.18 beta 2010-11-02 +------------------------- +- New small SFX module for installers (SfxSetup). + + +9.12 beta 2010-03-24 +------------------------- +- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, + if more than 10 threads were used (or more than 20 threads in some modes). + + +9.11 beta 2010-03-15 +------------------------- +- PPMd compression method support + + +9.09 2009-12-12 +------------------------- +- The bug was fixed: + Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c + incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. +- Some bugs were fixed + + +9.06 2009-08-17 +------------------------- +- Some changes in ANSI-C 7z Decoder interfaces. + + +9.04 2009-05-30 +------------------------- +- LZMA2 compression method support +- xz format support + + +4.65 2009-02-03 +------------------------- +- Some minor fixes + + +4.63 2008-12-31 +------------------------- +- Some minor fixes + + +4.61 beta 2008-11-23 +------------------------- +- The bug in ANSI-C LZMA Decoder was fixed: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. +- Some changes in ANSI-C 7z Decoder interfaces. +- LZMA SDK is placed in the public domain. + + +4.60 beta 2008-08-19 +------------------------- +- Some minor fixes. + + +4.59 beta 2008-08-13 +------------------------- +- The bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.58 beta 2008-05-05 +------------------------- +- ANSI-C LZMA Decoder was rewritten for speed optimizations. +- ANSI-C LZMA Encoder was included to LZMA SDK. +- C++ LZMA code now is just wrapper over ANSI-C code. + + +4.57 2007-12-12 +------------------------- +- Speed optimizations in Ñ++ LZMA Decoder. +- Small changes for more compatibility with some C/C++ compilers. + + +4.49 beta 2007-07-05 +------------------------- +- .7z ANSI-C Decoder: + - now it supports BCJ and BCJ2 filters + - now it supports files larger than 4 GB. + - now it supports "Last Write Time" field for files. +- C++ code for .7z archives compressing/decompressing from 7-zip + was included to LZMA SDK. + + +4.43 2006-06-04 +------------------------- +- Small changes for more compatibility with some C/C++ compilers. + + +4.42 2006-05-15 +------------------------- +- Small changes in .h files in ANSI-C version. + + +4.39 beta 2006-04-14 +------------------------- +- The bug in versions 4.33b:4.38b was fixed: + C++ version of LZMA encoder could not correctly compress + files larger than 2 GB with HC4 match finder (-mfhc4). + + +4.37 beta 2005-04-06 +------------------------- +- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. + + +4.35 beta 2005-03-02 +------------------------- +- The bug was fixed in C++ version of LZMA Decoder: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. + + +4.34 beta 2006-02-27 +------------------------- +- Compressing speed and memory requirements for compressing were increased +- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 + + +4.32 2005-12-09 +------------------------- +- Java version of LZMA SDK was included + + +4.30 2005-11-20 +------------------------- +- Compression ratio was improved in -a2 mode +- Speed optimizations for compressing in -a2 mode +- -fb switch now supports values up to 273 +- The bug in 7z_C (7zIn.c) was fixed: + It used Alloc/Free functions from different memory pools. + So if program used two memory pools, it worked incorrectly. +- 7z_C: .7z format supporting was improved +- LZMA# SDK (C#.NET version) was included + + +4.27 (Updated) 2005-09-21 +------------------------- +- Some GUIDs/interfaces in C++ were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.27 2005-08-07 +------------------------- +- The bug in LzmaDecodeSize.c was fixed: + if _LZMA_IN_CB and _LZMA_OUT_READ were defined, + decompressing worked incorrectly. + + +4.26 2005-08-05 +------------------------- +- Fixes in 7z_C code and LzmaTest.c: + previous versions could work incorrectly, + if malloc(0) returns 0 + + +4.23 2005-06-29 +------------------------- +- Small fixes in C++ code + + +4.22 2005-06-10 +------------------------- +- Small fixes + + +4.21 2005-06-08 +------------------------- +- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed +- New additional version of ANSI-C LZMA Decoder with zlib-like interface: + - LzmaStateDecode.h + - LzmaStateDecode.c + - LzmaStateTest.c +- ANSI-C LZMA Decoder now can decompress files larger than 4 GB + + +4.17 2005-04-18 +------------------------- +- New example for RAM->RAM compressing/decompressing: + LZMA + BCJ (filter for x86 code): + - LzmaRam.h + - LzmaRam.cpp + - LzmaRamDecode.h + - LzmaRamDecode.c + - -f86 switch for lzma.exe + + +4.16 2005-03-29 +------------------------- +- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): + If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, + decoder could access memory outside of allocated range. +- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). + Old version of LZMA Decoder now is in file LzmaDecodeSize.c. + LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c +- Small speed optimization in LZMA C++ code +- filter for SPARC's code was added +- Simplified version of .7z ANSI-C Decoder was included + + +4.06 2004-09-05 +------------------------- +- The bug in v4.05 was fixed: + LZMA-Encoder didn't release output stream in some cases. + + +4.05 2004-08-25 +------------------------- +- Source code of filters for x86, IA-64, ARM, ARM-Thumb + and PowerPC code was included to SDK +- Some internal minor changes + + +4.04 2004-07-28 +------------------------- +- More compatibility with some C++ compilers + + +4.03 2004-06-18 +------------------------- +- "Benchmark" command was added. It measures compressing + and decompressing speed and shows rating values. + Also it checks hardware errors. + + +4.02 2004-06-10 +------------------------- +- C++ LZMA Encoder/Decoder code now is more portable + and it can be compiled by GCC on Linux. + + +4.01 2004-02-15 +------------------------- +- Some detection of data corruption was enabled. + LzmaDecode.c / RangeDecoderReadByte + ..... + { + rd->ExtraBytes = 1; + return 0xFF; + } + + +4.00 2004-02-13 +------------------------- +- Original version of LZMA SDK + + + +HISTORY of the LZMA +------------------- + 2001-2008: Improvements to LZMA compressing/decompressing code, + keeping compatibility with original LZMA format + 1996-2001: Development of LZMA compression format + + Some milestones: + + 2001-08-30: LZMA compression was added to 7-Zip + 1999-01-02: First version of 7-Zip was released + + +End of document diff --git a/3rdparty/lzma-21.03beta/DOC/lzma-sdk.txt b/3rdparty/lzma-21.03beta/DOC/lzma-sdk.txt new file mode 100644 index 0000000..b874b0a --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/lzma-sdk.txt @@ -0,0 +1,404 @@ +LZMA SDK 21.03 +-------------- + +LZMA SDK provides the documentation, samples, header files, +libraries, and tools you need to develop applications that +use 7z / LZMA / LZMA2 / XZ compression. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + +LZMA2 is a LZMA based compression method. LZMA2 provides better +multithreading support for compression than LZMA and some other improvements. + +7z is a file format for data compression and file archiving. +7z is a main file format for 7-Zip compression program (www.7-zip.org). +7z format supports different compression methods: LZMA, LZMA2 and others. +7z also supports AES-256 based encryption. + +XZ is a file format for data compression that uses LZMA2 compression. +XZ format provides additional features: SHA/CRC check, filters for +improved compression ratio, splitting to blocks and streams, + + + +LICENSE +------- + +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +Some code in LZMA SDK is based on public domain code from another developers: + 1) PPMd var.H (2001): Dmitry Shkarin + 2) SHA-256: Wei Dai (Crypto++ library) + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute the +original LZMA SDK code, either in source code form or as a compiled binary, for +any purpose, commercial or non-commercial, and by any means. + +LZMA SDK code is compatible with open source licenses, for example, you can +include it to GNU GPL or GNU LGPL code. + + +LZMA SDK Contents +----------------- + + Source code: + + - C / C++ / C# / Java - LZMA compression and decompression + - C / C++ - LZMA2 compression and decompression + - C / C++ - XZ compression and decompression + - C - 7z decompression + - C++ - 7z compression and decompression + - C - small SFXs for installers (7z decompression) + - C++ - SFXs and SFXs for installers (7z decompression) + + Precomiled binaries: + + - console programs for lzma / 7z / xz compression and decompression + - SFX modules for installers. + + +UNIX/Linux version +------------------ +There are several otpions to compile 7-Zip with different compilers: gcc and clang. +Also 7-Zip code contains two versions for some critical parts of code: in C and in Assembeler. +So if you compile the version with Assembeler code, you will get faster 7-Zip binary. + +7-Zip's assembler code uses the following syntax for different platforms: + +1) x86 and x86-64 (AMD64): MASM syntax. + There are 2 programs that supports MASM syntax in Linux. +' 'Asmc Macro Assembler and JWasm. But JWasm now doesn't support some + cpu instructions used in 7-Zip. + So you must install Asmc Macro Assembler in Linux, if you want to compile fastest version + of 7-Zip x86 and x86-64: + https://github.com/nidud/asmc + +2) arm64: GNU assembler for ARM64 with preprocessor. + That systax of that arm64 assembler code in 7-Zip is supported by GCC and CLANG for ARM64. + +There are different binaries that can be compiled from 7-Zip source. +There are 2 main files in folder for compiling: + makefile - that can be used for compiling Windows version of 7-Zip with nmake command + makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip with make command + +At first you must change the current folder to folder that contains `makefile.gcc`: + + cd CPP/7zip/Bundles/Alone7z + +Then you can compile `makefile.gcc` with the command: + + make -j -f makefile.gcc + +Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile +7-Zip binaries with optimized code and optimzing options. + +To compile with GCC without assembler: + cd CPP/7zip/Bundles/Alone7z + make -j -f ../../cmpl_gcc.mak + +To compile with CLANG without assembler: + make -j -f ../../cmpl_clang.mak + +To compile 7-Zip for x86-64 with asmc assembler: + make -j -f ../../cmpl_gcc_x64.mak + +To compile 7-Zip for arm64 with assembler: + make -j -f ../../cmpl_gcc_arm64.mak + +To compile 7-Zip for arm64 for macOS: + make -j -f ../../cmpl_mac_arm64.mak + +Also you can change some compiler options in the mak files: + cmpl_gcc.mak + var_gcc.mak + warn_gcc.mak + + + +Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux): + + http://p7zip.sourceforge.net/ + + +Files +----- + +DOC/7zC.txt - 7z ANSI-C Decoder description +DOC/7zFormat.txt - 7z Format description +DOC/installer.txt - information about 7-Zip for installers +DOC/lzma.txt - LZMA compression description +DOC/lzma-sdk.txt - LZMA SDK description (this file) +DOC/lzma-history.txt - history of LZMA SDK +DOC/lzma-specification.txt - Specification of LZMA +DOC/Methods.txt - Compression method IDs for .7z + +bin/installer/ - example script to create installer that uses SFX module, + +bin/7zdec.exe - simplified 7z archive decoder +bin/7zr.exe - 7-Zip console program (reduced version) +bin/x64/7zr.exe - 7-Zip console program (reduced version) (x64 version) +bin/lzma.exe - file->file LZMA encoder/decoder for Windows +bin/7zS2.sfx - small SFX module for installers (GUI version) +bin/7zS2con.sfx - small SFX module for installers (Console version) +bin/7zSD.sfx - SFX module for installers. + + +7zDec.exe +--------- +7zDec.exe is simplified 7z archive decoder. +It supports only LZMA, LZMA2, and PPMd methods. +7zDec decodes whole solid block from 7z archive to RAM. +The RAM consumption can be high. + + + + +Source code structure +--------------------- + + +Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption) + +C/ - C files (compression / decompression and other) + Util/ + 7z - 7z decoder program (decoding 7z files) + Lzma - LZMA program (file->file LZMA encoder/decoder). + LzmaLib - LZMA library (.DLL for Windows) + SfxSetup - small SFX module for installers + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules (files) + + Alone7z - 7zr.exe: Standalone 7-Zip console program (reduced version) + Format7zExtractR - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2. + Format7zR - 7zr.dll: Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression + LzmaSpec - example code for LZMA Specification + SFXCon - 7zCon.sfx: Console 7z SFX module + SFXSetup - 7zS.sfx: 7z SFX module for installers + SFXWin - 7z.sfx: GUI 7z SFX module + + Common - common files for 7-Zip + + Compress - files for compression/decompression + + Crypto - files for encryption / decompression + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console program (7z.exe) + Explorer - Some code from 7-Zip Shell extension + FileManager - Some GUI code from 7-Zip File Manager + GUI - Some GUI code from 7-Zip + + +CS/ - C# files + 7zip + Common - some common files for 7-Zip + Compress - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + LzmaAlone - file->file LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + +Java/ - Java files + SevenZip + Compression - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + + +Note: + Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code. + 7-Zip's source code can be downloaded from 7-Zip's SourceForge page: + + http://sourceforge.net/projects/sevenzip/ + + + +LZMA features +------------- + - Variable dictionary size (up to 1 GB) + - Estimated compressing speed: about 2 MB/s on 2 GHz CPU + - Estimated decompressing speed: + - 20-30 MB/s on modern 2 GHz cpu + - 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC) + - Small memory requirements for decompressing (16 KB + DictionarySize) + - Small code size for decompressing: 5-8 KB + +LZMA decoder uses only integer operations and can be +implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). + +Some critical operations that affect the speed of LZMA decompression: + 1) 32*16 bit integer multiply + 2) Mispredicted branches (penalty mostly depends from pipeline length) + 3) 32-bit shift and arithmetic operations + +The speed of LZMA decompressing mostly depends from CPU speed. +Memory speed has no big meaning. But if your CPU has small data cache, +overall weight of memory speed will slightly increase. + + +How To Use +---------- + +Using LZMA encoder/decoder executable +-------------------------------------- + +Usage: LZMA inputFile outputFile [...] + + e: encode file + + d: decode file + + b: Benchmark. There are two tests: compressing and decompressing + with LZMA method. Benchmark shows rating in MIPS (million + instructions per second). Rating value is calculated from + measured speed and it is normalized with Intel's Core 2 results. + Also Benchmark checks possible hardware errors (RAM + errors in most cases). Benchmark uses these settings: + (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. + Also you can change the number of iterations. Example for 30 iterations: + LZMA b 30 + Default number of iterations is 10. + + + + + -a{N}: set compression mode 0 = fast, 1 = normal + default: 1 (normal) + + d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) + The maximum value for dictionary size is 1 GB = 2^30 bytes. + Dictionary size is calculated as DictionarySize = 2^N bytes. + For decompressing file compressed by LZMA method with dictionary + size D = 2^N you need about D bytes of memory (RAM). + + -fb{N}: set number of fast bytes - [5, 273], default: 128 + Usually big number gives a little bit better compression ratio + and slower compression process. + + -lc{N}: set number of literal context bits - [0, 8], default: 3 + Sometimes lc=4 gives gain for big files. + + -lp{N}: set number of literal pos bits - [0, 4], default: 0 + lp switch is intended for periodical data when period is + equal 2^N. For example, for 32-bit (4 bytes) + periodical data you can use lp=2. Often it's better to set lc0, + if you change lp switch. + + -pb{N}: set number of pos bits - [0, 4], default: 2 + pb switch is intended for periodical data + when period is equal 2^N. + + -mf{MF_ID}: set Match Finder. Default: bt4. + Algorithms from hc* group doesn't provide good compression + ratio, but they often works pretty fast in combination with + fast mode (-a0). + + Memory requirements depend from dictionary size + (parameter "d" in table below). + + MF_ID Memory Description + + bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. + bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. + bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. + hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. + + -eos: write End Of Stream marker. By default LZMA doesn't write + eos marker, since LZMA decoder knows uncompressed size + stored in .lzma file header. + + -si: Read data from stdin (it will write End Of Stream marker). + -so: Write data to stdout + + +Examples: + +1) LZMA e file.bin file.lzma -d16 -lc0 + +compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) +and 0 literal context bits. -lc0 allows to reduce memory requirements +for decompression. + + +2) LZMA e file.bin file.lzma -lc0 -lp2 + +compresses file.bin to file.lzma with settings suitable +for 32-bit periodical data (for example, ARM or MIPS code). + +3) LZMA d file.lzma file.bin + +decompresses file.lzma to file.bin. + + +Compression ratio hints +----------------------- + +Recommendations +--------------- + +To increase the compression ratio for LZMA compressing it's desirable +to have aligned data (if it's possible) and also it's desirable to locate +data in such order, where code is grouped in one place and data is +grouped in other place (it's better than such mixing: code, data, code, +data, ...). + + +Filters +------- +You can increase the compression ratio for some data types, using +special filters before compressing. For example, it's possible to +increase the compression ratio on 5-10% for code for those CPU ISAs: +x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. + +You can find C source code of such filters in C/Bra*.* files + +You can check the compression ratio gain of these filters with such +7-Zip commands (example for ARM code): +No filter: + 7z a a1.7z a.bin -m0=lzma + +With filter for little-endian ARM code: + 7z a a2.7z a.bin -m0=arm -m1=lzma + +It works in such manner: +Compressing = Filter_encoding + LZMA_encoding +Decompressing = LZMA_decoding + Filter_decoding + +Compressing and decompressing speed of such filters is very high, +so it will not increase decompressing time too much. +Moreover, it reduces decompression time for LZMA_decoding, +since compression ratio with filtering is higher. + +These filters convert CALL (calling procedure) instructions +from relative offsets to absolute addresses, so such data becomes more +compressible. + +For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. + + + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/3rdparty/lzma-21.03beta/DOC/lzma-specification.txt b/3rdparty/lzma-21.03beta/DOC/lzma-specification.txt new file mode 100644 index 0000000..ac0cce7 --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/lzma-specification.txt @@ -0,0 +1,1176 @@ +LZMA specification (DRAFT version) +---------------------------------- + +Author: Igor Pavlov +Date: 2015-06-14 + +This specification defines the format of LZMA compressed data and lzma file format. + +Notation +-------- + +We use the syntax of C++ programming language. +We use the following types in C++ code: + unsigned - unsigned integer, at least 16 bits in size + int - signed integer, at least 16 bits in size + UInt64 - 64-bit unsigned integer + UInt32 - 32-bit unsigned integer + UInt16 - 16-bit unsigned integer + Byte - 8-bit unsigned integer + bool - boolean type with two possible values: false, true + + +lzma file format +================ + +The lzma file contains the raw LZMA stream and the header with related properties. + +The files in that format use ".lzma" extension. + +The lzma file format layout: + +Offset Size Description + + 0 1 LZMA model properties (lc, lp, pb) in encoded form + 1 4 Dictionary size (32-bit unsigned integer, little-endian) + 5 8 Uncompressed size (64-bit unsigned integer, little-endian) + 13 Compressed data (LZMA stream) + +LZMA properties: + + name Range Description + + lc [0, 8] the number of "literal context" bits + lp [0, 4] the number of "literal pos" bits + pb [0, 4] the number of "pos" bits +dictSize [0, 2^32 - 1] the dictionary size + +The following code encodes LZMA properties: + +void EncodeProperties(Byte *properties) +{ + properties[0] = (Byte)((pb * 5 + lp) * 9 + lc); + Set_UInt32_LittleEndian(properties + 1, dictSize); +} + +If the value of dictionary size in properties is smaller than (1 << 12), +the LZMA decoder must set the dictionary size variable to (1 << 12). + +#define LZMA_DIC_MIN (1 << 12) + + unsigned lc, pb, lp; + UInt32 dictSize; + UInt32 dictSizeInProperties; + + void DecodeProperties(const Byte *properties) + { + unsigned d = properties[0]; + if (d >= (9 * 5 * 5)) + throw "Incorrect LZMA properties"; + lc = d % 9; + d /= 9; + pb = d / 5; + lp = d % 5; + dictSizeInProperties = 0; + for (int i = 0; i < 4; i++) + dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i); + dictSize = dictSizeInProperties; + if (dictSize < LZMA_DIC_MIN) + dictSize = LZMA_DIC_MIN; + } + +If "Uncompressed size" field contains ones in all 64 bits, it means that +uncompressed size is unknown and there is the "end marker" in stream, +that indicates the end of decoding point. +In opposite case, if the value from "Uncompressed size" field is not +equal to ((2^64) - 1), the LZMA stream decoding must be finished after +specified number of bytes (Uncompressed size) is decoded. And if there +is the "end marker", the LZMA decoder must read that marker also. + + +The new scheme to encode LZMA properties +---------------------------------------- + +If LZMA compression is used for some another format, it's recommended to +use a new improved scheme to encode LZMA properties. That new scheme was +used in xz format that uses the LZMA2 compression algorithm. +The LZMA2 is a new compression algorithm that is based on the LZMA algorithm. + +The dictionary size in LZMA2 is encoded with just one byte and LZMA2 supports +only reduced set of dictionary sizes: + (2 << 11), (3 << 11), + (2 << 12), (3 << 12), + ... + (2 << 30), (3 << 30), + (2 << 31) - 1 + +The dictionary size can be extracted from encoded value with the following code: + + dictSize = (p == 40) ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)); + +Also there is additional limitation (lc + lp <= 4) in LZMA2 for values of +"lc" and "lp" properties: + + if (lc + lp > 4) + throw "Unsupported properties: (lc + lp) > 4"; + +There are some advantages for LZMA decoder with such (lc + lp) value +limitation. It reduces the maximum size of tables allocated by decoder. +And it reduces the complexity of initialization procedure, that can be +important to keep high speed of decoding of big number of small LZMA streams. + +It's recommended to use that limitation (lc + lp <= 4) for any new format +that uses LZMA compression. Note that the combinations of "lc" and "lp" +parameters, where (lc + lp > 4), can provide significant improvement in +compression ratio only in some rare cases. + +The LZMA properties can be encoded into two bytes in new scheme: + +Offset Size Description + + 0 1 The dictionary size encoded with LZMA2 scheme + 1 1 LZMA model properties (lc, lp, pb) in encoded form + + +The RAM usage +============= + +The RAM usage for LZMA decoder is determined by the following parts: + +1) The Sliding Window (from 4 KiB to 4 GiB). +2) The probability model counter arrays (arrays of 16-bit variables). +3) Some additional state variables (about 10 variables of 32-bit integers). + + +The RAM usage for Sliding Window +-------------------------------- + +There are two main scenarios of decoding: + +1) The decoding of full stream to one RAM buffer. + + If we decode full LZMA stream to one output buffer in RAM, the decoder + can use that output buffer as sliding window. So the decoder doesn't + need additional buffer allocated for sliding window. + +2) The decoding to some external storage. + + If we decode LZMA stream to external storage, the decoder must allocate + the buffer for sliding window. The size of that buffer must be equal + or larger than the value of dictionary size from properties of LZMA stream. + +In this specification we describe the code for decoding to some external +storage. The optimized version of code for decoding of full stream to one +output RAM buffer can require some minor changes in code. + + +The RAM usage for the probability model counters +------------------------------------------------ + +The size of the probability model counter arrays is calculated with the +following formula: + +size_of_prob_arrays = 1846 + 768 * (1 << (lp + lc)) + +Each probability model counter is 11-bit unsigned integer. +If we use 16-bit integer variables (2-byte integers) for these probability +model counters, the RAM usage required by probability model counter arrays +can be estimated with the following formula: + + RAM = 4 KiB + 1.5 KiB * (1 << (lp + lc)) + +For example, for default LZMA parameters (lp = 0 and lc = 3), the RAM usage is + + RAM_lc3_lp0 = 4 KiB + 1.5 KiB * 8 = 16 KiB + +The maximum RAM state usage is required for decoding the stream with lp = 4 +and lc = 8: + + RAM_lc8_lp4 = 4 KiB + 1.5 KiB * 4096 = 6148 KiB + +If the decoder uses LZMA2's limited property condition +(lc + lp <= 4), the RAM usage will be not larger than + + RAM_lc_lp_4 = 4 KiB + 1.5 KiB * 16 = 28 KiB + + +The RAM usage for encoder +------------------------- + +There are many variants for LZMA encoding code. +These variants have different values for memory consumption. +Note that memory consumption for LZMA Encoder can not be +smaller than memory consumption of LZMA Decoder for same stream. + +The RAM usage required by modern effective implementation of +LZMA Encoder can be estimated with the following formula: + + Encoder_RAM_Usage = 4 MiB + 11 * dictionarySize. + +But there are some modes of the encoder that require less memory. + + +LZMA Decoding +============= + +The LZMA compression algorithm uses LZ-based compression with Sliding Window +and Range Encoding as entropy coding method. + + +Sliding Window +-------------- + +LZMA uses Sliding Window compression similar to LZ77 algorithm. + +LZMA stream must be decoded to the sequence that consists +of MATCHES and LITERALS: + + - a LITERAL is a 8-bit character (one byte). + The decoder just puts that LITERAL to the uncompressed stream. + + - a MATCH is a pair of two numbers (DISTANCE-LENGTH pair). + The decoder takes one byte exactly "DISTANCE" characters behind + current position in the uncompressed stream and puts it to + uncompressed stream. The decoder must repeat it "LENGTH" times. + +The "DISTANCE" can not be larger than dictionary size. +And the "DISTANCE" can not be larger than the number of bytes in +the uncompressed stream that were decoded before that match. + +In this specification we use cyclic buffer to implement Sliding Window +for LZMA decoder: + +class COutWindow +{ + Byte *Buf; + UInt32 Pos; + UInt32 Size; + bool IsFull; + +public: + unsigned TotalPos; + COutStream OutStream; + + COutWindow(): Buf(NULL) {} + ~COutWindow() { delete []Buf; } + + void Create(UInt32 dictSize) + { + Buf = new Byte[dictSize]; + Pos = 0; + Size = dictSize; + IsFull = false; + TotalPos = 0; + } + + void PutByte(Byte b) + { + TotalPos++; + Buf[Pos++] = b; + if (Pos == Size) + { + Pos = 0; + IsFull = true; + } + OutStream.WriteByte(b); + } + + Byte GetByte(UInt32 dist) const + { + return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos]; + } + + void CopyMatch(UInt32 dist, unsigned len) + { + for (; len > 0; len--) + PutByte(GetByte(dist)); + } + + bool CheckDistance(UInt32 dist) const + { + return dist <= Pos || IsFull; + } + + bool IsEmpty() const + { + return Pos == 0 && !IsFull; + } +}; + + +In another implementation it's possible to use one buffer that contains +Sliding Window and the whole data stream after uncompressing. + + +Range Decoder +------------- + +LZMA algorithm uses Range Encoding (1) as entropy coding method. + +LZMA stream contains just one very big number in big-endian encoding. +LZMA decoder uses the Range Decoder to extract a sequence of binary +symbols from that big number. + +The state of the Range Decoder: + +struct CRangeDecoder +{ + UInt32 Range; + UInt32 Code; + InputStream *InStream; + + bool Corrupted; +} + +The notes about UInt32 type for the "Range" and "Code" variables: + + It's possible to use 64-bit (unsigned or signed) integer type + for the "Range" and the "Code" variables instead of 32-bit unsigned, + but some additional code must be used to truncate the values to + low 32-bits after some operations. + + If the programming language does not support 32-bit unsigned integer type + (like in case of JAVA language), it's possible to use 32-bit signed integer, + but some code must be changed. For example, it's required to change the code + that uses comparison operations for UInt32 variables in this specification. + +The Range Decoder can be in some states that can be treated as +"Corruption" in LZMA stream. The Range Decoder uses the variable "Corrupted": + + (Corrupted == false), if the Range Decoder has not detected any corruption. + (Corrupted == true), if the Range Decoder has detected some corruption. + +The reference LZMA Decoder ignores the value of the "Corrupted" variable. +So it continues to decode the stream, even if the corruption can be detected +in the Range Decoder. To provide the full compatibility with output of the +reference LZMA Decoder, another LZMA Decoder implementations must also +ignore the value of the "Corrupted" variable. + +The LZMA Encoder is required to create only such LZMA streams, that will not +lead the Range Decoder to states, where the "Corrupted" variable is set to true. + +The Range Decoder reads first 5 bytes from input stream to initialize +the state: + +bool CRangeDecoder::Init() +{ + Corrupted = false; + Range = 0xFFFFFFFF; + Code = 0; + + Byte b = InStream->ReadByte(); + + for (int i = 0; i < 4; i++) + Code = (Code << 8) | InStream->ReadByte(); + + if (b != 0 || Code == Range) + Corrupted = true; + return b == 0; +} + +The LZMA Encoder always writes ZERO in initial byte of compressed stream. +That scheme allows to simplify the code of the Range Encoder in the +LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must +stop decoding and report error. + +After the last bit of data was decoded by Range Decoder, the value of the +"Code" variable must be equal to 0. The LZMA Decoder must check it by +calling the IsFinishedOK() function: + + bool IsFinishedOK() const { return Code == 0; } + +If there is corruption in data stream, there is big probability that +the "Code" value will be not equal to 0 in the Finish() function. So that +check in the IsFinishedOK() function provides very good feature for +corruption detection. + +The value of the "Range" variable before each bit decoding can not be smaller +than ((UInt32)1 << 24). The Normalize() function keeps the "Range" value in +described range. + +#define kTopValue ((UInt32)1 << 24) + +void CRangeDecoder::Normalize() +{ + if (Range < kTopValue) + { + Range <<= 8; + Code = (Code << 8) | InStream->ReadByte(); + } +} + +Notes: if the size of the "Code" variable is larger than 32 bits, it's +required to keep only low 32 bits of the "Code" variable after the change +in Normalize() function. + +If the LZMA Stream is not corrupted, the value of the "Code" variable is +always smaller than value of the "Range" variable. +But the Range Decoder ignores some types of corruptions, so the value of +the "Code" variable can be equal or larger than value of the "Range" variable +for some "Corrupted" archives. + + +LZMA uses Range Encoding only with binary symbols of two types: + 1) binary symbols with fixed and equal probabilities (direct bits) + 2) binary symbols with predicted probabilities + +The DecodeDirectBits() function decodes the sequence of direct bits: + +UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits) +{ + UInt32 res = 0; + do + { + Range >>= 1; + Code -= Range; + UInt32 t = 0 - ((UInt32)Code >> 31); + Code += Range & t; + + if (Code == Range) + Corrupted = true; + + Normalize(); + res <<= 1; + res += t + 1; + } + while (--numBits); + return res; +} + + +The Bit Decoding with Probability Model +--------------------------------------- + +The task of Bit Probability Model is to estimate probabilities of binary +symbols. And then it provides the Range Decoder with that information. +The better prediction provides better compression ratio. +The Bit Probability Model uses statistical data of previous decoded +symbols. + +That estimated probability is presented as 11-bit unsigned integer value +that represents the probability of symbol "0". + +#define kNumBitModelTotalBits 11 + +Mathematical probabilities can be presented with the following formulas: + probability(symbol_0) = prob / 2048. + probability(symbol_1) = 1 - Probability(symbol_0) = + = 1 - prob / 2048 = + = (2048 - prob) / 2048 +where the "prob" variable contains 11-bit integer probability counter. + +It's recommended to use 16-bit unsigned integer type, to store these 11-bit +probability values: + +typedef UInt16 CProb; + +Each probability value must be initialized with value ((1 << 11) / 2), +that represents the state, where probabilities of symbols 0 and 1 +are equal to 0.5: + +#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2) + +The INIT_PROBS macro is used to initialize the array of CProb variables: + +#define INIT_PROBS(p) \ + { for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; } + + +The DecodeBit() function decodes one bit. +The LZMA decoder provides the pointer to CProb variable that contains +information about estimated probability for symbol 0 and the Range Decoder +updates that CProb variable after decoding. The Range Decoder increases +estimated probability of the symbol that was decoded: + +#define kNumMoveBits 5 + +unsigned CRangeDecoder::DecodeBit(CProb *prob) +{ + unsigned v = *prob; + UInt32 bound = (Range >> kNumBitModelTotalBits) * v; + unsigned symbol; + if (Code < bound) + { + v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits; + Range = bound; + symbol = 0; + } + else + { + v -= v >> kNumMoveBits; + Code -= bound; + Range -= bound; + symbol = 1; + } + *prob = (CProb)v; + Normalize(); + return symbol; +} + + +The Binary Tree of bit model counters +------------------------------------- + +LZMA uses a tree of Bit model variables to decode symbol that needs +several bits for storing. There are two versions of such trees in LZMA: + 1) the tree that decodes bits from high bit to low bit (the normal scheme). + 2) the tree that decodes bits from low bit to high bit (the reverse scheme). + +Each binary tree structure supports different size of decoded symbol +(the size of binary sequence that contains value of symbol). +If that size of decoded symbol is "NumBits" bits, the tree structure +uses the array of (2 << NumBits) counters of CProb type. +But only ((2 << NumBits) - 1) items are used by encoder and decoder. +The first item (the item with index equal to 0) in array is unused. +That scheme with unused array's item allows to simplify the code. + +unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc) +{ + unsigned m = 1; + unsigned symbol = 0; + for (unsigned i = 0; i < numBits; i++) + { + unsigned bit = rc->DecodeBit(&probs[m]); + m <<= 1; + m += bit; + symbol |= (bit << i); + } + return symbol; +} + +template +class CBitTreeDecoder +{ + CProb Probs[(unsigned)1 << NumBits]; + +public: + + void Init() + { + INIT_PROBS(Probs); + } + + unsigned Decode(CRangeDecoder *rc) + { + unsigned m = 1; + for (unsigned i = 0; i < NumBits; i++) + m = (m << 1) + rc->DecodeBit(&Probs[m]); + return m - ((unsigned)1 << NumBits); + } + + unsigned ReverseDecode(CRangeDecoder *rc) + { + return BitTreeReverseDecode(Probs, NumBits, rc); + } +}; + + +LZ part of LZMA +--------------- + +LZ part of LZMA describes details about the decoding of MATCHES and LITERALS. + + +The Literal Decoding +-------------------- + +The LZMA Decoder uses (1 << (lc + lp)) tables with CProb values, where +each table contains 0x300 CProb values: + + CProb *LitProbs; + + void CreateLiterals() + { + LitProbs = new CProb[(UInt32)0x300 << (lc + lp)]; + } + + void InitLiterals() + { + UInt32 num = (UInt32)0x300 << (lc + lp); + for (UInt32 i = 0; i < num; i++) + LitProbs[i] = PROB_INIT_VAL; + } + +To select the table for decoding it uses the context that consists of +(lc) high bits from previous literal and (lp) low bits from value that +represents current position in outputStream. + +If (State > 7), the Literal Decoder also uses "matchByte" that represents +the byte in OutputStream at position the is the DISTANCE bytes before +current position, where the DISTANCE is the distance in DISTANCE-LENGTH pair +of latest decoded match. + +The following code decodes one literal and puts it to Sliding Window buffer: + + void DecodeLiteral(unsigned state, UInt32 rep0) + { + unsigned prevByte = 0; + if (!OutWindow.IsEmpty()) + prevByte = OutWindow.GetByte(1); + + unsigned symbol = 1; + unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc)); + CProb *probs = &LitProbs[(UInt32)0x300 * litState]; + + if (state >= 7) + { + unsigned matchByte = OutWindow.GetByte(rep0 + 1); + do + { + unsigned matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + break; + } + while (symbol < 0x100); + } + while (symbol < 0x100) + symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]); + OutWindow.PutByte((Byte)(symbol - 0x100)); + } + + +The match length decoding +------------------------- + +The match length decoder returns normalized (zero-based value) +length of match. That value can be converted to real length of the match +with the following code: + +#define kMatchMinLen 2 + + matchLen = len + kMatchMinLen; + +The match length decoder can return the values from 0 to 271. +And the corresponded real match length values can be in the range +from 2 to 273. + +The following scheme is used for the match length encoding: + + Binary encoding Binary Tree structure Zero-based match length + sequence (binary + decimal): + + 0 xxx LowCoder[posState] xxx + 1 0 yyy MidCoder[posState] yyy + 8 + 1 1 zzzzzzzz HighCoder zzzzzzzz + 16 + +LZMA uses bit model variable "Choice" to decode the first selection bit. + +If the first selection bit is equal to 0, the decoder uses binary tree + LowCoder[posState] to decode 3-bit zero-based match length (xxx). + +If the first selection bit is equal to 1, the decoder uses bit model + variable "Choice2" to decode the second selection bit. + + If the second selection bit is equal to 0, the decoder uses binary tree + MidCoder[posState] to decode 3-bit "yyy" value, and zero-based match + length is equal to (yyy + 8). + + If the second selection bit is equal to 1, the decoder uses binary tree + HighCoder to decode 8-bit "zzzzzzzz" value, and zero-based + match length is equal to (zzzzzzzz + 16). + +LZMA uses "posState" value as context to select the binary tree +from LowCoder and MidCoder binary tree arrays: + + unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); + +The full code of the length decoder: + +class CLenDecoder +{ + CProb Choice; + CProb Choice2; + CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax]; + CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax]; + CBitTreeDecoder<8> HighCoder; + +public: + + void Init() + { + Choice = PROB_INIT_VAL; + Choice2 = PROB_INIT_VAL; + HighCoder.Init(); + for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++) + { + LowCoder[i].Init(); + MidCoder[i].Init(); + } + } + + unsigned Decode(CRangeDecoder *rc, unsigned posState) + { + if (rc->DecodeBit(&Choice) == 0) + return LowCoder[posState].Decode(rc); + if (rc->DecodeBit(&Choice2) == 0) + return 8 + MidCoder[posState].Decode(rc); + return 16 + HighCoder.Decode(rc); + } +}; + +The LZMA decoder uses two instances of CLenDecoder class. +The first instance is for the matches of "Simple Match" type, +and the second instance is for the matches of "Rep Match" type: + + CLenDecoder LenDecoder; + CLenDecoder RepLenDecoder; + + +The match distance decoding +--------------------------- + +LZMA supports dictionary sizes up to 4 GiB minus 1. +The value of match distance (decoded by distance decoder) can be +from 1 to 2^32. But the distance value that is equal to 2^32 is used to +indicate the "End of stream" marker. So real largest match distance +that is used for LZ-window match is (2^32 - 1). + +LZMA uses normalized match length (zero-based length) +to calculate the context state "lenState" do decode the distance value: + +#define kNumLenToPosStates 4 + + unsigned lenState = len; + if (lenState > kNumLenToPosStates - 1) + lenState = kNumLenToPosStates - 1; + +The distance decoder returns the "dist" value that is zero-based value +of match distance. The real match distance can be calculated with the +following code: + + matchDistance = dist + 1; + +The state of the distance decoder and the initialization code: + + #define kEndPosModelIndex 14 + #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + #define kNumAlignBits 4 + + CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates]; + CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex]; + CBitTreeDecoder AlignDecoder; + + void InitDist() + { + for (unsigned i = 0; i < kNumLenToPosStates; i++) + PosSlotDecoder[i].Init(); + AlignDecoder.Init(); + INIT_PROBS(PosDecoders); + } + +At first stage the distance decoder decodes 6-bit "posSlot" value with bit +tree decoder from PosSlotDecoder array. It's possible to get 2^6=64 different +"posSlot" values. + + unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); + +The encoding scheme for distance value is shown in the following table: + +posSlot (decimal) / + zero-based distance (binary) + 0 0 + 1 1 + 2 10 + 3 11 + + 4 10 x + 5 11 x + 6 10 xx + 7 11 xx + 8 10 xxx + 9 11 xxx +10 10 xxxx +11 11 xxxx +12 10 xxxxx +13 11 xxxxx + +14 10 yy zzzz +15 11 yy zzzz +16 10 yyy zzzz +17 11 yyy zzzz +... +62 10 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz +63 11 yyyyyyyyyyyyyyyyyyyyyyyyyy zzzz + +where + "x ... x" means the sequence of binary symbols encoded with binary tree and + "Reverse" scheme. It uses separated binary tree for each posSlot from 4 to 13. + "y" means direct bit encoded with range coder. + "zzzz" means the sequence of four binary symbols encoded with binary + tree with "Reverse" scheme, where one common binary tree "AlignDecoder" + is used for all posSlot values. + +If (posSlot < 4), the "dist" value is equal to posSlot value. + +If (posSlot >= 4), the decoder uses "posSlot" value to calculate the value of + the high bits of "dist" value and the number of the low bits. + + If (4 <= posSlot < kEndPosModelIndex), the decoder uses bit tree decoders. + (one separated bit tree decoder per one posSlot value) and "Reverse" scheme. + In this implementation we use one CProb array "PosDecoders" that contains + all CProb variables for all these bit decoders. + + if (posSlot >= kEndPosModelIndex), the middle bits are decoded as direct + bits from RangeDecoder and the low 4 bits are decoded with a bit tree + decoder "AlignDecoder" with "Reverse" scheme. + +The code to decode zero-based match distance: + + unsigned DecodeDistance(unsigned len) + { + unsigned lenState = len; + if (lenState > kNumLenToPosStates - 1) + lenState = kNumLenToPosStates - 1; + + unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec); + if (posSlot < 4) + return posSlot; + + unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1); + UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec); + else + { + dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits; + dist += AlignDecoder.ReverseDecode(&RangeDec); + } + return dist; + } + + + +LZMA Decoding modes +------------------- + +There are 2 types of LZMA streams: + +1) The stream with "End of stream" marker. +2) The stream without "End of stream" marker. + +And the LZMA Decoder supports 3 modes of decoding: + +1) The unpack size is undefined. The LZMA decoder stops decoding after + getting "End of stream" marker. + The input variables for that case: + + markerIsMandatory = true + unpackSizeDefined = false + unpackSize contains any value + +2) The unpack size is defined and LZMA decoder supports both variants, + where the stream can contain "End of stream" marker or the stream is + finished without "End of stream" marker. The LZMA decoder must detect + any of these situations. + The input variables for that case: + + markerIsMandatory = false + unpackSizeDefined = true + unpackSize contains unpack size + +3) The unpack size is defined and the LZMA stream must contain + "End of stream" marker + The input variables for that case: + + markerIsMandatory = true + unpackSizeDefined = true + unpackSize contains unpack size + + +The main loop of decoder +------------------------ + +The main loop of LZMA decoder: + +Initialize the LZMA state. +loop +{ + // begin of loop + Check "end of stream" conditions. + Decode Type of MATCH / LITERAL. + If it's LITERAL, decode LITERAL value and put the LITERAL to Window. + If it's MATCH, decode the length of match and the match distance. + Check error conditions, check end of stream conditions and copy + the sequence of match bytes from sliding window to current position + in window. + Go to begin of loop +} + +The reference implementation of LZMA decoder uses "unpackSize" variable +to keep the number of remaining bytes in output stream. So it reduces +"unpackSize" value after each decoded LITERAL or MATCH. + +The following code contains the "end of stream" condition check at the start +of the loop: + + if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory) + if (RangeDec.IsFinishedOK()) + return LZMA_RES_FINISHED_WITHOUT_MARKER; + +LZMA uses three types of matches: + +1) "Simple Match" - the match with distance value encoded with bit models. + +2) "Rep Match" - the match that uses the distance from distance + history table. + +3) "Short Rep Match" - the match of single byte length, that uses the latest + distance from distance history table. + +The LZMA decoder keeps the history of latest 4 match distances that were used +by decoder. That set of 4 variables contains zero-based match distances and +these variables are initialized with zero values: + + UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + +The LZMA decoder uses binary model variables to select type of MATCH or LITERAL: + +#define kNumStates 12 +#define kNumPosBitsMax 4 + + CProb IsMatch[kNumStates << kNumPosBitsMax]; + CProb IsRep[kNumStates]; + CProb IsRepG0[kNumStates]; + CProb IsRepG1[kNumStates]; + CProb IsRepG2[kNumStates]; + CProb IsRep0Long[kNumStates << kNumPosBitsMax]; + +The decoder uses "state" variable value to select exact variable +from "IsRep", "IsRepG0", "IsRepG1" and "IsRepG2" arrays. +The "state" variable can get the value from 0 to 11. +Initial value for "state" variable is zero: + + unsigned state = 0; + +The "state" variable is updated after each LITERAL or MATCH with one of the +following functions: + +unsigned UpdateState_Literal(unsigned state) +{ + if (state < 4) return 0; + else if (state < 10) return state - 3; + else return state - 6; +} +unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; } +unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; } +unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; } + +The decoder calculates "state2" variable value to select exact variable from +"IsMatch" and "IsRep0Long" arrays: + +unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1); +unsigned state2 = (state << kNumPosBitsMax) + posState; + +The decoder uses the following code flow scheme to select exact +type of LITERAL or MATCH: + +IsMatch[state2] decode + 0 - the Literal + 1 - the Match + IsRep[state] decode + 0 - Simple Match + 1 - Rep Match + IsRepG0[state] decode + 0 - the distance is rep0 + IsRep0Long[state2] decode + 0 - Short Rep Match + 1 - Rep Match 0 + 1 - + IsRepG1[state] decode + 0 - Rep Match 1 + 1 - + IsRepG2[state] decode + 0 - Rep Match 2 + 1 - Rep Match 3 + + +LITERAL symbol +-------------- +If the value "0" was decoded with IsMatch[state2] decoding, we have "LITERAL" type. + +At first the LZMA decoder must check that it doesn't exceed +specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Then it decodes literal value and puts it to sliding window: + + DecodeLiteral(state, rep0); + +Then the decoder must update the "state" value and "unpackSize" value; + + state = UpdateState_Literal(state); + unpackSize--; + +Then the decoder must go to the begin of main loop to decode next Match or Literal. + + +Simple Match +------------ + +If the value "1" was decoded with IsMatch[state2] decoding, +we have the "Simple Match" type. + +The distance history table is updated with the following scheme: + + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + +The zero-based length is decoded with "LenDecoder": + + len = LenDecoder.Decode(&RangeDec, posState); + +The state is update with UpdateState_Match function: + + state = UpdateState_Match(state); + +and the new "rep0" value is decoded with DecodeDistance: + + rep0 = DecodeDistance(len); + +That "rep0" will be used as zero-based distance for current match. + +If the value of "rep0" is equal to 0xFFFFFFFF, it means that we have +"End of stream" marker, so we can stop decoding and check finishing +condition in Range Decoder: + + if (rep0 == 0xFFFFFFFF) + return RangeDec.IsFinishedOK() ? + LZMA_RES_FINISHED_WITH_MARKER : + LZMA_RES_ERROR; + +If uncompressed size is defined, LZMA decoder must check that it doesn't +exceed that specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Also the decoder must check that "rep0" value is not larger than dictionary size +and is not larger than the number of already decoded bytes: + + if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0)) + return LZMA_RES_ERROR; + +Then the decoder must copy match bytes as described in +"The match symbols copying" section. + + +Rep Match +--------- + +If the LZMA decoder has decoded the value "1" with IsRep[state] variable, +we have "Rep Match" type. + +At first the LZMA decoder must check that it doesn't exceed +specified uncompressed size: + + if (unpackSizeDefined && unpackSize == 0) + return LZMA_RES_ERROR; + +Also the decoder must return error, if the LZ window is empty: + + if (OutWindow.IsEmpty()) + return LZMA_RES_ERROR; + +If the match type is "Rep Match", the decoder uses one of the 4 variables of +distance history table to get the value of distance for current match. +And there are 4 corresponding ways of decoding flow. + +The decoder updates the distance history with the following scheme +depending from type of match: + +- "Rep Match 0" or "Short Rep Match": + ; LZMA doesn't update the distance history + +- "Rep Match 1": + UInt32 dist = rep1; + rep1 = rep0; + rep0 = dist; + +- "Rep Match 2": + UInt32 dist = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = dist; + +- "Rep Match 3": + UInt32 dist = rep3; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = dist; + +Then the decoder decodes exact subtype of "Rep Match" using "IsRepG0", "IsRep0Long", +"IsRepG1", "IsRepG2". + +If the subtype is "Short Rep Match", the decoder updates the state, puts +the one byte from window to current position in window and goes to next +MATCH/LITERAL symbol (the begin of main loop): + + state = UpdateState_ShortRep(state); + OutWindow.PutByte(OutWindow.GetByte(rep0 + 1)); + unpackSize--; + continue; + +In other cases (Rep Match 0/1/2/3), it decodes the zero-based +length of match with "RepLenDecoder" decoder: + + len = RepLenDecoder.Decode(&RangeDec, posState); + +Then it updates the state: + + state = UpdateState_Rep(state); + +Then the decoder must copy match bytes as described in +"The Match symbols copying" section. + + +The match symbols copying +------------------------- + +If we have the match (Simple Match or Rep Match 0/1/2/3), the decoder must +copy the sequence of bytes with calculated match distance and match length. +If uncompressed size is defined, LZMA decoder must check that it doesn't +exceed that specified uncompressed size: + + len += kMatchMinLen; + bool isError = false; + if (unpackSizeDefined && unpackSize < len) + { + len = (unsigned)unpackSize; + isError = true; + } + OutWindow.CopyMatch(rep0 + 1, len); + unpackSize -= len; + if (isError) + return LZMA_RES_ERROR; + +Then the decoder must go to the begin of main loop to decode next MATCH or LITERAL. + + + +NOTES +----- + +This specification doesn't describe the variant of decoder implementation +that supports partial decoding. Such partial decoding case can require some +changes in "end of stream" condition checks code. Also such code +can use additional status codes, returned by decoder. + +This specification uses C++ code with templates to simplify describing. +The optimized version of LZMA decoder doesn't need templates. +Such optimized version can use just two arrays of CProb variables: + 1) The dynamic array of CProb variables allocated for the Literal Decoder. + 2) The one common array that contains all other CProb variables. + + +References: + +1. G. N. N. Martin, Range encoding: an algorithm for removing redundancy + from a digitized message, Video & Data Recording Conference, + Southampton, UK, July 24-27, 1979. diff --git a/3rdparty/lzma-21.03beta/DOC/lzma.txt b/3rdparty/lzma-21.03beta/DOC/lzma.txt new file mode 100644 index 0000000..a65988f --- /dev/null +++ b/3rdparty/lzma-21.03beta/DOC/lzma.txt @@ -0,0 +1,328 @@ +LZMA compression +---------------- +Version: 9.35 + +This file describes LZMA encoding and decoding functions written in C language. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + +Note: you can read also LZMA Specification (lzma-specification.txt from LZMA SDK) + +Also you can look source code for LZMA encoding and decoding: + C/Util/Lzma/LzmaUtil.c + + +LZMA compressed file format +--------------------------- +Offset Size Description + 0 1 Special LZMA properties (lc,lp, pb in encoded form) + 1 4 Dictionary size (little endian) + 5 8 Uncompressed size (little endian). -1 means unknown size + 13 Compressed data + + + +ANSI-C LZMA Decoder +~~~~~~~~~~~~~~~~~~~ + +Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. +If you want to use old interfaces you can download previous version of LZMA SDK +from sourceforge.net site. + +To use ANSI-C LZMA Decoder you need the following files: +1) LzmaDec.h + LzmaDec.c + 7zTypes.h + Precomp.h + Compiler.h + +Look example code: + C/Util/Lzma/LzmaUtil.c + + +Memory requirements for LZMA decoding +------------------------------------- + +Stack usage of LZMA decoding function for local variables is not +larger than 200-400 bytes. + +LZMA Decoder uses dictionary buffer and internal state structure. +Internal state structure consumes + state_size = (4 + (1.5 << (lc + lp))) KB +by default (lc=3, lp=0), state_size = 16 KB. + + +How To decompress data +---------------------- + +LZMA Decoder (ANSI-C version) now supports 2 interfaces: +1) Single-call Decompressing +2) Multi-call State Decompressing (zlib-like interface) + +You must use external allocator: +Example: +void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } +void SzFree(void *p, void *address) { p = p; free(address); } +ISzAlloc alloc = { SzAlloc, SzFree }; + +You can use p = p; operator to disable compiler warnings. + + +Single-call Decompressing +------------------------- +When to use: RAM->RAM decompressing +Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h +Compile defines: no defines +Memory Requirements: + - Input buffer: compressed size + - Output buffer: uncompressed size + - LZMA Internal Structures: state_size (16 KB for default settings) + +Interface: + int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + propData - LZMA properties (5 bytes) + propSize - size of propData buffer (5 bytes) + finishMode - It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + You can use LZMA_FINISH_END, when you know that + current output buffer covers last bytes of stream. + alloc - Memory allocator. + + Out: + destLen - processed output size + srcLen - processed input size + + Output: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + If LZMA decoder sees end_marker before reaching output limit, it returns OK result, + and output value of destLen will be less than output buffer size limit. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + + +Multi-call State Decompressing (zlib-like interface) +---------------------------------------------------- + +When to use: file->file decompressing +Compile files: LzmaDec.h + LzmaDec.c + 7zTypes.h + +Memory Requirements: + - Buffer for input stream: any size (for example, 16 KB) + - Buffer for output stream: any size (for example, 16 KB) + - LZMA Internal Structures: state_size (16 KB for default settings) + - LZMA dictionary (dictionary size is encoded in LZMA properties header) + +1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: + unsigned char header[LZMA_PROPS_SIZE + 8]; + ReadFile(inFile, header, sizeof(header) + +2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties + + CLzmaDec state; + LzmaDec_Constr(&state); + res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); + if (res != SZ_OK) + return res; + +3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop + + LzmaDec_Init(&state); + for (;;) + { + ... + int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); + ... + } + + +4) Free all allocated structures + LzmaDec_Free(&state, &g_Alloc); + +Look example code: + C/Util/Lzma/LzmaUtil.c + + +How To compress data +-------------------- + +Compile files: + 7zTypes.h + Threads.h + LzmaEnc.h + LzmaEnc.c + LzFind.h + LzFind.c + LzFindMt.h + LzFindMt.c + LzHash.h + +Memory Requirements: + - (dictSize * 11.5 + 6 MB) + state_size + +Lzma Encoder can use two memory allocators: +1) alloc - for small arrays. +2) allocBig - for big arrays. + +For example, you can use Large RAM Pages (2 MB) in allocBig allocator for +better compression speed. Note that Windows has bad implementation for +Large RAM Pages. +It's OK to use same allocator for alloc and allocBig. + + +Single-call Compression with callbacks +-------------------------------------- + +Look example code: + C/Util/Lzma/LzmaUtil.c + +When to use: file->file compressing + +1) you must implement callback structures for interfaces: +ISeqInStream +ISeqOutStream +ICompressProgress +ISzAlloc + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + CFileSeqInStream inStream; + CFileSeqOutStream outStream; + + inStream.funcTable.Read = MyRead; + inStream.file = inFile; + outStream.funcTable.Write = MyWrite; + outStream.file = outFile; + + +2) Create CLzmaEncHandle object; + + CLzmaEncHandle enc; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + +3) initialize CLzmaEncProps properties; + + LzmaEncProps_Init(&props); + + Then you can change some properties in that structure. + +4) Send LZMA properties to LZMA Encoder + + res = LzmaEnc_SetProps(enc, &props); + +5) Write encoded properties to header + + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + UInt64 fileSize; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + fileSize = MyGetFileLength(inFile); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + MyWriteFileAndCheck(outFile, header, headerSize) + +6) Call encoding function: + res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, + NULL, &g_Alloc, &g_Alloc); + +7) Destroy LZMA Encoder Object + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + + +If callback function return some error code, LzmaEnc_Encode also returns that code +or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. + + +Single-call RAM->RAM Compression +-------------------------------- + +Single-call RAM->RAM Compression is similar to Compression with callbacks, +but you provide pointers to buffers instead of pointers to stream callbacks: + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) + + + +Defines +------- + +_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. + +_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for + some structures will be doubled in that case. + +_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. + +_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. + + +_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder. + + +C++ LZMA Encoder/Decoder +~~~~~~~~~~~~~~~~~~~~~~~~ +C++ LZMA code use COM-like interfaces. So if you want to use it, +you can study basics of COM/OLE. +C++ LZMA code is just wrapper over ANSI-C code. + + +C++ Notes +~~~~~~~~~~~~~~~~~~~~~~~~ +If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), +you must check that you correctly work with "new" operator. +7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. +So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: +operator new(size_t size) +{ + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} +If you use MSCV that throws exception for "new" operator, you can compile without +"NewHandler.cpp". So standard exception will be used. Actually some code of +7-Zip catches any exception in internal code and converts it to HRESULT code. +So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/CRC.java b/3rdparty/lzma-21.03beta/Java/SevenZip/CRC.java new file mode 100644 index 0000000..c55e33c --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/CRC.java @@ -0,0 +1,52 @@ +// SevenZip/CRC.java + +package SevenZip; + +public class CRC +{ + static public int[] Table = new int[256]; + + static + { + for (int i = 0; i < 256; i++) + { + int r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >>> 1) ^ 0xEDB88320; + else + r >>>= 1; + Table[i] = r; + } + } + + int _value = -1; + + public void Init() + { + _value = -1; + } + + public void Update(byte[] data, int offset, int size) + { + for (int i = 0; i < size; i++) + _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); + } + + public void Update(byte[] data) + { + int size = data.length; + for (int i = 0; i < size; i++) + _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); + } + + public void UpdateByte(int b) + { + _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); + } + + public int GetDigest() + { + return _value ^ (-1); + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/BinTree.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/BinTree.java new file mode 100644 index 0000000..e2074e9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/BinTree.java @@ -0,0 +1,382 @@ +// LZ.BinTree + +package SevenZip.Compression.LZ; +import java.io.IOException; + + +public class BinTree extends InWindow +{ + int _cyclicBufferPos; + int _cyclicBufferSize = 0; + int _matchMaxLen; + + int[] _son; + int[] _hash; + + int _cutValue = 0xFF; + int _hashMask; + int _hashSizeSum = 0; + + boolean HASH_ARRAY = true; + + static final int kHash2Size = 1 << 10; + static final int kHash3Size = 1 << 16; + static final int kBT2HashSize = 1 << 16; + static final int kStartMaxLen = 1; + static final int kHash3Offset = kHash2Size; + static final int kEmptyHashValue = 0; + static final int kMaxValForNormalize = (1 << 30) - 1; + + int kNumHashDirectBytes = 0; + int kMinMatchCheck = 4; + int kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + + + + public void Init() throws IOException + { + super.Init(); + for (int i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public void MovePos() throws IOException + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + super.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + + + + + + + + public boolean Create(int historySize, int keepAddBufferBefore, + int matchMaxLen, int keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + return false; + _cutValue = 16 + (matchMaxLen >> 1); + + int windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + int cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + int hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new int [_hashSizeSum = hs]; + return true; + } + public int GetMatches(int[] distances) throws IOException + { + int lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + int offset = 0; + int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + int cur = _bufferOffset + _pos; + int maxLen = kStartMaxLen; // to avoid items for len < hashSize; + int hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); + hash2Value = temp & (kHash2Size - 1); + temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; + } + else + hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); + + int curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + int curMatch2 = _hash[hash2Value]; + int curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + int ptr0 = (_cyclicBufferPos << 1) + 1; + int ptr1 = (_cyclicBufferPos << 1); + + int len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + int count = _cutValue; + + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + int delta = _pos - curMatch; + int cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + int pby1 = _bufferOffset + curMatch; + int len = Math.min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(int num) throws IOException + { + do + { + int lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + int cur = _bufferOffset + _pos; + + int hashValue; + + if (HASH_ARRAY) + { + int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); + int hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); + int hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; + } + else + hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); + + int curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + int ptr0 = (_cyclicBufferPos << 1) + 1; + int ptr1 = (_cyclicBufferPos << 1); + + int len0, len1; + len0 = len1 = kNumHashDirectBytes; + + int count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + int delta = _pos - curMatch; + int cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + int pby1 = _bufferOffset + curMatch; + int len = Math.min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(int[] items, int numItems, int subValue) + { + for (int i = 0; i < numItems; i++) + { + int value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + int subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets(subValue); + } + + public void SetCutValue(int cutValue) { _cutValue = cutValue; } + + private static final int[] CrcTable = new int[256]; + + static + { + for (int i = 0; i < 256; i++) + { + int r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >>> 1) ^ 0xEDB88320; + else + r >>>= 1; + CrcTable[i] = r; + } + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/InWindow.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/InWindow.java new file mode 100644 index 0000000..c9efe60 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/InWindow.java @@ -0,0 +1,131 @@ +// LZ.InWindow + +package SevenZip.Compression.LZ; + +import java.io.IOException; + +public class InWindow +{ + public byte[] _bufferBase; // pointer to buffer with data + java.io.InputStream _stream; + int _posLimit; // offset (from _buffer) of first byte when new block reading must be done + boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + int _pointerToLastSafePosition; + + public int _bufferOffset; + + public int _blockSize; // Size of Allocated memory block + public int _pos; // offset (from _buffer) of curent byte + int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public int _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + int offset = _bufferOffset + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + int numBytes = _bufferOffset + _streamPos - offset; + + // check negative offset ???? + for (int i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public void ReadBlock() throws IOException + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (0 - _bufferOffset) + _blockSize - _streamPos; + if (size == 0) + return; + int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); + if (numReadBytes == -1) + { + _posLimit = _streamPos; + int pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = _pointerToLastSafePosition - _bufferOffset; + + _streamEndWasReached = true; + return; + } + _streamPos += numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(java.io.InputStream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() throws IOException + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() throws IOException + { + _pos++; + if (_pos > _posLimit) + { + int pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public int GetMatchLen(int index, int distance, int limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + int pby = _bufferOffset + _pos + index; + + int i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public int GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(int subValue) + { + _bufferOffset += subValue; + _posLimit -= subValue; + _pos -= subValue; + _streamPos -= subValue; + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/OutWindow.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/OutWindow.java new file mode 100644 index 0000000..2fd2832 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZ/OutWindow.java @@ -0,0 +1,85 @@ +// LZ.OutWindow + +package SevenZip.Compression.LZ; + +import java.io.IOException; + +public class OutWindow +{ + byte[] _buffer; + int _pos; + int _windowSize = 0; + int _streamPos; + java.io.OutputStream _stream; + + public void Create(int windowSize) + { + if (_buffer == null || _windowSize != windowSize) + _buffer = new byte[windowSize]; + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void SetStream(java.io.OutputStream stream) throws IOException + { + ReleaseStream(); + _stream = stream; + } + + public void ReleaseStream() throws IOException + { + Flush(); + _stream = null; + } + + public void Init(boolean solid) + { + if (!solid) + { + _streamPos = 0; + _pos = 0; + } + } + + public void Flush() throws IOException + { + int size = _pos - _streamPos; + if (size == 0) + return; + _stream.write(_buffer, _streamPos, size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(int distance, int len) throws IOException + { + int pos = _pos - distance - 1; + if (pos < 0) + pos += _windowSize; + for (; len != 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) throws IOException + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(int distance) + { + int pos = _pos - distance - 1; + if (pos < 0) + pos += _windowSize; + return _buffer[pos]; + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Base.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Base.java new file mode 100644 index 0000000..b4f2fb5 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Base.java @@ -0,0 +1,88 @@ +// Base.java + +package SevenZip.Compression.LZMA; + +public class Base +{ + public static final int kNumRepDistances = 4; + public static final int kNumStates = 12; + + public static final int StateInit() + { + return 0; + } + + public static final int StateUpdateChar(int index) + { + if (index < 4) + return 0; + if (index < 10) + return index - 3; + return index - 6; + } + + public static final int StateUpdateMatch(int index) + { + return (index < 7 ? 7 : 10); + } + + public static final int StateUpdateRep(int index) + { + return (index < 7 ? 8 : 11); + } + + public static final int StateUpdateShortRep(int index) + { + return (index < 7 ? 9 : 11); + } + + public static final boolean StateIsCharState(int index) + { + return index < 7; + } + + public static final int kNumPosSlotBits = 6; + public static final int kDicLogSizeMin = 0; + // public static final int kDicLogSizeMax = 28; + // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; + + public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization + public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public static final int kMatchMinLen = 2; + + public static final int GetLenToPosState(int len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (int)(kNumLenToPosStates - 1); + } + + public static final int kNumAlignBits = 4; + public static final int kAlignTableSize = 1 << kNumAlignBits; + public static final int kAlignMask = (kAlignTableSize - 1); + + public static final int kStartPosModelIndex = 4; + public static final int kEndPosModelIndex = 14; + public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); + + public static final int kNumLitPosStatesBitsEncodingMax = 4; + public static final int kNumLitContextBitsMax = 8; + + public static final int kNumPosStatesBitsMax = 4; + public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public static final int kNumPosStatesBitsEncodingMax = 4; + public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public static final int kNumLowLenBits = 3; + public static final int kNumMidLenBits = 3; + public static final int kNumHighLenBits = 8; + public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; + public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; + public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Decoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Decoder.java new file mode 100644 index 0000000..16ee249 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Decoder.java @@ -0,0 +1,329 @@ +package SevenZip.Compression.LZMA; + +import SevenZip.Compression.RangeCoder.BitTreeDecoder; +import SevenZip.Compression.LZMA.Base; +import SevenZip.Compression.LZ.OutWindow; +import java.io.IOException; + +public class Decoder +{ + class LenDecoder + { + short[] m_Choice = new short[2]; + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + int m_NumPosStates = 0; + + public void Create(int numPosStates) + { + for (; m_NumPosStates < numPosStates; m_NumPosStates++) + { + m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); + } + } + + public void Init() + { + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); + for (int posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_HighCoder.Init(); + } + + public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException + { + if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + int symbol = Base.kNumLowLenSymbols; + if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); + return symbol; + } + } + + class LiteralDecoder + { + class Decoder2 + { + short[] m_Decoders = new short[0x300]; + + public void Init() + { + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); + } + + public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException + { + int symbol = 1; + do + symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException + { + int symbol = 1; + do + { + int matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + int m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = (1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (int i = 0; i < numStates; i++) + m_Coders[i] = new Decoder2(); + } + + public void Init() + { + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + for (int i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + Decoder2 GetDecoder(int pos, byte prevByte) + { + return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; + } + } + + OutWindow m_OutWindow = new OutWindow(); + SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); + + short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; + short[] m_IsRepDecoders = new short[Base.kNumStates]; + short[] m_IsRepG0Decoders = new short[Base.kNumStates]; + short[] m_IsRepG1Decoders = new short[Base.kNumStates]; + short[] m_IsRepG2Decoders = new short[Base.kNumStates]; + short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + int m_DictionarySize = -1; + int m_DictionarySizeCheck = -1; + + int m_PosStateMask; + + public Decoder() + { + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + boolean SetDictionarySize(int dictionarySize) + { + if (dictionarySize < 0) + return false; + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); + m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); + } + return true; + } + + boolean SetLcLpPb(int lc, int lp, int pb) + { + if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) + return false; + m_LiteralDecoder.Create(lp, lc); + int numPosStates = 1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + return true; + } + + void Init() throws IOException + { + m_OutWindow.Init(false); + + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); + SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); + + m_LiteralDecoder.Init(); + int i; + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + m_RangeDecoder.Init(); + } + + public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, + long outSize) throws IOException + { + m_RangeDecoder.SetStream(inStream); + m_OutWindow.SetStream(outStream); + Init(); + + int state = Base.StateInit(); + int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + long nowPos64 = 0; + byte prevByte = 0; + while (outSize < 0 || nowPos64 < outSize) + { + int posState = (int)nowPos64 & m_PosStateMask; + if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) + { + LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); + if (!Base.StateIsCharState(state)) + prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); + else + prevByte = decoder2.DecodeNormal(m_RangeDecoder); + m_OutWindow.PutByte(prevByte); + state = Base.StateUpdateChar(state); + nowPos64++; + } + else + { + int len; + if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) + { + len = 0; + if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) + { + if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) + { + state = Base.StateUpdateShortRep(state); + len = 1; + } + } + else + { + int distance; + if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) + distance = rep1; + else + { + if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + if (len == 0) + { + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state = Base.StateUpdateRep(state); + } + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state = Base.StateUpdateMatch(state); + int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (posSlot >> 1) - 1; + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + if (rep0 < 0) + { + if (rep0 == -1) + break; + return false; + } + } + } + else + rep0 = posSlot; + } + if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) + { + // m_OutWindow.Flush(); + return false; + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + prevByte = m_OutWindow.GetByte(0); + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + return true; + } + + public boolean SetDecoderProperties(byte[] properties) + { + if (properties.length < 5) + return false; + int val = properties[0] & 0xFF; + int lc = val % 9; + int remainder = val / 9; + int lp = remainder % 5; + int pb = remainder / 5; + int dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); + if (!SetLcLpPb(lc, lp, pb)) + return false; + return SetDictionarySize(dictionarySize); + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Encoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Encoder.java new file mode 100644 index 0000000..e421810 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/LZMA/Encoder.java @@ -0,0 +1,1416 @@ +package SevenZip.Compression.LZMA; + +import SevenZip.Compression.RangeCoder.BitTreeEncoder; +import SevenZip.Compression.LZMA.Base; +import SevenZip.Compression.LZ.BinTree; +import SevenZip.ICodeProgress; +import java.io.IOException; + +public class Encoder +{ + public static final int EMatchFinderTypeBT2 = 0; + public static final int EMatchFinderTypeBT4 = 1; + + + + + static final int kIfinityPrice = 0xFFFFFFF; + + static byte[] g_FastPos = new byte[1 << 11]; + + static + { + int kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (int slotFast = 2; slotFast < kFastSlots; slotFast++) + { + int k = (1 << ((slotFast >> 1) - 1)); + for (int j = 0; j < k; j++, c++) + g_FastPos[c] = (byte)slotFast; + } + } + + static int GetPosSlot(int pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (g_FastPos[pos >> 10] + 20); + return (g_FastPos[pos >> 20] + 40); + } + + static int GetPosSlot2(int pos) + { + if (pos < (1 << 17)) + return (g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (g_FastPos[pos >> 16] + 32); + return (g_FastPos[pos >> 26] + 52); + } + + int _state = Base.StateInit(); + byte _previousByte; + int[] _repDistances = new int[Base.kNumRepDistances]; + + void BaseInit() + { + _state = Base.StateInit(); + _previousByte = 0; + for (int i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + static final int kDefaultDictionaryLogSize = 22; + static final int kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + class Encoder2 + { + short[] m_Encoders = new short[0x300]; + + public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } + + + + public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException + { + int context = 1; + for (int i = 7; i >= 0; i--) + { + int bit = ((symbol >> i) & 1); + rangeEncoder.Encode(m_Encoders, context, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException + { + int context = 1; + boolean same = true; + for (int i = 7; i >= 0; i--) + { + int bit = ((symbol >> i) & 1); + int state = context; + if (same) + { + int matchBit = ((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + rangeEncoder.Encode(m_Encoders, state, bit); + context = (context << 1) | bit; + } + } + + public int GetPrice(boolean matchMode, byte matchByte, byte symbol) + { + int price = 0; + int context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + int matchBit = (matchByte >> i) & 1; + int bit = (symbol >> i) & 1; + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + int bit = (symbol >> i) & 1; + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + int m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = (1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (int i = 0; i < numStates; i++) + m_Coders[i] = new Encoder2(); + } + + public void Init() + { + int numStates = 1 << (m_NumPrevBits + m_NumPosBits); + for (int i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(int pos, byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + short[] _choice = new short[2]; + BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); + + + public LenEncoder() + { + for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(int numPosStates) + { + SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); + + for (int posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException + { + if (symbol < Base.kNumLowLenSymbols) + { + rangeEncoder.Encode(_choice, 0, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + rangeEncoder.Encode(_choice, 0, 1); + if (symbol < Base.kNumMidLenSymbols) + { + rangeEncoder.Encode(_choice, 1, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + rangeEncoder.Encode(_choice, 1, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(int posState, int numSymbols, int[] prices, int st) + { + int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); + int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); + int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); + int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); + int i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder extends LenEncoder + { + int[] _prices = new int[Base.kNumLenSymbols< 0) + { + lenRes = _matchDistances[_numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + return lenRes; + } + + void MovePos(int num) throws java.io.IOException + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + int GetRepLen1Price(int state, int posState) + { + return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); + } + + int GetPureRepPrice(int repIndex, int state, int posState) + { + int price; + if (repIndex == 0) + { + price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); + } + else + { + price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); + if (repIndex == 1) + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); + else + { + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); + price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); + } + } + return price; + } + + int GetRepPrice(int repIndex, int len, int state, int posState) + { + int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + int GetPosLenPrice(int pos, int len, int posState) + { + int price; + int lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + int Backward(int cur) + { + _optimumEndIndex = cur; + int posMem = _optimum[cur].PosPrev; + int backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + int posPrev = posMem; + int backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + int[] reps = new int[Base.kNumRepDistances]; + int[] repLens = new int[Base.kNumRepDistances]; + int backRes; + + int GetOptimum(int position) throws IOException + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + int lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + lenMain = ReadMatchDistances(); + } + else + { + lenMain = _longestMatchLength; + _longestMatchWasFound = false; + } + numDistancePairs = _numDistancePairs; + + int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = -1; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + int repMaxIndex = 0; + int i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + int lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + byte currentByte = _matchFinder.GetIndexByte(0 - 1); + byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = -1; + return 1; + } + + _optimum[0].State = _state; + + int posState = (position & _posStateMask); + + _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); + int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); + + if (matchByte == currentByte) + { + int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + int len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + int repLen = repLens[i]; + if (repLen < 2) + continue; + int price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + int offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + int distance = _matchDistances[offs + 1]; + int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + int cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(cur); + int newLen = ReadMatchDistances(); + numDistancePairs = _numDistancePairs; + if (newLen >= _numFastBytes) + { + + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(cur); + } + position++; + int posPrev = _optimum[cur].PosPrev; + int state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state = Base.StateUpdateRep(state); + else + state = Base.StateUpdateMatch(state); + } + else + state = _optimum[posPrev].State; + state = Base.StateUpdateChar(state); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state = Base.StateUpdateShortRep(state); + else + state = Base.StateUpdateChar(state); + } + else + { + int pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state = Base.StateUpdateRep(state); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state = Base.StateUpdateRep(state); + else + state = Base.StateUpdateMatch(state); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + int curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); + + posState = (position & _posStateMask); + + int curAnd1Price = curPrice + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + boolean nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); + repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateChar(state); + + int posStateNext = (position + 1) & _posStateMask; + int nextRepMatchPrice = curAnd1Price + + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + { + int offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + int startLen = 2; // speed optimization + + for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + int lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateRep(state); + + int posStateNext = (position + lenTest) & _posStateMask; + int curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), + _matchFinder.GetIndexByte(lenTest - 1)); + state2 = Base.StateUpdateChar(state2); + posStateNext = (position + lenTest + 1) & _posStateMask; + int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); + int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + + // for(; lenTest2 >= 2; lenTest2--) + { + int offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + int offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (int lenTest = startLen; ; lenTest++) + { + int curBack = _matchDistances[offs + 1]; + int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); + if (lenTest2 >= 2) + { + int state2 = Base.StateUpdateMatch(state); + + int posStateNext = (position + lenTest) & _posStateMask; + int curAndLenCharPrice = curAndLenPrice + + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte(lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), + _matchFinder.GetIndexByte(lenTest - 1)); + state2 = Base.StateUpdateChar(state2); + posStateNext = (position + lenTest + 1) & _posStateMask; + int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); + int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); + + int offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + boolean ChangePair(int smallDist, int bigDist) + { + int kDif = 7; + return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(int posState) throws IOException + { + if (!_writeEndMark) + return; + + _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); + _rangeEncoder.Encode(_isRep, _state, 0); + _state = Base.StateUpdateMatch(_state); + int len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + int posSlot = (1 << Base.kNumPosSlotBits) - 1; + int lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + int posReduced = (1 << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(int nowPos) throws IOException + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException + { + inSize[0] = 0; + outSize[0] = 0; + finished[0] = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + } + + if (_finished) + return; + _finished = true; + + + long progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + + ReadMatchDistances(); + int posState = (int)(nowPos64) & _posStateMask; + _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); + _state = Base.StateUpdateChar(_state); + byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); + _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + while (true) + { + + int len = GetOptimum((int)nowPos64); + int pos = backRes; + int posState = ((int)nowPos64) & _posStateMask; + int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == -1) + { + _rangeEncoder.Encode(_isMatch, complexState, 0); + byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); + if (!Base.StateIsCharState(_state)) + { + byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state = Base.StateUpdateChar(_state); + } + else + { + _rangeEncoder.Encode(_isMatch, complexState, 1); + if (pos < Base.kNumRepDistances) + { + _rangeEncoder.Encode(_isRep, _state, 1); + if (pos == 0) + { + _rangeEncoder.Encode(_isRepG0, _state, 0); + if (len == 1) + _rangeEncoder.Encode(_isRep0Long, complexState, 0); + else + _rangeEncoder.Encode(_isRep0Long, complexState, 1); + } + else + { + _rangeEncoder.Encode(_isRepG0, _state, 1); + if (pos == 1) + _rangeEncoder.Encode(_isRepG1, _state, 0); + else + { + _rangeEncoder.Encode(_isRepG1, _state, 1); + _rangeEncoder.Encode(_isRepG2, _state, pos - 2); + } + } + if (len == 1) + _state = Base.StateUpdateShortRep(_state); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state = Base.StateUpdateRep(_state); + } + int distance = _repDistances[pos]; + if (pos != 0) + { + for (int i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _rangeEncoder.Encode(_isRep, _state, 0); + _state = Base.StateUpdateMatch(_state); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + int posSlot = GetPosSlot(pos); + int lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + int baseVal = ((2 | (posSlot & 1)) << footerBits); + int posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + int distance = pos; + for (int i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize[0] = nowPos64; + outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((int)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished[0] = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(java.io.OutputStream outStream) + { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() + { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, + long inSize, long outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables(1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables(1 << _posStateBits); + + nowPos64 = 0; + } + + long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; + public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, + long inSize, long outSize, ICodeProgress progress) throws IOException + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + + + + CodeOneBlock(processedInSize, processedOutSize, finished); + if (finished[0]) + return; + if (progress != null) + { + progress.SetProgress(processedInSize[0], processedOutSize[0]); + } + } + } + finally + { + ReleaseStreams(); + } + } + + public static final int kPropSize = 5; + byte[] properties = new byte[kPropSize]; + + public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException + { + properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); + outStream.write(properties, 0, kPropSize); + } + + int[] tempPrices = new int[Base.kNumFullDistances]; + int _matchPriceCount; + + void FillDistancesPrices() + { + for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + int posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + int baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + int posSlot; + BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + int st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); + + int st2 = lenToPosState * Base.kNumFullDistances; + int i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (int i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + public boolean SetAlgorithm(int algorithm) + { + /* + _fastMode = (algorithm == 0); + _maxMode = (algorithm >= 2); + */ + return true; + } + + public boolean SetDictionarySize(int dictionarySize) + { + int kDicLogSizeMaxCompress = 29; + if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) + return false; + _dictionarySize = dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; + _distTableSize = dicLogSize * 2; + return true; + } + + public boolean SetNumFastBytes(int numFastBytes) + { + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + return false; + _numFastBytes = numFastBytes; + return true; + } + + public boolean SetMatchFinder(int matchFinderIndex) + { + if (matchFinderIndex < 0 || matchFinderIndex > 2) + return false; + int matchFinderIndexPrev = _matchFinderType; + _matchFinderType = matchFinderIndex; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = -1; + _matchFinder = null; + } + return true; + } + + public boolean SetLcLpPb(int lc, int lp, int pb) + { + if ( + lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || + lc < 0 || lc > Base.kNumLitContextBitsMax || + pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) + return false; + _numLiteralPosStateBits = lp; + _numLiteralContextBits = lc; + _posStateBits = pb; + _posStateMask = ((1) << _posStateBits) - 1; + return true; + } + + public void SetEndMarkerMode(boolean endMarkerMode) + { + _writeEndMark = endMarkerMode; + } +} + diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java new file mode 100644 index 0000000..7698581 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java @@ -0,0 +1,55 @@ +package SevenZip.Compression.RangeCoder; + +public class BitTreeDecoder +{ + short[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new short[1 << numBitLevels]; + } + + public void Init() + { + Decoder.InitBitModels(Models); + } + + public int Decode(Decoder rangeDecoder) throws java.io.IOException + { + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) + m = (m << 1) + rangeDecoder.DecodeBit(Models, m); + return m - (1 << NumBitLevels); + } + + public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException + { + int m = 1; + int symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + int bit = rangeDecoder.DecodeBit(Models, m); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static int ReverseDecode(short[] Models, int startIndex, + Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException + { + int m = 1; + int symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + int bit = rangeDecoder.DecodeBit(Models, startIndex + m); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java new file mode 100644 index 0000000..f9e97db --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java @@ -0,0 +1,99 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class BitTreeEncoder +{ + short[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new short[1 << numBitLevels]; + } + + public void Init() + { + Decoder.InitBitModels(Models); + } + + public void Encode(Encoder rangeEncoder, int symbol) throws IOException + { + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; ) + { + bitIndex--; + int bit = (symbol >>> bitIndex) & 1; + rangeEncoder.Encode(Models, m, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException + { + int m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + int bit = symbol & 1; + rangeEncoder.Encode(Models, m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public int GetPrice(int symbol) + { + int price = 0; + int m = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0; ) + { + bitIndex--; + int bit = (symbol >>> bitIndex) & 1; + price += Encoder.GetPrice(Models[m], bit); + m = (m << 1) + bit; + } + return price; + } + + public int ReverseGetPrice(int symbol) + { + int price = 0; + int m = 1; + for (int i = NumBitLevels; i != 0; i--) + { + int bit = symbol & 1; + symbol >>>= 1; + price += Encoder.GetPrice(Models[m], bit); + m = (m << 1) | bit; + } + return price; + } + + public static int ReverseGetPrice(short[] Models, int startIndex, + int NumBitLevels, int symbol) + { + int price = 0; + int m = 1; + for (int i = NumBitLevels; i != 0; i--) + { + int bit = symbol & 1; + symbol >>>= 1; + price += Encoder.GetPrice(Models[startIndex + m], bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(short[] Models, int startIndex, + Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException + { + int m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + int bit = symbol & 1; + rangeEncoder.Encode(Models, startIndex + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Decoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Decoder.java new file mode 100644 index 0000000..85b3150 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Decoder.java @@ -0,0 +1,88 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class Decoder +{ + static final int kTopMask = ~((1 << 24) - 1); + + static final int kNumBitModelTotalBits = 11; + static final int kBitModelTotal = (1 << kNumBitModelTotalBits); + static final int kNumMoveBits = 5; + + int Range; + int Code; + + java.io.InputStream Stream; + + public final void SetStream(java.io.InputStream stream) + { + Stream = stream; + } + + public final void ReleaseStream() + { + Stream = null; + } + + public final void Init() throws IOException + { + Code = 0; + Range = -1; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.read(); + } + + public final int DecodeDirectBits(int numTotalBits) throws IOException + { + int result = 0; + for (int i = numTotalBits; i != 0; i--) + { + Range >>>= 1; + int t = ((Code - Range) >>> 31); + Code -= Range & (t - 1); + result = (result << 1) | (1 - t); + + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + } + return result; + } + + public int DecodeBit(short []probs, int index) throws IOException + { + int prob = probs[index]; + int newBound = (Range >>> kNumBitModelTotalBits) * prob; + if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) + { + Range = newBound; + probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + return 0; + } + else + { + Range -= newBound; + Code -= newBound; + probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); + if ((Range & kTopMask) == 0) + { + Code = (Code << 8) | Stream.read(); + Range <<= 8; + } + return 1; + } + } + + public static void InitBitModels(short []probs) + { + for (int i = 0; i < probs.length; i++) + probs[i] = (kBitModelTotal >>> 1); + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Encoder.java b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Encoder.java new file mode 100644 index 0000000..d21b983 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/Compression/RangeCoder/Encoder.java @@ -0,0 +1,151 @@ +package SevenZip.Compression.RangeCoder; +import java.io.IOException; + +public class Encoder +{ + static final int kTopMask = ~((1 << 24) - 1); + + static final int kNumBitModelTotalBits = 11; + static final int kBitModelTotal = (1 << kNumBitModelTotalBits); + static final int kNumMoveBits = 5; + + java.io.OutputStream Stream; + + long Low; + int Range; + int _cacheSize; + int _cache; + + long _position; + + public void SetStream(java.io.OutputStream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + _position = 0; + Low = 0; + Range = -1; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() throws IOException + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() throws IOException + { + Stream.flush(); + } + + public void ShiftLow() throws IOException + { + int LowHi = (int)(Low >>> 32); + if (LowHi != 0 || Low < 0xFF000000L) + { + _position += _cacheSize; + int temp = _cache; + do + { + Stream.write(temp + LowHi); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (((int)Low) >>> 24); + } + _cacheSize++; + Low = (Low & 0xFFFFFF) << 8; + } + + public void EncodeDirectBits(int v, int numTotalBits) throws IOException + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>>= 1; + if (((v >>> i) & 1) == 1) + Low += Range; + if ((Range & Encoder.kTopMask) == 0) + { + Range <<= 8; + ShiftLow(); + } + } + } + + + public long GetProcessedSizeAdd() + { + return _cacheSize + _position + 4; + } + + + + static final int kNumMoveReducingBits = 2; + public static final int kNumBitPriceShiftBits = 6; + + public static void InitBitModels(short []probs) + { + for (int i = 0; i < probs.length; i++) + probs[i] = (kBitModelTotal >>> 1); + } + + public void Encode(short []probs, int index, int symbol) throws IOException + { + int prob = probs[index]; + int newBound = (Range >>> kNumBitModelTotalBits) * prob; + if (symbol == 0) + { + Range = newBound; + probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); + } + else + { + Low += (newBound & 0xFFFFFFFFL); + Range -= newBound; + probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); + } + if ((Range & kTopMask) == 0) + { + Range <<= 8; + ShiftLow(); + } + } + + private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; + + static + { + int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + int start = 1 << (kNumBits - i - 1); + int end = 1 << (kNumBits - i); + for (int j = start; j < end; j++) + ProbPrices[j] = (i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); + } + } + + static public int GetPrice(int Prob, int symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; + } + static public int GetPrice0(int Prob) + { + return ProbPrices[Prob >>> kNumMoveReducingBits]; + } + static public int GetPrice1(int Prob) + { + return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/ICodeProgress.java b/3rdparty/lzma-21.03beta/Java/SevenZip/ICodeProgress.java new file mode 100644 index 0000000..4cb8d1b --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/ICodeProgress.java @@ -0,0 +1,6 @@ +package SevenZip; + +public interface ICodeProgress +{ + public void SetProgress(long inSize, long outSize); +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaAlone.java b/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaAlone.java new file mode 100644 index 0000000..d1d27f9 --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaAlone.java @@ -0,0 +1,253 @@ +package SevenZip; + +public class LzmaAlone +{ + static public class CommandLine + { + public static final int kEncode = 0; + public static final int kDecode = 1; + public static final int kBenchmak = 2; + + public int Command = -1; + public int NumBenchmarkPasses = 10; + + public int DictionarySize = 1 << 23; + public boolean DictionarySizeIsDefined = false; + + public int Lc = 3; + public int Lp = 0; + public int Pb = 2; + + public int Fb = 128; + public boolean FbIsDefined = false; + + public boolean Eos = false; + + public int Algorithm = 2; + public int MatchFinder = 1; + + public String InFile; + public String OutFile; + + boolean ParseSwitch(String s) + { + if (s.startsWith("d")) + { + DictionarySize = 1 << Integer.parseInt(s.substring(1)); + DictionarySizeIsDefined = true; + } + else if (s.startsWith("fb")) + { + Fb = Integer.parseInt(s.substring(2)); + FbIsDefined = true; + } + else if (s.startsWith("a")) + Algorithm = Integer.parseInt(s.substring(1)); + else if (s.startsWith("lc")) + Lc = Integer.parseInt(s.substring(2)); + else if (s.startsWith("lp")) + Lp = Integer.parseInt(s.substring(2)); + else if (s.startsWith("pb")) + Pb = Integer.parseInt(s.substring(2)); + else if (s.startsWith("eos")) + Eos = true; + else if (s.startsWith("mf")) + { + String mfs = s.substring(2); + if (mfs.equals("bt2")) + MatchFinder = 0; + else if (mfs.equals("bt4")) + MatchFinder = 1; + else if (mfs.equals("bt4b")) + MatchFinder = 2; + else + return false; + } + else + return false; + return true; + } + + public boolean Parse(String[] args) throws Exception + { + int pos = 0; + boolean switchMode = true; + for (int i = 0; i < args.length; i++) + { + String s = args[i]; + if (s.length() == 0) + return false; + if (switchMode) + { + if (s.compareTo("--") == 0) + { + switchMode = false; + continue; + } + if (s.charAt(0) == '-') + { + String sw = s.substring(1).toLowerCase(); + if (sw.length() == 0) + return false; + try + { + if (!ParseSwitch(sw)) + return false; + } + catch (NumberFormatException e) + { + return false; + } + continue; + } + } + if (pos == 0) + { + if (s.equalsIgnoreCase("e")) + Command = kEncode; + else if (s.equalsIgnoreCase("d")) + Command = kDecode; + else if (s.equalsIgnoreCase("b")) + Command = kBenchmak; + else + return false; + } + else if(pos == 1) + { + if (Command == kBenchmak) + { + try + { + NumBenchmarkPasses = Integer.parseInt(s); + if (NumBenchmarkPasses < 1) + return false; + } + catch (NumberFormatException e) + { + return false; + } + } + else + InFile = s; + } + else if(pos == 2) + OutFile = s; + else + return false; + pos++; + continue; + } + return true; + } + } + + + static void PrintHelp() + { + System.out.println( + "\nUsage: LZMA [...] inputFile outputFile\n" + + " e: encode file\n" + + " d: decode file\n" + + " b: Benchmark\n" + + "\n" + + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + + " -eos: write End Of Stream marker\n" + ); + } + + public static void main(String[] args) throws Exception + { + System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); + + if (args.length < 1) + { + PrintHelp(); + return; + } + + CommandLine params = new CommandLine(); + if (!params.Parse(args)) + { + System.out.println("\nIncorrect command"); + return; + } + + if (params.Command == CommandLine.kBenchmak) + { + int dictionary = (1 << 21); + if (params.DictionarySizeIsDefined) + dictionary = params.DictionarySize; + if (params.MatchFinder > 1) + throw new Exception("Unsupported match finder"); + SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); + } + else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) + { + java.io.File inFile = new java.io.File(params.InFile); + java.io.File outFile = new java.io.File(params.OutFile); + + java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); + java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); + + boolean eos = false; + if (params.Eos) + eos = true; + if (params.Command == CommandLine.kEncode) + { + SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); + if (!encoder.SetAlgorithm(params.Algorithm)) + throw new Exception("Incorrect compression mode"); + if (!encoder.SetDictionarySize(params.DictionarySize)) + throw new Exception("Incorrect dictionary size"); + if (!encoder.SetNumFastBytes(params.Fb)) + throw new Exception("Incorrect -fb value"); + if (!encoder.SetMatchFinder(params.MatchFinder)) + throw new Exception("Incorrect -mf value"); + if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) + throw new Exception("Incorrect -lc or -lp or -pb value"); + encoder.SetEndMarkerMode(eos); + encoder.WriteCoderProperties(outStream); + long fileSize; + if (eos) + fileSize = -1; + else + fileSize = inFile.length(); + for (int i = 0; i < 8; i++) + outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); + encoder.Code(inStream, outStream, -1, -1, null); + } + else + { + int propertiesSize = 5; + byte[] properties = new byte[propertiesSize]; + if (inStream.read(properties, 0, propertiesSize) != propertiesSize) + throw new Exception("input .lzma file is too short"); + SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); + if (!decoder.SetDecoderProperties(properties)) + throw new Exception("Incorrect stream properties"); + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = inStream.read(); + if (v < 0) + throw new Exception("Can't read stream size"); + outSize |= ((long)v) << (8 * i); + } + if (!decoder.Code(inStream, outStream, outSize)) + throw new Exception("Error in data stream"); + } + outStream.flush(); + outStream.close(); + inStream.close(); + } + else + throw new Exception("Incorrect command"); + return; + } +} diff --git a/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaBench.java b/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaBench.java new file mode 100644 index 0000000..397e7af --- /dev/null +++ b/3rdparty/lzma-21.03beta/Java/SevenZip/LzmaBench.java @@ -0,0 +1,392 @@ +package SevenZip; + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class LzmaBench +{ + static final int kAdditionalSize = (1 << 21); + static final int kCompressedAdditionalSize = (1 << 10); + + static class CRandomGenerator + { + int A1; + int A2; + public CRandomGenerator() { Init(); } + public void Init() { A1 = 362436069; A2 = 521288629; } + public int GetRnd() + { + return + ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ + ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); + } + }; + + static class CBitRandomGenerator + { + CRandomGenerator RG = new CRandomGenerator(); + int Value; + int NumBits; + public void Init() + { + Value = 0; + NumBits = 0; + } + public int GetRnd(int numBits) + { + int result; + if (NumBits > numBits) + { + result = Value & ((1 << numBits) - 1); + Value >>>= numBits; + NumBits -= numBits; + return result; + } + numBits -= NumBits; + result = (Value << numBits); + Value = RG.GetRnd(); + result |= Value & (((int)1 << numBits) - 1); + Value >>>= numBits; + NumBits = 32 - numBits; + return result; + } + }; + + static class CBenchRandomGenerator + { + CBitRandomGenerator RG = new CBitRandomGenerator(); + int Pos; + int Rep0; + + public int BufferSize; + public byte[] Buffer = null; + + public CBenchRandomGenerator() { } + public void Set(int bufferSize) + { + Buffer = new byte[bufferSize]; + Pos = 0; + BufferSize = bufferSize; + } + int GetRndBit() { return RG.GetRnd(1); } + int GetLogRandBits(int numBits) + { + int len = RG.GetRnd(numBits); + return RG.GetRnd((int)len); + } + int GetOffset() + { + if (GetRndBit() == 0) + return GetLogRandBits(4); + return (GetLogRandBits(4) << 10) | RG.GetRnd(10); + } + int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } + int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } + public void Generate() + { + RG.Init(); + Rep0 = 1; + while (Pos < BufferSize) + { + if (GetRndBit() == 0 || Pos < 1) + Buffer[Pos++] = (byte)(RG.GetRnd(8)); + else + { + int len; + if (RG.GetRnd(3) == 0) + len = 1 + GetLen1(); + else + { + do + Rep0 = GetOffset(); + while (Rep0 >= Pos); + Rep0++; + len = 2 + GetLen2(); + } + for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) + Buffer[Pos] = Buffer[Pos - Rep0]; + } + } + } + }; + + static class CrcOutStream extends java.io.OutputStream + { + public CRC CRC = new CRC(); + + public void Init() + { + CRC.Init(); + } + public int GetDigest() + { + return CRC.GetDigest(); + } + public void write(byte[] b) + { + CRC.Update(b); + } + public void write(byte[] b, int off, int len) + { + CRC.Update(b, off, len); + } + public void write(int b) + { + CRC.UpdateByte(b); + } + }; + + static class MyOutputStream extends java.io.OutputStream + { + byte[] _buffer; + int _size; + int _pos; + + public MyOutputStream(byte[] buffer) + { + _buffer = buffer; + _size = _buffer.length; + } + + public void reset() + { + _pos = 0; + } + + public void write(int b) throws IOException + { + if (_pos >= _size) + throw new IOException("Error"); + _buffer[_pos++] = (byte)b; + } + + public int size() + { + return _pos; + } + }; + + static class MyInputStream extends java.io.InputStream + { + byte[] _buffer; + int _size; + int _pos; + + public MyInputStream(byte[] buffer, int size) + { + _buffer = buffer; + _size = size; + } + + public void reset() + { + _pos = 0; + } + + public int read() + { + if (_pos >= _size) + return -1; + return _buffer[_pos++] & 0xFF; + } + }; + + static class CProgressInfo implements ICodeProgress + { + public long ApprovedStart; + public long InSize; + public long Time; + public void Init() + { InSize = 0; } + public void SetProgress(long inSize, long outSize) + { + if (inSize >= ApprovedStart && InSize == 0) + { + Time = System.currentTimeMillis(); + InSize = inSize; + } + } + } + static final int kSubBits = 8; + + static int GetLogSize(int size) + { + for (int i = kSubBits; i < 32; i++) + for (int j = 0; j < (1 << kSubBits); j++) + if (size <= ((1) << i) + (j << (i - kSubBits))) + return (i << kSubBits) + j; + return (32 << kSubBits); + } + + static long MyMultDiv64(long value, long elapsedTime) + { + long freq = 1000; // ms + long elTime = elapsedTime; + while (freq > 1000000) + { + freq >>>= 1; + elTime >>>= 1; + } + if (elTime == 0) + elTime = 1; + return value * freq / elTime; + } + + static long GetCompressRating(int dictionarySize, long elapsedTime, long size) + { + long t = GetLogSize(dictionarySize) - (18 << kSubBits); + long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); + long numCommands = (long)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime); + } + + static long GetDecompressRating(long elapsedTime, long outSize, long inSize) + { + long numCommands = inSize * 220 + outSize * 20; + return MyMultDiv64(numCommands, elapsedTime); + } + + static long GetTotalRating( + int dictionarySize, + long elapsedTimeEn, long sizeEn, + long elapsedTimeDe, + long inSizeDe, long outSizeDe) + { + return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; + } + + static void PrintValue(long v) + { + String s = ""; + s += v; + for (int i = 0; i + s.length() < 6; i++) + System.out.print(" "); + System.out.print(s); + } + + static void PrintRating(long rating) + { + PrintValue(rating / 1000000); + System.out.print(" MIPS"); + } + + static void PrintResults( + int dictionarySize, + long elapsedTime, + long size, + boolean decompressMode, long secondSize) + { + long speed = MyMultDiv64(size, elapsedTime); + PrintValue(speed / 1024); + System.out.print(" KB/s "); + long rating; + if (decompressMode) + rating = GetDecompressRating(elapsedTime, size, secondSize); + else + rating = GetCompressRating(dictionarySize, elapsedTime, size); + PrintRating(rating); + } + + static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception + { + if (numIterations <= 0) + return 0; + if (dictionarySize < (1 << 18)) + { + System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); + return 1; + } + System.out.print("\n Compressing Decompressing\n\n"); + + SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); + SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); + + if (!encoder.SetDictionarySize(dictionarySize)) + throw new Exception("Incorrect dictionary size"); + + int kBufferSize = dictionarySize + kAdditionalSize; + int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + + ByteArrayOutputStream propStream = new ByteArrayOutputStream(); + encoder.WriteCoderProperties(propStream); + byte[] propArray = propStream.toByteArray(); + decoder.SetDecoderProperties(propArray); + + CBenchRandomGenerator rg = new CBenchRandomGenerator(); + + rg.Set(kBufferSize); + rg.Generate(); + CRC crc = new CRC(); + crc.Init(); + crc.Update(rg.Buffer, 0, rg.BufferSize); + + CProgressInfo progressInfo = new CProgressInfo(); + progressInfo.ApprovedStart = dictionarySize; + + long totalBenchSize = 0; + long totalEncodeTime = 0; + long totalDecodeTime = 0; + long totalCompressedSize = 0; + + MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); + + byte[] compressedBuffer = new byte[kCompressedBufferSize]; + MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); + CrcOutStream crcOutStream = new CrcOutStream(); + MyInputStream inputCompressedStream = null; + int compressedSize = 0; + for (int i = 0; i < numIterations; i++) + { + progressInfo.Init(); + inStream.reset(); + compressedStream.reset(); + encoder.Code(inStream, compressedStream, -1, -1, progressInfo); + long encodeTime = System.currentTimeMillis() - progressInfo.Time; + + if (i == 0) + { + compressedSize = compressedStream.size(); + inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); + } + else if (compressedSize != compressedStream.size()) + throw (new Exception("Encoding error")); + + if (progressInfo.InSize == 0) + throw (new Exception("Internal ERROR 1282")); + + long decodeTime = 0; + for (int j = 0; j < 2; j++) + { + inputCompressedStream.reset(); + crcOutStream.Init(); + + long outSize = kBufferSize; + long startTime = System.currentTimeMillis(); + if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) + throw (new Exception("Decoding Error"));; + decodeTime = System.currentTimeMillis() - startTime; + if (crcOutStream.GetDigest() != crc.GetDigest()) + throw (new Exception("CRC Error")); + } + long benchSize = kBufferSize - (long)progressInfo.InSize; + PrintResults(dictionarySize, encodeTime, benchSize, false, 0); + System.out.print(" "); + PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); + System.out.println(); + + totalBenchSize += benchSize; + totalEncodeTime += encodeTime; + totalDecodeTime += decodeTime; + totalCompressedSize += compressedSize; + } + System.out.println("---------------------------------------------------"); + PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); + System.out.print(" "); + PrintResults(dictionarySize, totalDecodeTime, + kBufferSize * (long)numIterations, true, totalCompressedSize); + System.out.println(" Average"); + return 0; + } +} diff --git a/3rdparty/lzma-21.03beta/bin/7zS2.sfx b/3rdparty/lzma-21.03beta/bin/7zS2.sfx new file mode 100644 index 0000000000000000000000000000000000000000..ba87c4dc0bab80c939c414017054d09dcbf9543e GIT binary patch literal 35328 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
8!uHUbGS z1RLu47)rPs>UklzNP`xZfv%wIaN|Gb#>d#r-svU*Ud1d^s@q)4!BDCW@{^wi)O|b< z_chpXFqHCw4FS0jd|U~07IQ?vi%FpSE%KP=+-ON6>Zc>=rr1YQK}1fA8x0lpAQ#QJav6C($s zFOR0LfTo{>WSmU5n*_I;OsQn|xfh=xTPYp8&%F=^oveSj)U4Z=!}@ornf2)s&DS#B z=U#votyv!~m9vafDNzaTKKH`%FK9JyDKEq`t)K-Vh$FC$zy5m6&4dwrO7iPhu)tGm zsN-WO5d<}|pabfl8#!J-&SLC7_u}OrQ1F#p1EncY?Ch8i$|5qmK;wd-$wE*yT`OVy zt^2<9KhRMvrGGkOUqIW?EX}n7|2s?1be3M|F6H2#;wlXqrvWuqN;td0t0FpG1&l9Q zh69&-0qU-?hyM@Ycqz-oz|egDe`hF1x2u4qD@Sn(NH^%(ERNTl-L9a+ zl|j9az7){N98Y8O&;KR1*5^xEtPd4)c27$HiHdY}hQ6_MeN!&q9r~s__QknD zwMDlTW9^ylAQr*U3;$i;yuQ;Lz}WrszbnVG6bB6xfVwru zKnwergF#N)4O+Zt@q#A`RDgjZAAD8{Qwiq__l2PIGhQ=6y0oB`=Zu}TcVOX>#Sq+m z9yB=kf^iXOSiQG50yOxU{Sq{%_JEgcw=_=Cc`UbSX z$(zTrt$~q&0n7%SU>N{9_UMN3f9v}t0o|^kLuFV|R(OHdnji!qjt2YUE65?Ppk={~ z2>EW;7oZ@sKK@b|)J6+^V;w3`6h)G`bMcxB>$Vvmc=>>tfdP~%I%|(~)}H9B-O*XQ zr<4tpI7B9Nw}Dc|an}Q&vbNi1LNjQ6p$LCVFDQTeC3L%4bjR#u>9*O~&2vMW=SQdS zj&7eDEYdzdSi0N5si#)NsWbFOr|+I_ksaNxZyc;$1&Y-`ww17SpLop%I(U$$v3nlK z7E7D%Qf_PC8%1o6oxV3-U(t4b(-|t#>3X2s^@gRZNU=<}tH{9zEX?3-4bZdqj|jS+ z`0pz6`c9XtG{~&jH~&k)mz(wS%=~^q`Czy2m4KiZE z;eVOLG1osF|H}lj7^8y&vlx1PkNhva^S|^-V6UG+c;NqSpi8(Q7XRM{8Y>TYvFkag zBEoePZ65Cw+1T-|j3Oe%R33y_LqZ^MmdclqZr!!<%gVPzZ zfXK`9plt7ZC5!2W-0%PYUxJS~^1X80^#-UqYpzsb;Gg0uZhg2!9_*x2*3Q@)uZ2OQ zVMF4wu?S*dFBi+6y7~M6x zU3Uoj>oB@2bi3{mbXR%#=r?Gk4k#=y{RCA4ovs2UaXSL;Ixrk2DG`G9FB9P?SAo|e zSqxbWFC4cpFznb4vIczJ9e61ww6hs~@{kAv;$n~v51wNVyo{Y52FDp@>~RE5nB(eN zw1*(N7N0?{r$nfIACb&b6vx)2lude$6?t^nc=F$8FUYLOfhSD?`di_A9 zI^zrQTmh®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 literal 0 HcmV?d00001 diff --git a/3rdparty/lzma-21.03beta/bin/7zdec.exe b/3rdparty/lzma-21.03beta/bin/7zdec.exe new file mode 100644 index 0000000000000000000000000000000000000000..c8d793e8e4fcec4ccb4f1b00096d1a46bc93fa3c GIT binary patch literal 43008 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

v?s{|B8O15vjCr0#DeBXn{0>K@*oQ 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�-&=7niDt}jx$^U9S6f?d?2iMy9Ofz zLqKo84k&rBy%0$L|G%3pt}{X=9?~cWEzU(f$AA}f>*0&?D}Vn-8Xo{H&E0VWrt_y0c7HLTs|!(L2$_7}7| z5j4mVVgi}u08MzX&kOb%x$a>y!zwjJ;DL(CfMdWWkI5k3gfs zpu@sIZe@QF1#$_f-E!vp-~SeI8Xc~m`CE;_?Vu;Upj-O7IsONVSRV#o=#U2*;_L-Y zCB10W`2XMdzhx|FP>Ykl?I;6i1($fKzD4Zk5-p23g%0pKt5TP4*Ebe3K$ilP=yWqc zTBw2D*Sk-=Fw$aRcrDQF`=%E>Hx&^6!e0-xE`q-mH1BT_r%=ja0Wl-VB38V_wmb9& z;w81#aD4P8*= zuJ!-_%OucT5LgrxQ!k9Q{{IKLlc(4926)oL>g3=5ma!K~OESJNgRUSt^TO#7C;{;F zy7qL}Du7nAo(~S_bv+Z%<)$6b<)#_X<)-n!ROZ`_|D|uF4=B3|1oXN|1iXj>862lk zDr*s^4I<=9gnL~NfTr-4DS;M=@VA0aakPljE-|)g|62}} z_P*dyfb_u5{4Z76`2gJAlK=Dn|4UGt&-i3#t$;eOSrnvzlaP0opB&w87ooB-03O-KF>%3 zv{}xe+gG6bgEiLAzg&7oe(uwkve=wVo{DcyTlMKWJ5M+~NO)9xtLm$`9`-0F^$! z?LdWlcsJhRoc*AQ;1|juZLskeF%SoJIA=!-$iP*0@Y3_9@qf^)hjnK)OJ_A~A5;O0 z_4m%wH?XZxAIh1!kAVhCUd%lQ>QFOx7IRpC2lXL zj_x1bf|1=On?5h?E`4MC|262YOK+BL;ZByW|IXk&Po*D$cBYs$2ySXc)`8} z4~6{)-~9|54Rb#ST0CF#!X8W)yf8lp3TK{PKZh3|v>6$C{RCdT&}L-lcH=>+Io!ar zT*v|}plK!~0W;7bd+Rq?qXjgg4IfSepQ}*E()^#TNW7bE*A^CchF+hFFE6fM24{8V z=J#yIms2$NDb@K%DvIL|x|FkL*1{Zg{Y0W?NOW4yIf9ffevZftph-YxJzFu?% zG(um>nHArC?uGhY(75N}9S1-j7qJD!ia>Mf2Zr$OpFyBqR5$NH2ONE$fOiOi#Ed~B zx3w=AO1ZM)LHx&eK*jVEP|jO*2b9*HypTN$N^8eKlLg3Lc>!vWv>bri{o?^>>j9`f z`?;G1RJAZ0e`~N{C}DSNuwi2;{b^awQse}xG<`0CJ!{tZTSU>Fp-8x!J*}IiAkEf* zp-3ss){>!I#;u#Zm!%-Bo5R5&t@UJyY+CbAy%O=X=AQ~BubL0DH2#(WX`BaIC=m@> zDeWKCL@|DXsNV32$2SFTGNMv}VwP5YFaA7KXHD1%|^f89>bi z<8PLQEM)=RjJ+ZS5c{ndO3c!1wHQha(roP+O0?2!6&Q+C(rj%QO61aP?HEcV(rjxO zN`%sEl^9BRz!TDJpz;?K7fkUCZq|h?MH?Dy1z13LrYmn?Hnm)87G z4^&_MQz+&1NITBr6wgrlB<}EzJD`ZlwgyF%OtA57(5};#li?kqpCMN{ce8bKSVppx zMuP4$W{kGJ%-;s;u6KK|fP4%&y+4ZyEZzrdr8{tB^nh-8V+i;!x`)x7A+q&AWNCR8 zbF^g~OIdz58>ph^c<~c56BD1s@|w4s^TjI&HzbR(n=QJ#X2zf9dKRWKThP4U6Yy~Y z!ndHQ#`Q@6XtSUeXt}@dpZ}nXU6@Y){U4dd6k+MkQpVNk&eF}E25Qr_-Y#JQ-PZ{k zx4lv9)6LdxGo$EPJ6>=z zfNsrsQgj*AqjWd{>5MajLg>k|fB#?R{Rh?apfF;7ad{bNY!VWxw?WqdlwNqjcj7O2 z#cd>L1y19EzyBeJ6sUk&lcgUzV>x<#*MLW1VlRMV{z7jkRD>PoEFN!Iu!GJ90bRF! zn7>5=q#v|f^G&zOM$l0QZxBZvaQqkSc70=gxI`=%G{d$!7u3`NE%pYj*87Aa}jO-vm1O z8I}UqgHFFFz3}4EF{H2x-H&C30q9VJH7|A@0|gaFB>2b@X8x8*pyG@p;C~>;%XUyN z-t|sKM6NqSz;V|*7K-i+FC;BNSE_@??AehIWLWc}5XB%^h`^jB0d1C0c{ z1kI6vyr_@W1n{Y@Fk>zr0__66@PY-|m~xOY$6v~V=E1_cKN{a|PIF*rPIFR% z4+rhlwwck*4vra~|K$SB$3?Oj!e0o3ihv_L&em}pMYrSQq7Q@m%HR{2vKScS9O4D* zTrBH2$|SqpSc3nTsEBm4?C53y8zSItUB^-M95hkO!2p`r?R0eLc2VKzbaa7i8E$?P z0Xnk@H2GS>)$A_7*c>jx@Y(=Wf|iIiyDKnuyE}CIyEKQZFfh6s2>P467HM{ufQ!m7 zFuH39`s)~f%M$2yeGwM$BHaR& zLp%)K2ZOtPR5*-px1KDM4hz@5z`xCcf13#t^Y306^A3rFuQ?n%OJ9S+AJo_cmFEkL zK^^-AjNn_jyFY?X-3HZpowXNUv>b(u8+6C=G}QAkbj}40;+7Qm_JVfDzK}Tl|9>-> z`M-st&_c8bOg6_-) zP40GX1ud0);qU;mJ{@Ys!$bf7gELb%=-heG&F0|Ft{@8oLzlZiukW6Y))vqi^zQr} z;FD-x+_?Dne|NY@Z!gFTpc7C*;|ec4Pe4rV{_wwa&kLr*fB(0Bi!70A{0ADektU3^|LD`k=G)$^QTa>tp<_*FbYCTWdf!F@Vk&-^s+l@S3%|_JZ-Z&QhLU-z(tSX!Qlq zP}m!WhSU=bAlHH_fD-jAju$%*{{3%#EV6{Vvw-C|gO8#+=-8zL0lmIFFH8ge|9_bP zDx6C{^tQVE|NkGf#0?bMFRmN{FL48z&Hm!kMbKczAGZHnL26#~9sK*hyA>4K#{VO` zO*VA7`B>H&bhw@$cYxAQk|?37VXo z2)Y2H^va9Q1E30n2h_p^HD>r*1VG^ksWCuj?EWtWHGbG$Bpv|G8<)NTC;HMW{{vJY z3xVT63l9H7B3!X{%L~t6ph=N845b;0wJ#b#{UOnA=3d_i;3Omg(W3>j!j%U!W}X2` zPoTjKkc~VLX>QOWL)SB)U5{rV27^}b=z=!Fx}GsU$^1jmcMGHI13}*>|6O0ap55zu z1)>Uk|6A#s7hX^&bTji$IT#3$16g0XB^)$F175$p98_{5yX$}HmDX?kt)TkyMd^M> z<;((#>(8LH0;!x^L1~x2$rH4L4w1(H2N-mJ==SA!vHL6&1E>=VvGD~X=<*uhKmQ@I z_d@Olc;O6qQ3R~@dWeJJ1;>6+3-rnh29TxQuArCzMMTM3a6!)Tdg=etD=!}J`}_a( zqi!D+mj9kC-Ht4!yr2^}yBV_>{|5*d9{`_>_wj`Y0|Uc1&~XeU>|rl9>;rW+kAa49 zk28X@%i$g8Kt-#o9%$5}`(wEA|Kn^eitY@cQS>^{X)B#|JiUG%owa{nsGS9kmWP1K zz!y?y!R>tTS)~S@bsC*@3Y~Ql;G;}!I_pe2>vTHnRKUlYiX3Mv0CiZ8Ar{g=HrR(i zBwonw1C11TybuLBEwa~-<;5=s==lRLF8}}kAMW-qd*N>H=6soah6!}A5$F(-@CKDg zhF+G))=Q-#t+&gPx(^>?R5<3ysNm@6QTpX|Q1fq&wBe_yM6ya_M(Kn$OUDQW8f2iIT&^b9dToL!3lP1_s1-i7g`|O zyV2Iz@w^CG1=&Rh+6mTu?#1$V;KT!8w*);0q>SZ-;GVz#yUijI13YoyHBB$HX8il# z?W4le&E9>n`(x&%|NsBXGl#Pre8zn65pz(lh(WK*2~e9x^aP_j1G9Ozi;7J15uQ%A zZWk4iPB)hS?kw@3gDMstVfSEY{^3x}+sV^_WIrd4TZ98 z{tNDhfo5fXZ30JFJYw}IXtE^$6aYM0pa2j6&5wn5pXv<#@PcVG$PZ6md_VE`e|H^= z@onqhow0vPe9J6B<8CYwppl8dThaA;m2J+fYLy>>xW+7DcuGyWIa6r*E#&#**aaPypTNs@*!xwI^zq_h;g@@0I2cSdY}a4?h7yGfpv;N`FCFQ zodON|-Rbq65&+sY^#U}y09wqh47%r_^a7}Mcp<(MWSdN6r|S;T5#W)a6%?*}__w>U zbh;im=DL@$i|qh-1DFv1wlL;yKMv6TL~v98wI=_zI_B;;4p0KhD+2XhL1zQcx%Kyd z>;Dp-@ZkSuFaCf6Ju(2wq4WMS@9|q95HGd(o z`(oX8^ktZ#-EW%TKxQX7x<6*=b)SE+0u+PiyKlTWb?Wbb>l^i~%_si94h9X{ed%?H zU1Ba{+o z1<2>!YM`_ZIgbXkV%GRuX8}v6?+43r7Rcc--Rx<*^cZ@13SN}#22Bjtu=mOswBD{| z?v7{aKHPm?`&dA)>yxm67mMUTC$aot0Oz)3Sk_Dg?=f%vRx1fDXP!VtKSBF_4n(#b zh%7Y(ofPt7_BBwi{RyaM>n&z{;lAzff9rCV$fAY~jG&=yL>@iF!O-o>0~*H!jb+Ji z`};rA=)mjSJC1>TvsV>za?s5zi5GXb{{7#LT$9R!{0B&Fugu2$oZ z{{0^hI&T$ZJ1Ft+T?5yvNS3lN?6?84AO>UssL$S63psTRyj)fov}~GZL+iKscyX3tbxmDvDhH zbXT%i|A0-MAsn5w8Rlr?+pYi0tg<*>_=AO9-?W0(F*1Vgc<1Qm{BJU|`^1aim;QrV zbqBgZ+Xz6VIcW0CjRjP7fo9G?tvkdj1@Juyfq}u@kpjjCT5p5)A;fii@`QzV`u^zU zVeWSQaq(rhNJqCTM|TlRx0Pi9OF35&i={;|OZUy!+TE@kmIW+DY~`|+7Uh!Nt{lyW zK<5{B7qD0tv6OQZ-R@?vW-7Ys*y;PH+x3t2;nFqWrWy;wjs#F(#3_Mdu>jO)2G5q& z@_;tY`bk(HFZU^8u|8ew*6Z8y0(_#8n*?aHX}6zD_vKF47VQh&$2)yHqz{5hd)En| zd$oK0csfISI_qR!97|w;-1+R=@?s4G1H)@m>*Ga+18CZC{sGVkey^Vl zXt~Cu1E4+$Xx$9si#9OZ22>Tlr~-9heZO?Xd33~icEovg#Cdnb`EVz1)m;k0_UUYzIffo%MLDQB3pk?wUDxhof{)2DPUia_+e^C3~@E>T~ zb&YmdK(9Z~3)TeCLEIeOZamC<-QhCAZYum^2ie9gVXG{=eI@D4r(_6Bh9L&F7pXnk0B3FP><)$t4r-EIo42THgg z-OuJUkOM%SNYKD2XcP~0DHS8wFFUq?tp6$xN@xzCL#J+crh?kTX`QiG(mG?Wb;jQ5 zb_LJ#c6)%1Z|*i}?DiFC{wc%X4m$dpzhytDHAn12vt%9CE-D*@mWQb4s?;Cj%cSej*=Nl9Y!F@rGBfgnw? z|Ng%Y-Z3v17SOMwn_tS8=y{gNHNRvj5o&&^1v(_kvqb-YS;+sgfYXyyyepiHZ@6JN|&;BUKI* zA2z|px0`DP{)dHk#{S`-;`-hq_I+pS2T(tO0~CX<0-*9GLZO7yGFE`Uhu)xv*+MZL-)6LS}UBSV8z1x9D_=Dr?tKGE{VL{>D z?EeFJvMf4dcXY3aaYE`zaz^M!T-sG$m~vq1%>_2cj9}@E;5g2pqXZgud(CA0A5`s}=&XHF!q&|m z4qC|X%F*i&N?*+X3lv@$*!=&WrSM`BR6id~zl;)Oq!4@#3~1dwvp|i?JB_ETn!pr zb=?74zV4>b>88=?r_$-C(|zv6Qn0^Uzm<4`t3H+zwr=L&{{bA}lWCcup5OpA!N5t9 zv)lDW0BE*}0~Ac4>j*)S^#mf+ee7ils3o8JfWa74E3sR;ittZ80E(wh*E66?WN$z= zm-yc3X6fkm<@jHErnmM%wJQI&=;a796M!Y_7e- z02)FD*?$LOKas9H{t~q5zq^j3JC293c86f>p5|H+hEo3K+6N4!oS?zZm)4*GVpoa( zrDwnej0EU7#4{zS7)}CR#|$0^9CMIl>~`h&U&hkud!*Yz;lEk8K*0YX0po9- zu4k-|mBd0_ZG8-yJ~+BvK_ks9$O53m!i+2c8X#ao7I*@RaAbiqFU!Frq$mEDK50l$ z0J)~S_DW}jNO$a=urSc6{+$I9odq)BY`_B=gg;XfiQyLOf8g+gWEKwVd*CRAra{Y6 zuq!|@jFjjsOP_#5U}?_v%uCP(Y~8*Wx*Y|$9YspmkGmcLjje&M#p8-#VCV+L;}LK? z%5=IOu|5WMLkZ}9K4{XS+!aS&=O6;-zw3?e(gWSKce-P*ysZ55|37NdB`0qgA9&5Z zBd8cwW}_9WBA}s1&~3C?0vQ)FK%*}_&1wuU7D|C<@LCU)h-C?6Z14q3yy%9Bmhyla z%WVH0Sd0(6X5GQ$z|ar}y2lD!(W2cR23d8>xDv7IR_2%+!;85REDV8!R^8$@Z{rGt zc{U*Pe2Fn{hX+Wh5=bd%*;pv(3_Gz+K9nW*PefG&sWc8pQli!nzxD}J+q)bL|4UR@ zve;fs`~Uy{Ar=VF;Y9}$&;CUf63_7k=#V{7Zzl!hS2J-?b!h_bHQWxjjN{;MsRn00 z4r^DQQg-75FF}U_fro}Zyx`mR7j#5?M=W=5=!0%Ij-cMqJKZ4iO;8rg|I!bjsaEU5 z{H=dMXY<6qDG_e2eGpj6`@i%J=wJZ;?SKEjPEG5Kg`F=CnqfTv(b)~E#~1_t2TFAR z04*aq1wIt5_5eqzm}Tq<$gO|iLm)4_xDGN#IL$Kl0Dmi}1%(*-^F7cJ`{zZ0*uVeX zZXC_NFaGz2KIx2o0(RkxAc*^TtPhtacGn7khNnPVnwMS$oq5Pzq79mL=FhU~_G$dl z>C5p#eb(RqV4?pdpdCUSFJ|rd`@j4Ai~UzY^F=Q#U3p4mnrojhcEoa*vK({eW^DfP zzeK0g^~1}D|3GI8{V%=nLU$RcZaw_k2()hYrYNW#bK!*qSn&93S#WH=z7CSx3zhq` z^zZ-39iUhS=R!nRiicrG1t_*UL_x8o0FA9~P^X5YvlO(TqsC$$s0mnF(i{2$?BORt zy`eloSVLmIim1KDqeL&$^tW418GqmyLh_ck^3+F4OHS{m|{o zlh)19?8?IgT9;PJniUiAnj5k>ZAZ)p22iUUbiDJ2(ram*lGdL)%UMb*yG!37w|Lol zL$5%r?FOBL435$d)}Kp2Gn_B3h=9+&3QKFQy~0r{2wG}w`@i%~_xTr$+y4H4&6j2w zd!f6I6l&{^l86IVH2sDQd&g2o44^Ma)7MgINA7HAv{ zJ9;NCJSsG^%%U>Ga+Xh;=4qCW) zaLeESX`Qi8(mG?Gb;iEwHtY3$5}3sb%Dilyv46r~dG^C=hqUI}Cmf}ES)ehs*V946 zwr{%6zmVJp8b5vV;*RjY|HkOoRd6t*S;jsoxewlt18ROr97aC zKPGU`tJKJ%?KbGpWeo+_|J{6`W0qb22fWY(RRIS|MJ-(am+*D_@?_X3fleWLvmLZT zCJuB`c9`+E<`e(Zx&=W?8D-L%e_54sv>vGC?LPLJGp+eoOeu5oiT`enj<4^;9p143 z6kf{0pzs0}38g&7x5GPqKlHk(bi^5Sx<2TwGwO_B=?0ypoz^MQ?IzI~C)4Ts0>ozP zknfBG$C{tX{}<0^gR;qo?of{KZjKj`piO><`CEOM7#OSpMc8 z|3QbzyIv^;?HC0I5-3z$-yCCLd~F9RtxB$eBl@+{|5EU(Sh0T~PnQb*FMR{@*^L** z;3Hy71iL?g%7m4Ipv3SJbpH!ztPdnKP4M4;i#WqlR*P8vlE`kp7Yd-F=7;s~8qaRm zC)O1##hjfLEZq!goiY{OY~8*OdR;1*0$xnt`1il{?-Fs)q(n`{zqIE6F(q7S&HwdF zK(#aILfdZNHyw=Kt{09mFm~5|u!ytZZvm}w`Cs~?`~3eh8_*2wIq0FnouHiyFgMg% z#tD>EfXDNN#YcfE>oe1uA2(xxu=QrI@put+S2= z*&YylGpw2j!ZpJKjP<95Dk+AyLgMYj06Yaw#KFu!#OY}TSR6R;0JUmL+AqBP; z=%PW;QMR3KEU%@&oX$9w*8=?8UEjQB;os)^W@aZ_XBf*dc1BR1egwK<;qYrN5c?YV z<^eQE^Dyi<0dn+Oeu$$X^J~b?c13cwL=bp1vYR~%R5pN{o-k+If{GxAQZBHQx?MlK zRt6U@P-n|q%m-~|EfMc-p94DGm#w=Uw4niX%!I4JF$S<(%|LGT{epVQClAApDIB|r!Cf`X6dwa|{4wXjyuYgX`(4cN1Yp%xC%Xb!kV z6bLe_J3yfIQYk1E>UDc4gmwD<==M+n4e0p_w4N;C?l$c9WMM4*A?W+3o2$3Cj| z$Z_(p@c|I-bQI`d>~Li4aAfLmWbSli>2&1ibQI|hl<0JnN$X_lbkykfR7vY(JiLS9 zxEsTZ{k)*qmVj2|z2Jioy8DiRimQE~;;3WZ4p1zCPW$g}1Dz1tDX;Cy(;3eq?JLj; zz6rIn542bgG)!3c|39dfx|7x!dk@syapmX@y%Ut>-pvuv8T;pdpaQ7t|Di+xbOu#0 z@4x@ut{+}9fwm@v34?_G{rmsF*Y{4Ro5%}O-hbFk^62IOo!<&NstDCIR;X!PK#O25 zfehOSGfd*e3m&Y7nL`W%^`lS?+ra~IS~?>GsA9ZRB9YcydxxXj^+^fqjuKF{*6XM7 z;?x>Yje6%r7k1M4j6yX%3Tis&=*cuty93$u5Qym}FLKtvrh@Oh(BS#^-!fLD zMA#xun7`#bXl;p`2qS+hXzx~U8z_3ZeK`UkQ5TS<6ZHbr7zI@<;HCATJ1@io!n0JO zUIc=6KOg3A1uw1l<>_`6VCENgXX*6i>FxtZt*bzH8z}0#FLwXX4&{-q6|jIr|1{9` zE1mm55nU44Jr8_Z#xxMw{kuDeg}IieGxURSsDSl_a{VF}>z~E)+UGmxf%J68e(3a5 zkUrEo52W{)n*iu0yVrcy7mB#bS*(ASu^e*~WW;EY2r%pr0VPf)ZcyTc^jM5JcGmm`SwFbBg94UkJK zxCYpz%t$W%&iM~pBX5Td$ff5vK}Rgb@_@Exgm>2pbn}G=zbFG;7jvLAv75j3WJx4w zUj+x~cs7QEFF02)mY6lC3NUmtf`+zxLj{5|0({&V0{?>+sJ0#`;qK5d%Tz8oN1g1cEd!a$u} z(BPskPr!>i>d>+C!e&^x4vq-q0zI_*P2(FD4#-N?S`Opepz_<@!1{1WayLhC@PF`m z)R2y0X>hl@L2oEWXDmlhH^)8(4hDwaseiuz{~s0vDz~i!lKdZVwSibs_VyYc zoq+a&ffwq!sPI5$90WiW6$ir(=M!!WFN8Q)7#iQ~VFLLPyl||ubV)ax_3;u8a0SfK zY1i$>VST)W6UwavO^hJ(c|gVV^`HO$H~Y!_Z&-E%v~#Gp4RkzWZ&*QZugw4d|2tbV zKnp`HIxARSWbFpsivU`82U?6abJ^ejS$Ysv;5p#0t3W&3YQ(z18hc$FnR2_1-Yz3_q?sik@1TQLn zE!eyibSMYIaj-Z8Ljyy19Y?PlC?SB?8!Nyh;_5MTUYS#H`#&qz}&WsGbk0!VvMkKJyF61zJv4S8fFHD zPS=KRHv>?w=pyKt*xCjr{w8bC;5|ohaBwgvhk}M)N(}#(o_SF`_3!`x;5#5+WPq8V z^z|YZ%mk&@7eQ0OvxP6`fi~BJr#?Dkdpct$bjD7xj6DHb$;{uP2x?=1qwz(jCMZz& zTlqj8Jh0HN4FFBhXOA62fABy^Au1Ie8-E`VEW99#UL8upBZ2#*gw5s zCfGksQ$YTacsX5-fuWl(xYxBOIG}ebD53r@J@Mk3I%qN3i*7#9!L3ly9RVPjJL(J! zFD*bl$u~T`tswQ?XF8XL{Qv(y;KgQVkXgIHF)9JxtlilPI;)qzhnfWHZ}2CqAGN5j&v|Ns9pbf4;N1udU9{(lTi2OVn-{Qv)d;<47C|Ns9N z9cvB#|Np<@G4KVXQpZ|D|NsBbu6?4n#TKNgONPTrqSV^G`9FKnn}#aR;!^!@PF##7 zn%&?tiMzq!0lLE1WXFrN&7dQ;KmpXuv*W*Y?TH%Z|E?#DZ-X|)H=Xx>ot7!>N@LL=bC2GDx^(w-NWCV@i(RBpXEHVJg(V{>f-Q&Cre2n&ZX3aFfldpE zV>?9{yIoI!+SVN$ki;O+RG;Hy(QYfp58HW)>8bM#Iv z`2YWZP!2(Ef=nCjQ z{eLsaw(u7fpzC!$7+uB;k8X?=nK%6yB9$j3w+!e zKnGNSx7@t|9SB|tI+CZ{1l&mA>Hg5|`U1Sdh8;F}7M8`3#n65Ff9abS*FXOM51Omw zZ=DP(t3kUKCW8)ItQKbIbrvY$`R2gFSPHGhKy_oc?}dg+A%@;Up%OMwT~f;1-3{`2 zcj$&=EP{+6fAP11#`T+PXD~p{`ERc6VB~KFb+#Z%13JBBdc7T9oYZ7sXs~18Z}nkh zU;vrL-vYiQr?=w&|Nk$}D1!^~7SL7RFSQsM7(kl_gh3$)iC5n<4Yl(bx>z_$__}K^ z^!l@O_JWQhf34hdpo9Y?;?Dk>zq|HAL+y5kUU%M7=3aNM&Q_3;?h{?k0xbtRTtAmM zHPnkRl-P7PgS$H2pz}?bn?b!|;cn2P8_+ra9Nnj1G<^k~nFn&fB+!LO&O#;33a+2K z!4`HmgH(2J2I*=&P-9fj()z7T2NVva<>2@&Y^Y=e<=9FlhLY5VdQpZFzUJc+*6yGc zN1@i{<$)ltmx#9>sNn^tSz9%d#q1!mY z2WD8G=kEcXao$iN#K7Nb1B#XkQ3n1N&>Ts(heY!M32qM-{#Iqsme)t1@y`!0=g5PK z1W+zuvp)3l5a?b_aGpT6y>!Ei9?*8^(lakwKs2N-sRT2@MNJ-<2`*}qdqG8w2zW^6 zWhugNq+ZAOm+A=dmufO_2fWOe0M(vvx=+98kp@jWgPn!YY5eWwTRD(wj&6o-2M*9} zOW-|Bpbe_N7eURY8t-nlgD;p@FoJUECx#Lm&;{TZdO$V6nHMKOG{o(D!A!8*H-VX8 zw=eGjyFH6B;^l5R28Jw+7kNFP(hppxfj1^`f;T4d$TNVqR9PSIYz0k`fyzeY^%4r; z13Qd*K#lLn60PG5SCrftjx#KfaA!E~z>*>1&d^!G(OJQBoM8({!hvN8XywKS(83SU zu@w(sD?T7=g1CGAc>Whyyr`7=4_boLd`zOVH3ifI*ct&MEjsN$`>yI(I%{`y*6snd z;w|@r4uRXjz#sr>(DQVEC>JT>umqnnSIpH7J}MK`f(`@iChlDO_kVZn3D9(YH*;WM zK)1mEAOTQ;0@_rxFB zFYZkMwIWM6I%{9Nd=AP0YzJTPfUe)T1>(4Iv>pJtdj@E$*ac8Q47xg``3Dn!E9jg; zP-(#53My${f}2L?UYN>*GHr=gbDar8iApzL_r-&+*uNbD-Li4<;43x|i|^n|j&BDU zK{ftoaEw%Im{wLd<1+xh_iK^NzoDOIFl0o|D_$hzCBqCFB13s{r_4JRMM1i zLj+%lulo1@zw4E5*DKbp4g5{V|NZ|DTBB0K3*I{q(xkHov^4e#Lv!r}2L85Lpe|ME z63{{>*Pd=)P~dh#ZVTmyoZSSeiM!n`S`U;+!Ykb@22icreWUd@f9pa}DenqNQw;Dl z1(s@KVqj2oebVa+I@^*jp!?kaZJ^pG`~}1N|NkMn=Ye$lK50D(u621|+Jh>?(g)2; zLEBdunwNg~_y0dbZ!3uRzuY3A+x5hMgKlWUW6GfykxC2<-8Y(lGnPtqL)`5PYP|4v z$bbe2TMxW^4yuc8^S7FTdg;Nzpu0hzyqNIn|9|Vl&{lV=9%%pNJW#z*BgEeiI>p^` z9;klcZ(j&LoG1r$yk^n0|DaP-`McXdQk|_J!R|hgrq131P{x3a$xST*vq7V4ol`+u zC>!>HMg$p3*^jl}`1k)mqxI=}xf&Mh!^IMetsu3Xb3rC`&IOqv2;N}}uCqbSszsnw z3h`7ZwE7e%VedZJ8^Q8gyyZX%Yp)~wYaVco=?JPZ9l5%1G}H+&@VBso0u>ZUA`B&# z-Oxc~aCHfGy)f9_fdS#&=U#-q1C^w(peP1am~KM+tw%v!7f8j`C0#4n4XL)CNrQ6$ zlhN%KP{e~qcW)ztorQz38yqg&tsvi&sx|Bdd6}V9wj1oRUhsgmwFgTPPq}?}FUa@S z9L1*HQ$a0=Zr>-pV9fz9K(-)aXD%pzgKzSK$roS!|G&2v6l^aXu7WBKQ0n4E+NKXp z{}cF|K_`*ERQe0L*Qw{lwl+}Bu;azLHdrYKI$ILGoI+GU-Jf6PNPsFJu=%YAN_K&p zXdJIMb%PT$vX!MhFT$b5`$LVlK8($HgfqLhf;xRKIVBhvpuQ=(0{0EV6`(%epH_&= zzqAtRa){CE#6hk<(d!3VkD>u;oR&W6KKDXS1Rj12xNPi#+Sr8G#+QCS;6`n|40k-j zk08g}Lyadb*H6bCcG zPUL9;HBERR%f`46!3nL2tq;F^AjH4`uP#Ani3xYcu6VJw8PtGrU2)9yj|gZKe+8)D z=3srS=!@}x(AmiiovttV+g5?f6>z_~Tc*+aK7S8*%*qwk%$m{7)_vmOOCC@?Rs`xq zG}LJ_l!P37!3Mc}>oX&$0xYuz)nhC>nk!hCiXlA?yJ3yS{L+b_Kh%2{aVZ zU3wxsJiMDNJOH!^RG|BY_5G57|D`KlJZ}PJik=tu!StIK*Fp4Fa8RBBGr>W5unC-H znvaNpn{?>8-TL@T-ar5UXL-CRY=Si4l#VlaaDp0e6ZkZj zk)R9)Uv~yjNhH{9-+W9XEW^RaodLAuQNZ{=XhOxo!umLW3+O~ycy%2PuB|^YJD8hx&sw&A_xIc*mgHU!nPSqzj;v&q9I{h0A_;2HnovZ*d_=vF!VaxWH2x| zfNqQ7S`5-~0hFjfXOMqngtlTUgc&;bJ^;0E_kxbR?ySAiS$m+f_DHE#H@L~&Tp_?% zDhE1UiUG8HqExt>gWH3pl&9N+quYU})AvB9>k-iMN7p0T-=$smfRYz~Yc{Cj2))wy z3uHNeGiYb~P7t&EPDJLolptsrwDHxa%BT}sx?$LM;c)7zla*`%}D;-x8QsP?4wiSpbc7VB%p z>Dr&94|bpH1SgtO>&Bm;Qm5Rw*VzVK{%C*fW(ey(p?!|o_ex;EfAHqt?%D(0u1A`W z@ED)e{s%gIzjlZ8!PjElwFjD0uP}7G9%+0JGNiM1NAnGaPS-szL5Iy~Uz0x3*$Wz< zEHwj#m;ghuUU%)4UT2%eV+;)c|93NJ{|oQsVS`!He1wOwbVq0HmFCbr3@>%KK&|*I z{B5A~kU)Ks=Gp}e{4L;e1ss9hp&iW!1iCpoy(GGQ4>TvqFm!q;bo+L6haTw+RO$BR zXsDEADB*6lU@T_?=?4v#ePZnH1*M7ZR#2K~JP4XXXuiN;eWA#toYm6zK#^{@YX>N{ zAO!;=0_Jgns=Wi9tzg}*M>@dq(=}V1|m>53% zXTI3&dqMjUX!xbnuiN*CbuVbFh`+soi-DntzuWhKHTZB9{`P#3bHQwF&ap z{~x3k-0EvydI!`7Z&;fB|Nno6W38YAwHW!gv2b*Pb$5d=5dhg;qTbyLQfloxp;)H- z;K2t>j-6nEZr`465yp*-ouM;cZUk384FCWCZ~O_WD*0PZgRUb7-?`Vl7gVfti*$4! z@-fmwGkM^R5t_YuBFzKWpdqfL7~?DL;FS- zi?tOyf2;0)&=o%~+%0`y6umJz+3m{FauU*1V3`0pC)HdQ zLe{ZIN_o3$H#FE-G4Qv(1Vv=+f$rENEhjtog2n?o=Yrc{y4@Z+#+R&b@i!g&_y2!6 zhxJeXraf@Q+CQalAuI28-~jCfcu`_!9lNK_i=649oDW_iZ!}Juk`xa zXkX~&3}QYQ@IMqhq?ius_x)f3oxuK?fxi_rbkOa3rrUQ0WE76EgrnQ_Lh}KZ*RtU8 zHxQd0)RWu}TI^rK+I)Z)bN~cbbLtv~PH^j|*L6*|?-J0srNsZz8KC8dwhzG_2iF(; ztxGr<7%W}a@V6WW9m@tDdFTe8j1L)Y);``XBz?MhDd->~hUTR|K&k2AE7os^7)$IR zgVT_lW_+O254=;vO#*Zcf?5erK>0nmn*&s#3B1;AP7`2g zP7`71bW;FrF999GA<=yfy!l$@MWXD#|DAh5mUhks*=c;qGIT-b)BsR5GZl0QPKgAh zcIoyI=yvVs^pNNbkm;;Y=!{V51`oM_I^~@L;QS8?z)p+K2o}(mk_DjcKOEf-7XM2h zbo;K^#2C=q3NkeSwEyXZFla{YMK|~~CD8CS>k7saHqc>9uUWc}gGO;*1cE{mbP^cn z9dHnW%Xa?OH|z`y3a+=CYhN&yhJd@cLJXyf(9y%%IMCc}hd@ctH%Asm{uUn& z28P#eQ1KGmZw?}irREJg!2Qh3P+IR>Q2FzB% zMJ(2zi}=eqtoMShxmiHtMco=|0ANoWJEICj&zxs7z|$Z@YBhqR5;UQk@azA7P)jk8<7Fs_2^ta*W+>roc0Ir-7<=TkSj)-M&kz?u z-BJo_c0n_*?;2Q-I|P)kKY-2yWCIu0AZJ^HFSOuq2OXbR#0PP*bt|ZtD=r5+OPHZF z50b%}D+Cxyl6ot6y4_j2A!m?#uyh+(gJZMEvz)^k94JNh-2tHX9P_nqaF7Tegg6Z{ zdLRr|ZGEs@64Wp%7w$g)!WA?r3vOS4Y$#m_nndSsaR9aZKt2VHp%{Zk#rJ}uje)-f zbm~QS=@O&cU2fnRg-<13-L4lbB1B4@a1D|$gU>?~1|OLQnO`{fLg_AS5@r$`1A~Q| z5NLkk6C?z>PjG|XSt8%CcPFTzD>VicBi-OBu@css`=E z?5;Dq!DB9+tye%R_rUot;Kk3wu3Wku@?`2{rmr#1C+Kv4T*-m z;A~MM-LMy=l%YiEnCnNz?zu6bYPojDOP?>GbKX8OynX}ik|2gWAj2!5(?g(}r9fSh zA0?13$p!FqqP;(^mr-B25OyxJ7EOuX9HPM+VkRHG05j{UVH=5 z5c^+)nPB@L6cg|h{0GFZLYx58CK*ND;K8rIaI!G43TZ3j;&T?NX4=)r#O`RpQd^dZO1);lII) z?Tr8bcb6{db-e?cv0+mLUGE_9;^me9|BtnSRyr{@gAYvn-@FV|4KOq>162?VFV}+Z zP6GFXMPKy)0G*Bs?w`JB2D3p!8^SM+mw?23j=BC3da)bK2F)D_zF1!ZI%Z0+pibY*W^nK<=?fqB^lo1f{gc;1O-I0&IT)B*3ybJ}eU;M} zALxqVHQna|UZjJkf@gI1g4@fGNe9TvLym56<=5%K0yX!{UeLO5a8$f__vPPz<8Qst z?E2sfC|iPk`r-$_00c0@aRJdB%)GzdLATQ#e?ZLFTz1IB>H^7Ops4rIOY+VuE3jsKoi*fAkC#` zUa*5`$OQJET+k>n*e@T!Ot4>`<^KKOd_<%hbixY!yqak6VM?HLE3j^--INO&MTcBs zlLA`9>UWo!AutSln9lz)8_;Us7k#;Z|96*hAe}+ijeOTm_d(;6#~oNoc-J zbb1JMdWeAfPaZOz9ty`9IF!Lt-#?Vx89)bLg>{z-pzac`z6Tlz2c6T(4&D#^+6E-= z1KBJb2a_y$oF$O)0V?VN6D<`74RW6NezP}#Mf#-jsZPHC4jfo_6LWOCag>TcZ>)vv zCf=Nb@P0qY`~G*}-tTr(fS#I#NC}`F=)HbCFUqAE7*GNMd}5YFaG3G8?pv0n9G$*z zI!nLsw{2!%UGm*bPW{2qda~2^MOj+6gF&b3hi;DUK$g}^rJR# zT`Hh`u8Ylz#juq7zv~}2%g{f?60hI=2c0tfq1*RI^8psnNRR7>Vv*OIx`f z?fa#fr{jNj=@&QaQVx)doBaQSk2yPeNPwZ6a~J3oub0a~1+(A=#)GdoTP~FHXR+>D zpy0^K*uB)dO#b9alqC@BQZw3iCGHy>lMu2B&vdT9h& zfPILCVFTmqZw-~23?880VgBrOz0!Ru zpfmK%i&{{LU&>*88?;%a*H7k!Pc>u@258sW>nu>NdK1}vfT!2bCZHqEw6(Eizgf!?cjY2 zovs|99WfVPID*dccjb8b1hnm>x%PrXsX({ujbm;ejGb;8-L7{!-E=^km!)oj?)&j5 z4N2>agAbxOQ82A$S+Aux+I9PG0a!Cv1B-5*|Lfb2i^k_T!% zM=3X0x6F%aRiG_27hbqywK)i6GYjZ68IaBJV3Gov=F0JMFJxo(1(5Pl%j0@?EeN&d$9r~u%l{)}* z&q4Qj$RUy)vD_~{f;Jh(a+e5nyFTdleZuG#aLmnY?wKj_ppP$pS+9h6B#K$m!gcZPzF2Y8Uy8T+U+_62CS zcPU42=!4GKKS7{fiyuIn7{PlO17RDHZ@l*4-|qSV-{!>^oot{Tf{@LNFFM&^n-^bz zH!r?G+PwJSg(}#6pv{X9UPxa5i*0vHX!je;a=-ZomU3SKdPqbXOcGq~D?rQr0GKF6 z<^Jw8M7jS16rADLn4zagfKR(bl=#TEQ-fobCpheXsX+I~j?n+09gS@NOF6>+2k;o* zwmw`MZV~&xB%s$-xcgi{uj?1kZm*75;m+7Eov}Y&oHzwqWKwEu5i4A()9cFLeJ&s? zG^!(({{`qmAnU`WlAvAXLjOxey4kWAv;KoGi?Tip+LjXsK79(b-5Y*@6%Xj(+Rz`} zH_J3Zi*?vr57dZudvkP${s0ec^St<&4K9Ke{=5EZKF(rU`lskt^SS?^k=lK!pyLK0 zC)V;XbeH~l{W2`PyGDhl`(qb7=o&w^E_cQbH^we^rVclzE_db*H)i}djf0NWd$Fe! zbV8j(WK06aY! z{(=K83u!;}25@}832Q&_z}pY;;NwU@XL|j2;OTbY0UcBbX-x5SyYZm4CQ?%nsY>sp z8^a66D@d&g*tO_LY0C|C$`&J%K$!rjg@HKi7p0A{BLigS+RLDfZv(0wKZ0Vj@ib`A z7;-hNB^!UsJy7G{jiWaXw44pP)2LY)bgfix9cbkkOh}!fn=Lrw0BH4bH)!oKTX@C> zIESyd4RlIGK$cU~3xnVP|ASIDe`_nqXue+X`2qo1j!`c}q5JD|pc0_{_W@bNe#XG zK<70;j*RFAFFdpU%-=HyGyw%)?6AQyPNp;fv^3HS)av;FIcu2dg-zk#|6u{Wp`Z(A zz?%s+#{d5x(0v|sbkK`Kpk9CJg%_zwpdP@H7qMV^$BWP;P=lQ3wN0<<9Z;ug`7%%m zPz%~;=O+O=e}kp5*MkRiSF@tY(6P8YU;|&gU;zn4f>v^T zK|Xnyg<(e@C}~W(2ud0};5woEBlz6qKb^53x@*CQrdY(gl;~!0yqJ*)3M9}40THMd z1blcQ^5Gw7*Keo0$xG0QhnDdMrS(}6FVYf0>l8rCVW1~)op>?z#ozzkH-dY8K|MFd z7q{R4``=qv(Cbzc(0%^JCQzr|yw_Xeg~&E=A*B1_HuT(C&~o+HcYayVKDCv?h)D@BjY|%fS1rK-r`FN4M(-MAx|+Vg`}`_~tN_lTJa$n|6Z_ z7Zrq@Yx)9omssn8lDDtf8qz^W_r-$_H2l~Ny5U{-A>SI^=@a4ERN;_ERmm= zHd`E?n98Ag6y+OQWi$H~CoGMR;eA&aATD@buDK)Vgk<^TO3*4z6ABzq|T@Bijr5zzXG zV5o*{(BTdrtiSWOUIMkaL5ul71_iuO;f0=z2{HJ@g#Z6v{sv8U3R!Z1oZeZwrHuW! z>jOpyhK97x+C6EVwfj12k94#3hVBWf_DpB(h0fY5z2I#Tpxd2ZD7OFq-|g&> z#nI_Hr<)nF`=ZO0JF>T!qjzu0fAIQOj?YUwz2|j1be+))-pvv4LhUCsy&IqGc3=UWp?t9UA7iKQ1OAp0 z&|2MZ{H@HO;WfzO0^cnGy{(|x+W=5Fy#kHafbXez0175hDgy;-z>9rcpv8hqUR(y{ zs?swrPRBrRs)&TR;zd9oXq*RBYcQjfMxX)?S>OYtc;asfN6doyfM!AeF_tQJ*FNcO z-SZc8bBe#giyhzo|L<)DWr$vXm4Fv(bD-TFNJ78g`~UyTK2ROzyQllZi_f5&YU)8; zaHxQ*kv+X|Hz8JEL3V>MAq#-rge>sjC3uT4!lWYdO#-hID}}AS1(kRYzJmM(NuVtS*AIJr_q>oh_4ofvv;Y79@9;e3#_)pq6f;90YBn|9mjJ0JJIg#hHx1|9kyvK-u`k0T8X-*Q_^D$as1?>R57gx9mwO>-z*c zXwumRx@Y(W56I2Fpo2k~UNC?h91CiLFgI5lFq8&2RJ$;g`gVJJ^t#>%=nZ}H;`$8G z!Lc{My{0DtFD5a8rj$Bec}mRwm)>~67YRyfPhPM^LUL3j=mIFVZnm)h0UX_~JTE~9 zZFGBkbccbqlLrR;58?^#KHphv(OGQsBKHSqV?kFN=(@qy+a2zTB`P2zcSk^s+#G?$ z$iuJ8jBi`URh0R5yOlK9NHCPxb-QJN?;kw#-(<#%t7)K%5&e0%D?!n;`#3xu zfsX4w&h`M*S8`)10aF|oz!VR-X9c>3T?EuF?n(Rmzqbyw6^XI?{0qHVfB*OTYrH4} ziTcHW(rrgv#EbMaa7yY0JGnD1qcbk2Gp?XBuB0=rqBE|h6LhLfX9P#*JW!N&&I1i! z9%tJFwvJ^5nBtfLrg%D(-5F30^@fe}qW9q@o`Ck@N<`otwOW`MQb)}yO8{Jvg};c$ zkmW$?#yP@eVcj?$L^ny7BF{)NN44`giz+JjgBaaV@u_ zOW0p5UJAY*2XrJH^e~N+Ag3svc4K(4_$Z=x37(-j?)rxfd{PLkZvVdxlo(%}4Fw(L zUGm~+D5TJ2js&^f+z%ug^I|<%*5k!;FfH<8ekeFqG#}xC+8B58Fev1B!o&WTs0h3` z0J^;4TlbF=ZqO~>{{uk7_DrCA8(^0J@`QDN3h(~etj5rs#=_7W`sYP#!QcO#u3tds zuOIIW{ZW#f*3ALBX*Vyexq^wIG$gJ0r(+RkTJz7Sa^~iP3jEs-Hor(J321)7S|Zi_ zf~7>z!=r?=`2~BaR+h$Vt}Kz)Y*}2dnX=^KjW1<6L}oE+pO1JUdV-n3GW16gcR8!2 z>z5)HqXVGxW4?d}M9#nXah#dqHFLM?7x0l=pxZJ|9^PRB3dFc0p!hTi?(_wnE)y2s zed|R!=#b}cmc=amZPP)WLuS}*5pI#-+afrbkAYU;eW+#Yc4h$$&%1u;J`KJz;z3xz zi#+gtD$tz~PZ&yaLC3Li*Zuzwx{%%VKtONkgBQsR;K}HqEQJ@mAs_=IOL($4dP@&P zcK`Ui^fjn==*toCA{I1v?Fz0WL5J}cFuq_5`TO6xm?aXjlyL(i_=pw6SvR1IEg!si z82lG}d&Hw15g_l?9|n03bbi#Q?wjFhyQ~z7t*`5w~;Wr25MUL*! zI}M2f46O%hHPX7J(wcv3m2#yuS1~b^NCdsEPiy|IT>2f%Fa6MvD9CWkQHT+g=sOvM zUT6mY{cl~z5?P$o%?5I2FHgmbYvG{a0o~4F(F(eqBMx*s$2sle0bs|yVA&12Gvy5f z^n&dYY0$BMzAs)FKmwQtWHe}-M>XT?1t1q63xWg<6PBO@kF9kxhIM~R>lOf=fan8G zn!O%Or3zh#Y!XXEY*I_OY>G-PK!+r~);s1V%=lUZbUM;&rL^W>#ia_pp+8>y{qz5S z%YhP+Zr2~j+(a2W-6XnQ|8%;^Y+!uNWOM+Wk3M#@fo{QptiozmV~9HpE^rK9%y{q* zbS|s$0ZT^yDF+Vk$OA>+frF4Np7DTzf#JoyK+wP)+Feo{FRn8}x>TU(QU~33gETt_ z9~fb8xDov_c+ z&C&rn{j~|?4hyI|vI<^Af;3^??qLZ!b{l%T$D%^evWqW>+pJg^c1!~q^YH-0J6Q!U zgs>UI^Wqa|8#~At&|!P$Ui3GE%OZqH91MuAJlZ`WF7rY6gggxR`#%zVPso4s7gs;#JW!A|fs{gmEVMgEg#&c)>Vfc1 z*bN%Bpu01ag1he@e9RR5LNDO&|KLv0`GlQy9REuh0$#Ko1XX_m(V)6A78Eydhw*i@ z`+=^nQUqD>`W@6EJHCQ~ZP$KKupwP?(t4ni4O+&tbi1>FbMS#qH_*}Ppw=l%w>zk{ z#n^hF(~Se64%A>_0*Ud!#CqKYdi?}I-A?8gfuK&7yF;&^1BlP^!V%0b==CcA@mXK+ z#{d1_>t56AR|Dd+z4#mV_kV9Ys8!kvZkvKc*iW)8Q0X081ISUrgBZa)HMgUIf7&{1cQ)9||6!CNuG7sz(EgSt(f;PaKb+d+4; zcD8}Yu6EFJqz>?+q^@?*IA{lWG_W8 zY6rKz+dyPjJE#rb(FP(xk&iU30Lo;FXWSTGT;7Wo&AomCootvR@4fB<0Wa!e|NaNX zd#}4p0BANeFBWtTu|}_-0cbkXT?aHB>23gu6vh`pv7o540nLnpntm^wV*mc{a`))= z{nFv)(dF*h;pW-p?$zPu)#dKp;pW}t?$hDs)8+2l;pW@z9?6X&%p3&)+(dC}g;g$pP8?@N~ng`oq4)WNqJt!WdWRjsh z2IB4J<0|33ekw1@W55Ljnzh{_pqyEvA`otUtwgrlvX{l^;)`ycc1s@>o)Upt&@n*F zy#b8Y*Giu@pZE{H2(LLug@xs1*wg?2A*=&%*1r2Nv6Sa9)@wNH9hAlK(hbf!3uj$` zvRGce`2y2h_7%e7czFXV#_=)q=J>YDgN*`1-`mtG0`_Y2BDI>g)@n}3QH z-EaM0B6f^T!L9pR_xTso-2eU$d%>}vnIV$-LxUPa%k2{0?yJ3ijK|m%Ua&GSFvQ2j zg6@RA)qObh;0vDS2mGMIu&Y5p#hoFGt%EJT*Nv$+pD~Lus@In>i}CWK?z765zu%I& z)bPl);gD`e!2hVrkFprM&%;E$K%xRsmmfg{n%^@wJo0Wnzzh-&_}BWscH_6>93|Y{ zhcCWRQQ!&gaAW>#z#Pfd@<=0k&_)nZN>!2OhBUgmk!ZHl%SeG(HCHLn`6x z4dd=UeawwZ;l*yZzyHCm2UiiF8q^umy4lif9T-ZLn(KHNdi^*`Ih!pR_*IfHbYFk*$mQ?<@E0rgGBYs$h&;xw+wI1q`u{%z zL$5z$!2dFi7Xq$-|G&;ivp!Vn*Bu5r(|F>)|Nmcyg9O;S-8hWDz2-@?6=f(j0Nr<1 z#uL`-&lGTs-QbuzW5tVlkX{{-QlV}?j_&I(PJ#ra(`QM*OLE1*9jj0O(LBFE$VeW0Gg!u9QF4<_(14j zaHGHb7O0A11GVHE6d0O+ixlNH{$^lcVJJ^cYqn=BVb2KBc4v4U`@ft8_ z_aZU)FK90dM9dQ;cD?&t7EhKyMu4_EL-30n(9k7FNFa+P!v`!B2@*Q@LOuBJ|L$|a zFAfF&{r{RL!$sSjq5Iqm-C$7UMjryt!*{!KgmstlSbr#k$iLtRsTFBXw`^ z79PNS?FFbW1e(9&09{QG2p;9=_T}mR)LHwdS&^Z+mV=`hqP_e4OB2w#a67nn-tupY zW9*FO>1CPA!N9;^?aEPpwUg2KKvx<|mm4epHb1t54>-6F@^ABF2QwP#m>4=;Irv)- zfllA4V`kuQ1=UNOSA=#?vinEm6wj z)O>)Y`5;U4FV>oO&A(VnOq-8OH2&YA>dsJfy*rktyY^2;3MkOezt|D@_dm#MrSc7R z%nYTHphnsG7n(tT|G(DzUoO(^`{%{fz`y@ryJRFlG_(i){h!4Y&%aH?93%;9iMu!d z=cswtdb>=%`4~s{?{42eS-LMCyZ`p})F6HvbnX26Z%pvlt`NEZIuELEA-G z7|P#(l!Njk=$^Tj10{F z2fe;40$%tp_zRsMWqi>d4(m2Pc;V;@x(_O^v33Oy1H*z6o{Sj~z4MXu3d8j>z3@iT z%j){~zhyZ~WGPR^1cP5Fhn11JdYfRg1|km&i0 z0&RDO7YD)Yuopt09__c1qVDrAzK4QZG8_!ehdElml_h{q%>E%z?8Cp!L;~yO%W3@E z4uFi^W{#c*U@~*e|Nj5)%F*r0VeR^+Xx(d`j2wvjoWuV9-wf_)_xi4Q5wsHAJL>|i zCqizj%>X3_|IMJ}-~!4mpfOMu@Xa2e>3z_(28_L-Z-O!sK*!614vZGCjD1t`05rm} zJ%W+pe;G@!FKDeVLi%~qSClq-v| z*LTBCa=F7yoT@Up7p6O=U@ZaFY&ZK|;-K9Kx-4aeV$G@bzlj;N_O;U(_561hhHg&KW$RhYFCIVp`~Pro_sy{I?qZhi zU!ZFN`F?}$uI(&mDUt8yH$Kq%t&FRa(V_Vui}kUhZ^0RxZ##jqtpd3H84Vs1=@#nd z>}Kc|nE*Q9NvNCSgtjj>l`d#CGX^Gre}E)Jw)gt}0Sndg zbhB*lWSQT6@8Yx9M?gbAEc3y&8V^HQH*{@*ST`T&(#LL&7cXl-?VK0W^8fyS{TRIZ z;J@e{26s@)l%v;=rIYOipXXn2-37YiqeO+{#ZAyI3(vElF}V_^?i=pbbvi|l!HM87C@Fn3{=b^OA0iUfmJ6I&lIVd}K7 ztQFvI0}V@bmvVHw>2!y2SYP080yW+{Yj^be?g1@BSmF!HOn0D@PcNqWf)>1T^!nZb zO{p;jyjTcoUerEdF6PNH0F7@R3i|v1^}Aj-2hiG}@E6v>e?gbwwc3Hx{RikwAZPc9 z7i}9Mm)n8X0)aZsovvG6d_4myIk$AX-U$!rtd!^u-2%E#yGrJTz!Z?@_`#Q9bo=>$ zwm7|*Xa=qcdVTiw`tiy^jC8{Y<)L4uZz9_QN z_I)Ak`o^i#PoOi5qti{q_&@kGhZixupc3y+_lFk;ZIP@3oiE#c>?Qd2GCzUtFcE8i ziBeYUaG4V2Zg&>Y-s+%kiNJvW!2+!Z_*+4vDBW%Xo$eCdZX%uTGTpu}x?SIB`%6f> z%NSp>zEI9n#A@j)P|VsLEAX1B`)0R0OK&JgQ1Jg!9`JA{56F;aP*=c}gV9~0Ib4PT zbj!{G#xMavHxb4#2|+iRZZ{cgHljdF{gRx(Zmv{wcctTDCh@pxccF9`+)w2TGH>U3ow|9e@&;AJ9KGcdVZGrzF9hO1 z$>uL2njQ|WZ&c=6L7lpjmfx7MmzzcU!HIn*=p}9_j0d^^>kRGU0qXNDZwaW+MY1bzKFHU-bvf+~#HsE@nBNBOe zC!}W!j`m(hiQYgS(5(?KGCe>o1P<_6nh3}R>sDg8;3%kPh~|O`x*!)AfL*|Wi+%T z>jv_4z>BHgfB$C`u(&gT6dnO7Jmv#-OARy$fI?$8s9Gw0@0TfnQW6}nw{g1c{a zd$2VBWGn;qef-11TThnocZ1fjRdYmk8+=}RjG3{ynuDRYnxj^?*Z0ATSxNu@H}3`w zEi+|tM0S7pytG6Vv}W6v4|i~70$Tgp8T+SJ;J@h}ZIF*%yg2Xq_y21%&^kp=j&7DliwF(=7Epg5w11@g z#EVPkK}&*sL92@xUn~Xt@&f3_Iado%dlR%g>Q2Cmz3zYiTY%SafU1`gzW=5Nz^31M zQRoS(A@2108~UO$ijr93aD{rUgjGR~&VG`!o*qT6N$ zsNU)IH+W$L)#Psz@Inot$)6|uMe?8j|DCPlY>LjtgBDP2HvjuSax)_+2dn@wyAFer zB)shjx`^44r8`80CD{0OH>lGqGNId%!y-zigrk{(Q80q#wYEi+Y>7y-g8-vogb4WX z1jYgd!3vevLd^~wjDit7P%#O?3Yl&vfo@Npt{|Ci!=QlwVHTi<7Yjpkr3_OEv(bUW z4V4lMrJ!v=FG8dL{{MDE`hdgX9SNX_*|`i9G2nuvmZ$q>w|F=A3-Bz0aW4-;TCG6K!0Bd?+5 zVQ8r3U?_PGHKz1lTDOfM_zEmG&=pvv=hB*M+?W_jk1?O>4dw|1rH_v;pqvf9=rQ2M zJ~vR-e(@sF?C<}`4UDfB1O_&zs4y@DhlZtf8-}NKTcx#rD@pA1Q4#6Br5U0klGgga zBq+`Ldx?32Z3e3c14F4;_xTq!puWnvwC)!#imdmd0sFj{rzvb8FV~e886f+{H=VfAR9o_ zLeRq+dV9Bk&fZ+_{P%xv?*Y)kEv0{6EOh?+Kf^%JodF^XY8C3c{r%tD3R2tatr76z zYtz5~mYYG-NTpKUt|A#CAjKXmFV@-q{SV$|`4Y6irMnw6_0*91o}qU)h?TZ0hT%o9 z<=_9-$7&;bdqLZxUtG@k`#-$0nN|)&Uhi$2(Ewl zdtGOMh9DNX{QZB-^*!VNQjj*r7q%vU|AVe1jx4q4=6~_A0i?K8x7$}FJmZ6|JHrc} zFQ6rn|F?pC_(H%0WCzGEFIYk5N4~r#3fhzpk_63gzj$v9SMbCbbi#daFX;4{7vEz4 z|8J;OV8~*P1NG&MK!bOu|ARO8|1aJ1V(u^ST(uxXxOC5pA7Ft}uKl2;w=YkKFfjC1 zd-S?q0d*t){Q#Aypy&aeDa=;l)Y}U3HOOC{}-zq|NhTngoyty1zFGW;zT7lD4i@^g-fJ+TS0dK zz)SzmZSw*@W=AsbOUI-NW}W@|JSQ}eV4q5ac5*`um*)X zXNhu_!i!smp#B$R$w)CrBy7n@07$J?(7*r2|2u0pbk=SGb&-1i`~ff0<$4ho{r`Wj zvqr;Ghrj>-Gjz7vfR<;w?&)j=spxfG(%Gs4T7K@jp|e#3%(xQJ+w1Zdted-YuMTLH z_Z`Q-|GP_N{+C|qKG)6mKfuHKcnM4QkJmZ>OC@?C27wb^z>9OYK_S%ozm(guwddde z|24c>jPZ^CSsWM|N||2UbhCy3FTDaurGcOWc=!AduxUL|y1Dg#seJQZ(0O=_WdYr; zB9Or7^kV3Ubwp-v*%4cEgL$29Om^9FZXZx3V!Z{ND;r9k;*=uDrMe zQty};}(ET_ap!&8% z2vls?=(;n298+%j_y21HP#UVOL^c(alUy4AfX;N<)7=1`19#?lvG6-6X_fjzUG4~W z*oGIDAcq}u{R46NX;!$)6~GFvypS+}cGMyvA@$-?)c^mGO#_)ipaK9K5TEoR0r5&7 zIUs6S89~dPN@XCS0bWIV0;J+Kb9bqX@qf!|j#`KRraM3l4oJcF$PQGO?E%df^So%N z`2WAt8MK4|mXW*l|AI6{)TxL#-#03BeP07^0p zhX4O}AM5pF`F=zC0O<5?<%7Mw44`tm6||Ay#U#D|{~LCL1_(h3oUgN1g1@B;bhlkE zXo>fWV!i+Wdz--xt6tDqDInMJzX-Aa`@b2i;D2-PAJC=)NFmU<7kt*I)w;j`yTRuU zb@z&ZVi0`a5aet+$kOpn@M(ITy`Xd80(yHv$E?0+@dlk_1G4p)>mR-ss(SzbzXY8F z-H^)70IK=;TNOYnQ&I&OnyYOX_}hd)Wkj$=H&gS06yyKhCz>spO61)^vnv1Di#}yB zg0^lnTQHPz!|J|Ipd$>q8UMQqG#_H=b``L8wkbN;P|M8#J+6VR``rHkht>ln?Ag?nJP zFApfJ1YYnMgK{FsOVASeknZ3At^XrS6d~D>zhx&MsB0&Zk)Q}k+_TL7{(rdyB*@m= zJLB*F|DYTi;L>`4AAHbXcPUSE9Sb9Ws~~voI=E22kPk1EML{lM>-7bl?I8Hy;KdCa z$o4D{U+Bee1&~6Jo-78?Nx+gNpyHap1ynP4g9}Q~L9;C14l?q$%m9rOfD8R*UylEs z;8X*R&|VhMZV7OT=8%MpgFwN29yYU zCBTY6`MkFkoGg1~K;o_vCBnU~9FV{a=ymN0cp<3|TGYhFJO^X8cAACVI4hTX@&4Jf1k zrdzUqp9->R4{ZUf&Zh>>L>x8d8NBpiR1C zu75;J)4(-PLbtO;H$!g)Pp`8Fs0MdbV_;~gRc0vVY~Br8-oj8~2TFaV7SPJ5RR5T} z4I@YQV)f5fd_CzJ~P zFYWnXI^)0S9!7VD$kqdqCEAcClh_L`?Z5xsBCWw@6z%z63QAC-FTQB~{qG)WU2RkB z|GFL2^P6h<_kRWtsGJ5L6e96L6%=m14_-_J(XKtcz7GOk`~b5b^!A4Q1zo>nVg(9p z5If_;4$!5@x^tN!9x6-hcD4Y8Qa8(v-U6Ny{@zwl4D|Z(1iUy0j!AGsy40xke>oed zlql8cb$tMuL_Y^Q&mQaq$rmTfL8-j7_J8REQ2e~G*ZTWE(%rh+rf8w@|6bpQ7nSym z;HWv~`bUPp1+=aRxmM{80o^Ok)9cz0@FE#>x;r2C~07ibq1=tMbazu}ncANdl+Zg8yj`W^^-@zV>m z*xLGg8Be$G0r+9nmen?$wLJW7;O$POGN5D(I;#;;pMxs$PVm8Rui2ZIg8DQJpk(OF z({0lMY8cd+gVHNFvW~g_Q7943cmoOx-z6_tt^WS+a#ikd<#_D@Y18)l^8~!$dk1dR zE;;7lQ`V9bL_!tkdheB{1xNsYtKyiElRoAvxlIsYF*Ohx7qu*8_pw zrvpHd-s{d2(0n`v(r^z4HCC%YCo%nK{a;!K8VB0~E}#QImv%sIsQzCHa<=@7>*}EC zK%U5MR~~C;8~&!Fpu(}E;~^zjVp4kH{v45* zI2Hc>@7@dY$uZYI$}jmq^=|2s7e!D*vQP}Eg&U&sf(glxBl6&oRDF3Kd<6fJ7sgQS z+9=xX;M&z*9DasyLn}nP`b$u4*j+2q4NVJS&=!)|G4SAyD^H2#|I!05uBkyi2J+V{ z(0OCvW3GT<-h@^3(Z_k8K4{msuy1TR0T1?nd_Y@ z=;oA(ppzIwuXOu9c(ExK?1C~-VRSwqV-Ls$J3ywoUIAzKZ?d4%H$YQI;NI_RKIEw* z(7fe?7qdXdmmYXA31l{?*aACqsRAr<=)KSa83+zgkr!`d!Oqlw32Ll>N{eWaw&SjU zEh|Awgi{q5GM0cdpTaTMKZY+@BEfFW%jnT@2TcKfee(Z*H+$=WQUQqD z#6hzVFJ?_=WC%;6bwaoD4X0OkbM) z13Blxiw;Xh2IFtW|1FDcj=BCZD=X;+?T!SUP8|rk+3o-+UG;#9*j~^zC&yg>n7`O# z^!GpH`0L)OP(h0qrr?yu-*OeSR2O_D3b=j~mjNXWkg6A#l|f99$smhf98reWmytz1 zy}h6_hF>IussS+bnCl*FW|zj)8_^Kq4Ub9CQ8S@S=kW zT(*J?cYIMM54y+gkHdfP5vnhgl|i-4RFH!~R{_L=m4bUH$6Wt7z3`9+&6oAO_yfAa zV=GA2i;o~CcwEKq#Zx8letUQ8+9&)?>Hk52z2t?o1tUXu?Ur8OCE>?h|2V$@odwug zyTbUtW$BhOht5(F&@tb>B3Tky480~CVJ|*UWoBshvctWbq0>#kx^_#^VdHOE2EE{e-opZ3?3l{T(CxaS`3O&EE9er_Zr3HflR>j) zy}mO#!FN@?=w|%?-?9|c;&CZ4%aZ5?AEy}>@S+xE>k*!A-x;0Yu*+hM=xhbumeSb@ z>d!*db+&@`Y==SY%i;(K3;Q3+^S^Y)i#Lj(LS@N|CyJ1aU>n&B4zw4+QiynT2eDx> zZT6y$1(aGrO%lTwIv^=uP==I$5dzx&Qz`?kq4`@nKpT{MK_}C{xM0S}02%sneR0H$ zk-_-(G0IHh^wkD&6wp$)CUfUrK_E^A+g@pV}UfVFN0}K0g3;XP{~2y8DllkHw69YpQbT|sqqVsqWm<}q#O5z~h zPHXnkknUDc*VEdarPLF2HcBt}_KSf3q6Zj2rA?_x^KlMHEQTWlnUeG>faBt%U1IRZJo84Y~mjCmSb-hjPIFkOn!VCyNo`kW$NT-<}sY!$7GF z)be(FQ3bUaWPZ_-m!QS@kgZ{5@Byy$e#(JL3UId&G_dfZSPs;I z2lalzqa8QQL3jLId2tD(3^Ys%Z6fq~{{P>7{G~c5KtOG@fQar7AeXg%>-C)h8GLvl zhj1aN{slE9xfwb9dAztNi{e5vs0$6` zpyNDH7ryrR|G)d#OVC=-7gNOGVZ{kD4dfIC5Ch~CP-+%IatUY&E2NzOc1a$>C1+(J z*#qVhcT|_G0c}|>z4Bt2EUHTqJwUg5gJ(ja>%^i@9+Cmgl)tzO+6>~S@j_MS@Bi*& zafe^Z1^)fNLmf2Vz}pL2><>Ob5HutEqAwoQ?PGZXs(&NnkoG+s-r)jLf42uTw<7>K zauB4Wp^k^4#0)fXcw8HlkwFy=r!cAy<7H-wy8x-QQWd26Wnrt3Y=h2WVNwpOUif z9iU-A>)-r6Yd9Dfx(z`4rYFGnO|$j-ehADc@Ns7V-PptUA9Sg!*upj1?hF|PrS1%! zt^&QT0s$}P_AxV9f9{C=1J%gUUAhLeOzm)~Gp6E#KG5ncj$YRf0pTyU2r@8$PMUjC za=sg~l@Mu}nd_66ANUy z2O59^-NR_JqlBlM{o)JIwX9p&85k_)fyP@(c)QsTzF-0gE?@`UO$1#@*9*Rnjp;>; z0jO00x>E_f51v_wfuXw%G}i<=r~Csbd%8+=#`0K3u<*CJfCk%KCAxiiI%2uI89+Bb z`rdf4QWJF29;nh{;co%;?YdppbjF^roB=Y0zikt!hg>Jn4Z5h{M0djnP&2-TW_pmVwUa>2!TkV-(QqIs-Ip^7#!Y_9uX}fkc8q zYXD!QL-eUZ1}9ivUI_A4&^!43NnPTo1?cCBomM&`eI5Us54^y zxik&DLUKdEi>HF1{ka`kti9m#MI(FnPWbo#|L3K>zGq(C6ax(qUg-8c1Cj=b_p*S- z9hiG<8Y4e1{aK^_`-85EPufu4e)|OJ^K+ow7jBo#DkdQ*hgo8D#${ z3DDG>>jlt))F@Eu@;#Hq*y+j<-&@Gs<@VR=Fn`N_1_lO;xc~gE+dxUhjj{R1fBqIF zuv&#~PnB+##%>RrgD*kDlO<{vawUR{dqHQR3(f^K(_VrW7c=e!rDwspD?mO6tueNU z@F_8eC`DKtl|^2E9{3wg+`H{tpo8 z2455Kmy>}Z1Jp=(Ater8YR3USyqFz);Z?IJ0|Vq}2~hC}>WVXWmLf{YTF}wL99`f| ze;wdWf?e&P;jfOir3?%VUG1Rg>SzOPuIOq9O(k@+fv$Gyb~Wg9s{swPA1)F2Z_wKZ z+OPA%cq!K z;VaSE2bwAF^*z%GKC8UjSEdtuv{)zj21U#HpqyXA+3UNZvu_4y|6%Nl&e%5=^FgH( z=vLU$0#FO+g9@lj5doDc;De19f~LzDdP8S)gPNi|FQmgjs~`TCf=$ z3r?}Wppqf7M6}mcAmc$cXo}QT;N*N!h8MLRpdx?93z-0LVZsF}Om2Z{Emwia?taiz zV`uCM>(iaFPdZ~&_*ISDDw$ov||At}?y8F9JGUPrNw0 z7<9h#8_=qfLty5O7k`w&ZsYBY1+CY!h_ETKwv6Q{6Zv1t(d*&U?cmcH$&%J7@#3R8 zG;C%ByvV-|?kIwSf$v3}D#U>Qr88bDbo+|*x-JQLk$wxVg8zjLT*Zf!P&v{BHuy~>IQeoy_tA26yS@NT(8KCjlZQ1RCBR`4l04n zD*I}H41H0`1NICT$V3AX(CCdmJW}{u|FeT?ZT=SUQppa`9@Xv%pka7s@bxLe6F{Xy zXXt~9w0ain)1aLLprds-5tid{4XpJ5tAWjVAf@nnVQ|q1ZtWlpfy^|XXJ=r@3V4wU zQqt)P$+QCCOnVb_Lksvkn6O^(N++()Qk55%7s6xy1c=%G2UH9DnFPG3H3Y4l6#-SE zFN|)254{1E?t(8`At?i#YE?k?Wa;(#IlMT}28uzA&NzY2IEl_Ug-$o0&Nz{Kk~qlGJ*0<(E;l43mI{IFga$+;B62xi9tT~tF&{KV z%-SUCF(j5Dx|NpH&cmDvH0yP49HW5A#cDsVhPeeSz zV%w7o;>Ux6Sp9hXr*bNwUI87osN@W1p;uP?`o-}C?de>oMjGg9G2 zgdn8A0G$ey(DD!JM4&DU> zdI!{u#;Cu zLmzbe8bJ26|1Z7MEg0}$h%U~HhC1&uKi1fG6?yp;biqR?M{xJK7t*I0!My~U2ij3~ zNTAu`bX7bv1A}F(3_s)|5?`4Yx8{HnTc<0{-KGh3+d@8EA$Ay4mb-#dG0p_l8GFD2 zTuOi@Jo#HEf*Oym0-zpE8;A)m%egy1WjW+mek|RgZ-W1C13B&gHc*xG;_69822kUzq_EqSdhR*I z3UQAWFLbN{+>wQ6@?$S!;T2(NXqLu{*F2#3k1P=Yw@xIEGeqdQLmP`>pq*z)v;Y0? z^^*WKHNs~@+IHYj?(|dWZUFfPTxke&x~X)=@pQ(Cyyga%Xa`f9Cbh~~C1MS`7 z_+NSev}+3#1p*~rWOx}|v@r9xfLDfqi6d;Gj>g9tO(@vBjaz~u4kB!Swt|Fh<1ChSf8%p>vmP>c2McI>1aMK@mky>f~mxy z+kwOSaE)fSuS7Rzw@qX7aSrR>B~rbvD-h$GwcOq8ovtfD$62_p`R^*yd`zUvdhx>&FrB;!VQe|F6ZnYgMd&gH~j$0IfHic>4eU z*KFOTC%S7@EMpBy+^j!$#vbX6JyF8j>v{w<`M!GQ-~X=_yIr4HA1>j8T?u=n)Aht_ zo^E%AZhw_d*CU<2C%Rotx_ysya&-Hi==5N*{#*h&#x-lk-~X?f(7c&AcWB&dBze5K!#&o!nnIW*-k)zv}12ifX+|AMv7T%fq z;eUV%Xo1g*v>E^Y8y|Shz2mu%GsEE>d<^Uj;K+pzRYikN3d4HrI!`s|6dKTB&^lQH z84IB2t$(Y6iHc`QQ=@LVGnx| z&k0I<$3UB|cldz(@w);tw04{koOwMZK)z``S;E%M7zjGT&lfSc2Hr>ZA{4Zu6LccENGIsJ5|vI5ox?jSLGE@2xf^`I zPiN_e<7|8M+!;FESUO$*bh>GP@1iv5bTjF6v*>iQfgIt;^g>h|)P4DKoNWoHm^ubO zw+OU{2=n;+mP%|Po(B`f9pWV_9FQF`@MG*C*O@$FhaY3NV+P0z4dw8`*#Bh?pm2Y2 z094VHnY`EmQXARpr}3f&)D%EEGwSe;{UE(A<)9%>P`5catkd^J_or@O4$%37FF@0c z-FCgcZvw-++5ZQKfHp|*w}OY%eL1>I-@MoYswsUr!d^%m1g%=i0Ii8y5evE*$TId# zXY3#TwwIu8f$xeJpfPJuJH8d9CICDN`eJ_a|No#HA)bTOfF*i;cLcnM6$h=nPfVTODy||DDF=P?A-~OT3^;kf!>xzJ| z7fetI(7;q$XY7r%&e&U^K_~WJ-y4Bh8eyPGLMHGv38lGd&9yg#OZmH9AAqWb3pEMN zKbY#H!J~P97+)Baf#RA2WNc^YnHSEC3=AEyfBu*5coEA6UaVC5hQCQ1v^U51&;Q|L=eIvDf=R z+j9H_UMv&&`@h*w~j4N+PQkz=)mjm{|g0Pbg};Z zA9)ydO+fgI^Pn2cou?PH6zVXTEz#>I5%6L=m<_rFAmGJnFx#Nl&miE%e9^!EyWBzf zq{Gdo*WDrDMXxC6x&WVEKcDayjiAwrW8muoc3cCcy%Qynbem=H;w1~HIKepdtOXS5 zek|Q$oh)75zF+>kvA{DM%DGw!!QJeB-7*_mZdldcO z{KZ-jFFp?BJ?zJX{rU$wTC5GE4EdO_9j`!cm4Ufcw;e*4+!$WOgKh2pn8ov=0VId%_!J&U5(J$tcTyR{@vtP( z&5rN1stZD(=$Gkmlj(Ao?QoOra+m9Hlk0Mq?{Jgva#sMQSa+39HOt-s2 zr<+1I#DZh+o3TK9>OjZ-fwyLJSh}(Bw}O^vb)N`7_>yV=nKNg2dR-V9t&exQ{wZhb z{?W^_KltDSrhpd_On?6y-;T6CT%z9_{@?m?jY_WvlT))N)Bk2qw*SqZT>m>F|8+$E z?~v?>WbBCKYd$FARr;X&$7?3z|J`mZ)`z1@gnC&TKxX|n3x82u46X$Jo4rtD0<{VL zM0VPBx^cwELF2JTg{L`uSETiia;EO%y(|s~ zA20{J*v$wUm0;_v;{fL-@QF?@xfmE2c0OSDV0c-;z|4>#Bkj!aqM?MDA@XnrNc6vG z0fRfk;T`>;;PxwoA2tiF^(Gj&GaPqgsR2_Q9TFfOPXd@H-~*;aY`~NR=m6T|ZZa8Q zB?=}6?hKuAD&RAZb-?wwNwc5D|IRpv&N!FOIFHUaAMhiwNVmjjzdi_$syJ#-* zgLXndjzK=k|Mx%WB-(kP-h3zcY}L+rpjhgh2dbEw`@ky+K*u5@A5z;nZw9ClFmC|^ z0|V@sWYAb~$2`y|amPH+_;ANO&}dA@JW#8*V;*Rzw__e?khgOlXn5^78wc1^EMN3N z9_F|Mrg#p3DS?9g3SJ z(5%J~9h`9ie6>kcAvh7V9snPK+sXD4H0m6jF~J9Pxk)TcvgC1aMgv&L3no;`3%>oV zH-P0O=$xV83<2!(p!D092P!TgMFsfOXUs!!%L-oX z{`cqq|FV=9o56I%i`D=B{BJ(O)9dF0-q$7b9VG4WVhUJV=S2_57PQIhKOox_K(=+e za)8>c9yOqH2-H3=73gOCU&`}8faNv!jutr_jdLD`9UPb47+&1T1vT?sA#MDyZjTyp z8^4qXG=0MHntR7lTn2D3><|GNFdJ$B*bxaBj^KICy@OL8w<8olW`u*x03}Y)eN~;Q zAG-Z&I%EHUoFHI*xHP>RGTq_I)6Ln-($LG&*zGG|eY%9x_>zSL|I|aBg5AC%)~8Fj zj4xS4FhT@EC9E%($TxHS?{?s5{_(#=q#HbUVtu-VqnopvrLo&VrIQKVeOV@t!*Sq^ z@Xc=ox?OpUPd2|`OY8Lgkk;w@snhpINp$lI<`R345?zlHX^+xyP>OOWu|8Ph+k61D zJ^8~6;hew!U)#gQO`8u0ynY7fsx=?rczqqt75`sg)9d@;#q{jI|6hZTnECJ`4YZQE zQ~)HrE(f#_;lm5t9MJOQlaS=e(e0zc(yYMHuyZbW2|wF$(8wu+@d41TSr-+aW(80p z7C6pe2kOooI3xf%hO9eO0GwR9OGU!FYbA_tcS?22b;?`J01Xk8m^9b&*p=#8%mB^x zm8x}nlvtlG(dhQ{us&TQ(d|&s?T`UF4TYnVtJ{I4lkGU@{00W_rhCw-0o@K2)`v?z zbUW}^A1-;>%@H0Jlw}8+*nfR5wEIoBs{|;4)QTA2Zmt!u>y+=5=ysLqlqlh9t`&%c zoLtuJ%3(2MHfS`U6?Ai9_XJQ;3p&a`sF$bHBBqO}m#3@5y1S60`QQH%%%2n-3;9<8@e4-UNdzc1C3^L{V$aW|6eK)5cEG#;B~S^By(v@cR)$E zCkx0C-9;+hJbk6&7BfIWSmFfnsdcv#$eXX_Kn^R_wU{xVfq|h!)iTne*U_Yu!!pvK z*HNcLw40-oA2i_Lz|zUs?J5HceQ^09!LTDAl&l-FK#NN%K%2z zXX*z~3b#Z$j;PmWx`ljqDCig>M*bGi=w0(KGyYZsMg|6JHw*rjBv41mpT+t#e-G$t z3dm9KprH_%j$ZIZqc7Hj+UL#&-O)M$pqo%2cVsZV5DNy6@wc1>b!l90KokeO&<_3k zzi}^U_8xSO7HGz(M5MX4fw7biHZdQO0Xi)ZbhaLNx)Ly*&>RbBRSe6Er5vC> z$eG?y5SR6ZiY3UN64hSUC%vIJ0zd;~*O(X>0wBXfY%e%L>xWAZyx8;e59nf{CoeYt z{PX{R>6sU+K?0HB#poMe9LNN9K5o321`-6FT?BFO3(0tp#T#CjXM%FUOVE{y5E+n~ z7r)~`!*4v@p#sLYUq>|miYg7ZcC#pT?RK;24$}dZ8xFlJhq@gEdRZF&mo&0~3K6KM z4g|ai`2{{^8nh^s{Y6qb$N>jlh=LsO5;Q<*8PCGs`xvynvYwft#Jc$xTZvioFJ=&7 zU!v3ei@ijm`Ijhv>j6dv2FL+XE7Je|f4LE~J|`Ho%eMcN~OEOZ42wuHLBJpN)@}oC)HXXE)frSeYyFUQ7OM= zJWmZ*L%je4f2$YRVN49A!VUXCtqO(`2aw}fn}6AtnsvK_i$A??@C>x|=@OOhZJ?nF z>(3<|-Dce^ZQTwkpgZ3Tg8~Bohe>pQcnP}cs=J=0`Tu|Z7Vyz5;8Wb2e{q41{9xHp zUSCqteX98-bBQyEFz_r9@bu(w1#RE{UtseR+~f6tEmUALJ_)K>!D|Hq0$+XvP0%~o z9DKo|!Wi%pw0xo0^*}hNX@B_#JOVggJWK^gz{{$C|NrlBRfQGLud6|&W*EqF?h+r* z5|`$enk8J#FS$y+yBvI8uj}@(>2d(s-0+a`+fC_{DvW834;cU;wSuP|0Kc z&&a^QeIgJP-dbsY|GyS&J|OX$x%q$qD3QL1O9NRf((Ajy_}dGMbWo|g;l**#H3gtU zvEWU2@O5}QR)cc*yfjb_Hv!*y)fxH%bnz-^p8E{s+^#If&e$9Apmim+e?Yx_-xs~1 zpt~BFUVM}QJtFN&Nk9{LQlVPMH~~@8$Zz+Vw)QdbjJDZr>ZA(u`+gH$yjP z_k|ZrBtUy_OL^S>yM6$TTf5#Vx@i5mRHxhZMK{L__E1pfE9C=KDjY9I0T)nmHg`%s_bLL;fL+k@B7(D;=59pLL z(3BbD3#WH~{`dNx>4^RF!u;Kz|J}Y{x?SHOpM$`{fYfI=0qQf@d|_h92vB!sc;S-) z?lXWy|3mu>zd&&yl?sZ3l5SVnjhFvBEg-c$=x~_S58a%dwSRh98X9aG8G2F0$tE9hLx?r0Y4`!(v_el@+WPl5wp{Q3$`*dXsSy^sJ;KY$8L z#uwYafD1v9?y?HdhUP5B|D_!NOK*V2en1(k%$uBgql)KS<(#=?%!WXD?X3 z`~mOYWbZ!y5_BIf$btN=DNGCu4f_^@8zC0WwIU3lDqVz;zttPGVuRzw^3Q+%gErIg zH7Bqz9B1%Rgt@)-TS*T18Won;Dcx>0-QFyq%FL#tx!!=Gl&!hmf}tcVOW{TO=ReR6 zFJu-5)&HN7{NL?v&|R<787B}72?f^9I*v{^iOx8Y7dsoFq407msEm$yA^7>v|47hq zgGlR1(30H}&KC|5~_BSY%y!z>B^b z_JMk+3?-4>{ye?zJiVa};3@6a1EucGwF?-_9J^gRdi^vyT@Q4-_H?=)>2{sa30ikJ zrPK8c$V09dy4`d-T}66b4+Okezy`XcTEyB z%FAK@MN1e!XB+TzJF|p!a~@;iVEivy0TOZ*_+R>@)8a+s)? zIe`o0?hqB0ZYP%312y8^ouCdobk!WVzG;5I_*$|%h@b3|#rXu>ogtOi+&eDevYvxshXBZcKCl749KoP|P+0dy(E8h6M;6ef*WG5u zw|i|my9GK^KUl`>7na7M51l^1QGZfz|OxTYzM?2Z*^{{6qC z1ax0)J81Z%^+1ULC>CaP7YKAY$aJ{Ac^%l@4{FM{o&;TEdnF+F#Trl0p1RVo?skxP zcj=Yx%iSEku5SWftZ@g)l*qrfYOdvBDwXZ_73d9Jm3G{9g)+m7kk^0ych_?Cmab_1 zR?797xx1EQ-vI;Ao~t+A{uSMfVIb!Q=ztEB`0zsaJ*X%+_L_UgMqM0nAi%K00~81A z<3Mp>0y?E77<5u#ukVA-)DNIDUuOON^B)u?pinR60*|D>oCrFbtCokcG#u*p%@~@4+J{JM|{7~9)*8|E7FQQ)k`QKZ60A!J0iSZ?i(D&ippe}I`*vA@> z?RD1gU_M@~httR4{NxqWda{%?i!tK066j1{*g=3n5#2s2JYn4?hdK@8x?K*jbULya zA2`Iru%iqVOdYYHVA28idq5XZho0#5U<3tJ?4K77FaG@Rbv*%EF#F>5pFf~oFO1E# zcbFhYB;I&2pAmFKVs|M=FX-T}lzR0rpv;UiWMlA}dxyCJZZmp7W@tjq0O<}6>-I=N8nQ8Y&Ap=n zmjN6MI~ITpco7XAWewjC8h`En7~Wa?0a^(AsdUHk7$2}c(dqi9OtL#np)-`HJCvte z$U2mx#JJg&hsDAAVA0!fNCAyr`E(x!m&%B_B@TveKb>IEaEo6|K)2xkAcgJ^t=~!x zK=pSYdwuS|A;hf1JGOwF<_mIKU~t$zkki7ue};9IzJaZ1Pq*(E=EL2b7hm*>ICR@w?B%)G9mrxC#!_Ta&TeT} zWYit|!!nGe+^~qn(ym;)JCLK>lc&3mqto|8w;zx7uToZP-w!2*p!1yhidZefIEvZ3 zZ*<1~c+KL_>H5bq_Rs5?&2J>K*dn|C1b<%I?fc~gCuqVDbTl$(dH|G0ZoY5?34spV z3TEl%?zM5~6$v`{ocZ7*X6@^}E)L8=y&{&qEC+)E{)?VqbZ20;1`Q;ZsEA~-ftJTR zvw%)H1MiyYb_2~al=^m`2tN3dDZDp^kr6zEZ+)YjsrxW&1pgfm`<1XaiLvJ}b^cxeQc6?ho}7Ym27L|%$OWkp_^!Nn}0 zEQy!jUO;S)Mw*h2GNWD{ce;Hy^oq!J zGjxk^b@T8;PcuI8LX?Gp0W{cuoDFo9ZL=TC|K{T?&Bs{&yFLKTHoM*^I@}$5!}wcg z>7LHg1D&NudVTkRO4AqHAAtIAdq6pC_rkybn`=KXl<9W+o&le#@q+IqxGe!v%JPDj zxVMePS*#<2fBTibcgQgtzhXk z;pk@J?>5=gEz{J^*Dd^FEho6!%h%0&!oZy&xcl0RU!cB=>x1s&-M$a3eLp}Pd#Ty? z#Q)CF2c4mBIzum5hkhvHw2Xbj-^>9zIOqI-<8RiXA3AG$I%_9%)=udxeNrsc?YabX zx~=OOP`86+N2lwPZr3-~hl@SCeK%N#e(08I1ce|&x5b8f9pHz~s?-pjM_k^g*}l9;f53pzD7bI%_9%^X%vheee== zP)?m>ubV(;Y)_}_72^XIZVLQU4|KYAyaeq50rlp6-*mHdv>qr?Vm=6pL6F6b-M)9g z-OX;^BL?ma;2!5EM$q1vJq>jV4Ba9-Izz9N@^|x|0rlkF1Oi@M0Syb)$%Aa}jO{6r z>vq#<{_($*x!aYa*N-C*v=1myqWi=P(8`I|OvVR5?LzbBAB-iM4Rvx1B~sn4Pr5m* z`AP-59aya0SV}pMyLNzXXn8Gp+_eLAxy5UNLN`PAg>KFl+t@*;u>LQd@%^^c?SF?~v_JjxzvVV)jjQVk&@H~PJl&^Xh=G=R zRI~J!b{u@p!ff3g`e5nOrAz-ivvkMacnLb=sXLaZ)As`SqP!EY&vpCqyr=-}m;@(h zrWc#aI<_X#j!2#P1 z!O`^9p5aA)I5R_U=#TCbFM2?C+4*vSE+A|KGk#D#@-f9n1TO6mRrFHG3L8Be&& zUB=2yri2rexK;i+fYJ)|b_nnp=vJWOWd~@a>copZ|3OXDQlai++Q+TGBl{CP9~{>G zF}%Bu#k!88BqrGScI*EVm+s>SAFu?xXnG78B#`S3|KED4MzYs~!>QTx&;Mr5|IMB( z|CwEEP?;c0$ywb1;P=Y|7I^TAA@=;ERmgZoo*b_pv4s3AE6aq zK5~Wk|Nnn}>l@vmN$cNGtJ$GeD?qFk#cDNVTmW1xmhgjI45|{%;nu%;1S-nyIw4ge z_~=+0aP4jUzcciUWi?A@?GOGo(2}Cg+CSaKy}mb?OaHtO0_9&f4$xu&*E`*AEDfo* z7&=`a9CN+Nc+B+%V>eqjPowsE{ua<;Ay3e8&qAK1e#cyIGg{WM@XtNa;d<+}ee(}S z{ua>mh4pd%7SIy;*E-EVnD|>jlh2?50-^3Q9_#Nl+}+FvpRrihuyND|Hl*HUXh^-m zaLn}5a(V+9RKrg1QXnUS!?}T`(#z5S>NUD@fZ7rcEXMy|3wM{X zSbwhpohfa7zJwLjl@j>x`lH$Pk3hHU4{K)@{wC0ASlzxHFM=S)>4Vk*F7z>k?<)NO z+8p}AJ%pJ7S@aFKQ)d{$%+P(%=w!18%l~E%j{nUbJpVg5Iy@LVJeWE>m^(ZK4kM+Z z!eHau*1t<4ds+5_D^%Nuf53Z*NLmRDidI8KoyzmFR2LmW?tAY+31g*Ra4D5F0$YRK13<@;9 z)a(1>xa*G!L(u-(KQH7L{`(Kg)6j(=S&SL6HqH#k*%lbOGyE6Lfo#_o?REVFJx9{@ zPm7^D!warpW`^!#aVHNq*Ql_tLi%Td|5-scH`{_pCg}s;Z-8g6(N;$~J^*)BK&vCO z7$BB0A}l-Hyc2Y*9YYCk#s(92hUSABFF0TR`41O%08NXBg?9&VbQkb23xE#S7cOAw z3{>bWROt>-U=EPzu2AVM6cDbEX+CJuDb`uX@#9 z;<)*ZLRdKHr1_8Czj}QifQs6sH$lZK_&l!nFaG@RKKJ4bmQZ|t9l z7ioda49u<^-RFcud757^Hs4}+Q5?X`(0x8Ap!@O*ZIBDjXKB9Jb??vrxOnhV-Z0Pw zMnAjRKn3sx?u#WFpwfl2_2jNMChiO+th=6=xHANT_AI{xP4b-2cmVRsx96bT!_n=> z15-VN2dw%AOf_id=>IaA?(_f4BwiSTx;kzG+-@QzYTf5wYd=7N&1PH&F{O|vN&}C$xLitno z&lh?iAG#TAX5@A=Dbeme|H1{N-p!!f&&239%&jJ-V7IE6LVYFz@|l|jx0_9gZOiQv z&hGOsc%T3I|C$GEW%v0P>|jGIy8UbrhDbmR;eiNQ$cbmjh8%hZ z^0mvZFHm1QyqNR%|Nr>7=)*fyK)FWS2bOEVx38Fk^2(zpfBtueg7XT93p#+eyNu<( z+5gfP|Dgp{_qi7l_dv~@7cXq?fC>SmCAWuArd=2~JQ!Xcy~V_kaooX~;l))y@U#m^ z6gKT*0dmJ;Z_rYgeIW7hu+CE02m)j!N%M|9;0XZ{(8#Zc0{HF$m0k~t7aDmC3@=y( z85qL4f51ECpzE8VL%E>U4Lf{5<~tK(KIo=^|X^S!#+@L@;as4RpmGX6R6Ft4rYS# zz-t*W6V#P^E!gd<(yYMnniDJpYMeuiZ#`Ke`6A-ZpZ^W}GC>xFO;%Oz-^p|Du$i zf#Id-|NoHVsDlylatv`1&>;ned?#lHKPP8~6enkfNGE58awlg7cPL)#lkmBBG6e-)_s{NIpyFM@$erQ;wg2WB zD?p)it@(&R_xa!#;&=c22VEa|`_KRGSf19~B>~;c%Ff`iY&TGffB5jv|Nq6{Wvjiu zFa8_9SoG^ZxVC^BHwSFoe{)clxYm3GRHJy@hU5pGo8bHax?#pRi=j7k#fxK}pm~@Q zRTKwJfSLeWa{V7_1S`lvz9^S@a4_uX0C}+41C+ADc7T#rctEEsG--8%rule`Z};}` zFoL!`{&_JER5ZJaWHD+Vjx163D3SCi;W_Rqvd7e&A&V*UwdBGL;MRi3>yHap7`ijO zW?i@jB4F89z{tSB-xS2iz+gEKl(_g?+(60m9O&qW7cQXVYDz_V_kp&Bcb|V@_wdhu z%UGTg_U`j996_}rI6ZdDfu>%xfmqCXzME);e=|2D8 z;Dy4d|ZP zc+igRZpO|?7SPR*5P8r!nA{Ad;{QuUUid$Nc$W*}e2eFQKwGt5EYDooo znC=fqi5+<&T7&^~_U=p2>X`0EkQ+d^30XFR0=bkci=p|T#0$L)28P2s=78dQx*IsI z!No{8q8I_4hW+P-I1dAZ_3_eFa09!!ErF4Nfw31%30AN)w?#nsAWE=;<;C_t|NnRI z16>o``oBa6lmL+%JP^Muy7A|K_lXxBAgT|f^hMr{KmT8><7Qw8#_1yt@KXF56#>XK zd!Q?x8x$CNo&Pug;3!Z1uhQ!1?#$3_dIFTh!dfqtaCDnq0I|KgP0xU6Cy3Y$5ZkQV z^a_a9>o&auqSd-hAAo4NZqp|qTCCgj1&HSBHhlx4*}6?XfSPUK##{IK7x(V}`QQ4j zgbQ>x*QNV^{=XK<_`wWns=PRIAC%F9UpPMiwUMF^u`sN2b7nZ@=FG6o&6(kzn=`{R zH)n=-Zq5wf+?*Nyxj8eixjQrL*a39`||NnPG?tKQ=6#otWmp=J_ z-Ey7)BLhQZWQj6F^1ngG0SRyw(%S|qA0oTK@f+}h0}?|i zD#X2JeG$dUzz};#0CX)F%dy6XptD074}uP>c;Wrz&wt|shgcYPoB;*?6lZ3JK=A!B z!C~RxRzYX#2c*$^SC0Rspv~coy&fFh4jlgj1Q0ENpyZi&7p~g9+3k2N!WKW`P47r2B>F)j$6sWm0?z zZ^i*rcZOa+gBMS3gMtFIav1E`<~KZ$dy~6EIa)83mt>|Nol>LwValywWc(W?%aAKQbEBMPOmr@co|U zr?d3Mi_aq4_S&NB&1Em-?tli!-t@ZO33zen7AWQ1dGYKbX!7|D=uRJ`g7ol?FCh1qIfC5J1770W zeKWlK*MH*-2{TY97gYO1_PP~B26Uf(p>!2IboIjL0jS>~18Rm@wt?o*OT|I8yw_u} zbjA-;cZL^l9{>6O+NV|#XtWe!TVegvs)~n zD`|dpe|)hCRGXd)e-Q~9g*umEVCK&7!WYa2cRqH3r887O!e);_D zeeOm3H&Abpr!)2g_^>KV(1@rj=yZy1hHjgV&e}K4#|0Yd85z3cSxT6jPb;+EF6Fe0 zmw}dl;L@e_WQoQL>r0@>{=iTo+wJ-WQoJ-DChtHV3dUG}p^8l=ydp3rdjY|Hj?!5}mFuGC(?Ed9C~O zi`^H&0o{H2#Su_KI`LxF#XtXX847oSz>8*(YKZ$XLCo_nJU~Hk1ME+C4d{v1;EW9R zXE4avTDU(!xf<-x<(ELEDv0~S;3CYQATGq85g>mm{Q3XCxh(+VPY`vi4OGZL{iy-= zCs@nv5?zo#RY3j(=|uA9-njs-#SdKo`4eOsV=vfjBts$XBXHw=_65u~QUyqB zJr6^T5kz4xxaHM)vP2rRJR_9jMg5=u@D@LNH~$Ow3xEDYjR!9x1f>)3X;~-#{s$e{ z7%Nh02ryfV&KqcHf-GBf88$eP?XY8LB zg<#|Eyl^@TYUx8v^a8mJ!ZbMl=l_cWP_jX7$_p?wR5CGiJ93orHdr#0aC~!QaVTZt zaR6`Cd-3G!|Nq_F!SVgA#Hjn+iy!Aeh53KeBcP@ZqTBuO+@Jpq`(fR#evpP2`_6%i zftP<685nk`fC_?88&E+2Z@VB*${XK?lnb4)e@dhwMZ@M;1_nrB(1BDKfa3)m?(ye9 z5s4gsZumD$)r4|<88nU;|fsuisl&!Z-1GM&-ff3St2gTs; zk^)fs^8m7U&c6gyU)K!JPWGXQIlPFC`TkD2}PC)!_v@y(=8ycUXOgO z2s-64QX7$oKvTIdv_S@yK6&xy6e1O|fE^8L1-^K7=Fk5Zpewe!KY*KJubH|(!WKIC zegSU*hYxbFFn}@_1KMCQXl%P-pC!11uGqZ~boEH<{}ORfB(xv}U-$VJy=VUXZ{7#m zE5=YF+Uv*hqAD76#F+`GJ)-a;(WJ-3d|T1{=B+=q?ap4&Z={-SRLCfCq3T zItyix25>pR1GqYn0o>$U;K9rM81MkD*Z=?j5AiU7hQON-f=uCfVVBIna0t}9=>8ZE zbCYmy9Y+>p_xTr`(F~w-wQom(7KuW9X44Gz8AIUI~@f;3za$@ zMVb$Cyx0}Z!0=)^L>Wl7^+1U0^kkTBGQt+~n!0twni-N;? zH-hN!?phAx+nv6DI^$RrBrM}u%CtZidUl_C@f}oeuy?b}==KnJ0b179eWCl@i!25P z250MdmZF>8zJD5aT7jcfr2E{96PNz{&*JSq7xe;kb0b*N8Z0T@eeT6-kXh$mECH$E z0jW_2rDfkg-8(@c_22xz89Y$Vzvwyzisa~%hgcZGyMMM`Dia9n{*5z4!zwxk1Cp-3~0> zHamLVSpr@JgFNHT(d{qL>H6kH5oo~mLiaiC&^IqYClG?GAC7L{57r(WMcW#7Lqf>5 z``n9V7ytavP>=_$M}P1_8&t!k{$a@CjRNU?@?sKr4-0ry9c1bM(g)xX|IFim{zo?K zh6JTl_qi7dAQzo`5eYJk#oV2t``im~^8oBgw2*W-32M1=be{&_LjC{m|Nn6>l0ZEM z-!JjVt-bC>&=Fj%2TJ%Y8$qWDma=CtywHeXU^onpfI7ag?oZw4Up&143jS|#@rRLf zNqqu1m%uhGhxhh@nn*7eUITRtrfn3x830 z4K#eg@!~}U1H+4>zd?BbG9lgg26X5zXk7beXYG$(e~uTSprGyt#awr+K<{=C!}tLB z+z1v0MoVWF{x;CGLN{}_@1Jg)j)tWi|NsAIXsDH7C;=Tu_rF}=-~+baUXW;Sh=s@t z4UYf+d%?FD1-$ULWM+s2ok`*^@L~bz60Zy0t^(Q@dV5$w%3o{*FL?aJ08SJ4&i{ex z1D%TU22=yP{sCS6>daEq)Lr|dVLv3!{kzY-*mNG0D|&rTMD^C50B0Vsdo=%-^7Q&% z?XA5EnotQj0P28T4R~?Vf|(&Qi#JmHMC-{q*52By+CRg)&%NjbRp=mdA*q0```n8t zkkGjo!62#~l)V2NAo37+QeOl#YT0_JOuG9NC{OHAP*70l{&(;t)92OQr<)%#e_j2I^yi69j*=n*?L8ABSL^%!_wn3=A($ z|NQ?yF8YuFLnvsf-uQp_OUpWrvLMhYPFalIXS-!~bYFhq0*Zz@3C2>s<~kXMQjTuO zlnQqiQ}^ZWvoBOZx!6sC+fAi}JBt}CBm@#V`@;O#pa1UGbsR+-qT}OY5AW~+l^DB? zK?iYwYPjIAZtzfTIApB0+nFWc|Fy_SP|qy!%pcJ92vCPD3v@efl=g)epxGPfc-Di0((=DKit0T7wK8knRhhp{Rb4i(a^a+yiEIUwg3z-cM1JE1V1A1N01a$iDcrlrQfnnbfTTmr) zAne7$%b>pR1%?vtFpz$S(|`WI_5~&Du9JTt_eU{VmL4gS>2^Jk*3D9oX4}9}%pU+! zF!SJ_|8CZ$M~a?UmmVqQ=>;vVITP^0;1sC)@&epyJa+)J0m^j;==7+w3JeUO`l{D= z#|wW@o&)ta;Eh5ahUT9M#X|p0dJ8~t=cB^$0_1?#s;!qwc)ER5ID%djUHJ3=wJ4}5 z6WD#CTL84Bra_6}h3M%&pq5Zr_s9QbA}?YNfMyUmUVsYB$jG?EJ6b>i_E{ekU?Sil zm`>j(y}ob4yV(N6{s*WS|F=F~>T6m1rp&EdR)Wc$0kp=p*O#lC4LqLL>-!?G*Y`tU zc-a2{4bWvJ4@wQYeV+t?W>QK&yvPM5uu|}`mH#ihTi3oRIsjVEhn7MAmwxzvx!d)@ z>!+XvzaUEv@0bB{Rt(r#kgZ#tzAt)xKR}%&0(O>{W$lMDXPC1%7`oX&Wen)_pI%=M zu#+S}PI^*m)b0BMw2A5ssH(ULzTk%g6x3iheJDDN)lD2AH$8d%G&sEbr}1r2vrZ?h zo4wm)Mz^2F3q?>)w_`44F~0PgxjRhff0;;>r#@i-)nDP=ZY*7K0<8x+V&Cw$fp)xgvvvDEX}R5P z(*e4i_Ct5LMsE)*=$?-kmMjbm-R>HUt{+~jH`hxrl!!p=>UI}_`|UOF|8kC+t;iGY?1FdYP~>*H_X2W`hY z|B@L*x$894voLhJUf^#54NiBv@$|-?2=0x2(e1zy+#7qQn~yeKYE0CY3pdr;3k z^hN6>{+1meru}Bd=Kpr3+Re2m82MWtfrNa|^wueazgS-U|3AcKi2lXP7SIaO|Biy{#aDfR}#%|Nl2WnbzrhC9TuFO^<=54h3^~w zR?q>x-L)6GT|abRhb27FE^5Zw58#EeY0W74^Mzx(uyHqe$skipO- z84OGO;9YFNFIMO=Gj!MMFuH!QJ|4;63_8w0`^W29Y0W=5N^L+(r{i?GProod^XGps zBo-|8{rTTe`-Y*{O(7t-ga;xxbMK%3uj9HyFLe8>ya;DxV0ayv#SqXNdZib9@8=7V zg8yJmB|;GI^|pd);eeO#Zr3N)ZY=ywp@07Whe%A`1L`oK?PTC!0Pksi{Q_i` znAYF_-G^V_X}MIw+4vFrY4UZW?A`OpKm~M4MFoFb_AOcb#0Va?D3s~TxLc?QKrd!``N}cS8U~YIQ z9L;p9A%T^l!-M4z2ZQl}u+~f6AIoHMH>X~|J`iOKiEqJ!$C(M_^G_O$iTn=-kIP0gQJwK*Igjs z_0#4bJf+eNsY@6d>NOZjxO>ADKvxxlFC%qb67V{w`3G}p5@;B#4b++_HvtX2rv72* z^?mZc+~5W0P4KJ(x2r&jB6#%^NF~Q1P=P4WE&9U()UbN;zm(_2gBzfmaGrGgsTf~+ z@#zPc14{HSwr~IQKk~Ie#vU$r2BwhZaF26!QH-p!h7Q^{+s@>aAyGB0~h?F@ZbOc zS$w^@%LhH5tkaDJWCwWB^^Px~Ff8&fBNVQw{=@)Od|M~yg7BM@=)9w49+Y>fH2WqjeJ_1>?p2gT3 zdZ7FC3vpIR+Zc3cz^tvH5mvC_IE=_*2-qcJ>(0=9`b8wjJ=eQWzc6G4-Qscq6mET> z!*`k6K%0$)!IvX|yG1;K0a+^Dr=wo5fV7xpF=Xj8D;%V}5G2ml>w5>(T-E`#OZi(hL5pr`@00~Jr@mn5_5IY%7TD{1ArRD9 z4iAG?&Hn=oKjk>h#^w>${fbMfI&TRz^WrGfkzPkm)dU1FQ zsL*`zV)-Uel1J$eaxm=2d=PWu1DhpqL+NWu|xENmOZ3pe0s0jj%ft7+x zGlRG>gU1fMk_5EQAa)CQ<{UgB-s}1TG$O|jcS$hBC6-{l85~eu@vlXpDy85mH6beb zK`KjMy!gEF&wtc&$+{WCx-X=48#p+mwSFs+NNfJbTgsi*Y{6B^>X60d5SP|zW$_JxbTIs;kKnpFZA4)1UP`7=-v6v`@~{?gCxTcCM77f`1nl*jm6Sa7fJozBuf zFV?01|8H6PprjBK60diHe02fb&6Wf!<>+<25C9Hp(Dq-Z7pp&jl)r%_fD&%#a8zXE zYc9~S+vi_IYz7TTL89?mcjz7P2vZxlM|ne3nmZ?Z503q!;TP; z>nAIKTrUu2{4KouXIf|JleEs#XPu>Qx|u*Zue0>e|5A>i{{aft$4XebKfD&~4&~@| zeG<@p9#l>K{s&n(6a~8H))zck1RoaQU;sDafu#uHWaxHd zDPiJK2msINcb|V@boc*%&;VkIU>4&puzh8qRg4LEQoKj2Jt2hSz4zbv6t&n!Ro+AVX9) zgIjW&HiFiE*mQeyWHEG$Ga{{Q9~HXyG-rxCl)zi0(1KL4U_*H=$ z8{^xZa-DH3of5sh5ul5%B3NF`;$vX2h}8hC8WYN5&ET+fXMjk)c<=^vlOD&P|Nmcb z@G>y;_Bw!=e|Z=fx@!eG=T`jr|G#r?4Ty|=((TS-eYixZ`N#h<=H?Us176Hr2ihs* z`o#EvWjqTg;ezg(e$pYs;b85~QuL+URiHEW3TVe@?3Qi^md@B6psU;<#|fS2jJ*Ty zKJ&Nvae{XK-RbsyVj;u9->L!T3UvG4u>h@eJJ8M08G8h>`h&j}bTMXcuK}oAx%9)I z|Gm8tAm*z*fBtu~XE6pqq>j1%VS2&w_0Rv71N^O^V@9ASko>UzUCNrp6mR{zp0%^~ z#B2WUW0}?act$vJkZL#S|pbZP9%W zyoL1gddMU>izT8r3@W+Ktp}IwTh@b*1Yr8V6>Px7wcwo`Z@PIwhJf>5H`u(_QQfTp z|Nj3!_=05xV@V~%9U1HY{9g!CXnnZE8@!4q6^m^Uv%+6&-SFo>#4u1nj-0N}z0d`@ z=G+T45LIf?%*ObCD=64N5hfVN^5WN;KmQ|NZUo(V3=Y}uRuj<0wZ3N{$~t`ybh;h^ zD|Wr`;w(sUZ|@IKfIPScx@@%J4|s1Z%L@xm1_rQ$|Cbtcw%UMZR9tl+H^YOjdh231 z-fHpp|9{Y!N#|UhzyJStv5T3Od=wB)qd#0@QeQ-P73$67P0h z(AmlW7UAe@W%>92f0rvyZ?D2Xu+3~8tup^W$&>@+sKz~i{#(SVl-NQ-(Qw@#*dU4N z2MeTFf=Jh`{{!uca;$@~{()-RR*<(K{tV~^J0jqPQyAzV>`vD=r9zf-O+dTvdO#~? zK=;eKzOjW&-UqUS*19v6FvHW+g0=8?GQwXx zUkBCmAG(C{T666i#>mK0@$S$)kSOnM1;s(Yi=5y8|G$m`hdb0XgNz-Z_`lX2`Ubu% zKoG0|wzA|}cz`7;1UL$ctGI} zN;n5W@}P5OdwW5l^`eIZRDgh-1xhV1aD~*H?e?_+T^RQ! zs+-+1!lHzgQBW|F#WF&ol*=MQ2t)|L#bjz=vLdCd77>Catc+rUaV(Y*I#5>gahCtS zZ%VhmX3k=aVhr6P7`uZp^on5Y4U1TwQonBSR9|fe9s!!3tR+*rU z-H@P%q@b+NphUsnn#9V$un&~ByU)GYvl^5JHA*BPV<{PHK=A=C=PhD2A|p#xpoMSH zD{$@8yBd@MKxOrdUl5V%)qnnXgKg;s56^U$bo}XZ)#%)s0=mBte2{y$oz>ya+BYRm zP_u+Umq@uz>5QEb4iV{)cyZwc#BIkwqn~aZ)`v?(0w9tvd|pDNR)elC?gcIAeZj#F zioPA7RPmP$bSvwI&bc4J8S4uu>#+xh{|^uWohDxn)&sg9_J!#-9M~<^S5$<6vRH_Z!HJiZZhu<=*X$q z&n2ob#h(LSR53vO<_K2$xrEaqR)W999n|lEnm8fgg(Xyx3|P_Q(lm?M&n4Qutsrl8 zL)@6i0x{<&Xc*U5p?4}s?!{NmfB#z!yf)|!UDDeN^3jWrCqdCYq1W|cx359~|C9p( zy`US_Zk+?yKrQD$mm$VJ+}jI^3|nNi5(9D}tt_H%tr+|6N~n zyS}h?-N4@@4N4kQH-N~kpc@&xd$)kthnSBEgKu01Wy45|xidf~iUnHC1x?qLdRoo} zWvCLl?x~=R*}WB%D;Yx%bc4+iEIrZKl=tQBMy zqhRlpfB*k;PX*al%6_c115{;kgKs_uaX~xr7(w~9(jr!)R2|}v7jvG&1|FqWfadc- z$sQsV@M813|NkMSdW|bawv7bmY{kZ&}A@LQo%m89MsBIPS;sP@R1Ej#1upHFRhh&-mb3r*Dl&nCx60QQx6)cS9+?KI7%GsK0uP~P7cAtMC401~^xa4Vg_WytP`4@~JkyenKVF5Gi zEm-2kvOf^RcP#*wW~DnoZT&4TxL6n%cD2}m7M}kvz45>F%8MV&3=F$^K*KKQ|Ce3> zorwC3nSr6%jW;&p zYPYy0InH(k6b(pMr|i(a;l}V{n-IjB&e9Jr%0Yt?pmDT649#gK48499 zoo)s%;z2c%p9?sQg28Oi1%pg4+`;S^aND;O)J^fr0HsmzUe{jm39z7+-U|g#_2v8J z7H2z3Ge=B{J*pGL$e>p|7Jg)|DAT7bppM95}kD{ zpmQJ3uL3O?QURS!_7Bw1MeS6Aw$cADQ+Z*y2sBkJ@j`RapZ}n#V$cjS_!=%qK)etH ziTC<(yjWqxzz_%0_2TCL|Nr5)?R;DaYVUw=+kxF~!_wiw(di-3=^@hLA<^NX(FwZd zMy1okpwq+Ta9DVE4QQus_>0G{{{QcFx9Ih=2zYTFRE4`2bo-Yux)sC=`jvo&I(I~X z{Aw!*?p1?kt$B=Zho^PMJ^^>tI^sCeI%A)8#=hxh?5%wg-U+(rbbjXH5|-{8 zuX!PNbszou_kV{Q=rpkxe?hn9`F`m>jI=-D5C_AK9FRp<1mG5N;Ik-;CnykPS%8E! z#2)3e=GrF?rGlXA{MIFcv(+r>lv11#^9W(eL?#MEDv2#8sL15gMave06?)&FIXb6ny0O*_- z)H_J7f{Y0S8x!9BGt1yb;e60Oj7U)WPW{8s`mIC^lnPD2ju!!Y>fQ1`|3Ne5pdm=m zKC;#O!N!8t*}{fSK*+fO(tp}4(Q|%(DJ5o7R=jE=7IJ6 zpZ5oP`w3_VU3}c(9j`%dpUMXc0?;y1$l?F&y?z{>Y+ddw9d0b3%RyfFtb>jNx{Cz# z`iZ>gUjFAl=sqytFNoVgAlHw$>vX#5AbSIp@nvthF}yI~0}W-Qu!63A5C1Qkz~Ihc ze7iGt3GC9eKmSEj7(n9`3IG594|w6Z_RoLN==zfQ-d>OhIM|dY{rRsD`{(~wkjM+e zd4K*}#;%Ag;|T^$|ExO;=9UU|^U82|Fl=Icu~(LX;pGR=qRZY5pka!Opsn) z95_MsO#;;?pDyn)z-&L__dFL&d>OMLHXcfkSn@dLAOrt0(BIuK@)aR$wP}lJ$*~? zWz?OqFG~0j4D-=K;l;~~fB$#4g67gdrxfrnPGI$5SR4Q%99TUVEa!q+Wu3K8O8B~4LEf+i zheio=XXz8m*cZoL-vof#_bR=uA)u(u`ubmV4ud;Gz<<#U@F5{3T>SgNQk|}EvLs#@ z&jF7zT>;+?%L=|7_LCq31LPDN>))NVpff&MI`W``i`;Ko9hB5J^q8*eISwEsi4Mc0B8f+ANCh_+(4@? zO2rmRpqs%1HUrdv?3`->HUqR?#rT`$+y#))4UV#?&e#o|v0FN0cXYST0S~Qi2<$%J z%>wRe1-uA;@((o7)dD(@r@3|uBY!KX_tfpWp%>gP{crH%hYC2YaQrXb@PcIh3c_OWUciV!_jp=Ol0eJ+}1=IvhO}U==5YRfoFbo)N(X6fkl-4g&>0L};+ z4RL+bTp_?vq6R*g1Z0dlM6}m;PxAqufERZ_jV0ebS(-2Wdg1FIoMnm@XYuxi?&&`F z;+G`M8O_x?pnbE7|IIQCkb?Ptu?}br`CQO8bFdF0!J$)a!oUwc!?_u>Y=r;6S%wCZ zrfz40Zr?Yc>9TH?j!xG*pvlp)9I%JDA)fAb1x*bwbo)N(V&Sk+C}Xi{C^F{XcA(Ss z%E1>b%|EyhQ~0nD?RLEq+5CV%6078Y(9#Z&k-kr?Jy?pSKxfRHO`z9*pL?--7I+|( zJf$^f-^+aU1?+a@W9{wiK3OD21-RE93&jKek1!V7>dyzW}G$Ol$&4U3v zt^hin`?%|y9iU>?^-c4s|J~=hC0;a0FfepGi-3+h;evQGGV(PCsESUT^XETki2*FF zsUp&vH9P^Tzy%?iLGumg{ulH7FXni$P97Fd|INCi1)vLbz-^ir7iWTf)9m_&1=J;G z1-X*H2{cU8eeT5;kfd3L2&#AH%><>k7Yxm|d)Pb}82H;J@-Q$QcYRZV>Y?@G3=G}D zBHib*SYFtO!(0#<`M;Q_`y9ww;&_~81+v-o1>9L6n~D~_ROew}faH1h(wJ`4oc`ae zdn#yLptsimG!!ea?f?JgAB>%@5BOU@a5FG;pL_9i26R-?`fv&Ve}fDLB!3-uJp-DG z?Tmf!@(?!zLqqLn2L9F*P{$8aobtDXgL|;xBDMWEs7U2+;RP*y+6y{~hM`2laxQ2T zw^ShGiyx@g2Mqwf*aYg0_Fnk?|No0ypZ@<}2r8PoOJ6kX1szt)(AnDY=RahO{Fv(> z(azQ$&^*Of&}>BspXJ;ye?axYG1t$GuUQ&WKQnZ>e(vpE@&`2TyzmdGoc{0!)UXIx z2CDLB{QCd@#X=zlhVE8S=QY*8B!tl6vKZY#(S3$CcjR08l~N8US|4i_W<{Ao;B!AhOj36ewr885nw7L2d_4 zezbxDDxkL&q${AewE#3e)Z2Ol?C zAm{uPVqmb01uZ|8ghc?z&E2-3784{5_x6^6LgQHvDA-;=oY2{71B#|rP%Ec%ZVM>P zwt9fby`bppXgvwiQ4Z?Tw}PzcoeEx>*xL$fNe1-xf>mR8X_s@fFYU${7eefcl z3l!QQ1--sKpboM03z4~hps5lmtp0BWS=u`lWbXG{kZ^PD2!KQsII#3YAc5sO07)K;D7!rgS7+$7xFferU3fQ|dWU)uRm;(|D0i7f8 zzq58vXYGN`+9RE{8#-&Zbk^=@*t-qXzJr{Ia?JG)Plf5U_n-eSgBckZz#|X6y$pZ;|3BXP;rIXlZ~WXDUL1Y@|Np)Re(nsNTR~!7y&(UA zlL+W)l4Guac$H6d_I?2+Q}Ap-XYUUX+xJB$IKOrKzVWm^-r2hblp*C|4NtNE2A!@~ zGWPhnGyK0C8QJZ76frOEFMt_gd?~QE7i0?Pf|S5s-#vi=y}dkt!Ba+jFHWrZ2Rc|5$929)nFwvp9zW*#hacRW-3uyTKY;pw*5AR#lwN_J(#_J< z3M%S)`#`5ubhLqvtbmj!pyVg;V#-3$vJ24Kb?`jme{hNZ;svObuRXxXKmCAZ?TZfZ z$~s7~*4YL+WT)HpNoO1A2pVX9YC8h%5`o4{U$B8D0l<@Yy}cj-kUfGgen^4}Mo@x+ z)E>+ot)Ri)uGXF4;`G(O|NlFdzWn$9KmU{i9j&iHjnr09EfUZR9t3_Na}RWREjWVg zK%I%+07#Qu=*8`e|NdL<1s&CY%=M2jsL!C(+X|BH1*_?FebU?d2UK*uXgdaOxo;I_ zVCbC+8h7so7i~ekQ$gl-GX(uFebRmH`>kF-fiUSy%?EgtFG9Q!6bQP=w%hjvXsvTE zxC9L7Z3Q*C16~wv`1jv(A81w%R0cv1dQwtkV6fZ^s>4gX!1HF-$4gARPky+9RF>;IA@(D_dj z|NL*>Cj%OqFXwFD2RiwKvCI>6SQNzQUhtV9@Y9A)Oa_mdBuoS^@|Xcp6ZwA|XiHr8 z`TyHMJDy)GhA6TIIRU(Rox2TmFK~%&>wi#12s#8RqXDiJBn8q6+VcJ)1EQ4ytQE8m zn!C-0k%6Ja5TX^barwV_Mh09vNE)Oar1*su)v zXZS#LLImOd`Y;LXuZ{_z-PWL!1Gw8lK=xX7pMOz|E~xt7Ji`HEOyvJ1mo?!qt52PMs9!U3#2#9$f`a!FyKQolD zLz_6Q|M^=QL32sq?TwH?;%_wuiS&WaJ?aG?g2e5?!rv+f+ObgkfPudiG2%8PXnt!`kgU}cW~%`-UQ$`*i>&3VxdQ6}FHPC#!!my%zOjQn5P z(0%^@R!|Z9A{CE zJ@%I)A;AexEr&occ;ZDA$S80Lam@9P&mDNT&xp67mMpdlq@oA;!S)f9o00 ztfpWO=%6OhtO^f*3kxX1KsOC>y!;6&{(LV$%9B9Q<<*cjaA0pQsOc8i+Y2g#13PPP z{NK78)Wod4(^-3=v-V0i1Ei{NKEMMhUN-#Sng*(3!G+BKtuf#hnCl*Bar1vGs00mo zVR+~Ne`s~m>G}ZN%`P#qti4jsYFT@sOso6ci)v8Q3A|+jk=jeIbf5cQdf~+ZP&A)- z5z+hSzh&(mke(Z5R#4+gK$`6knh(I^9;&rrhG3@*1AN?2cn@_{bFdGNxB4-}-J0`$ecE=V(lt+yA{vV7r} z09wlf9*}80P{P&?+O)v|8BBtVuYuG<#?oG7)uW746$l~5sh&51a={tYm6nhz=RH`! zch2*4dI)rYM&(71GlclNGaLqOT*Q8pyA;Sy=)I;kppnOIKbaT;JAFSKX9Vd4Ejs?qhL>cLalsO9vST+K^;?8$4&j z(;?Rp$Ji0a)Dg!FT89&Noq4yblW6JTgg6JcmhlK>r&dw9nykbU2OFfo8O1$2K52if?h*-zkqZ=Fc@c_e!~ z;#fN3SUcj_I^x(n;y60uI6LCFI^wuH;&?i1KfDN<$H36*4?0Ech5J14HGh5v@u1n2 z1=B$ebpXfJl<9x|!><I1j(L3y;dZ3`%~^&MaU4@q%$NOVLn_O@*U&Ei9tpsk!x(Oodn z7u8@*Cm6w+xL$aHxep**?ia78fk*y(+d$VF!YuCG_k)pvp>rSTfXU-+ptDK9{nL5i z)zZh1CQTs8ilY;pusS?=Iy`tgJoq|1_&Y!;Ot8~Kc2BF1cKrjG;j6` zlrnCEuVl99j02ru)a&N~8k0We=EC@b^}^r(y?vks+n|u_M7llsh26A2|9io^r9rb6 z9rHlp(J>EnL|ex^a4^i<&cML%LL96NG!F4TyKldjpc2_ZBpv2#dNl z(1s>hcy=Qlp9z{+X#gctju%xM{{3%G(_m;$(_v^%GXN*k=7Sn91qB%xb_9Te&Ep#r zLtq$qA_0`udi{7_aMVMlTf5J_5EB6BI{1b2hj(lOX%a?g`o9h24CvLvFMQiT#d{yf z%`Yqk85sV9C-`2Nwf*`3e;X*cUTA}vpk(wy0n7wN!wbe z3cwUc0?2Bld)h(AJHxKcZdPN+63BpDn(g|HiJ|!jPwRnF_HI{>PPW%!Sppdgyg*lG zYr&*So@NPTOaP0C!NkCKY=f?~W_c}>B>=s;`o~w8VN#$A98dHHaKLY;ZUA{2bdBZ? zCI^Ow_&C`8)T|)!{|wy>hgcXumjVCp1PSyug2-+#StHTHiDX>osBVIm7w#04)K5!j06J%17v=gtJm#Az>B_SQ1W&A0Gbm9Pfvr=_KS*U zQ0fJF^+hh23ChPWl0Y@G--qTSJmAnf_d@64|Nn7^cd*}aV|elD6C|yHE|zy=0rk?s ziv>CYz$vaFz@6cR18ABu^$$bCGLSbI8kT|l!O+{M0y;zx)H~_+{nD@u6eJAC*%Tle zB?8<*Sr}dk?$82R)(Wx=RPup`2RchXyx4pnbi`I~AE;RBjQ!IAK1iZt-cAMvhU0CZ z?i467cFqG8^Dl%zV-0t|22ZtLGo}K z$g8tHLc$f4hyQN_2B@S4SQ6yp z7jqjy>OjHtVp1cd)B~TDs0tctMBX3)DpUWL@w~_Zn{n>NlgdA!$nFF=iWTZ8P`LtH z5+W1m&hR4fAEX@Vg`B%@j-mY|q82JWjc9%}=gQo?ww4Rojn z<8ihpXt51Wksu==QZF8WmUV6erJfg88$fF+x{*Q@)TD+iqBx2iqH913yTKtE+WiJp zUxJ4wIz#`oe(Szjq7GUfJ*NpY%n#kzvBCtjLI8YjBxFdvuIbPJ_-@xf837l-7Yp>d z{t0;Tch2AG$H*zbOlNi2*oNotr>AmrHp5oBcQCfC_^S8xQS% z)BHvttou;+N62oP_NqVsL9BD24fd>{v~ltfX!*h?;{)LqY~4Rg*c}>d3>Zp(g06pcbr21{=K)@vZzn}fdq^(7I!JtZ(wSfX+X){s=y1rv#MXjQ^YRK;y3a^oxRqKmT7BT7N7_ z>pu4)86psNZzwMRh-DmPv%6Os3mepx5`#f0G?AZh`Wo@0}O%{h-r7szr*P zbW6A1F45_}-0OScMc}4C{{wn`?|}2`deAUK>K_JB4==M8R7v>Wd7%z6v-SZ4=+x>v z-RCj_K>5C?9z0%>4LT07^v(+#km4++2-LpPApwRRJ3uMs)EiKW;Q?(!`e^*W`<7)L zOIbiSTlZ;@`x-#OX`BH*q!+wAx!a8=GO}A_2WUSMXzR*<15it)`}B*ybzn;$*FlOf z(3Y>mHGlrQM_Sjh6m0H`HU*o?@??$a-Jfz*SFH~1!3P|G6_ax3JYi~|?k83Hy=L54=|Avovu$heIIoDo-sbaeW*M1 z0Qb4>(j&(Ijc;@R;{L4tL;B-RpCESz(A67XK$nuGgX+522i>kum}5T(yMAe|{ln1d z`lZATJo5hEAj1LVB50UrF=RM6@iY7{eFKV{mN!fcK>=C(n-n5nfT|&w4ih9DAbXzd z)B%Z*Zy^cU1~;jkhZdI}GyrUF-0pdnh&lBshqepG|%DA;N?(DukJ zAisdNM`kf(G)$Yp@V}G?RC`FgW@706(0wQi{Yv6>@R}8B0A9SC~;&>tQ!5@M{gf!AmW8{ z0jR+RYT<(S&A5F0|Ns9s(01h)E1@b`d%;)XzF-9{nJ+7OF|qv5|K7To$j;g~z5bx% z!?|Dl%Li=}1o!ViC#3iK`G6ae&+|bm79C#1mxE}77vUfin~#Y^c9y>B_2W72`iBSP zx&!%;;uy3Q7qpHSRN%s!?jYZn>Aa8uY3)Au;!ifXJ=p^C@YZLLMlN(gVy~ahi$qWh zpp56m+p<4syI_MsBWpa}H^bAq*?PTs(mI*D+?YC?nY!GVJDiz8M`1a$bh~kMI&<{8 z@dUhJYzN(AE74mmv2^LuCGp*dA-fl6gY30Mw^!iB-#m~HSzeT4*t=r`NDCKOOL+Is z&e{*)x(K|OQMjAkubXE>>&cQ&S&ZO9;q}Y^<}VCDhJbgp!b2fAv^xiMxo;th@uk*p z;U&`DlD#Zq7hiPSG+Vzf5vv95US;kLV6?tg`aCr3MHXlg>9P1Y@NUu_M?fy|rm~g495o z{~)FTCdb@I%iQ$FnRnY2pew z?fT%q!HecnaLX&R^w0ktEg)T4>@S~#S_Y+ey4h^O=SE9(^Mb810htW8DvRUgVMYc9 zThN}wQbDN2q9AFo#m(Tg6AUG$I|G8<8D4+}N4v#9E7*)L{{8SAjyK^u8S8ojvg!one~``-FEUI1{D)W! z)1U#>UDC<7=!U#i~DpVUgT-$#$&^{HgyTN^=f5qrlDM0mH z2K6dR&p_Pv;$<<|Yv(bP8@-qXDviNzLJb#Copk~0 z3=qF&F~xyago9SxOHKU$zxx=tl@HB*kakex8_<|YZ!2iR>o}MM@dN&g#(*2mC49|$ z|NQ&^p9$1ri#U1M_`u1-kY&B#E8m!l|NI9X272?wbI{&Au#;QAl_;yG08A`KZ2N5TMZdz}>R3dV$5mYrYb~AwvF?M3!nhm?naOb zkRjl)y-r7w7n7HQk4iSaWHAwBdug!cM9>bC5^vC8V3_rx61i>zi-{nsItwL0W*5qo zaCaMY7IJ`gp*!+``r2{Uhf0JYib}abHbUhN;XOuG9t2LtG?FObX&&jQfN3NFoQ9t?5O4GIjP@f+|kj|zB@ z$oPQqrS3Y8?l>OMYPbKY%BP!u{x22oX6p`P$r6ct5%hqG;h5`x-`BF;=ebXph-Wcm zrThooGWX)f115&x@SuPf_V<|>g1|R~EYAR)y>chuh0H@HhDe7l-~U-G9X_nL8&X*B zFvMFQFBa^Lv(WyLrO`=x~Q zzo-SIYub?dpTV-uqoknQ&A|G2317GG7i~Wi>l6G<8lXBSOaj`J{89nhQ(EHL8>Rx8 zS$nay2`pmX?N(v!CQz#1?N(#$CQ_>2?N(sz#!)KW?N(y###1WX?UrH9R?5@umIFG2 zt>q$k^6Wojx0^+8oJIG!&T5th1%?;9{(+8x`_E7!+B*%@mhC?Mq7iH*f9rfk28LkB zCa)K=pon!7=ney&Ep)0xE~wY{LcoiL^gsW>VGxiD3a<;@rvqLbEc^4{vQDN%1T0|= zl5mp%Nidd!BsBP2Kr>O@ZZ_87U1I#rpi3FRYPrE`ReI}UKuKv;4d_T=P|SzF2nRKq z`#|how}61~7Z374Ng;$8Zb%#GlG$!I@cEuUN=mz3e;jH6Wt-o`)wGa7hexHxEB32YVA8ZaATZ6=zvWo*s0 zKNw0Uf=RA!w}9rf5C+h#RBizv4-1rmMvr>^T)HoV&b?-6IZ$E^8Vm*PA%Ud!-hCiH z{Wth;4C$UW>;sLMffk0dck{o9$o=y_xYy6+#R533R)Qbh?T3x=RGSFf94=zxlXIub)cz3zh0W|3RC1KnK=?MonLW zI!QY8kXm4_6cu@$l@o)x6^uK5UgF6GLr~q9f1e&n^ZwWr=zt<0P8u50} zIzd;S&e}hg6)gO1ppI2=H|WNfKhPUre&D+C1$0etcOPh~q4i{m@(a%#&_a_x;A6jk zK*awS6ufZF0oT#mIp9lBL?IHOc_ip%FVfTh|8E9e>SEpvzMKu|QkO3oXqUP?%LX-q zzI2~{@je@D>QxX0bArH&V{q<^H6Z5s7u|FI{|B8|S;}b%y1WH+^8=(V06TeFHj0x$ zGnODHPXg&Z@uDId=46lr#L1u&YF=ba136iPp~So!JnI5;vP!4xmkf{!Na6tx!x_V! zYy&Y>2}FTspTYOA2xo)tVL1rC-I5#Pv=<+;{`_wS-NT{{5$FY9Z~(c7?kc{s>_ku0!&;JaW5O;=Ne}xzK z3jX|$H$DIwrvKOs$%iE_poU90XbWR+9ZR=|KzD!$vj>N801q>VZ~#lEpGaqzM7M_m zvxh`?fQoQ{OecS@pGIdm%Zs<=pkDrqpFjWqkMDN-)9d%=e}F(7=<47(pvqnCI;dj; zx=-pO=z0`TApkzAd)ANt|1H4_1o&H~fm)P(8$ct{pu1?iGeJiV2rOI>3_3t*At<1_ zLwP_~4R^WblLD!f-izW7f zN`dh1n}|DA|Cd5;cHIq{c<4U=Vrv{ISMl`v^Ss#B_V<4lBj{W<@W9&rfB*l7!EZE- zk25|1A4~>q8a)EC=Ji!%Ykp!{Gaob^(0%%aAJiIeo)`XYfB!ePgRZJ$>;+RC+sDWEw~-!H}o;Hxsgb7LPNhyS-8DDi}K4-EdB_JA_c_2wEC5l}@X2)ZK- znzc`+{rUe|2%-s;o0ou9g6_!#Iq}8xG)N9R#KHh-v4K+l8ql^tXv29f=m-Trju&~L zi;2Lu4s^}~P32o3?wkjjoG*#9h*1&f=A8n{0c_p86N23t;LZyCf88=hMIth?1mqwA zsDtLG<8Tn60TfO5P%Ma-5~-BfaXiE0D#12>w%JZcxY$% zgg_=3K`9>M%Cjkd{)6Y0KwgE^LIR-h0Qszx=f%b5|Ik|uAZZbDe_(40Bmrh7{efIh zhnxa=ps6GrdO0k3%^2hY3;vc>3=9mRpgq-Uv;Y5xTnW{!3mOC{RfgO=Wc|BDvitlC zWsnW#87Uz5UX27@z#y3N=YKEwf~Aaz5Kyb{#S>7OcmBm2P%Q&aci`(}uSWK+yTQP~ z5D7ZGy!-46sUlE&6ci1iFOH|c*x{is4B(s>Ta*9%x0na2C}Tn07Lei>lfYu2fsfvO zAhJ}{avnI@bAX)R`04-uW9*Et*+Exj2*$}k-AH3;SQ?sN>l_uL$=ckL2LCm zUM%_yIt&()ToL61EQN-G4k-agO6$oIz6P+Rpv9aL$)Kt+?(j?3Y5)I&wSnBnP*NQn z4syxeng9QH$EXPO?w$audCtE`V*rnh$wKqe%_NwgGme15?fMJQjBjtXNB8*`))1x8 zOF=SLK;%Ky8bou(1dzyO@bxzkkr!P_p!@3~i!?#whM+M;#V!48N`)-_9D3axO1UgOSir*?afd-QweclO!BRWRK$cQV%Rr7&6U#uJQhm!n zfl@8YK#@{a%Rq@z1JMffBJ#258sb9|q7t3@=_ZHi7Q)fXsn_F5m#&@eImCps5e=>_jv8Qs&Kx zkQ6;V9-5+&OVk}UAd585gL?MRdJ?Gu1LYRz)g2`w-L4$H{v4g|0^OjCj746o|AJhpv$8mH-nT2bqjz@hg}{O^zr}y7y45`sRGBX<}3^^ z_@{u!V0NT{>`DdM6&$t$QrUk*+z)Mh+agw=GxiUEi!>wX{zp*zg&%xHQ}?-JuELBj z%BF)3QReC02TDEN=U=3!gZAumfUkAV0yQ++Kw7{#5Zn&z1|M@`8OzbT4>a@>8QBTG zIk`j(RP>yGp#bWVfm=!8FANhwDHNo=7renGApFIY1enkZ$plc|1g%#BWlfN(7vJMS zSJi-$X^A)F>Tkv(>uxud-Z~XfUkPjx_=@HZ38-{At3|AEsW|A&%XMiGhjT$3G96s3 zzF`0G|No08lm7n)_lEFXWZMxd{JObeCuq!yp@hZw!0Q~)tP4l$H_*ZKb_}I#-KHI& zPN|EENET!3fv6HG>q8}CSVU?^eV!DH*r@S3mn zz>X&&?hGZYJ066%GgwXpjiyOmYCg#E?@&-c*bD1_|NqB9uEgbNhTefD^&K3yVd48h z5emNdt%Sjy0aPZ1H;2hEK-y%W)-mWXhYC;%NInD2F2?`6KU&su@V6`lbxl$FdZ*w1 z{}0(~1HIP{Tq;?gFJXOA69?+s`o4Ja3{-lC@^t%h^tytk{sLZzw1KXW2DSDfTiGC| zo?iZM4z6DQUj_|goqyp4Zr%w%oBiA3LG53#p7SsCMUVr>4w-u*MK-0i zo#FM@9UP&cd(K~r?g(K6^I1aO8D8Jp@g>BaAuA>BwOAJDbmf3!t{?J`xqd8o;THxP zDEVLszIajUc@P&FLXg}xw|NpbtUrS}Ny%sb6_F6cL$_Z3I66QBc?qCZv5;QSi|&}e zps{f`hfX(_PB#zmMvxt#loNLxRONP;a)fu+aWo&7K-}5h?Z(mV2W|j&hlyBw2$Zr~ z2Z)rYfNp>R9kSmo5fm8kKUkpkKy;}eL~W-B==Q8m50P#+j^)+9`%Gf<@4R|GVm(jCgtDTsc1I&|*nBd)RlJdf>+JLj4#ML*pB8Y3-^L-0Ax!tlL+lyHuh228M1|k>=VJ3f&GS{M%RzI$iga zaqVMtU}$(L2ihjzYw`d8{}<A)w<3q#3$h-!xb-l!)~Pu=GOQc7Yev z#O80E3!0krebb=G(CwJeTbR&#po9mqld4&bq1*ROLuCL%MhmE~Z1F-Y6ug^wPU`{C zd~FGL7DM-m7w5Pb7+y0OAL#ad698II(&-q{eeOlm1O;Nz|wl4guVO2%SoWU z{HaeEnrl}u@PlV^jBj_lF6lL4?q*@`_G3|Duw`IoVJPKjJ;~oP3v^dP>Jf(K)DsN< z%UF6tj~JZXM_TtDj&}s1et)MG}y2}Kb|1p+wTe=?MZ`sDo!0=kQx%LDDf6EzW z1_sO03;eC%Q~O-s^oAY@g1U#J*B7)Gjq}CAo1k+_L8llqy_gC*ZUl5>$&=>864tIO z_?r?zbDyzSx?SJ&7O?cTg1iMfID{$k@BiLbP+IBra|n3BRs;^eV+@R-P=t6`#Q2-_ zG5%IgkO8hD4XLjgEK65(mLBMK(CI9_(apl%>Dt2I=FY;vaPR?hXX%Vi*9G0KOS*k$ z{4c%1e4^X+O{eb@s9SluIa*J4|14$hu3%}Xea+BWdxyUjbhTSUtph`eE9kD2Zg$Ys zWf=>+-5J6`=hXZc=yv_kdZ0w=f2m71$1&H}jNo$NL+dyGR%y_guOL}a0)XwrLo%cQ zY6v&X5ZV8wJ`h9xmwF(~xdS>A2#+}zpyu$v%rWlvebODsV||IgbrVRhCr7sdsCWzG z>Hg684^)?wvVyZE$d&CN6?jZP0NQQ>-lPxlDu2sqP z(9PHz`XC5&$fu5Zr2Chp=Z*%Sv)#eyo@h(UFmi`(-Gpq=xBYe=rQQP zeb*2FOV5DwCDgWuObiUYzGpxi*9lldqPV!GZ6cq3u6s(|-oDNz$ zf*z9Hu1}2rch)}XE)cN(-dQ@QL}JJP|NrH!Ka?|dA3OMfIpD>$0B||*#2R$)fLLek z2Z$1Tm=dOd7n>nUK7f^ogOX*ND5!+0{m@xB1tBQUa=dtZ z6(RZXD(Fa0P*!Y6{loCW9pofvsi_+Zxw!*$zS(6i28JErBHt2pz;5i7*UZf)|F@p3 z5$Sdn>GnCr!tC49?V!=ia-x&{wYBj9OV=G`!ri`GxwyyPZr>Z$y)mHk$hbik`!48q&|p6JzjO-dTAI=i-JUVsf&rlOQiCKwvy2t~ zpkV^gNi$3@azJd?8_li@IJ!a93{Vjj8Oh&tbGkEJI|7%G|0vCL-juVuY&%D?JvIw*ZyVv)@i?5)o-bxV( z98~taW`~;GdVs&B5|kmqn}T10jxq*$zS@MX1oyyV`5zrCqT;>l7T)yT50s-BwSF#woL90fXLwST<1pfYwl!a`gJj zyb!zd_y0>!j%cWLX2?<~ae9&K3#!T@ON5&fSQwfUBp8k}ObG=oOP6@f(wr*6@V`_7 zr19=;P$eVrzf`2xL*m7G5YJbn+g0MV!wYRp6I!sCFdL-D6=p&&hzB+Sv~9Wow8bh* z%%1ikZroh8FZA~8M?t|kc9R6cDz`a`xkUhp5N`i|NocDfJOwJK_F8$Y zWa)FXK40{qyH){o`~qmxTyv@eLvyVP=)5-Bl59kLYWaiWvotb`=fy8?a2`+qCuq46 z^Z%tP-6vkmVq#!;t=sJ?1M&o@V+bz7Il3W94wOhi9Y=`Z%e|m=>IVXPeL-8IWnb9e z0>zF)XDvtTfl}sfR~2x6*6H?)3Fvj@=oSnJ`yV6&x|z)ZY^Mw?EW%z)_5Sm}+f^hI zEG_{P@Ad5fWsw(mvr&q-43NX2#hYIMqImlPD%6g@PWWG{0rqf6*o$=ufB%Pd|9D{v z(gODb%>3@}FdM2-ZD0c_huZMQA7R5JkPVQ&AYxj|1GJT~+YQvX;|<7S_;2$AW18DxX+p(nEM}-5-a;=0KC;)9%Q%(!tmp484~UcpiqF1 z+;+NgKqHu?8+^($*r#xlAvYd__Ju*W_x>;CX;x!+k+=&S7p(_M#Igi36nxx4I~ZPg z!$eDYz&n5cJAj5CS;5_u`<(pZ}4NG5Z}3 zAZN$!fE=vQ?FgQ6M9N%93wcAqy8^?ze|3NCKK}x=>aRK7g#mQeXFN|p_i4~^zjolZ z>mN|>uG5*NxsHdSOs(7XPq!aO_l0iegO8Y*Pca|*@A{`(uv4Jhlcm#x1#}g=8&A=# z?l_k2^T97(GyeVG8PC!k$I|QX5d7jDGpJ$L8Si50$5N)*>H7y{m^d?Av+Ey;?g)WS znXc||hi-{ZnNy$zf-a|69IgFWif(ngNr0|-juUAqrk>@MQzcI4?S z{Q+9VRL9aC`=i^y+Jw2ZsJnp0+PpLyr2RNYcj+Hc!>drB=w5fF3s~>}GUaY3hwefL z?GN2DY}OK`4&5U;PrR#1_Or|yWK$JN9SHF_5S-Gl$A?VIIyOc$sl#m)RF*7 zE&AJFsRcY$iaoX9PJPZu<~4xKyT6qP^In36`a#oOX)FxQX&el_eiAR1xiB#tXL|z4 zMc{)(1YkL*L`4LYb=0;)vrZ{5Xbngw8%i!Y1lsG3%iD8Y5t(EG$e9)(XCj@4;3g3O zStiw81|IM41|Ld;vLX{4(gH66T|s*#I9_;yjEwB&i)%eu!k)$a0(4Hs;V{@?+2_U9r{e2rt16UqtKx`v{~BdZ@HoFlbYS%!bz6C1SnaEH557Fo7;4 zyy?Ki5d7jA$gtLLrFTGwOP>UBK!-(d0r@9m3#cH3?2iDYwr=zt8r_Vb?fNXQK^qbJ zz*&D&f6#e=_FZaAx>#o+T0XLVF7n!?(kXCG6oZLO?pZkH^0j z?LPNH7_{X8Bp&v{1}uIIyvyW&A;$|H5Fb<@fx`n-Zd%uIlxhAqdm-fV=RY`bI2gda zph)W<(RaZKIdbM?DJ|NM9T(J8{w?fa!W^hfgn zmjAAQtObi6g1V8uZ(0wO&If1A(C#B~`c{C}BC z_xTqu#26U5!$7{eSZ37e%K_S>7U#gsu6?oDl|!OCWb&WR0D-!@RbO-ML03OgN7HDM{55o?bM{W!+7HkBK`x}7PqJ)D-*Ba^!7)p#^ zY;go74c7;tv<>RpWifW2c#-q{KX{}JG~6E0>&MgS#_~ex!r%YhZY-}2UNnNVbf4(- zeUQZ%(R#Ae^-l>$z>6kV$mkke58I3P=l}i(w|wBkY9~6~IC{ezz@0i4(509w85tN9 zUEf%`iSW102K7qZ1iF3SblY?^Lx;?|{biu7kJghlqP?z1HZcags67PgZSc3&fNpx0 z_+Kv48+v3TeLw>fFIo?ji2pCs0XLa>Ko{6Q;BN(Yon2pm zo4f4L)(R-$filf%kagg$Sp(Q}A3&yl2+RNt_JB;~{4Zcx`=KPO+s&dm^$J6C>J5fo z8;0-~S`OftxYAjB1KdU6vh=ekQ|xv#=?=YuGEQ>^GEU=XQS_)g_DQ$vhw%TUS0K*o z{&CFp4`=KDUf(PHt*=3w=oCN;jQlvjqlS$C12`bPRdz&m)Os7#Mu&z12PpPHm*pM> z-4E>grrY(6wVMckQ|iC}|3L$;Uyv7zv4EE9gN}{p{_tA#xa%Jl(0;7X$6fz`*3N>* zhCzcMtVdz(?;|gM9{Kyf``GL4y}l=4tNfoGK}g>^^7lV@*5&ooZdcHes05uUcL>z) zc#ScqItxnB zB|MN>5BX+AhSyTvt|F}mN|-t=y8U=sPnK|GF@(S10C(j;C(eMI_{ar@iwaM-kBR`J zn?|^xpAMwRh>ttO0lJns5LCK=@_ujVpKdpfaMUT79}t^ZyM6z3azHHO%3}CmD)3?^ zXh`@tsDKe**l`#Xg7#}c1xy8~c>eezhns=H_%`S^tqGtp$vB=;A_(CvHT#jG=+6}&v%t~{V( z_jb2iOcrCL^}$YG9{x7aQu-``7wc^P{I@FX)WmInJOE2AZdP&1C!^bPE3k z*xCEtt~0uQLBl1i-7Xz}dVPC3-N84RzBnuX_kR}4i)5%#ES(mhGB^MeUovtsSWfDtg>z931C z7vi9RcYOgmbl-IkfBXk|HkOCKZ7S%JAC`L1xW4O!Za>hh94NAQ zx-G1Kmx2cIJ7e#F#&PciW?X=dVsn9t%RBHP5}wZ3DH^^Ynv_T15H&f960FKUB4v_U6ff)y&*7JfKDA4VD!7`Sk zo1wRc@k3|rk&^T*kr(T%An`8-kN?gHf#VDUC`kZxYAt*C{{WWGc+m2R@Bq+!!XLi> zfe;t*w>p7G$c}WMe{tgDpa0gsK_mMmQr#du9Iu7C*{u(ka0a}{v;xJVJg5Wb3L5U? zf`=Gr#1&M2BLpC6q&fG3gthA#{wC19g`m^{iU|Qwq!cE+kgx@f2=TXqc5!DJym(>> zGTl`GoJRQhTf#uK(TNw+SwKfJ3%v9K1=oU=pi=V+D6kM#b-Ug{v%7S|i@la0m2V=! zrXeaiaN&%UlzV+488a6&{RqCbis^+CKPdCg0MA1{0v)aB`lKWF53+p^K$Q)$z=4-Z z%nS_BaASjnTQ}h_D&6oxlr(o91xjrb2`U`4>+#$%kS3X4e~uT2kAaE^flhZG;{%ql zE6PN=eV25H3Uu={I&^b(2J%?Dt|)qA85dLHmnHGyzd6Kc`0(ZjQ19*ssH_U_^?lP> zd*Veg*t{p!hd~2*G65hf5{`j}4Fo#lMgEt*>Gj?4LL~yUB0b)+E~ZSp+qDODskqCI zKmQG0a7X<8?`~ZeQ}nXi^#Q~P70}>S?dR}-|D_wc1$$lh1c1i^t$&x4gD&2fVop** zaftv;en3k0pFD^N0L@W#6HF+_UxE&L0tJRpx9^Gng(BUK0^Pm}0WYo!fjkresu5gy z%8VdI_5V_t?wXE2-REE2JO&E3PFI0a|88G};Q!?uFBS{^{SV1xpt|8)cdbNcEKesW zb6Uo^l$AktE_M6z{5R?7^>cXP>-6`(_2F8FZr>Z-juPF0GM((5;ViE$K|wIljHn>! zE){s~*zLy=&@K2sNTJ(TBq-p8ERri+in>6iIh#SYJhJ!tzIkzQHz>G3Eh3f|TX+Bc zZ~P6G<9>&MWFP^#0kjSPT6GqH*`OTvqGdO%h4tV?#cogo4BYfU41g*y;2wt9V+!xz zHy`A9S@P!3f82`u5sG&_0ksLVm%_#@z|AQ{qZ4`Sdsz2J#3&$S(1Pd1M`I=i*ujg( z*$hD0<`}-=7ZD_@SsuGFyx6b=)NcoGDFrug+<1r?hX@CqMcSMu!_e&}&|4?adZ2_8 z+_2_oRtJr&@-!dg=|1;D{P5rZ-Dcq#3Eu7uVcl&11;D*(+~HDg0uRI;Dj>%RgB;iC z`vLDrBIuH~;|?qdVeSl|$qn!r>T!mEFn5OI4lE8~h(lpHy4^U?#x7ZrZ1e}&xNtE% zIJ(^gj=O?3#e-JKLfazUWjvsnN6>;yECVzj$J1K}TK(F6 z{zX4%wZEUk3xA8h|9epnNNocT0zl8f>um$|%VEdg^@5j9zH4SBjR!Qd<0jJUrvj>>I@}~W+$4{?fi^HO9CK4(>~K?jQRE0- zQ`LP8KK6Wg$3Kv%Ay896!O&Z$0_~r6pMN3r0<>=WMY|DbB#Y-oy%D630A3096EydL zdV~ph45#~J_zMxxys$e@uOCmq3syD;hAwxB=Hn_IZW3MYUpw3+yWM|uy2*68|LJg3 z=yLxX-s`6Va$l(ve7oWfi6?FhFZL`1HNhi5aTMOL4-}RR{H>cobCPZ%#{aF4^S4f6 zU|?vdGh_gT>kC-8z5s`7;u0nX%Q}S;(Oy?H8TTbj44~r^e!DR+H2dBF-BaeeC%V^9 zAfU7M&vDl?jO-uTI%_Y07A~CyO$yY3&LWQt{P(}xou!*Ui=k7d@xMDuuV2KA&4Hlt zjT8n@#Sb#^o$lZNFAp#=Fjyb&tbNm2`+>g=baWDE>^by9bDaW1H_ycGNQu%Q59A zE#CTm8E8hi*Dr$kc)$z8Kv2#0yXY-r?3-S&LpKCK9SU*gf7cJ)ZX%YhANZR}L9J0Y zh1LW7E$hJJ+8-EN50n*v2MXL|y8T?3U0-wua9CgL41L1iYzCT#6|la@->d^-)j4!K zuvoK9=Wmu}0u9f%UMk~Y=5IdE;#K;ix6Y?mh69vuc>Y2HsXO#Zv+E0EMU7(ZO>tYy7s=D1$y7>=2U~0DEU?|Dy z4$A=bfxB6ly2AxpFLk=UC=>0D=jnERVaZ$~_uutH^I;Cl&<{oLnos?2y;LLE?dAho z8+Pyk)9ZcRp&wqq?hcnRKG1rpOsLymqC575rDO>=c-6t7qL1K32Q{1lAZLDKgd{`$ z7SM!2w_8lNp9{$1PSB7_r|*+8x867(&_Wy656qx(CeRofOCxCZ4EiX7|?eE<$JXBKFXxxOem+U@!xi!u5&a~5NCb6N~2*5W!{U-bIUd13AXO2a$; zH>Yl3=yjbF(Ca4v?sINA?z#q)j$d$tBJcc*S$>FA(e3)?zdOr+*Ee9dzxRVxr*mHD zY5)EI-}go7((X8s*4rgg-EIQjz2H-kx>;uYFA(`(An?MG>+k>9kDBXT1j@y_-DQ~F z1)6^dlyi5Vf6=24ij7jp3e?x2iyD(({r`UqyeEJWeY6F%%Q&#xkp;AsJ~%Ag_1ovu|pqJY_!gW6q22#AO3FxjnjfE%om4rL1#mO%Ig=~!Awv={$dT7 z2^#-=u}~MZBTE3(Eb1`&`@h#u;Kkiv|NnQF@qn^7j;aJSR~goNp!;KqeD{fNwu29u z!UMZ)I0Bjvumt=UJpnq;j;;9!Pp1XAO5NcGa^KTApvB+au^eIDAFc0|vUDGN9TDDr z?u87fWOHWeJ{QpG%JG6b9<%}7vX-OFB1_@LT^(>Y2z;ng>wyx!ZtnjkJG)Q3*Z`Uy z2dy3SW9b$HxwDg{>%SX|yLBx`(TVP3-~)|Ns*xy=3z9)D2l5IyPtdN)2qsXvf?S$;)(3Si6g0*Q+GqowIgmrlL-2KnGTE}cq;DU$LZ(3Kgl%$0je{20;;j&&VNiB7Qb?biP#;^1ivq*)A3 zklo!k{+qo}1F<^gI_p@X!RZ8-ZhM$+rhpfxwLlYjAl)xOEF|4Knm_?jKMRx#KsTE5 zyqFJC0g2>q*5^Pc&auDn+67v`0rC#$2Gf^b;5Y__C49;|3|A!EJ^b@O_(dVeP*^0V zfH){OnDTYA`~5fB@WKlu^ZMO?^A`>v7DNsBIF|4i@@k+`32}l!x4T5An?$#}OsAU+ z$SI)Hr4KeIa4<9{@Gu}vexW70Z5*IP_fQjdoL6%?3qyPy^bD%-oeT`kIVvnHFF|`$ zLHV^Ik&mGv(S!kXIEsr3N2j9#=!lt4N0k>_7#SEqd!na+0?=+IC?$n~jzPHH?WfW0 zrqdm!(Ean^a~9@`217IB8hhO%Aj#??@08OyOZvXoqbfG{)9WO(PU_(70LkV|7 zJud@zpWSOF;{%{E-VQhZV{Uwm-R$77W$AR2Db;PR9HXID4 zykJ9MUg<6~0J#t}(~;ew;evKI(l{8p-4q(q_&|+x z-fj+SKaEn(<^wF9ZVLbXRQ|hZfb1wy;Q+VRWk7R9#s@4M`Ag)w19if>3pK*KD+RiP zA`U)d`F`E9#)u<6u7o*@IU?Z2r2qf_gXRyL>r@y@^g)s2r*ZHhOSeM=^TBQoZV#4H zsVvZKcp9LM-3LnfyU)E?^dEHUK*?G7zK3pCkznK7Vb+JkOPD$(x_t$#PxH5&1+82y z<*Jt^V)+VG+k)BGetq6WHx1@FKqrG@8o+I=#bH#QJav6C($s zFOR0LfTo{>WSmU5n*_I;OsQn|xfh@QfyS6i9YHgx|G`YNZeI@T-=${Or%NbOH?B$6tRv=4QgULx6!n;q@!f^g1Z; z)Eese7{EKQL6>fV4uxnvP%8ZTaTa6uxfd`0fWzz>C{2N4XNUY#H-;C|(?ELxKn?R? z&@85e@$Jsk51>)sKb^I2U<1s}wF3Vk3jrBBV^8o;ag}bUm1Zd6>}~^{DbVREV0_6k zRG?H$A@q;+Fa8!OP=f_L#Q2gQR0*B`-xe=HTG0F($n`AUv2U_Kv(VrX{`=Se{O@W5W!&Cg z(A~2EFPzST4yAj-0GdpD5||<2>&^h0Ok@2okY(}Wy$XtDY$cp8v_ZQXZoFnPz73w> zVg+9UdjmSn#R3`t1NTLHy+I2~**l$eUN~+Bt$(p}73p++!9Vq2hc}ON(ZpJ^Nw`Zo+xDlB?plS-EE+>0BZY!a<9#V z=KudYYeo25Kx;d@`@ky&+ZKSNVs^50+wAP-xuMPTqto|Dx6ch0X`de~-QY8Ax@$$8 zIzz8?`kv?(+0pI#!ok{ApjZuLX9-L9iPvo1zC56*?|C4*EN!|=xvhP#6tOvW`d)c` zMceg7XQ)W0>zZ!YE0(Sz#WLNlA_pI^Ft>rz9q8CHM&AvBu3P@QioCwlpsT05ea{30y$JmI|37o=noiKVq$f2>379 zka~%sA@wptukQ}f@cIi`L(tfOO0VyZ?l#cg^M+JzhW}-tyWhF~mq}zXMh6G>`d$v~ z^}Q6>>&yMW^g$qK!tGA4?}q=SHv*w+FarN?TLYS(0q2eX+g30#Fa*5lJq;?tI$cHh zTR;ck+kzH~^S6LDMmE%PGw`>nF@la}gDhT$xQ6dV;&spl*5B3ryoVj28ybAGBt^&p3tVo=f z4!>jrb+SS3RO)tp(t4mo8oWv%Jc}vdf1n6x?RW`jw*t@0PRLziyr7^Dgu3&nJT`ZN zHaB$FuIP5%(Cxd0(Osk4^@yOq4x_t5x9bT(ca@h{LD310*c(4U)nBKpKuP|N=)a)z zFkL~@B<#p3gM_rD3#zaPN29C2YZ1`8^%qkoGBND946+xzWfwf&4Q-}JpFAW2UIUwU z<^TWxW-o5bfmir~23z5GBpq|$W$g4YIL=T28fAq{%EQ;pK~|f7?g#g!psP(6fG#2{ z<#}-zCQABh(_oN0pz8;{L2ZTiy`cUGcmTWG%>c`YEeEIu!O_j$kqk0o4YCmlpk6&9 z{QsA^fSRVw$5>w6kOkGA=UyCA0{3YUqn)5e%16-h;a)$J7fNgX{_n0)k?3|&5i!0U z-s@-4>88#KbIGQ*Z+VR0WYF%{{P?XC-J{CPM|YRp)*dTBTl9> zPNmz82Q&!^Y2omFrJ7fR+H)#)q%}B8}|7R@q`d|8?*N^8#)@sni+6U{yrM}&6CjZ?Gg2B6C z6+pAdZ}?lMg3g@!-F=RK%7K6v^FW#3^#dqitPhv;L7e%zts5=`8!kWoI&wfWHOQ9PKXUfJ9Apx356sPf!cJ)0d-+{kSU! zhz;7F%Mk=R38a(<)Y7v)Tv~4#%TXE%(FC0%>5Sv~?`8mQ{)U2wPED}IBDk%nV12mM z7IYY-n@+JY=&pE3^IPj>*?&+$$VM66GjFm*B- zABc+vZLtNdYXNmp!@`>t8M7`g)jjK5j`>n>3dDB>vBwEk4a@><#YQ!!t+ zgHN}}hfcw6mk%tjO&TgB7)k}Y19&ieCL6xen@2wT7C6mIq3Fq@X_qxHscQs&?Q2k8{R-O9Pr5# z(B*EOP~LI2BcPceHmb=%ZugT zLC55DpX+eT>u}5Oa4YC=E9`J9>ToOWbp6xeR?^{C`r^Ji_zpAVX%J|U2s)0T8R?p> zdtJ~%5q8a13233Q59pe$!!RlEHCqS3V(VdINY`vxWeH>?fMq9Q$Z~)$;VJ;j7QoQ3+5w@<1XUeC;2k5eVuE zA&TZ+H;M1}q`xVD03U}B>Yp&bc=`=`o1~x0i?usP5zg}Dy2RRnhQhad+%mf|X^x~j6*sA^}8g z19dNY_kkv+UigCq%wKqbsBImfImNn~7givi`3qwZRaWpq8%(FXPzKWxFQmb)wCFzf z0<;nlG+NgE@qd}m3udsq&5Pe+p!T-Ki_c)%rt>vHGX8E~2w8rn4@gvo58xE~B$9r?al0v#zAGuA7mo0#69;n3mX(&^#R z>EYAq5zy%oau`%ZgLWi!H-LvQ7{TX}fVLVOX8;W=!@12rSc;(2A*%e_8X7>;{yr)K zos8W+Dk5q8+Zyh0xih47GJ?h*n-v(04;&I<*s%Z<&IemSQ=dGbgGU-=K|3zN$5BAf zWBWA)dISk*!A`d?Xf4|dRnTHp&@dC|Fq0QS@*q7gUYr#HHH8q{c@9C3%TZ`Z{m&2v zTEh6T*Y`hYz+VWI1bqK%p9t(e_hOgaAIOaxAdiBEfsMa)pJ;x_-~5xSn6>$!!E5H` zgXY~KDgu64EFC;{kuNrZ2D30!z+|U@WjjMu1h`L?ZtFf4|NRDNx#o^NAfH}u2Kf|p z&cE^h&eRW`wSUq&YtN*0)}8}h+3O05X~yOsI{fYNj0_C?Ev}%cz8AcZW2u^7aF$p% zzu+qo^YGwru4t8&q4ka&&jh05KZofXIv77x-HqgL;>NFRy?)oW6Hn zD9QYR4o@*z?*kP9{LSDwTk!3i-JsEd7rnlBx?_H@yy%w&h5HM|QoYvOrCJ$3!rU1^ zcS`lh{`t?pZ5pV|08Ije=0|&7_w@SS33yQ``{(~_%f{LljEu|-rHZY$OJy@&a6`0( z%KrJ^JqbSATAwe84t#Ci?aI-x1GLzWp_Dm`F&=7533Ky#Ca6UqwgS|O61K+k z42%p6;UGI6gDx8b)tCP_fMWCi2GGT5Ac^@|CGK(?l@+0dDB@&L!Kjq6l25(MU3AzKP)a2j`k%q(Eug#l(aurF1 zXK{5OG`6aB^HAYw(f(GZr?w~cb{rFXwbpu)_tr2v}ZDH<$vZ<)`Ks&HfMKV z>pt<~IQO6b9TE)*j0_IZafiDPHUH4)zF5Z6pu})^1!E~s_lb)yn-B85T)_S3|HT&$ z!OcIo!Zv3Yu{9iKYJS0$#oT=&?((zlb1xd;#>7Q~=1)O)%Y||Thc*BDAI{&h8x&2A zpz5l-6LfZcx5$>N9vozpTCv;ijcP51Hc%P;0MgPOA+ zxIrglaD#XF-2mKM>kmfPCyoC>v(Tk1t+z|mzqxWNl<%jV+)HJ!p6vbXO=S zk@)hwcnG>DEtCVaK7rl%z{}5|AtLY*cMYlY8M?uD+Xi>@K!g1T!*0-xAlx5mj5(kaF@7uXH>H3Y&Au02w1FF_H#%J3LnGrw zx9f#o6UK;6S5W+Qx_$sH1^fVu5YPtZJKeXsLm#~0Zen8K{=t3gzw3w2+B@B@A39?n zSi8O`x(MD^@q*Fy#y8jZ0wn^V`|MU~fR-sSnSKpWVz|&9 zdV|sRMz0B1L+S#C=Gq4g{O!6-3=BnF&9!&_^S6V?ZG7)E{sa|m{H>r9kDGt69(Vl^ zBJa+?-x>)jZ^IaSeHXl#_2>V8{%vN>|6)NS(Jl6j3=CPE-N%eCMSlO-eJqQ$`uyh(yM@KmT8Xt^jHNsaUGe{Dbkh>xT(^Ag6&=TJdia z139hm&;S1~L9Lj^pNuTb45iKxFGz%g)PcNo%ymJ2Z|Fk)ZG8I$!rd8O{AK_1zl#^d zY&qG%QNrHk&*<*(`g3;}Xq(YS(BWjs%|Dq-MIrXB;d5sw4dUO%*BiRP@wH3iPiaPG z=2Fh%t{*tU-5Fk6H2!3U39R6AXLzmN_!E>}Aonpsj9>_NXDH(DV(SfE(EPx@`^1ZC zcF<7P2T;lZb?>_bjK8&9Dq(kPuwi2;{b_u_!gT>?y*xMQKD7l5r9Z%HPkx2o1R2&P*dgHX`b%@|3x*Ok=Fhz? zrXbm43|3vf3miH)92#mDF!cH^Ea3txbZog)`VC|@e+y{)0rT%;Ew=Oj{r|7%2ez|G&2QUwYuhUXXZm?HPs=&F0@MMJjOnVGKP?Mz=3d?-a0`UKCY= z&OJrm4|#}#0es_@1ZV-rp(@Zh4c3SGTftpb7Znk3fBr}JL{K{vG;w?#G~(3!pNGF4 zbSMIU%VW?wtoO|PEug81W)Nc)0|SFUe+#G%_b&wk%M_s$cbb3R$7^S7EYGB5-+9t1CsF#=tS?8cFHoK2LWGmPh@6o?-O<;U^7 zvlQDl6IWYfuS>yqtlTGJjMDQR0r*- z0M$VgKs#DNTbsf=Q$HBr?q&-E4G{(ibk~Y>&f@?rI0S9ZU__dA?Ti%xZ#-Zw;REd& z5eWoO;DrAdfJ{Sn&Q1CM|9|J)jQ{`tcep+QHI{loBA{u%j(MQw80eT(ZB@`YkDy_1 z>+V*lG&AxJ2hh1MOb7w6jf~KVU(lrO%bTEXMH^_apcia@KyMo;Zv^zVfyQ(KAPZ>! zmx>%~1KG(K@M5J4%t{OLtbCmbI+L>x6k;#zrv3d-jw$ClWBu#w95N=-yAR|f>%*O~e@ZwYBe9+G z(2)~!P$+?i%aF&qUQFHtnzet;z2h9%Vk}m&fJ&c_#<#;e=7Fw8@0jPw$iUDs540<$ zW1csd?E@zLz@#r|(8eEZ8R%Z$7oe-v|8E2J^LzJ!$QN_j{`~Kh{|_EU>D>qF`oHL6 z`}04tQ$DhD9!PcPJn%*A^T1cC&jV%7__*l9;DPlQMW6zv4b+9|od+U8OLRdSggn3| zSa(*lK!#g-=YfjD7lt6atUK#sKqCa8F@usw@GyZu=RQy|)Cs;`r4zjDw{st;C)2qP zR7!U412t|t_klW2AiKlDyFVKL@3i}0#_{4F>!1IfbsU{_ES+@%opmz*%T!*R0*k5q zFVlFjAI#MFU#9b73z(_%zs%spN-)#lf0@aPd0?i=|1ygglfg`jZa16eBQn;JYLZ>57r=v)xqfDoxN~fa^bnVfS*RcEV!rnkw z94{w8#W-F%LB)7p)}de4uomcbli0)<(Ca1;0J?^u zrUkU2veQkb7CO?v1*(e582|kTl}w;>QYAo%vY-Ui%~lEP{@Adu8FYh4DX0ZI36vIm zFT4?#|Hb!Ewxih4DB8CukQg=pwQ#)+~Nd zbMfNJKmRiX85tO|I6&M(ATDT-9n=rJ@M7~y(5mGuUXavs&^|3+ju)Yl;HGCF=+r*d z|NsAks_b6h3*8@HoO=XX0*+F_vM}t>0eN73F~|cl!H{*6;l18Gy=|cJ$bc7%umAtw z>t@sIdn4dQk^}<-Xo2w^P`5?C+x12_%Z}y>0ft@=o>Hz1Q2X!2CZ0e4-K}fy6g_ON zy~9wd-RpbfMZV78|J{BDpcN#XttWS?goBP?-U(73*z3XbqMql^|6|S)jK-HN!y-y_ zj89qy3zP|WA8J0t!|crS-+|*lgQK;#K+)S?HxH0AvKU^xb^G`Kn6o5fL+WR6R|jMl zf7=33FQ2(P7Iat`WM6o%pG5czOU=LkK~n_hUu1w-r(YOLFferA2nVg?VF52(;%{vS zRiMrS-QFVI7q~BiPQd!i*su>Y&&y9#)yM6twE z_W=VlLy40v12Y3diIFb*Uj~K}6^{}r-Jc8$4E(L2I=TD&3-HdmAE4FXua);RFfcN_ z{=A=|fq~)mo9^>3K<$s$?A_;I=sf!SzxzjL=!@oR0maga=4ug!(xUFr7ga zl`?_$$zCp(E@HO@C4yph@bW0*OV*dmK_UzSWgrm-0pm;7p)bn0i&(6W7qfPUzUV#< zxpS6H__8Vk!-xNoFYHR07_wM8-6|qF!)mNA6q%N@TE2=0cyjBC*$PThm0;Gx& zp^Cqpt+}p(p^Uvbt%9M`t){uIhM`=nh_kV-0(4_% z9Tv#j%0XH8V;18Jm6f23TBF&`*Ui${e1IdZ*+RHfy4!(c=Ylpy2J3^xOx*`}F4)b> zV12Mmqx)doVbFT7m4E&>|6na*$>My?+x&yEh^^O!;s0yU-B_6iK-$3Lw^>Xtj;{b4 zuG-Dl&C{3$+J|$HBh6Nrp_H}Tk>j;|nyn~9DF^6y)<7Px!Mi{=r=G}SY(6L)aruGq zrMSa8?tyZdX91|Wv4e?$0aT{fav0w>{$@EJbb2XhY%casXX$|w^WN>CwbRz0K^!d$ zaBWj6VF9jhN(C(Dfohym4vTr9I;Vtd2WZ{K%SBwEEPvufyC?&LMSL}Af}n)cBEIUF z>tn`J=8o9M7V)(pftq8kkH7+ty8P>{PM2_Wxz}~LzJJYf%=JBES9>D^1B2D!67H_) zpoHHM$_X0-lXVq+N>Q(|rrUtP*>8JEF7)fHr7DVOCukV5{cu8*uvgLt5tg@3B+ zd#l4B9;iOypX$op>wD!z2;ZOopt-Bg*caWdFRWb!_?zv(OOiya50}dQFTL`j;s5Xd zksYyrK&Jp`$^L_E?SFZKlYyakssd<&kRzyfs>c8S|ATs`s(`5fr7u8h6F@VwPfBD! zM%W@5@m%KL|8CbOFWW%|fcFKz*u}}fU^y3LL`Uql&e%Dfu?zU89UdVQ}12K4rWV)VsYIR*xZ{w_b>4&UwFe4V~?y8T$X zOAmDVF0gI`)w#v|-F={;P74{vW3Jo4akb4Nb}N4?s4%g1%P5xV_Dcb^r$xH`3c5uO zc80ce`y6EH^zGQl_?n|Lwxu(+!|0?nIO}!z?(FreDV7Ge>q|tsJ$b+ydLSAmKs5Ap z#!dif07YGg@2=iHP)`7&M*yK`O1H~FmQL3h8^D%K>5QFWbfCj^cXz2suj`dw-z5Pr z#P~p$Fm2&)abRI!u!!9b4c}Hn76#B>?VSJr|EG1%%>y@!OF+@d*4qmb49sHxUkci* z$PxBGKmv4~Jb%k{&`=Fn_O-i3?ADSQ7O~urRc2|Ob3rFbrghGZ1DgbDHFvv;^iBnd z24!)AMt4EGq*(&~2Z9YNQS1euJ^A8R4yd2J9a66fwxk?znJy{^{({&u+HfUXWm578}HU;1$(y_kpBdTmfAfQ@Z4ZFw}kA$nM)B z0SUzrR&b&KX#gdPhp*Mrn)iZu+#pAS7~so#(=6wLtUc!XkP%#FY=>C?q96X3-H_~R5&Mw8 zRqN0H{}!=3_*)eJfKEu+aPS3-3S)=s_LqWx{{K&F-V4gLqNUQ^t>A3j3p$6k({&E_ z!A{==CFT~f+e(ZeIr~LA_%5|2FP8m;cxK*DB+s~u|NFlKbh63Ir|{ekcAjD8pZ~q! zQnuIkM8FFne$dgXkS)uxAcI_AbeA58e7WuC|Np(cAO8LS|HA$lh&chWFpcwt!Lk4U z|CjUhmVfDO1<7}x11-1VdLjH3vf`1W#HzO!t~vs&8Ke$WJ-zS*X)e9;;?oa^TS2*W zjuzL1iZIiwSE%D_~wgPLzDvv&D8y& zxAy=jcGa0cZJKgOTz0mC#7cQBV!2B>I_Dnw_y7NEo?dXAbhd(c)}Kp6EaDSN_$}sw z&LKb6dIA(DC2SpYL5${q9KF33|Nj5ypL?LA^(5#RR(Flg)-(V9|L<~r-_d#jERxdM zdIQYJ=xn_MX5@6XJ^(WcI$NKB6uXypw7vi{$~szKf*9?fZeK_1D=-@p@vlM72VK+F z+iUapKdAY`|DqIp6vQ4-#p$~z5Ikzs%@%gd^^f3xf&Zm@dcpqd-VbULc84Aa08JwI zwt{qbpAYD51vx#S*Y!le3z2XJ22f>LstHP=CZIzRz^;dQF94$F|5i|t1iavN1}W}# z-E++KkAOA&P+BBsffgo1w1Seti+WIR$n^;7ksnBzM)@!($H6m=$YD?-yz*l2S45^s z7ykFZ``Byl9XjfuVI3@^D*~W}mBt4$K%F7bY9~hUVUZ%B?mqY~iB7kGPPdR3BFjLX zR&Yza*H7aGH_M;@Mh80FtUBDRJKStK+-y7C>^j`+yN|^k?mpOj>OXXiMTZARhX-e8 z0M9W80mjY%iOv9p&H$Ot0F@38jbjd)j2#|Y#~id75AXN@YM5_G0d;=`K>JkEI%A)t zb;dpet=MDiEqwwW3oPXb3j7}+VSTuSrTfNf`?TiTCk~}@pmS$KKNz1h{sx+)kK;UOgif4JnqvFX3*Hp~S*ucky5;}y4u+R*3@>&j zL4p?)7?9C3=)q(!K7IQA|NpippaGnHAd6l+1PPeGxCNrNfevcz-3M~ui<2M$^B0Fe z)HcvPp}qS+zIw3{Bw+qx6^Pmfns0!NP`;Q65-@);2}ErJW%J&;iWe;)p81Q~Prv^+ zAJOUc%X#tX)$jlR%MxB>efs@B5>zww`h~pM%Fe*>zs%!BC`fsk%?n>JZScYsq|X<$ z;t15%GXo72q8uFnUakyVcmzHfqSHeJb6E~(qZepQ@7qU^-4ZX}foYx>&p@=V-lV|j;TPKRS|hhtucV}6HYL5E{uhhtHPV{!AT{~eAc9gd})ff1d7 z3CA4E7&`-FIs;QW95Xu{GddizKvuo@A^!J&_qi9KDku&z;VuB`7T^32IyU^ni!ThI zbo}9k*SFvQK?gR1F0kPTUqaaJ%F!G8r`Lp`+x0`Q4O{p57a=?#wSTOCmWp?~e)#Xo zk=AU(mdf7>3ixBrnT)S1w9jAs$>_@g+S=v&g}=N+nt^mGcy_ zHveEOX3b(Wz7)~v9MKsZ^V*hw`^n~)NhK=HFIh{Zn_se&2zh#za5cYVFZIaMhqS#qyG8lQaeB$b9tIOUjg24lDD7fV+T{w5FbQj-raW`6knKN2){ z2%e1(c+K{|^uue$uosOWad3m^_2V5Ppu{PY04kGsKtTc;Dd_&lza4ZYR8aE|juNrv zAKWGE5aqdPmhl{*e)enYZhwy6Q0^CwQ~vyKIZ&$ezZ`UX<_qcnzyJ5Tf|k922Hq$C z0~OXUx<9<&16kR9?6uA@S8hg&Snd+><`e%r;xaqkB0Aj?I^AMA-BLQ@GG22XcZ&cw zYvN+i*Byg425W#En;#EytUws}qSue00&eNQ-~YRP!B;N)dC~Ue_kYXU7o}YLK*ixp z@Bss^Ptuw#ic3wwXB)||{sAlC|6dA9!@vIh|NpWOTnq7}Sz45y=yiPpYII%u`~Uw- z(ByY-=m(G`A0~qaW*{SU-M&wD8R)q)y!i6vH|Uxvf!?t4ZeN}kJ(K_Zf2j&G%lFAH zAJ8=OWrzaS-mvV~cR|`bK%#pgqPn0N$xv=kn7jy_{0Dpx259oT%at26Go`xn|BrfB zurDrx(va_yT`nNq^$^{1Al+fPFT|lb*D^3L9COQIH2(Gyv{xQvnFC0907SV!Z&)74 zjiA}Mm!RPnkOCW!0)2=A*50rJh#M_HqLOgYqSwbkYE3|*%y7|?*Be2i1|ZS5pTWVv z(HmCw@(ZZ-;`?Nm4oKn(Tq5h`ZE$Mf=|1`3h9CKr2j61x;1{C{+v7p%30goPs8-MHd766TBmHz46`~@^8!vE+0|ISj- z@u=3WBK*zrptu0tYt8{WC&~B0i>g1MqypOV!T2KP)9?S5rB7ff{T6n+&x;XAeZ|Ic(5EpcqC+HrUiD0b{(wZ%-N;iQO zZU-xT(;IpRq_DH}%?n4+7|yZMOv}Jerk{`5=t@KK7 z?TMvJm-cQ3Z7J?P_aYlKCg8@>&DUFc0#pI_vN-hGG%j7b^ndAt|IJ`OZv>fP{Oz@F zKwz)8z>8~t{{Oc=RwC5>0c61xkYx9@D!Z93*hP z``imluqxPD7F;03^BF;|0?*>^hytZ4*=Sf(#rOcIe(q%JbYtms1C`*Nu7A2KS*(AQ zNP#x}BX8RmdHwr;WG7o^9S7)8fHJErl^2X)A=fwH(^nZw1VO8rIRBf>>^|{A{U+oP zTF@Ar7$_1T$2&M%-!B3sebCa@Xy{_LlZRNqm!@Yayx8#S_kZJWk=Dmb_?kUr{&yO5 z7O->{aCCnF?ezc81v)Y-9@G|vHbgr;I1cZ~0r|)~3e?&N@BZ0Y`=Ps>1+?tC^;-$r zZhP6K|NjTSD1P<(ebW`bd*9dr_{qy(#Zg-PTH*N`1Re z1Rs3K6y6)d$hadkG*s03MmbaW;a(PpgP?0OL|^{?-~9u8J40lN5LEQPS@?^zDDYl` z|7I^FUxHGIU1uCed^FgT&=bGWqM`T;C>q|pfJFoJ(1Y$kmN4T3#@|{mmGO0RHrN<4 zlrTEDS$`_}0`8zR)Uhy>D0K66J6d!HuxJNxl&~Cgv|;RWW9{Y(cmdk?*8sl3;lC$K zw$= zK#37(p&w7{|5DZ$nxInB+u{XivakDtbva8B>kCnk7<;$xpZ_Ksf?v%254wFb8dUy+ zjO=p#pJDLSouR|^f3NHRfEVFWOrVZja~%syDeH?{AiLaHdU+fiK*_~Lg`?M}kE7Gi zqWdH01d>iR&|>UPHx|$eWk|GIyMe3(of-hT(txdth0(Foj{_VvH7Ww#A6x&IsCK)t zXuEM(|0rX90b0xmI(n9wEdX@;^oyPdaLh8+aexo0?G8}^9sB}LyT&J>`Ysl6m$QI% zTmS$6AEp#^wK6vY149rfa~%2q|9>2)5gG{U9QC^X2@e1{CyYh=A~W9$Ina`t+CL24 zKe}&~vcC8Vs!d)0bYEt4;{ab;e-fm#`Hetu_pPw-*4y15Axn(-x3Rf-uW0CW{ZY!- z?aOhT5!8x$30jTQdb^~Ke;eD(EJio*iq9|J@yA{NfKKJz0UEmNK7aW|x9^YEgC&-& zw@X6!x3P8m{+aorE0T$U)Aa*q=$B^KKOAn}?#;D-96)P9Il4o?K<19ST|YnBhkfOODf{6ii6(;E9iRJ?=)^03itS{dD{r?{nOl;jOjLio@YlXnspxce3 z`2Yt*$w{b^i_Hf)n8mu8x`QCfc1!`4U>2dEhJy?!%)`5VIkFUb<085*zxY2FREzMp zf|{M(r(Y}tpG#E&no@TIwH<1CTK|{uce8W5vy^gVF-E)ut**!b&8EH(e){`AC`4Uf zfQr{Fh2Ve}Sz$~J&8ZIs#f{4c6u*stwhQ<|U#H)lB9kLJif-<|P8nhgqy|l|6dR<@}o6+4(hd^I>M| zTjiqNzq?Os*M4{bYWcMsDAnlpee-%fqwj+(h33#F49q72VW%9`@-!dedFcqc#FR1a zwPlt9uR@EzeXKEPc2K-l#OW1WMbn@e|{LwA`Acx`y|afNPyK;e&pVc`M) zg9Jd0j}I@zpCH$5>UW+fc`}r&PV6j(L5lVnZE^dZ~0n9ji>K zXqHH?A5YW^eP<>HZ8wg%?>D3mI2<-Q0FHN%_E4~Pf3S8>uy$v#c3ZG^bEx(YPD~8e zZXBg78yMpbXK@&xjIiJ_D3x?*{-IFx)xwXhl+(hGy_5xXlX(_n1gOgycNm;VU=zbH z;z4Cpjfy~ToI`LHV>f#iLl#5${{Vs31Er3jD$640a~zNo8NjiDjU266{ax1Ys})4%`! z=RQ=z1!AuOtxtUgT3ZIbF~I=Tar@a>d*j7i&^Y=H<8RjYI%8jyigdYhXFzfmcdsjV zzzeZZ&^m99;1@Hu{r_)$ue0<^XXy`q@U?QCrEfs{)k@!VpJz6Bapu?m|0@o3xc=vF z1+7$Ue!$;-qWLFBr|%v9c5zU?aOVJ}=nK}T_}keT85o$^jc+T)UQvww06KR6Ntrch zeeaWQ-w#aM-f?ask`@SE#@flhahZr3ZFa-D80CBoh3UmW=T|9|)SPB(!U+d%$jKkg;~D&@Yp z{#Phb?mquw!SDb7d*e6)Ajh#4GJ|H}?sT93Z~Q_Uv{FzEa*z#oz>9{5zyE`(h{)zN z9?*fB&8}}G7+t^o2Q8NWVeR??dZ!#{{+Po%xVM0#`&?(~ix(faf=>GQ!O(iUEa0^^ zdf4s?W@11WTNcd3&|UhXo2}dTN3Y3=?(;AHfOevv?__)N`Pcvd|6PA{y0KWs{wTWD zUHZlPb1_DQrGgA_<pqmuF z^!k43bp7!n3REh){)p3d{R29}kpp(PBS!|aG2@GtASMQAbq`9!wLIN7yV;FTcKWlV zb#in!gVvW>A1n#C>;|nvEAadls3=9Ir7QJErt;0DwLwU;h zg1XPY;Cb^Kyb8ycqq`ZTuk~9mk4HCq8E;y*WLl?$gM*`^U+L%0a2D`6I-rHW;oUz$ zJGow*^!xL_yB%a}>w%Kg=KUbu3?(t()xRy?QpQ%>tiCCnLxi zcfkWRhag3OpT&zO-~a!&c2VIdWwQ=Z;VBX3K2*y3;{7*J+Le-PFD`&0~RcHCETF9mpm+9EdBBS zf4473vnvOSoAu{T#-az%N<6F^w4S051qao;KIR|qno)q^i8M8iSE!3ogpV!K&HL;_WwVl>l?w)50;@HKm%l!u5XH2 zUwr%u$|@X|r5r`ayQRUWYkmf8iE#N0*0l)~I48JImH0LP;3~B@K45*J)Uwm{N~h}$ z*glIVouG9Ue|lZ71b})@pc$+GrQlP(UzFU1%oyg}{rx{O^7T59JAA+W|NnXkcu^># z)?#7UaRw9wAACST5CcByFueO?7WWG$P#ew9;)TNZ|Nk3Ow=guMZe;*jSo;J#yttvW z_D|T0o1i&7Hw(}`@ev%o{sznvptTVe+!3z z7no^3wkSPV7*V*Yiqtkazr|*JJ-zA;CD>{AGbh}wtg6HU%I(;vIeC>OM zzwICBJVDm(*fXG}sYR#nkxt(?pu?d9IJ7T!$6jF;=ytd06q)fN`x~f6>U90U-;%+? zz|j1|fxkT-#7I5C(0YKs4ZK<{_D1*V7dyT{>I827)-upemk0dKKR7yFAMm$VgT^SF zS+t!wEL|UzvA%Es`PG}Fo0<8b@kvYH2c515I(>I^`tIrUy;Eidsu~V-``&?94c)Fg zK)YV{M7|L5hi!Yg(^>g{^2Sw*V!4`X?+Zi-E!+fyQnWM2j0MvRd<^#=S z`TP7Y-SOg;+`s?dT)72~yMi{uF_b8GpMKH%_5c6o9}bvU^{vM3Z9RFQUbi1CgcKyKLGzFB9Tt9#>fhZNT^nFt**qnNVq0{%y z%U7T_NbHT*kGn(PcvxTHZwd!rdOPFAQ;@GfBa};C+yXH{Cm?b#c(fiU3k0Uo&^Q9svbH%Q=vKf1Pg7z0glO zS!Oc3e&_}z>nGjr2Aw=Jy4kf4TDsmTV|{V!BPc@dbom}(biL5+ZqmUc;cOlIqBHgi ze-jI+(s8rs_SfkSebODlp&fe$l;N%%e83b8y3EPnpgZ&ehyji~?a(vKg5CZWogy5) z{x&bnfB*j9db@-__rg(w-eV`>VZZ|=t#f%qrH-Cc{yGBNWj;qi8@c+N@ z?e25ISv)UHLG^m+lU{#~7Y1VBDe^K2P(<*2`v1S%U!#-drn7bIlg^Nve~Mm!#J_-i zaf164e+w6AmFEvG{#MXd{l7(l^s>BIm3FG2I( zXr(U)1E|B>{W17O?QcjGXV!YVOsxBKc=tu)1Ks})zGV8my8Be~L*~z`;^U$Zzr6YG z|Nk8iKn1qFJE*|c2?p=F=)MWM>by>+`+R5YhZm>vK|2F1-B`-_yZMi^G=iFw4xmwj zkDw8Z$Pb{xgBMhZggz)$H2!aWy;Rz=j-~7oNY)4xaegYDEIZw;>sX53ygmb}epp&B zl}I-K;4B3(6uUvy5*JAIulN7|zh2e+gOk7YDgy%pD0)HX5`r>Na~%rWoGn! z<6wQf=n+W0>z(de0dCg^{4JoJ5Y4rBxcFNyFo5IL^#OnDQSiL)iB8uuovs%;UH^cV zG<2W-U;5^SGN{&a<>@~EzkuZhsIzZ;$@sQq7)xiUKxZgNS#7tUO823I516`nIGTSl zcKW_3)wB*1C|2qA<7u!FWGIp7=0Cc|8e~65 zQS<-O6QIG=7gw+R{@)$@A@VhNOl`~C|NlV|zyB>b)VU9JhCbkLTc_)f&d@)lX|0z^lRyoz z>mZp}o=)cOL!H4a*6txieC6!j%+~G!pz{Cq|No%YToS0NW&_;1a7tL=#VF$9Ox%LM;sD}Q-P%0VLeI9gpf+VOd z>2L8O4xtD%&MMtp$HCAW$5ASj#n^rNMYsS1LpO7?0z)(CPU+eo9HolQwSO2&rT>>o zfXopId(jB$tNL5K5Cs_&`scL;sMv{9=|24;EE~MBp^l|Yv70%(``mGs9iU?8g$lR; z0A0GVVjVO;-0yb%!R`7dJ}$b1^~LK~|Nn!I2m@_AgPf&m(k;@|?Ww`P&4i8lT3k2F z#qN-cERb7hK|_nBJfOpqJAMCvLf`!xXf2D;N#om{bu8Uxt^dmuT27YoLOTU_U;Y2T zv7zMz|I|YrBE}b9f~F-P{Q^+usQV+RWZwDeKWL^`5H#-FeGWvv0QC)C8+FI1@PLjq z0`)&0d_@$_lHkI52O}dRBS!fQ>QHBj zhSay9GY&xGYv2rLJo9V!Q4EFVVdc z(Ax^q4O&&l{J&Hn_{HBp|NnP^*G>2K{`vR+f53~s761Pm|F;D1#Tjl-)0Bd zV^aI3+gId8R@a~Z-6y(Tr*!(h;NK=<(e2v93_8=Yqub_!^?%S|_x!D8pee>1{H=MQ za}{0`eER)AOXNk)h2P*C#CSU+SdKG1k#L7zHx63$zoUc=d`>S*aBvo5@c&YkUf<7< z3+`C|mnw9F4u|?*Dg&B^aedNR$Me5bq9gWmH$z}>a9A)TNdA|;3GDV2=oakuWMK~F z5ccH>3<`kw>c!Mb$STMO{H>rKwMFdb683J_C&wIY7_I9BN?2b=fWqJPjdg3m|NsAs z^}E6Aut6)%Rl28w)_QjPzUb!cWohcZ-s$?{g}Ody@aly%V+revd(Z#>xBd(YDX0%P z{=0(ret=g`^EVv_wWLd*bhl=J&)F>z?gmF-x5$ZZmlG_EVHJXIH4s;V7lNj31T9oJ z@gn^^sCl>NMLd|k@*?~^q?y-zga_i?7v?+uW8OEYz|iF?3~iPP_qqxPyjbhV#DMBP zB-?&$fY|o)9K^PdVEW37m*>!JJGmXy#C`C(f5$XXqAaxoB}&i&e{iA%<;tzk|Nrl< zz^-`%!Z#yXEf>tr?2bFq$7B70AgG#+OouMC$Z$px8XY7OK+BeLd zv42XlL8n`%{V$d1b-mF$AGD0H``rIhk^iLv|4VrSg8y&l0WFl?4!Y*##a;0E!JV!g zB_fb)bmPUwW554*yK=mY0&PlY2dV1r2kBsB7W8HTIZ^<{@&%o-OFCm$K(?%Q&IPUU z?VJlr0lmGTWxnA2qxty%|K{2^ETGsabpbigz84&qz4Jk1egVC%3j)G>U2g<~CREme zPPW8m?+nnX?ye9|H`l&lm{)=(kvm(Lc=)FK2KS-P*fpJ@8~9twm>3vd{CEl$?{t0A8Tz8zkwx1P zG*)u4h^L&@()CFh>x=JCK;_^ZhKAI+4Bc)PS&aWnLFb&ZcYAO!a|DKgZWVNR0t%@O z4E*h%KwHLm8hKaQ@W%gPXq{bS%t&l~&OZ7lww^7KVn@Rt8W^`!)oG zfzF0~Vf*C&|86&n-hR-yRd)o7b_7T83&VH6|3gNyy8SGI172JQDRSlL?FZ#$hkzG- zDUdc6N2jX<=#Imf?of$thzW;}yNZBzCTbt*s>j`bf&y*|LqqCRh*u|oy~_C_=<)ym zpo(hG8}KSw_Fmr!FV;N*<;M-Z{h(yYvx|pGXbD1Bk-c($N&GYH-W}|+Cj(fyp{wp-BVr* zg6W#qoFKX#wDBdN*YyS{^?m{AXfVEQ3F^9b6xo-vTE;#pvjC+Vx5uC=7vj%m*AB+! z%M8}BFN&U&OLe<;Si3$cy7gM%SUYGhFk`oyMYjh_rw0dwq3yv@!un#zBaov(H{G$l zIQj7Z|CjlH|Nno{^cY+ebh~nBy9#uMez103Qi3t?{Kkffp*dB8p*dBAq1X4!i@b-B zVWJl$Vjv&P2W=ecKKdSce_~S#_X`hYMmA|CECr9=z6}7mB&Neb01^+PFlcbNrbinxRw8fE{tf{MErpHKY$|9>mUOD|r4n57F|JUD@< z2z+n62t4>3v(6D=s0egnm>uZCuprQd!7IRpVRxVl!{I;|hSPyA3@U*x4AMamydltq z;ZdLq=u*|@H$32)1JoD=p9=TlL;`4?XG|~nbhsD05H4G82y}x>2~RgzXEV>t|F0cE{b2SNP7lCUB-s2;nVsE! zDwZreOPSqYKY*wO>FczaSttav+EZDXY06_qJB%)A0-^_ z$J)FY85kI?>sX4VyHO1+VTVe(zXrEd5AWCksv?8TK~`X26HRu4om6w%jk~F z>2!V2?N-w1%F*qX(0ZUV^i8Ml2mV%P&^Xm0?t{=3frmj|&{jQ0&=9SqF9(0CGDx1S zH+DyG7Gt+SU?6B#6m+pP1ITo?-p~y}Sxns=pn1c9|A7J^8PL&N-QXjPyDxO#)DGPt z9lNJ96x7Px4bs#Z%TX#|eYu#Y`4@9%CJn# zXjl$91c9Nm9dt%P^K#JX1Pq`HFgn5Q3jUs*3=9nQ9Ico5n;^p`4;n!+=fK|%I2Eq8i z>$HabAXhPzvO`rd##Ml(8p1&P1G*0j`qeNW>b}_NdPO+&L-PRzhy%M%HD6@t><78B z+s{M0AKU_R^O0@`HG-@Ul`9poTKirpmOj=FI>>=Bi!lPN(=5W!&6dRgs@*?ybNnxT z14$62H?41%vRb=7C}9U57XA7pY$Pc7#q=YfrA4k!K-+fsK;5I@?h7wWYC#cP!rp!3 zCFr_1&^1+;Uwl+%Vz71v)ds8X{Qr;SJGeGWt|J*=h~I&9 zaSn9G9_frd(d}meZj*W41r3KWmaAO4q0fP%LBBfKpf{$kqi z|Nk56Y#2bLIJj(r9KLRjm{5J+>-s+6#Trv42G9+$4WPZ#j61GHx-c9D^TC=Rd{{z& zF13Rl0RG?X#r;FS|2L~KfR-G}Te_(5M3%FFR$d)^z#Q;m&LL3Lvw?s)URUQ}28`476&n}xynK!*s2!@*Y^%|BRb zz8nUPhCt7?3{ert;^<(pi*$SO26Rd1KMv4Al{L@7i?u+t!N(UdAQzOV2=vy4bf16m z(*N&&24*(Ug8hIOZie95 z6!6kGkS(BtOzJ@1{O`u|+P0yNli`1f3P*`{ub;$=D$vNLn*jf|5EYK@6O9i+RfqAZ zgD*I`d3qVVJQ$2mbovRr<^bLF20E@4lqWzZi92#wIVRi>3Q#9BAIV`}~W%|Ns9V%u(Ut@GE@_8>$Qo&*A{7Cy^j={|SxA@d70Lna0e*FXPD z|8)EQcyR@Ee8{&trT?HS(|^1;3L4>nyW_V3!X5X(6Z&9>G{4aRCHz_r<8Ph5f5QHk zv%H7}Ex0ac=`8)g-v*js>MZ@zUHav?D`-(B1GD*YR}KzP#&cuomg{tV16six`lkEv zi&+Lt4BUrGc$-~0IR3l-Xs+dOD0vDbpnjtpu4qPxm$1ZPdVt>{7?aObR7Sb10Kx}1h`IgyZ+!h;Q;Ct zb@<-s_Wcv^LiX=}$mw#D-M)Xa7(mCz&jm%EE)Ww1tJv;Dq9}^ z0S)?nXm(rwFlo-(y=cMhVsKhG+y?!1BWG-~a#4 z*6}<=x4PX$Kr=2f#@|{Gl!%g|9>~@a*?7};E;xtkdPSf1|1azng;2< zxuK!VxSOxR#*(3gnZxzZg%_aFlt104UvPuGmHLNaLj!o?=(bHm2^T1iPrvy12fF+f zv;Z8OAV0nUjkk2ys0e^owRgL-G#_9;_<}j$#k9Zw|AWSL8^J4PVTaf8bl(IC9=!bj zKlmOEAMj8G=-5W^}WM{Lg<-sFaCyvw>9oVEJ$I{00ZaApr*PnS4CPx5K-CTE?-Ilx4Al7s6$MuBklq8`PIS53;EJ519F4{qO(( zE#p|qgu2@#6a*P<+O*6urv=^~m}`!}2jIBF5h=i#5u`yPZ|K&;Kv^!1CYZ z!wcs>plB`DD0&&(ef|Y#gLM`|_xTqwP`7X}?6?7HBz({UjaVyyrW1L>vp70^KfJI6 znd&BEeB1bv_2DwBZa;};OU6V-{+AqN`EPQt+xNqZY>?|*-~4ywu|8gO-Pt-$ zrsybW5bz3o9I!JM+>mtTF#Zo7*ygc}U@6N28PBokmRzw3=|2ki|ac<-Rmna&hG>*&H?XB zKrF}+UM|jwa zNYLPsiv)9b>>toVs9^ALfk5}^7koee{|^V{xvQW-OVCCoo_K3FSl;{q8ViEt&8I&g zZUilA1iSCbkN^MUqE8+YU36`^gT8l-T&Bxf? zoB!Dt-32WfM=KnboCl5Ml$d5QgL0yZL_pXJK2X^R&Y$wo{4WT}|0R%&`r`*Qqdo+c z0UQiF-heW~b9GQgkO&S7@AUnUrSO7z2W+#70C<~<%yEVoZg&RA#cJ07kd8F$j^zpK zEdA5X-R;cM>Ce$wF3{^Q)9EhJSuXM-#O?3@?ox^Fb1yt@gZA`v`>`Bj;b8pl#?l?k z(#`!sQJje(px2M*1q0~bGiMg#+o0)Z*C*YsAAL)*1Vt zGxo&`{s7P}U5FP>KZ{}0;GULphrThGgcc2MKw+QRQ{B58kMYBL+x4waoMFVZi zcQXhG4t`Pb3nUN{2Ab);{R?#1!vjbb?u`8d9bAuH)9bqd-1WJ48dM~vfVyyxnG>Q3ChSTx_y^)g>r-L zaB*GnAGE`B!;8*qpe+2R*_B5Cbf=74O3}vd+7G?1OF+(ZeGt&=77`Zl;^Hqzc`W}8 zl#w^Q;M)eu$V*P+`aLAM%>kGk~fBuK} z`kv^lJ@A4RY~vZ@|HdaR<5D_exjSO{L343!;32YD(CiblTY^OdPpN}N1aEif9?&Qw zkGMqyZz&6ChiA9%3+q16(w<`eZt!k#3mJ|QmJN)rnT!r}hn}!H+`%GV!g9=&pV7V9 z^^Jg|wO>l7?~9@ppxv^3;1Y6AKoGLpXyv=Ok|F9(z|89_IJA1+}8RaF0dIeKf{ znMz+-U*>P?1+SlQ&teG(f6)i3K72noI0U@t0j~%CkR|xS{R?P}FCe_T_Cxpi7o1-q zv2FMToYX*-Q((7SPPZ>lXDsMq$4*z!NnD_|Btu#^i%0kQfKJyp;8RVE4|JdJa(x@{ z;@f9Xi;V-cfZ3PB+JmL++<#XdP_gTlQnckYGbo9u5r(%b3E zQKr=mRt}np6z=W=?acpg(%60e#YM;xKnLqKsLG;ipr(S=XNdQWK+?XT8U)&-2Q6&g zQ3Wb5b}NB~B|&>kz~isoz8o*qm_aw7mvVu7mM_7J5q&vcd}9KMmMDSR62>RN#TTe< z1|3VFF2n@d6?D1#@XKz{7@{kW@onqF9kHKFlr1AzO1Uf|6hW83@pK=yK3pOI;<0zT z3Rp;h64htMZnqH7$ro-qFDjG&{O@x8-0Uatzr&3Kbjt*29EIbU8z*CD9M22s-=GBc znZJb>WJw)QXY7OU&e$g}R5pRe9b6xD);{U>E{yA8Rr4&l7LQH?TF*( zh~s>56O>HcJS^RKO1Sp3IxsZ6JP4`|eH&gd)PrU#d3t?8hwLzRxhr8t_i1W(p8zc>j!h$nL+zMz(9HnoO{M@k*%sROz94+vA$5k(t4@Xt9v47_6*9i z>7EFhW`pwdx+j9>0HHjE?unpm3groPcY+FE>w_gMttU%avKS){8y|r0JO#~Mh<2ZQ zape-U&C#I3!SLUW<@K{}zAhIPftCXuES4oo)^!3!!oj_9kQQUz`9J@y>ja8FMT1&P zJ}M%eJUim!4k4C6!Az~gYpM>&R8fej;FjKsE{M4w5a#~q_EC}O^!Wigds+ZAA_v+5 z7}j0N6AoU`*yX0uU7gbFUGd*6Ap8X=-u{>Ibh)Yac259}c$IMkguh4!wL!~7y4=)y zyFrEJ|1yDq@E4$UeE-X2y4=)zyFo?f|1yby@E4%Hi~q|My4*B+yTOHI_=`)R(}vtM zyH5v%zpwxqS}M@%o%14Z*>BLLE4{TJmM&e|d^n-|^wJk`penYSrML9M!RIW@)=NQ~ z)ty0mEkL()fG>{^@BV2$9~2!$%3;0RK@-Z|=UzlyL=Ah0isGknkO|^09~FW44jzeU z=w1oPE?sxzUAq7O|L2G7(glxW7Oh3vqRS5w0`1Q|CI=pW`fv84axJJtgYD1V(E}=| zg=9euJ08$&cE^}D*spHT8@T??Iz=B!H-REBT zb^Q6CCDMH^>cuvYcDAVQb1y*oCyNs#wg@C92x5U804k8e*Zlq;3GQ~mYP7?F!J**5 zx!qmI0vca!{aGBCu)#YRUSVqpLoR>%@=4C;m{b~75^?$)q=1u^1v370#_h<`<|U$ce301YI9 zbb$svL95$7c82~jz7*c=$I^PTOr@Kx+rql`Pbp`21Pk~oWKhqU!}?;;i`N`M-RE9_ z&UOHep!_fWlg03&?mg(*!RV9V(c^9(6^`x(Q1pUs?}POHKur}_p0IH1Mv!>1W_Kqj zYK{MQn;h(RImogzAl#jyThRJiDd=PXvF3vUjXxD4+!=~qgHLh*jRT4>bcc#`J92a~ zrFA>#FzB=a*ii$uAfuFmyYC--%pCk;`>NmngF%N2 zuyodO{4Zq)c)>3NO11*gppybX!Om3F>&4jpvzsjwl)L4b>sWeuPV}-|IQX17 z9JZsg`3TQ{KTyHJ!T`>EAYI+nEZuG_%*O-3WACm1OC-DbK%@W60o`sa|BZWD4hFoK zD-E)dhp~l-f{K+9nctprWToapq0A1uK7La!fG#eIP%za85^nsN}Dda-Ew z+4ui{uLlok!>IDXZp5WohhKtLrTpV%VD(_w35u|n2j2euAKLwQ+%>g1o7<3cm zApwRRCqQmJAOR{-1iD=XKutgBqS0>9{n6lNF;94>?~~pNjqdX=jQ9NhpQYD*9@IGg zv-|h|t~fr>q0=q5OIVxj7)leZUEkDkbo2MtI5NHF=yqr6=I^y}1P#A9ntVIbP$G5k zg}@5W65-}b6^33%g>sHY3kD7bh9aiTjNRv7G_imimYiL2yvJNWGrktybs@$bG``id z4t#bCb5|Ts%WeJ^(DJHow$=muEub9N?Z&a2!2xu-XbERX5+WnyM7k+EgvU}i26wPj?7Dgs>%_*$^D_Qh+J<{!+*U0;AE2udWnU3tR)m%jL4 zpz^;!;f0GNcvPFo_?z|jQnt?8C!HY6-hlc|*2hbv!3`G<(51?s8A^D;=SQ<2cYOl7 z>IF2;=KCZ*4&HV5{bGCoF*d~m9k>kd{?&aGG%=UP!Vvbtl!1Yv^+2giSoihr(=U!g zczh6ED)b?4dN+V% ztUtw-o3CImHD*58Xc6Gbz)-5mzukkS`2b7fOVE6FiAnRzk`fJ1&k_|+&l1Vzmo_E5 zjW1JL7#K>Vj1L@QVb}=@+}FZ8LBaQ$XD29VU$gE6c{HuDLV$s#{3ic)2N7Ft(D{t) zw%kk%45i0GQ*WTLi-_0zAnpq*3T&ukV=VPzcZC92IYcuLfb z4}d0hTECTi+X0H`*J{l_G)g3ze`uHRH2<(GeXs-M#@7NnK+*r2v-Ml)xg8+Kg9`O5 z#!kkF*9TfJm2emz=u+%*WIUYK&3HICG%OtA-tM3LO`w)gH@oe>x4+Jn$bzWzC1SSc ze!cxy!fkv0*V}*mt)Sz(jK95R&SH$~zSir{@}drOLclSg1a=V^;=2MZm@f$TfddK?*_Y0p!Hj+&2EtEUbF57IU8i0zzcm)O25|Y zFVg+ug)##JgDvQE^K#+FzYGj44CUOQU8Px!oe~kRnLs;5V?oKG^-_rx|F%FTsJHmH zc`_e-z`=b8L>xQ}@?%)@FP-qB@v7WU@vv#-(Dzo@C7sf`VXz&N{k!-fmY3wYxlZ~7~k%# z;IRHxF5hUwk&;-F*j>ZHQXsXZ?2kKAcun73A+3%i}5(TR0Ke^AE+`D2n#p<-)Y%d$-9aMEpeb%Fr zcyXA4fdMj(`Z2saOa?SG?kCb+7113gzS}&D|c1wYd z@M=E58W5Pp81z3_p!GnhcC#PL|Au-#h7#_EdR~T7umhQl4|KROfsVN9W(Tdb1|5FG z0}jE%-HsyNfihv;g%aIC5g->a9}DmP0cuoVcWbC*V(2WCC{gb&Wchy0vWTNZw%b#s z^<)Wuw_p}?Ko(=*{~(dp1Erihm>3uoAc^NN_!ty{Za)cY50+xxZZ{F;gWY~IpyRF_ zBf2@bJy^g4uVSF%IS!Qacb@}Kz_uPJIR&~U13YgX*zGC;I=a&Oa5(6m=5AjB>(l%# z=Rs+>l*1y9lfMPjJ2O6D?Ir@+eq`+@P|Vut%ki46+fAU;mBS*AqqmNuGxkr3Sht%= zZz%ZgX3&}!@a@f=u751zxJp24B|(=c`0>0DW@KUjo&V!20@`?Vx`c_5kN(^7C^wxoJ{Qo`C@%kx^GyUt_>DBoDRa+EQH2IJf;;K30N zYCwPnRs48BOW*&z;9-CSgDZ!on?Q4%2t$K4LkWMkuLvYCT2F!krn~k}>;Dqw&N`cJ zKLKt(ky6R-(=T>H4xI4pKKrGQ z{foWpe*f>92I}Sn2Y2rSE!6tI4P5&6fiKi`s{oBc1oejA3F-}fAJiNAE+{-8I5;r4 z*H7gCHqhaU9TNYyfjcJKKuPTXHgMN=8>mn8LfaEGRB@-%t>(p&`M>{1z839veR15O z1~mAz!>Jau_NMfO@$GK#DVU(zz4@3)H=Fh064?Dca^MwN&{ih2WAML#b zGU;RlwI)?RfllND9WV>pz@q=wjp4;ZKG4Ws0yAjAVRxxaC-{8j@a|jS1SZqj3OWvt z`(S79kAMIFmx>twKMocFEl23w3le+H1UeP{(~AXVBr@* z83K@XDWD+wFKB(ggs;0BR4R8jgBCKrW-&f#e8Bp6Ig9oAGKYpbErwF7?og5NfWU5u zYra8&VH5 zbeD2~x_=61ubZ`td1$;?e=}r%+vVa!P+^d=(F(w&{jnW@Fg4F zoXtP~m#}q*KIvrX0`LBOVOh=6S-Xe74YVkt+jkFWn)s*jrGw9zI;VoJ0q6`p(#^x( z-3&Sl$of>LZ%a3eMd#ES&<>%{2L85&=9)=RV?$9&;!8=yEg<3Dw$akA{i%e^%vS26`>=yj*dV~>dX16Dcpl?HW zDMvT>;;m-a69UbyXILDpeOroFHrF0u;0NEt*xQ={9y1O8|Gyh_x-*Cu5Y~PAnCl8^}S=R4;Vpr{!IlL z*6X|G#a~6xLD1Hv6N(`~Y$`55S637v{R|GV8-y7{_8_jHOJ z><&HB8FG;2zZ(n4@Dk;2Zv)VFe-X=WA4`^QlM~t|7rK2;ut@t{U|}qsA?Q2jwRJc6 zu8nTj21ef*$6PNn3cAjL?9nI}E8?&OuM#ij=>*fA;Jq6SweJ}~qv4krA%O+jKlDO8 z3>07-|6TWVyY8`eX5nw*`Ul>O1L=Riuk(023doHs#plJz`heK z+Xnp|{R31&8h`7oJ!1V26k(mUcc2rtETBbI z|4Su6TR>j8`TY6c+iURu|Nj>pQGfq;ZUt51-L*2ky*nTWqH}b)YX`g#)Mj94sMlsV z=K6=TM5CehGDC?HM9GWXV9+6$CBk)Fs{j8pFz_-kus3x7cxlAKz|gQ%^Z)<<3=K=Q zKvd^e8Bm(o3cj{wE9gp>W38a8UKlOQL5D_jm5Mhk1@Y0ey*Bw@`k}WMr1wRh`rrTE z?mX7V>g1b$utT-i2si)WJk|=bim`_MSS!df(2cg;z8uE?jlXp>SXQ!hf@eGU+dwUi zZpLnw4WP8a-!c_+5pIPw1Ai;%%Ik&-D+c~n(7a@KfC6`bN=aqIQqb}244~ZGxpxof zet^B8)9p*-dwW5=z<@BQ!#v*q{|{P9vV^~NJE&0ywyt+7NKvovnl1;$4)EFcFE+}8 zDirHlX!c%b0L|WE-8MVA&%a3C0Xig^!}!0Obs-CXQxIr$3LIXbaDTxt12m@r35j~y zzyCY;f{w-Sti91tdkGXX-25%AppjOQ7we~k#*`vE_kuQ18h^9?$KL{4`+c0fLc*P) zvz(>ZA9Mu^?~8W*2iJF6_(b2=tI)F-E>G=Hv_p3Qlmy-s+r$@D@TBv?f=CdMh2Y zyt(wri}-0sS@;-67KZEJ0a_vZ@~{*GLuaW%H%D)%0{HF-zW;$d*2kbpwFMj@r3#Qs zAMiO`1>x}96X6cOFcFW#GxQ+wv2H3PK9)@-&f(qQbp4W3ih;qhRH20Xf2l&RKgWxR zr66Mzj=}G!01s98@`U{_6?w4}ysFOnU#Sr2&;pAq|NnRY042yiP(HyEAHM4F_+UYJ z>*oYK-kPWj@z(VzAoo0ZaefMs-a7u$Op<}2b1P^&WhZ!lQRi0hPTE>fKH;}4XDRdO zW``CVCE^Vg)(oYppyHxbzS~2g`G5kq2g_@rZqP#V65ej_h=UJU8frLr7)p73!wdD`fB%iYS%NKvmQUb)y`ZslmJQvU-8PMoJ+Ln} zFZ%tzq27|Ax3vONGz$cjsP;|;pZanBg|afJy#4g=|9^(&;~L>mJxWV{|9`E}E#3>h z6eFPf^b1{3u(pD>Pj{aV_;3DV*JjXMFqrQv5CAbd0IK}OsVCqWWB&hJK?+{fPyYSi zEz%m|)+SITY5eU!IM6^*{~}>BD7cSAb{0r<7RVSMuq@qBCS-iFJ9JI+L4i&e!9Nbx zt{aLzfSNfX+MpD)p>r$f>J|Pr8F2=N?oyfVy&&$v=Pdutm}}Sc_JY=?zF4i!zyRtd z9&`O8Si;>r$N{~*NB)5J znjeq*52|~*eS4ZyJ3z&)P&Z3sXR8G0{>BOc2L3it(47VjJl(z>-N7ooEGIg_^>Q~y z_s34(1qYuob(UV~wlT7-VCk%Ffov!0cKy(Lpd`6lAd5LLiwUyRsnb=2zjZGU1B0Tg z2&Adp`oG)6pv<=W*ue)ZpgmRI5e+qrJPalB;B)jvvY5lVIkFfbn_oIzm+-gh@PdxQ zdf?W4K)|wAq|^05(dq8c1)!E;=@n4pux27lugFx;z;5SM&`nz1B8J^2KmM2A0W}tD zey~W_Twv)Az0%Di7#`Lwa)Nm>cyQb01Pi2JB-{)-+c2Qpl_#h>Aml}j1ZZ>??Cb=v z#YY$mBm^sDx?Kf&Jwjfb)&$jf-KWFG(H+9Zqs_x69m2*E6xi*%n2RGC>L5||PrS`dDO%+;In%gfMr8 z&H|3k0-oaxPh#8|jytei0nKQD+l!#(h7USxLFXH=hyM>?>2?JfBic}*&A{IR-ZQq< z<{xMg9mn^3(%+hwf_ilf${%{coiRv5AfVS(1hhCq>_xOQylMH@3ADuubm&>@A|B8c zdmvN(Zv|=Z^)Puc9o)dM03CF{6?E&+i#FN6|GS$($*yy50I1p3>H%794o-NTtv(>O z>w?bK5D)`wH~8pqQT`TCzaHG!=6DI(+Lq<;Vo4vki3|z{>tn}U|A>Q|$ZYbUR0(P# zH>cY$g!lS_E^-#_1Ya!of&*mx_g;6fCqbS1hE!#S-d<3@$f=((CX4o*E9UB1w0H4mSEHQTjF^c82)bs+0^TA@uENmbel7Xcg*#V1Y#)S zKdjj%`r>Zy@BiJk4J&9TdU*t%iJ{ z*ac;bZr>fHDD9-=NzeBru>Ce0@^@Xfac-f5?k@s-QX_ zT;BG!g6fw5&{_OB{{R2mf`(&3;nNZhNSMjmE&VzXs&(0z~9Qx4`aOmi=AQMZ+#28 zHLw+Qv4}M|*YdYs0gL#6j@NK);BP(3#=!7exf^U)w}Vad4@Ul$b$p-#mA~~U9|MCW zC`Bv>>2VY2E|chXVA1{n9zO)-Kjjbnt&2bb-V3?|%NpFR=Wp!;i#z}g&H6U*x7PE4 zE*{+hDh*zE3I6>LN$SEc>;(V*@Ah5N?Rv!8-=tWwJKUh#Zctsu!Nb7c0zR(U6;eoUXg$E+vk;`#mjm1YYN!Vt zzSj?0uF(tXf4x{S^Y{PW)+wMnq5Ui zvRJ!6bh}=Ow02$ad1=wsE^s>@Vta=xcR1 zQ|R_nVFa7l?J6S(KJEr`=#909N_kEZH)Q0++C!l{zM(>cp~SVf4zw^pYR+%a!N=g_ znWgvQ!R+7vt-+jn*6uQ$*UY^IjNRPD$j!izmGHu>16jkvsUDiTQZI z|5Aw;0a>7(z2I}uO7C<+j^QaVft<|K?JLmP3c9KfG9cC2x&u@Zy7Ke}f=bn(fL^d< zK(C`pK=Z+n7aj_rREJWkZUwpUg|HW>$mee@;|8U@j&2VFYY!d%);V0DW&Z-8qM^{F zSi1S3K{sc&$j5GqAQ+%x{LQjdq_gxv z=T^}1YMono{{R2a-=@XLz|dLS0`_N1Hwz;qYT-Sbn^VzxHu3=_a`2vwrx@rwM~z2_D>_E%wS1-VtQ7v$F0Dcv3}-8>sRd*6V<)FYsq$G(+;IMx{ISZ$&myX56W)R5&vb*upa$Nmw8hwSEhxMNq; z<8iD5)Uj>NkdUowCO%}JfUd#=4-UL=Z-%T87lfp)7onjjpms&~^u zP`umWkKel?BJgk{1Gz}BmH(G50gMfNGOB%qInZ_3pmd6U28G3b~t z(Bd7Amp4F6VpHF(dekTYtyPDNl7WkHE&^`5CJ1+1Z#CR)P1Q(lgCzpk=)RN$BnlGh zAyE)fPka>YV`gALnK}BXKUXT@{yABR$3KZ;5dSQ%h4^QFEq?#N zA|BFTeaXZG>MT5Xt=R4QqV+(DU^hn=)Bn;1ppnc#&>AZCeV`@*_@ZcEaK?IZk_piP z-OKd%KeWJ9uSJbXQ-7404EOr~|D`%;Cg;P;n+yyLU}Il`)|NrqQ7@j?K=jLi8rG>G zb4&NUxKsmg+8l?<3r0fo>lHr~3%+^&{|}j8;(Vb7aw2^4^Tlyc_Zd9H1)eUwF&}g@ zH+Yuo#UDnHXCP}j#6=+?84I$s^vR3R8py#ppo7j|ytu^p_djU)Ot0^U7snX?{s;Hq z!5--T&&@M1ei+%M-v1BhQ&(S81fJxIi#=fzi0irxoWuhf11g%(us z0ay^c0_yw=QK;Z)upnq7PWSm23{b&sU_sD6obK~4UV}LPJTIg`w)BCv&b+uG09q#u zTHN>IEJ)Um=f$6yAh$`p_yVR?UK9&3Fo4(ZHNO!7E!+n0obUeBUCq+^zf7xJtee|f zuvDPijm6rLrIe$~jl;^31GL2EPxC4yZ(8t)?53g`!r}n&x=dK3=G|% zO+Ifx>k+}5e7c=kdOa9By}?_3K>IYB-v~6M{$OZM{lL(i`UMo8pSpi`pL?+qG+SNE z!O-FQgTJK*lmOf$y7{u0ds!Ufx4#3&FR!CpFO`QEaX^*=mHX}jt)|sJRifMcQldno5qw!fi9+McKcMBx5{)lGOQlK# z8ef8zN|$gnz61@fmWp>X*h(`pGk3avC}r*h-JtN{1?UdL-cZn%){Fl@Cs2Uyy6JXg zF}~D#piH8hv(XZ|NT!m7p@iG1`JjaLg`!tR2M%vwJlxG_3tB^6%5mJ01++l@Fl2qY z5@db4G-Q3c2xNUaNDXLx`r+n87KX#e9a%tA7>9R+y>(-FG4TZ>1L$mQbr|`m~0@P?Y(dqlf8Z`LCSiC$c5IIwX0krhIn=?49o1xpJqnoRnr=!cw zsw>dS>QE_9SDdv~q;-i@%k2^_@DkhyOdhXQzul6))cok5Q}?0QlHGwC-F_M`X3qTm zzoE{Wp@gHM&WfRg>HCd1(4yrX8K7w3dd|qu{Duc~21Iu(csp398;kJ)3s-?oxlT8Z zPB)%THv#?@&|G|PHE4{ctP6A-oPYy(1BV;W3+t}m|E*mG>N&cdbvoTRUS~OUx^Y-L z>y#vdc88ULS{7~`psd)-!_dv1*3H6^X4}9}Y}I`;t@S{OhK*wln@vmr7(oA`(`YOIf?b++II-Xt`9v z1rjxXu96^gLl@Ic_ zg6_fqohjs}(JSHznn&~3=;d*I@of6<|E&l3TVI1TyYh5HrFps`(#N6FpgYsM-0fQq zlnPq7*_VLt?c2cscA7;)ojpTILd$^?Jupk7+Yh{&J6xvIM@6LDU!pTaMaKFB`1U1{ z60YtL6%or26`9v+-F_;d@w;%9P9GJSZhwW&5ET)qI++sD?hq9j%McZj@+n0u)+dVl znosCn*hB`@x63cG3ZidDR0Z=(sD$raZ!cfZf!h(r`;U(xQi{=Um#u6^b8V&FT z*XLd=U}Ru;3EFC6d>eGanel;_5sVBBpaXF)bA#p)E#m~rgu72SALe29wLy1*4zwzzHpP<5a7uZIY*4rf<)~8ApTW^=jb_NJECx|d~pF8d#0V>a4 zYygdwxpKVx42mrN;|`z$0U0_yz^a<1Ssc1u8vj_ku@onD^L2v;WCgnYL~Ow~ z^{}*_Ea7bap;+qPda~5H``imRaDpkdXuVxx()^pLo)zR~uHY=z?sG4eOMni4ZvM?& z%bLX;p?x?Yi>>?Ii-{5-e*|Z-zi0=sTsh+7qCs2r!n!|ZvA%dG1sY(jfm}lfQhpaK zQ2RcMz5CpY3t$fa+yilkn=1tvN?2clj=3;C0I5cKg1aMGK*zpBS>GxP?5-3r{?_`x zOuE~Vr}+Sfr9cUnTk`=P>+i*!uRl3iUoO^veIHccHmCkz=#Av*3-9a5!N4HE5Y}1y=eX+yP~dgeUg<2o@nWJls7-kw1GFSNi{nKTgd3K{`=T7e%wo!7 ze~}Gghi9?9ND%+?zq^{Hxmtjsv-VA?cNSBG^^Ytt{*@XD<672{`VGxCfd5s zfzE)B?EszR3cd~d0g^8SK-UPmez10CDLUO<`zDJquGjTI_vwHa*IYnb?ZM2`F8}{` zpMC*a6w!L1gr)n#>tN6!rp|S;NT`KtExa$*8 zz5U`EhC+xc<8Po^4-{l;b3qH>P|M-N-Hs-mP6}O)HXTkH;Ju;Ujy#=CEM1Pa9Zo9U zjsl%d9Nms0olZPmj&>bRs@;wfolXMXjxwE2B3+L59ZqUpj#dpx>I@xDnuo)>KY=cw z4e$Q>VkziII(LQc^POy(!@CD1i z=z&R=JkAoxNbrV;mcc|z#X+U_iSIXi16ZU_Dxd1)`|rR3PHIdJ3=MIypiT1KB`O^M z{W!YaI7&rYzm@QHpL@Z}z`zjp;$i;p|B=SvjbA(FfYM{_eMW}BPTvop^q%?$bVnv^ z5iQc*&K)N~N`pX3!G|J(nu=~3oo+gvu75h+3_9H`GC=z+Kn<5pH=E;ZEV1qkFZ@AP zb-I~!gQ`sUb=8M=+y|M(1~sd*^h39s3aG9|3=?&iDS)E7^&7l_gLK{X;V{sB7_iVR zQ4wiYV|Wqu02Z9Q;9W&*{~ZhvA%X}HgKjqiv;et~hX@dncWw+Xa_%uQ1cr5g>@58N z@yP!&ljE+S<}SmF#d)CfUMwOJZUs5C`&{!ej_)_6Pb!~#AqPq?$j;r74l-06WGJY1 zF}@AH1U-(WGmfJ(j^{X=fdD9aIePs>I%EI52o(GOzjGcallSfeZQbaU@0*PeIF9*1p$y&nx0(8ncXme6P z_j%BY%g(kIkV5}IfBqkL18?5|#|(16jD=yxMv!we?jnT&$jalcf57#QoW`I3-EANj zfp#e%f}y(&A&d-3N_Nc6w-Z zdgyd|7<77=9A}V-b!RvXYM1_ZFz9wL039p|N#I!GlK~VC&;j;C|_LgT*Am zMd%S23qB_ealJY?y>a~a1MTUCC!KVS|Np~YOwEBOo#5_6VcmtGC4HdNUmO-F=^ zbr?&rOt)QwjW|PzNOu_zL_-A!LBLLAO0@5SE z0BS;j^ngw!=!j5*>#;(yM*^Zp2Bb%Vp*cYYY|jw}28NCZb&wuWsM~lUZZnzIS)lNm ztvNw~!RU5JgogFR2MnM-b9Av_cPHqO5b%XgtXYhapyT8_JTyVudzjz5F}z^94T>4i zfxz7#LAm0EFcSjc8&=&Coj=_T&2TJqRahjhnr-#`;SgHnJ)J~9c~I; z?tjC3{Zv3Htiw(5MR(Qj|Iic-Z=JI+fKn4|MUw|drw31`he@Z0MW=^Nr-wtQhfAl2 zN2iBRr$<1iM@Xkf#Bm0TSnzr$4N#f`l{Fk#%h8!x@VMWh5AuxZEs$rx#m4`#09b)h zl=b`n|1y^sSzy}YMN$^105NGk!h=YG-DNzWY=NV=110;g?vJepI@wAfB{NI+G0?tU z@P0!UYd4M(Q_vX?2TEkYM;PDC1g+}sc4GnYK!*ev-3FD70{_ikJOxR)u|#&-b-HoH zgRgo9jY_z2l;}ZB5DR!QD-+~kmhK-Qt>16Kw5~$a3UyVp8mPh$-}(Rle|zhLWlY@% z4?bWDcoCWjn&4)`?M{|}7lt4ce}LV|0zS;33vQV$ND9fFJN!TaeB}nD^A0+c7nE8$ zVW&Iza&)@>>8=Ew@gM~{IKkc;dfYNoz>CuvV3%~(aTwoj{aI{L zL=Zg9{NH3|_lXxBcK`o_3e0XlmToanoOH5u{dZ#l-Pi;g!9wl$fzA=_{+XrlB0U3k zHXmQJhs^&@gU$k$&H|3^51@OmN>l`1yaa99I0kMi;5?l|Ik;D*{@`P#;1?1Z=*LqO z+yqAh{CJAc?l;YEB*MEZS(^VdcGmtWix2LW4D0^h{954RyYTL7-KSr0F)=Xsm45C9 z@5nt2YVG~#{?J?d0#qpVdJA;_=>GWM_Yas?`l9>i(*LD@nqLSkT?#tIG^*3}$I=%k zKsP4V{$VUX5*HnR5;Oqz-|WTWboklX_Mp=c;b&(v1-wW|2M0AcX@+GXEXEhJ7#J8{zx;3hLL6it>iH?)fRTX*%#X5cSip!}1RucuW_ApKx0-v_uT3s9Hv3 zSPn}!meSnr6Tt^xGKKF4t$XN=VPv$vU(VG18ys5!FT~S89r4H#h2HT0t(R&14tHfzYa<$JpavJ{7MBy2JHA9aJYcB zkA4b2_>6`5BP1bohW_aE{j;=JM#wsrqujSxzPFgM`!Hz3vg;qvA;~Pvpo4-v!6zxy zF?HYT_Wc8v?ls})^?eZr-dx{$pjM>2_D5$dc;|HOpNo${Y3lX5?%E%{r7u9Em$l$j z20hFdRBRYsvIyh|E9J5X;3(k-_2rc;0yrSswI#X*yA7F~*zL&zIzaDW`CaJ) z-*12tRcQAc(8=4N6IP7>TgP#9*0GeC{Wp8TpZfcMr(I_q$Nn>C&hSJ+g0h!oKe!}1 zodO9%BGY{^IINdvQg{|?uSo|aFhD5*6gsYdJ})hg1LdAS z*0CJLa{o&OdU*eYAAIj5u030~3f1t7^9lgF!y03v{YNfkfe{}o) z$ztt{{n5+PaPhHqEJv?RW8~+hWvjYFe{{S4>E)S}#oAl?q}Qe+^7B$~IPowv=cur- zyfpjr|38EUIzROc6m%a93*W~I8aWTpF#g|Jb)&QD&2c8sfdbX(LsWP`oq*u5@SUJG>wZwT ztNVlTZBQUFFnnHKDhfI~A-Sk;HAyBN~ zQNjZ{K18DV1yiZ+Yr(W;OW{)0?n(~OSrrTot70Na<8%U|?Wqd~*RbZ`h*p0(9Fm>C#Y_*;e97#MoX1wiNZc9y7QywLso|G)8D>!bXw|3FLpTU5R< zF)(!IsCZZ(Es^bJus&KM-W|Zw&0&4DoDVe10h%r;XX*4&@#xG^5$SGG`M|`$&>Ny6 z5(MsfcQbUZ0Sg6mbNmPQ7PzbQ2|Xjb+)L0n%~{WdP`Iaw7>5MrM7O4?g$a) zo1I*pGHlIWVrEvsJXo^ zDkcHlFrsr0*zC?dDxltFXN`(YXN`(Ow_rfv{~(_34`4g3zw@`Q0}VUosF-xesQ7f3 zsDKPm>Hf?7yE{h3qWiS)IqMTe3gv9pH7W{464ocm1&YAza*i$+6`_^`r7T95UNdcC zggMmu9Dn;P&;@H8)<5{$CxFJeFY&i@fSetoVgTwhb^53Tbo;32bk?Z&G#_LHrA&t2 z7!?!Y>%pBhDi$Dzb{hl*26XzU*mQ=dIQ$PoaxG}x#sB7ij3si7|3G`{_*<8P7NNSR zh*%#79a9qUKZv8VMnweXoGu>~p_Y>+R^3xnK!e@gd%%(1-2;wn?d!}JyM0s?v`=)q zsHjLEGyZ0Ms+8aQSSk1M7I5@{#;`!~{lWxvy?l&{3rznSuxZBMy1f;QFKPemKCXRK z8Z^wLVfd@VA(P^1~XH8K47l z{<82lgJvhYLskoPm#iu1Zc+Ke#K55aDXg1k#f#NqpxLF?|NN~DAU!P*JwHGz14C47 zx_wj}n6C++?+j6~>GV-?==NzA==5m;nE^7pJEU0!B*c8Nb4m-S|Nc@D6c3;@>8Zf% zqoUDrsS^?sC6=IY=$--zmh(_=YG1d$$lsI*(gTr!1`DVL(Z1LT5d+^L^zZ-wA|B95 zJPZx|?H!=`YabP#?kOsu$pq~aoom3!p7~T~4>%jVO#27AQt3447S8LSbjVo32bKio zz?Xu5|Nrj_Q4wmn#NWya>cB&?ad)suZ;nbxXAdL>8A3aIz=6>jq7u<<5M=y6FaVT% zz^Mh4tb0Muc2NnjK3>WN%1VqcH-J`;m#8Rohp4D@M=LOY5WdcQqtiu2qq9T>G) zIS1_j?kOr9%;2l1TWUdCTvQ~wb5vr$Nh(Gqq5DMlKkc*9zdLJGB1(Bc7b*!b@Ha(+ zRQjmcbl0djFrVmjQHkkh>hw{`==D*_=qyo52<-JykrDnE7}Qy#Qt>~4ryIO?jTJP_ zAOX_qq9Ss<1zbXcwg7{U6*~&bmja*!4Ou+^y05T%3pjCf*QliQ#;6n=cTouem9X0P zy2ZO$jJx@?4+Xra5c%`J`$g;9Qj=~Mm5}D+EDp`bSek#Zbh@a7)LaMUKopBg*t)@% z7$0~!6J#U0L!cd1j_#wcYp`hsFIeh6{yH9;B-muI^IzMe$s_g*cOQGLgeD2@P=hsh zAA=6NclW3~U;>Rr#KI;x8;{&!VqiEV!vLv!KxAn5o2>sC6ELcvz;0KSZeNA&P?_Mc z@Xpi^0o|?=f!)3$LEWJOpnYwD-M$<_ppHH$G+&s34#I_xn8wFNcR!6iq`Cq4|gatd&Yqdrbz^UXuX_5u{;-y}gE^YyzUarT}V`fHDgc z==@P=n@tAPW|IN6QeX|i1}r)*fLh(qb{nP+1}r+}fpzeJn{}8vKm-1umg(o^rLb0H zL9d4Z4%G$-^I@u;dObuiRO4%NN?@plwmFd<7mw2B1gB3A8OKf!neKzIq1SFV8IMjk znNrmDXG=Ji_Gi}r489NO?YrhTpn3n!5)~eB`a?>3$6Zu3K$XP{=HrYEt=~#md;LHs zY@K{z0y+WQM@1kGnunT?NPv?NsIA}aqr%d9fPdhwCxY5?y^aN71;!^kz0P!Ubb7FKay1{|0C%b0cAt-r zd#RGn05%hpe45{AH2+`$op#6H%E7|G&|ISu!pPtH7u2pOQL)Kl?DbQ4vG^0LCHe{^ ze(psPXl}sGptld?oX)lvprr+ndxCOQ1VF7%r1oG4s44T}LmH?*#oyWss>s_wRetji z7XIdNP(4-C7Srw1rU1U8M5=olNYcUjc=wcPAk(`-nErQ!aQrWN200JEv!@Lt3{lqE zGY!Tc-+`5!d%4>}XE+ojK>J4D5yH%G-o`*>)li;7RTNLN6&OP@lw6!Yjol$C9<7&3iXnpCIp+#`ea;myzv|TNj$~=R%+MLh0#d^KtMx#sU-N&K zVo!+5=AVoutj#}}N-fE>va}as5ZnVL;OeUNKYzddGw7~!>6{0O($)hdirt`LQEBi&q@Yy}+GnK?8DFx# zP{dKrV*Rs>srx7M{nr1T^FVh*@wdE(RG|@|GHEi14Yt3#&H!Y+_VMl-6$#^$%tyN~ zbh@Z02%qkbQIXNU-u+Yhcc+hvN@tCVNhwF;F9rq&hN6h>X`lo3yXS!pNY=jGJr6V~ zWBgzHR`)c}N-*i`%s0ASR3bWKR5XMyc7v{P)9DRSQ3&b{QPBy4Z3VFfB`y~gg>I1P zpynrNO@@z(&5Ps|aAIsJ{tH^Z6$?7PnIXFQh{hoW21vTx0VPRLmDAM*B3lkXRs?mofmWP>M!i782_VB@ zZUEy?sQRc=yp-DX+Bl}Y72K;w*D_s=?<9EogvW8 z!F*NwVmF`hTkTWbVJy;DyY;PKmTv9#XR$t2x(<{roSTnvG#_9A_3VCwj%aqM*$o-q zfP@3Mdka}n0tyyz1rF*@^ME?-BH*bZ_%J_9cguWG;}zU)0k?=cw}1s8y=5M7VKZUE z1dvt^u-5LDeNYX8knPLIAp)QVNIa<14=(gT|V-;0eRd zd7ufyF0hEz>F^T4Zh=nlxpAPA8o`r^o%28?XmGC|Pbav-e{tvS|Np&yZ@PcH*aW%` z1)R3Jk9W=k@Uc)~~}$m^)(`x@%NatbdpCz`}|Hbkt;t zicDvWih#vDP|v?ar@Ig2v~F-@cTd~Gz`&q=qPq>`7-;6<0%smjS6!vMMg>%jt90%I zxdPOd>E&VX>;ug<_4a`pD=)Ssf)i`29uot@YYwpb92Jdja4y$AUSiuFq9VY2!TL4m znC%kg&QJz$3%?JP(wKi}Utm7bS)-!R3FddVfgB@zxHCjWr4!8VZUaqmfs5i0P;RMd z^Xc|!6EHqt{ku%6dm2a*QWS%nf?O1XWIB7=K*A7Zoju^<8e*X3oHkI8i@)_Es1)#N zQ|Zl7k5N=@`tUdH z0!7OYh(1V2cZakIfXh!%{qn*-0UYct-QXpj@G=4%-{3%t?`{EmGA=f{`3OkZGDbz9 zR1jio_Y|-{K+C@@z|-C(_R!Q}-VIKi-QWnZK3J;W-3Lk;kf^afQ7UdZ4^#n`I(2UY z`Q7?+32XB|j#6V#9|4jdVRn_ECPHvzb#Ivl3P0=5-N#B$K?fU;$@HP$up^2s(_IfdSlD znJ{5OHzOj)gTx>syl$`m|A!3lLil2Dkog=h)llR)UVcO2v%K8)1zA1IOSf zYE{A;n*xVHT;l^s0+1pv>wktfrukU`FZ^*D&iRs9!zWCb@RFMW((r^>H({qnoIAtI z>eIiWqqd;-IcUKIXl@&P-ZWGli~`pm-EIQiVH~}FJOQBl0z`s9Ma2uDGzNxlKMv*- zoqimkt2H1xvP51?_5S_e_+;}D7VCp0!l0%wXyRPpIKvfgcZN<69?<0;5VasOOXNi= zl6rB7`r{6ugDV)Y=)v%h2gpCGPa*r~xC3Z?6$98i5ch|u2!JjE@#BDa;D49^rprOD znJ^(sGa?^?jWFG=E`uKfg|3X0pW)%krzvm)JwzM4?3cq0gIk2kr$;% z>QT&Zu)u1*E0TH)^U?KWiM$X+QjcoB30Cu;dLsObX+D~sERh#mk<_D@FJOw*{8l9O z80Mqv$r5=HiliRJ{0Z2@UlmC`hWY4v(9=)YzKl3`hVFAOGEV&d-+WA=@gFFDi{8N| zg}_ax=KoB^Y{m!TK~pk5Dm=~4|AqCMSau0^IWl%Ib_6muA7rvVSNgvDcpOLxBq2db za3X}VK@`+H7F6^81cMEXWQLe2*%isu;mFhx$=DId47#fFTl5zYY`bwi9Oh#a0U0cG%D!h{Ln_AICnk}!T7ZkZ=hs<4xR zfr;V8mk!Y1+5~bk22I$~oaFa%Yp*u!Jr87^VGf$;EL`7!@NVWCVP8SuK5{+)I z?m7kS^W9Y}(siJ|n@Fjs^@(D^Zl-QO1?__%HT*5$X0VTnLT`yVJgB`t&etwsg$N#pDh7(yJW0?6dmaHQ4x48&>g10d;z4&O-1-&0=-vky42VspU z33yror4dk2Li#hU|DpR?Si0SiPAclGlQ`}s1M1WqcT)gS;HDI~Zv)p4(ZCDs2DwRq zltGhaU~h;D1IQ8{P%Q_FdT?FR?FO#(B)U1kJ>Bjw2~d3w3K)s*Fq!5{44q*z-61Lx zt(W3JSCK>>5`elIoIgPK*aQfG4zw2mA83y>zLfPpV+BU~1l{BVI;i?(mc|Qrm*4-5 z|AT7N<0XN|9athjW3dh#;E`De9v;xBt%JZH9(RV$3X#qViOvd{&I*Oj3YFsw;FRqE zN!bpNlI206H%6d-sjwE-IkI zQ9&Wj7WO{?lIV6z-1+x^oD7UGveJDUUnZuZXfk}2)qzU0Uf`62vHD2 zO#t=(LCIer43xtKx&wGXs@YN)Kno=f@qq6s5&?D4c|eo=-L)L8x62&6OH@GlK?X9# zuMVEmw`hLB0GjIOEfEJz^=rNs=&s~w{?Aw>-}oOi22(DMnCU;>S<3^T&b* zLLl?}p!}1?kj2>L!2%jO{dclkpug7tH$G|1oJ^(Gx4v!We4!8Eu|hRkAs zDsJdR06xXAdj5hpw4PT3ncRAygtga$1+ldBtSv|~KP3h=rM9?-fA#3B+<_(D}d z6oE(e!CnCqptQr$-3D^0M<wyxJ;|`E@ zJPsUZz`+PIiQ#wyD3}?*!6=ge4n`g@#qkFvG$%|TDLg@jg2EF-6AVv~A}orL*7AUM z4+yj#C{Y20ry?x44|rn+H)t{0Nlp@cVj`)TJ6Q2CI(7gjz%#t+i|BKMD3Ub6i|<%^;5+tB!K|54S4q3}6g zhM}nEcnP`}1kr!zc&P?g-+gcwXiJmvNkqPa)OkFhI`6oH0BBP3xPu6!T9g3KR658& zYDa}P;54FgCjr#))aVRw=nQZHExKgr^e{N?5Wv8|-~iqyU~JPOdT5#^M`OdKzA$l zdO+qUF?E1et)aULGHVK%qr}t^fW;2bm>F!I5>p4#tR~!5kXcj6TqULs?6ama;F(QK z)e8_VLYg&Iz)%g#>;v0B@!RiTJ3nbT~p3 zgT_mJR5*+ew4MZo8~@Y;onRSwZvfOkO9&1HRayncx5K;LbUNbet0Hy`WM z$6ZuFXM8erx~P;u?q32Ozu5%3382f(qB}02J1@jWqm&i2kXcyuKWO0oMDqj2i!YlG za`P}SKMP$fG+%#iY|k#e(@zIA|qSZwm)# z6J0=P@QWEM85xXETAwQ7DQB~EQ7I_{O>LHRyQq}39stjxm4KQi-99QMojxiC#<#me zR4RIXR3d_2^zQlnzZbNu%SELo;Kc_BPo{g13TP@Y{Dt72-~YS)JbFV^WWL{*{@>}N zBB1=M*F{Ajyw^uXBB0yNrZ+?-A+Q^=Vk#)0H$){Qu-i|k*G0u4s4L7O0Mz{Mj8U<8 zv2+OoL-&d18WjV^GIr2xN@th{_=+$W6_sw#y2d(CG~}6-rh?WRS|2Wr?RHT~us#f$ z^yMfCus&VtZW(7&;?zAw1w8hCxkRX&$@+LHdv_3v_0J|Vk zG_<}}%H8b%>g0r2AA%}+@p{+q|B${WC_+K&osIwR1g*pCKGuExh0H2OhSp2v(najH zpn9m7eFunoEzo+Y93;XZPzDlV5HP-EeZ8Ekh{gI?F$+i|>;M1!4DrpE7*rV;KKzG` zCQX3U=ivUJ3aCG*f!-g4rgx4`4;}DO0*nu8*MRD(07$j~Wfd@Pej^dq>!ZT*V)G0J z(ArIfZZ{23{)2RCJ6%**puOR4H<8u@ojxiYrAm;Ly#$o9*UkXVxOBRSl=6TVSI0FU zkvPP`&>iLw-dpDp)P4R%)h^JUBb9K_0!mPX3Iulhi3D|pDZKc&1f(~2?QArb4zOadeiuAotKg>N&dIKnmdfa~B5irT3s^ z{Gjm^kZCfY-v4oSkVLnOiUc?ZOMp5By&)}Me{2a`w~vZUCx7dK_!8dk6E9Bh02QF12_WMG zprHy_&mQc(36S=Z*bmh9j@vJMe2$mTz9Y+Xyc9!GkIv_LxeY}<&&y{&k@chV1zxtH zs26y-4MjaVU*u&Nih7ZkZ7Ax|`4TVHP}EDj3`0?m&X;-l4P|~v=A{~ndUU?R%VQ|& z6<&Tr314)+%FAge>Q!DILs5^+2hHc;tN-A;2*AA$Hy(#X(C{GW*cgUgb3hdWDBHkl zx8rO&U}+W^FvY^vb z1VHgy;(LgNA+6a;xYV=T3p!xX=@kGH>}E={6=oj7|B>$Dyy1@+ZAS`U=6zIeR}lpt&lLB^RO<$2p5ls^ zybU`bq7%Ht0+iJlUVw^Z2bLRPisJ;B;@JVF1eSm)kqKZ*q5(|F6eNNM3tT{LEzl_f zIh`IU$a7RAmB$L8@>l`fZ-I=|VK0v{lws@7L;Bi~Jz@%=GFbtX%U}il1VjlA?*~Kr z+K_S?QwO&GJfyD;DVs5MVC&CA`r45GJf@BSgsWgRML{og%`v8Gq`o{%wNtMLq#uv0 z8dk4>dh+PI;voHaWYy4m1z8BWUV)TP3XYu~3P|;df=8#L0&(@pIW2HLLF!*G$H-5} z^NrvH=>|!VZjc1&21$@^kOb)lNsw-k1nCA&kh?&wj$XeQSi|E5>j_YoQ{}~63kHVn zZJ-53@a8pWUV;Z#a{^SpvVdkSJ3TzW=@RUJaDUqY%m84W34(T);?)Ho5^b0XQ5C=ME1JtbM0Jq~aK+X>6^^171 z6y)9$FXX`6flGOM{r((tGh}?x_y7NY#M%*1d#Cv)Yq`>YmEMNWE)2#84uj1<46X_f zgM0Xg!3(SogSSH*?)7Ad`Ru|__}PUa{<8~1`DYh~?9VO?sh?e-vv1(>V9@?l>&u;y z7W`8WSRL+gH0zACDdFyB>U6Z|4r1vHwCRlW=#2E~j5KII81o|f00RTk7E@68fY!%A z4ipgqH9LG%I0Ab;Uc6WczI7L^1_QO#Kw}M%_2iC_P8`T%Pz*8;bZc#QfC;GoXMx`T zYks2x8jtuG-tDFW8pdk`9b(~T3R=Hf23juc=Fsiu(j8X<>e_&M@0~F!ph-&b{B&=f z2k2lkKb>AT9qWswI^E!Hd!?YcECK&P~+fVL)qmJ+FeD|Y6? zfdR}{d;MZw{M*L>T1qL?9jDRl=g=8u09scGTDZ)7i}_S%oJOagL${ktw_nL_kn@EP zce=TBAJjhDtdot_1z+&a?Wn~?mP?YyG88B zTvUV@U$cTJ&`i5R>+RC4)=QoEofhAtNs z;g$oX-mkeq<}kkA)g7ZE0UFl;MX(oW?^>8ccMfRe$fdhR#X$S2^!eU8k4_&Ii(VfU zlgfzpbX5+EHeDhjO!O4GVsRAiceFqWEixtX*aC{YAQQ;Ae}7$}N* z-8`C)Sy*2zwFezZ5dd0-Yzk@yK}I`t4)HKRH!I3F|6neW>hd#bIa$IAI>L<)RT((X zA#_2LGMEDAb8uQMV&}|gnZE5{IzLcvwh^4!b#rj$aWKAW=TmI}sre0$^`R1`P61HfEK!jO z2QB>Va+7K~P-58aCexj#)9t6w9cQ2o+JdPeecJkBk!(4O^@}3$?iXEd5}=Ei9w4zLR2(*>%a@s_^l6?>UF!QXtW+ERf7y`K)0`hVzLdioi;qEJB$Om z`~Wh($kWZQeFC)C7`(#QM@0a%5?>_{q^{S`f%#DPoix)=@fcFNAbcd)Y zboz;O`|&WJ0&frXI*iF@Sn0 zB4OdJZ$ZHe65($F?Q-r8*6DWE=q=W>b}}ttkQj|`ylgo&{m3rFPT0s?LN``koohH?qZE@ zZwKa2%%?iN9lD)enlCVP7HfcdOr6f4J=hA`ub4lz9_TDlktkte6li_R4?gi9l%hZ( z6L|=R8pW|g2ih7QhW+>{>`8+S(P}K9hWJ6Jp&KGzohN52J zgSb-a%X zOK+e;P;a12w+F|I9!3U+?>D3msIL6~qnOsS1ET9dmES-*^BRyC^wHQmM69$U<5o8B^dv2eOqSV9itM_U7`}x&E5QyuS5tu+;T18 zMK`1>H-9ah)@;XJYH55j&C-v9f9gR{`^CNa7IMi1De|g~;Pm2NoiaPd!-x8lRH> z1{$3L=UL@X;QkP(1p=y=WkB{@bo+_Cc<~1m9H5#RbSgw=m_(-=r~@n!hjqNldI88i zu<@#_{~50_%Dcdf6QHvid1OE;u?-Qmy(4xAC+mL(_b2rE;=nA07we^Q8D0sg*;$bG zI)D-^mdy{?_9r+bxih@HJqtEI)chtQ7<7J1Z@j{Bckl#G_vvHqG7K-2ofsLK?HNjy zA+uTFdD{IZpxYNa*-QE273M6UH)iBvae zSXsyVLMeB*8%uYHiUDF;Qy6lLA|wEynF%x>ez5gGjWTF$o=o!#rV>FA!3Hh@VEt>* zQe?!!LeP8(M*Jg9pbSLP@6tWQV z$P^^bKy@GJP^eB19;ERp9*<5(9^%HQ^d!Lf6gEC}oDm!$j*tj(1V>1>rvP}OV?j70 ze4iP_cF24+s2cV%zSK1#fYp`Zzsgh_R#yh&1D%banfF614B*rQ;eqRr9iTl3$b2r) z22!wUh&;5_G2sV`D+4pDD}ykrD}yq~OjcJ01{M|;Miv$pCKl{~8Rjr39UR*IG7QwY z3~&C)TdD!-o}@Kf2!r?Of!iF>py_M}j`+@2&;d1ZpatiLI2f9L3YV&b6^}Q~1=6Jf>2CfhRO$y-+s%;%(kRm%z!Bd$6|^Secq?dYG^i+nnVi=AQ&R@%S`*XZ#V*u5RwV=(9aJ#y1H2-EUbxrGL zOS9EwC=p7twL-J6`4|(_zG9GlJ}MH{=SuFSHCr;2-e^5ga>W+B4)|=RYe{@(Yyr%- zpk?&UM%>|KZ&~_a!8`GjxZsfNp$|206D>u=yBA<3CX0QuI8& z`NaRY!`*C_(orN$1u zGHlj2i#~RH$#lEQSf40WY&}`Z86OwBfie0J3qyC2M0c%(@uknpK=Hso<-j2p(0&mk z@VS6sXTyo+HwwYsH$%g^xx<@(+LvZ^d$WL+f0YSz`7m>I_%JJUd$TxLA1wON?JZ;c zt@UJ?O!E%~{^o_CRaU_g4qZG(ZXG@n^4;Dt)*p+WfaO{l85nkghCzF4Bowqy7$4}q z2pR@h-F*r)46q91q~;?Ehns)0m9g#w9ckDdECVhRFF)w^X6ello;-RB(cOo1jhM|3yLl&h87Xmq5d-;L1+~zDz&{)c$z!vxSkN+nc5F5J+S9!QNty z?q47$z(*pyWxA_bx{D>c4>F@j^wwzoFh1FRy|YF|rjx7F3pDhv@nQz(!Y&sT&=`+M z^H0X!4IpDd!xY`e%Je)ztGZr;=2#`V&oUqFzS#W(Vinl8OF%^}SV`&K?iv-DZf>Yg zjlY4mAAydm=swncp7~QJqXY9<>tjXVK^rN$T~rhTdMARcd0}18$Y5QfB2#p^yF^8! zH&~(j+>7m?3nG0~R6s%7{SRc_>h4qB*TBIG4yXU3D^lD+Q63EnX?SFV`v*5ejo)@V zbA+`X2rrWZuOV}0=|10WvLft7{@?%qTMm>8b~|&pTE8fI79ST2Ni#bifRf<%UUvoU z^Ialr9Rd!$B8<(y6pB8zzAaG%-Im0&7F4JQ26UTnG#_9I_%C{b(Vd~&nWgy%Pp1Jq zVM6*Rpv9Bn#{awBI9d;sNr75or@L8p1ibk02W-7qw;PAM^^c-wpvydLAk8vRPxyby zw{ACrdUO-9XL&d8rQ5OJNd0FFx}9{vY<@H6O@h9IdxY=f%f$yRrnl zxCs_viH$xC@t+vne>(#>JQ!Z4@iIbZpfU{jTp3;zG{W4U0h0eOTEGBW91d=e8(%U$ zd7J^%28Qe%1|KpGnQjv3^bqL`kmwAM=?qZl3{dIxNa%zeHQwnF0}7C={}~<_?ejoT zj|prOs0#zJv4p`Lbkb$_`LN@#m2d|j=~FE@3>>O2K*!Z}-DtU83cB`W^RNH^!@AFd z`}Zxkqf5D=in#y&{|`3$zi0)6JE)(`6OWi}grCa=iJb`(K(QNUd?`zy*YQdBhk#D8 z&M=nFFpkbJp5u;RK%U;&07?#`5}@rmXlWB!(X@yXZB zz25&1JYeBE*nO(QMTN85Ma3Yj`(=1-JGG3GEG0;dxPg^!IU|_xTq$1sE8Pvwr|}z}#8x zfGLhMN$w1`@=j&$u&$xyqz3_le=mVt| zfo?a@p^M;2RM4~sWWow`vRU&n9?<^HZa;C z_!MM(0u+2akl>R56&|z-zA%lT7biG=|L?BjXg+KTB?$a+o zH>-DhO9Z}H#PR!o@QXPdkU;xidLz0!j3wwrH%POOiU@MB!Lk~pG3%{k{LT7Yc!_X# zHD)w>OBf&MEEec27U^W{t;USrV2z*`8XzmOLGH7DSCZ82%;MW^vVwZ`m87Z?LE*vktHWe+gR3%uhspz$5_l|&ri5&(H{ z23i6j3t^T3p!%-c5o3G?GV1{9zoPHY>0<*08hkx!*8hxjZ0WhvM}_4$V+*LzcVsC5 zQydA&?hM_5GT;_6Z2l9{QU2IA-hpm6DpBFV zRzF_-2CE-In`>be;}1|cxUswdQzbW&-5Fj;uwtnS6@#-Bg1gVZIL`^H2@imjyR)nT zQyg=WDXIxcO3xS-8}{^!p$tp?2T#w)6%xEg^Tu3pjamOe(=)OGSkkkL3QM;KhhwJ) z2YCDuG}0nl>Cg%|J2IQpz$aUe}sb$EM@5o;OGqC0SyOPALMTVodOS9tI#FZ5duD-U!?Kje^BlI zv-!FGw?hXyt5=i?dc=d~isNEcK|{8nTLhYaFqR{Y0`f3)g)w%&1e;K!BGULAWWvFh zY~9zJA2K#S=Rf$0<=|U(=JU)~yI=PDXfatIL>`gkVQ4}Cy2wF=4 zN^_9&m>V#HJP>^Q2k88ClW^;Eov9x>OaFkXQv>u?Q+KUEx3h`$j}pypX9MeFB|HHy zUNe9a1WRYJf%U)6Vv`ch@E04QLe2)A)h5>eO2oQLdAiScR~vL6gme`kOGJzhbfcf@ z%)_w5QpT0xF!<(N@FW$qpa!4n4D$xaD_{)q&kQX73F|K92sggnnfd{A+G6aV7au?V z|KAzQ(d|~y8_E%s0j>l&0zmg${TJ*89eAPH?aI*+`^Wk)f6FvbOoNY&>^_d+L>7i_ zR}SmLr4ry(me`~Pdi`v&6u?W;z$UB0OopB9jmy;Du$U}?AaEmA07EAp_mmZcb&G*- z5db@_BlZuxn*zF92^xgZgR@x}cFd8*8N{eND!}tAAu8b0UU<443W7j4H3SNP*XDpC zAnSj|Zj8VO_2)phO1#W+c(MH7um9aQpzUVk1J$^4 z^agWuTXtG?SF&_gv2<5*bXI}po;$sGI-Mmton^Y~WUPOHx^E>~;V*(gW}feKmgp{% z01d!3A7O!{s#D#EAU)F(6`f9JndV~(z10ffF__L66`jvZUxOxlbwC$9`m$J`0Il8x zo$X#4)P3UMOQzluMn>=rSB?KbH*SHBNhxRQKGrMJ%D}+D5cJ~i-(UZ`eL-D-)|1^g zO1QgA8M=ReUJAM}vD=j);Kh@_zd+~EbjC7tmU4gw@49PQx?LGSm;K0TpX(Lbzf zWdqB>hfIM%umLk)&>{m1(4d*f#%@>8@S}u7e5Wf*9MYjFB9NXlD6}U)_tRZNS%1Xx z^4k;S@n;sa{azd|QP)p#ygY`Yp5tX2%K9Rfmu??X&2#&N%rAMVh9X~rw*Rc;r5K9( zikII$AnUJqiMs!+;^i|G^H^RU`;M%h<>fS#{c7m^l9$s^)R(+0gR9T_pK%)_eS-Ff z@c)6t7UtoEmEVY+{D;)vzpH2GBd9Zur^`o0rVDf{gNuqnho59em{g~m zNJpH+F3@&uaD%!tMn$AEPN6eS1~Nbo+W##B9-WtgkIt)rx|J`Ya~T7kK&~4@DeL}%JU51JKZ))T z6@h@}g987rA9E971h4kxVF1rgBJU^wofjZb!T}ZsoeltM&Vr6(?KbQUP-s5zr_-pr zkR_nAh^4!bqq7KFB)>fhNiz=?F%Kfp_y6pESPI`o9b`1r55mMgVkHy&Xd-Us`j;58+ay zZjR=k%;ly|%?H3&F*X zFYAAXHD>Z93#Wt7t9O{|3yt0 z-9gu4gs6!0`lu*?rT|~qrZ6)67q!8ZP)T8A$S6p0XZSDr1~jbxqxFA@T}DibJ45(? zQ4vOW(2?-!y*=Pdg0d6>|6gc1P$HhC&^tv1v}6Ee{@xVOny)*_j36B^KxW8VFuFr7 zqxvt}zyLOaKMTAB0HprK#$-l@|Ch5^KugF$0$>NuNoHi&4>GCy8fcTo3z-x~(DEsn z7s;`V3|R_bQH2*}$&3vCrFVQw7lH+3UVKevWH{!g0G^_2JOT<5=!g%-{7439e#Gqy z>`>Z_0CiV}7XcaY`4Nyj()jU0vA^oeS1-ugrqMei4hdkAQc8Lo+mLffNoYO5$f_`5$ND{ zcJOchp-}X$^?zw^G}y_|$&(%xP*B0=Pa2PaP7p_K4q=?KsDI^3#|uA1wc#ALC0w_|IofsdKa{s0ko(Bw2~e) zzsSJ=IeH09g4)AbYymHp{Qv*|5DUYZz+M)WfNsX)E-Eab$_{KEcQ=cQ2dHD%{D3X; zFjyO$Xnq5la0G1u6X;}70o|e=qQa5|3L2LG7eL1+pxAci47mRq7TyhUzbe%IZX9?# za0j0U(A^I)zx!jipM>!NZ9kFl?q8+qmdqu}-F^a{ZX%s-65Vc~TiFCUT~q|R8H2jR zWd2_OO>%eoNmz21F?Dix`^hl-iFERVf{KL!)UrUBRih%%eXCU2lD$M8ZkQ!|8B-^F zx1T_Fm`pcg`2P#t{2;UV%a}U(A!fzLb#jB2HGl$*F;K+#08$u&X70M(MY_u+v_F(` zcKZv&$8|IQe*p4^KsUGb$17xZFLGK%{k>Y?rn!gSvyxch>zxi75y zQ|q@<&?L{{g&-${ciV#e*Lt8t+m?ZW!J%BG`^3eU)*s7cJbHNyzF$y2VSTPh0Aig2 zC^)XS9w_C3@EO9g82(?6k3$aA-X_qbr}d#?P^h;aDES%i;wq@fIsuw`I9c+l7rf4{ z`9VXc#~+Zs)=MQ^-A;c3UhGZ+dlQ_#{CW0)GV|qU&Hq@6S;05gbh`^!A1h)7C8ER4 z5150yZ}hSlGas@(RK(xy&(VFMoALjJ?h~yiOWD8)?QnOvK=(oIL(GSnkNJJSrhJU~ zP;~c&=0|_xJH7rOJGk{y317D-N4FzO^P@lAL4W=~0J#brm0;pH;|3j2@?%lZ1*bbu zde!N0H12dX>2$Q%!N9`6z`y-Mc=w^>jvAbx>yRpK4n7jt*~q}azUdPs&YbCX zGzks^UvL_3eXKkNs;k7HJJ6*07h@?~bEO4CseZR3kF}#ri2?sMiS9~^gU>mfxPLoz zR$6pA@^l88SYIo>(0t;*rK3d&Yp0{hYoGWy@G6(+!|`#)9W_A9;*1YOAMSPpUE@=v zw-0m-jrFl|)!q~phHgg%YeyCS7B|pl%|MN=5J8;|f&Y#g4xNq)mW3K+_d~(j82MY2 zLD$UuVB&9)0&pHVei#14Vp+dK#iuN(5jDMzJBl(H~;!;*0+i!cQ9};FlZk;_=1)BSZAO~TBl2< z&C8enKnudOZ*^Zg_=;8gQ)i_~XQV}1XGx~bYj$W18Xst=G=9N9^+0z?Ba3xOqeyQB zV@YkdSo1NKPLrM8l?vU3D$R~MEc~am19h~&H~(WPO6e3o_)4PrI7>&Mac8B%%jSRo z|Hq=lAcO~MCV=7-!UHX60r9$={zH7(DX1MN5c~a>^riUbM;vjWv>6CGOYd-JrN(RX zjzELfZzW6};s;-GbOahU|6?p;?g(cD^NgDRF@bnYV4iWWh#knafeM|48r`t?R)EBJ zi3F~=j*SPM3kgr=;QW!+>1Y5-363_MjxL>!9-WRposI#Wjxn8%8K_wXw6Ec~qX}pf z=(wW;DAONz1a0DG>8;GcnvX)myX!0(LBqKJiv+sEY`TwcRCr+?2U?n4V&7fI(|q>7 zb)8I!4`>r`n9W9o7t(Qz3`}l@?j7#`8S@;v-5id&8U7c{bK!P#DZScR$J1SB(S7{j z3yBUl!)7-JM(_^9PB$AtHR9y4@7I{ZzD1G}q}cl=3zIWZ`ey1j>>xSzdF1 zE;~&H;781Jv{cd8+w8OOZx*T|l=)>;DpN z?J%F-5GfYx>%}77VIjRXQWxJ_|0)J;y#{sd8M-3=L$l~hNEST_&Y}mqUv}4-@Nf6Y z%Yo+4i_JAE0t}_{ona=sz`69|!B?!z7t=aJ@^U)e6guJzUatH1|371xMRS-9gZ8g( zki7P(&N`E{PLL@a&2Ann-C-Wg7rQ)|n-8#bx+xeRX!s4vv>kp1-9BwB4xpGT@#H_% zDF}|QwwJO0{{L^T(_t#L0$(z1S(i~P(i{KhMJZ$vt_ovZhGktw(fiIijriE;xX8ot zvC+`Y>v55XJKZ!o!y+IO;M(NOndUb<;LcccT?|7wf6HRfk+Ci+paBVn-nfMB|J{B% zpwpf66uQG=I(<|mdVRzaKph{@P>-LA^@|er<8C?(pwaPTFB(91fz~N>yTxe#Ykr@g zeZ12xri8cqboYfW8OshyN3YWF&2<`}K~2!MS_#mh?S3kqVLGJ=)-Ow9EL~Itilw@I zLH2g=Fgv*ZcTo}Obc^ZCQ+QbhT7LMVGf&~TTMX1P;lH4e&|oQ5?ydtT%=6%^Qo_?E zV$l)8mf&E0u;@#tUkvm4PCo_ElzQ_Kp2KI(1cQccc$y#mX+Fln42i+;?t`0OmzY7) zzxAQw$mRnq77_nTzjRmpVgAqjU;8KX59WUd-!nBn|Ns9#L*sb{28P$26@Ok|?)7A_ zK2)rUuKtJiKjxp<)W^qZ9|ZLzpkWW9f>=y5&mrfjQraQn43RwD1T}`z|{Ef2Ll5`(F6W%1^*5{;$Z#+QqcT}y;tND|2Bi> z156;nYuz8TzcYWm_>TEn_pO7kxjQ2MfN0@{$Lt*e{~AtzIQWXA;na_gh`${H|6fl5 z)pynh%Tqu`VX^B8adv4FW7iDrgx0$`a|Rq90-#6|XnqH31BG`V?6ncJK3?q7 zCD43;rQy+^hF>0~@4Ev2H#}l)_{CWIq&wgb|EbouB^=#1v~M!sd(GB;Q~QSYJ?6`e zkN*Gv&)j&5fq}t;|5RtdpVvF$<6=>x0F?MkR0Kc?;vEa~#qjQf-M=;;us&WK4YBT* zLn&)Z#NQIGhF|riFDxSd7Ci>r$9#$T5;(d_IJ#eGzhr**nyve#_6zNI%vZtIGB&;f zm7|THKqDImUonAQ;Q(>PLL^r}`hNnUVciDd-7k&*H$P+V%u(TK{>56%4XVjvL480T zhGrKP3D)4=s6WhiLEY3|5q;~+#X`NF3|(9ekOGv|$@+59$L>?w=evJtpVj_reVM=c z7U=ropG;+r#^3n2d9n05GOqZ?-@287fq{RU6Z64`9NZ`Pw>dGv7>pnWXkDO8uMU6n zan|M<6%~dOUFM^&wJ*PG{Z_KO`5#NUaPvRr629(p7hm#ka}i{8Sn;oPaq~Hji|^cD zrh#(l(bjJz2F=gdn7=W9>%P%_?(%ErZ-@Vtith$(Uby_&+xRfVSQh4^ubH%ug0?Ff ze*=xVg63Q}I-D3gyqLOA9DE^h@TGtXE0a8 zA6>4@U8gU-P~o>>EiK^R=E}go&G$d34SKNq^yL>T3QD6vQ$Ig0zwh=@QD8pR{k`$o z|Ns09pipA|*7%%(p@D(>JM%YK*nE7=r2X;WI~I^Cd4}%OjmH=m3K;hP|KHDW`8i0i zpW*Ve@7I-oaDVSCWpHjj%G&&!g})6{PJ-v3K$j=hs7N#)60p9`-(~?iHYPg0`w-Nl z;E;e2ft@@mb0WGg7_+DZ%$*Zqd?;wHB8y5liwbn0qWO(Ta9H;zP|nfAJI1oZmx1onop1a)6CKKUZ&|NsBJZZZMA zeiDJbVIo1jVFKW@OJ4;4|NkG{8j3p%I#&ncJ5YHa-d)LJd|=m;6n6&WZxbx5ew6Ze zNByymlIDdBHE#^ca@h^P6VO3{Pn6aVAmq7eb}c4z(;} zU|@i_@gP(LbW32biwXy5yQ2W;J`5hvMpz!>lP~uF`~Sb!MMVZABLk9=0m;Zf9J~lL z#O9+S5Y~P0;0sWX@uMmOKLbPKL(tV~+y@((Vr1vFgBaqt~S_m3Cq z|Ns97ZAmouC{gw(WTF)%>5o*fky!2B2mCU>1nc{ExNhd8t^9`M+ApspkLcB}be8o0c4C{%=;Y8`P@>X*_f0Oye8yL0X^<3CCSj zR6wWC{}+vc432VvQY)+U0f$n4;{yj@NH#xUY&-%|ez=!M<%QC}|NlXQUdk>i5-5_e zr~%U?n9qr7{-M9f<|9dh&4m#pm@kZKeiDlLNRlw4!8CE^a~dB&3KivYW{$db;*4sx0r)0#OIb5ps4^C70|(1EC*k39(>8Fd=SM^;E;h3@cc9RH^?IX z7SNrBko?mK6#?DAgFXM$|HhMll79dHZ+rlBVlOP%AVCJY=>qHn5V4bifuR93-VJIs zzR>^u|34`6H9!L$Q!{8~1H>56TJ`^+o!KrbJO^J$H9uekgAQIv=Fqr|W*0LA^ zUw8(B#>+rWOt3hNXnX@22M+CC13t|Lw2GShDgZ${oqwR<^iW=BZC&N&x3+m34syEchGk`{}c|d!N!hEz3dRQMS zW9mMn>E_eR!`SJ^Q_6D8O@=Y@aJQIt7)!UC4RaWe_913BlTH?ul9%A{>h`mMjOhQr z(CHS_dZ6@DH;YQ^fs*5lZam#?Jlbw7)^0B4dm#q+fekpt>}S%+qf&YVRE2gkhIJR3 zgm+guXdlx)-hH9@Q9bkZUK_Da%kD}Z?MjyB2Mx@>!kLc+guUqX1E(O=@ymuvd4^Ky zhDsTRQqkth7=}{*ZbuttM-y#EOGg*!0}h~_=a7(xklo<$uyk}O;sh1@nkVPNQN%wb_*IPPcw+O>Dw(E~IhkapZrmXV>iFroWU z^8?23H&hjxcf9RBb@8R~!R`~y4;jDTYwU zvKxO>2B<*;uB5|23C^9R`(t;QO85Ey7eG;d+)V|P-Ae_#!%Vu}SwO;VcZ`&D)^)6;L1JWB03G9}PxO>xtP#MFey( zo1aIx^}%AM?t`6fE?sW&pqaPhZlL{c;Dgpmy+XUMy@&hxIy8iYR02?gP=SCrcPTyANJ`!F>YMOksjh zED(x=``|_J4hO~}zUE)drR+OE{o~h67hmu~3}-E3<^BJknW587$D#QbQyDwRZqNnp zznII|8$qWdGBPl`g*4R3GIZtzbh<@!)=6}qFJbQGvF{F3>8)YpZ+`xv^->9k<-PwSI>R*LOa$HFx)i)&tPv+2T73 z1>&p^6|*zn=#1ouKFoXzOq~huu2kvv3~4T!EhRX-pMrn zyo+i4c{kJe^FX~xmR=`?H2$QUY5Ylt()g1Ozvk{;0?weI@;r?{-{V0VzlHsYH2z;F z()jB^ynK%jC_*37`13iCML0m(1dv5M1ey;x^aebzzF4{jG!F}NPxC>J?!X_`7eG;@ zeW5e(M|a>K1n*C`AeuaSQ;2;N0L~?|8|7^WoA`SBIw?p=js~3uyx{qrg?__E|#Nu80viorJgAZZ7CQZ$c z`K_;&h%a2h;Q?C0z#8`d!fVd%Q{Bg37=em{b8)S=ON6=^t&cXEO#h@f56&^EZRe=$X)cRQtH~3F)`W zueDz=zXWY7?A3YMeM%d2yp@dgu_C7KV_h;FRx$#meh$_yDjFrSy(R+P7qvrF48Zky zmyD5>T&aqK8%VPBV|OS6XtF=PQ=r=ybRdjCTx=&7xSuM+08&wM4|GZlc-=P-hZT=N zG3eelflkZrT9#g4mhKPW{%?tj#A{G*R|F)^(3ztm0@~aC-$%uvMBK7QMWI*_d|IWC zibZ#fiVgVmKai!M^AqCZVnK&lFfbek`zn!x?Kqa`Br>k2q zG`zclrPH$8!=SrDq&q{RvqVLs+W>U(RJVslXNihRcL59Na+J;z6@^}&pS^`Fpy=oZ z4Tt!sNEn~g{(9U+MF-^6&Kwn=PSD{Bw>o`POu#3rmZ;cR=BOx?vl)NuEK#ws{>0zR z1*&{XR1~y7TmO^3qZ8uRt;8Wo3Lk?Y`*gAf&i?!VgqtWOm)bzcO9NjGPw zk4iunkChdVR%xu0b%=^Ui7Aw;3*oADpJ#rh?V|!Z9M$DDXhhkii$~MSm!Xuy$rYrb z^bN==%McZvVrkHhdcRJ=&O(;vgB+b9DmtB@y9z<3hC)m&mIKv}oswY7BUwO0?LOcO z`aoxi8oU+*-){ktmF)CUk?B4K^7DTm6^jxb%NP}#Vm0tF6FDkAFZn?sAEFWfHc$|} zz26Izu4Fp7UV}0MXce9eB(5R5#9{Fp?-<+Z!4eIQ;uq$S&Ylc72Eow`Cz{{5fQoQ8 zf$;8Moi*T9QXI`cn2Y(lkG;468h<|?57yNk#uD5erxMz&$G^>&fq$DTqp?e00{=E& zrtTjHA95Iw9-3$T@44opoJEwqI-F2WFP8F=L7c+JL z>W)#d0AKTBeV@O%88qO3Rr_)mla(t&X$3enU+(o~>b24Me#`oNi9i>NpcP{&tE2V# z(l21y8Wj!gv)-Njo$)Nq$2qJ|l)88O8FYt9fNw|X4$}zi<_qc$V*#CM>7ruu;wY$# z>BjQkP2@kDLno+_4H~XF_Coge|NpVk-7rtqsAzP%8Fa@o`l#4| z5^yG{bTR361Ep$-?h~CkDl*1zwNFD6oy7#wGT2M@2*j?>6HOdBA_kN+CM=XkF8%6Gj$*BmhJ`> z05K{7T{0F{G8(06pmIo{#16_egK+h`?=!#92CbQmQE_<9`Pc%LSrRjr@SdA|z zhk$^fM$*Ox-V;A=;E^C=5P58%1u5h8r^K5lpF?1fjZrO zSd+2{wxnzVs$Dx{AO&)#i;4> z)BzWg zr(S2~UL9fUqa^~}J}MSnJRDXWrK}FtM@v6wAMQTU>Hov}6o2bk&;Y8NLAM|1CM}V` zZaK|+R*1;F1a0vEw+{w5|G7Z(UyO>+%Mg(N zKy?YF`R~Qo|NlwLf2`pA2M#}2{uATh#>KzQ37Yr3nE1Ch{=@okse5;r0qDYUKarsBFj(RZf~4Ny7l*!JPrXuK&{HpH zlBL@ZS`&8SsQ^KZpKdX%)u2abjfxNcvV)V6fnfsq^*I z^KbKKH1?U0z`rdVRQq+`G(N?@{bFZ`iUj|*aOUoi2?>plVHM!TZVwja0G;la+B)+( zV^lOir|5%fhVGZzYvzG-+?;8kOw}2qA_J<%J9*}TmGpomJA1&A-4PPjr;C}oZ-Q`%@Pms25?y&)+Hv5-Cv;==J*F=?AL(G>)^uD!*eKR{l)_jT>7U0hcD{4L)=bpoil9U##Sa-vB0&u$M;6{yke!NPnOwCk?BK%+B6MWH(Y z)U4A1x5i^sWIAh9R60Xc3_43xOged{b>9S+->tX#TR>xkpzHUvPh0z_DDXFfCe*Ai zO5awFQBlyo$$YC@WL}qye)q@k_do&HE23v5V^!+V70b~5*Gj4sv^GV?-TD`Q%W_Z^ zCvPQVUh+ZvZ#SsZqGJ84SR6FL>e(p<^5U=NV;o?2l&A>&_fgT{ZvpLRfp!^9K%x0E z8X-+BvFA9#p#2WWr_qfVQy*K#0ZULFF8m#7G6Uxm1;`54D*7LW|A zZvpQ+zPR`P|Nr>d=x#{50yV&z-(X39ti?Ppnm_*k4^`JK051EB7>!Fh68N`yF&%u! z5!`*x_#^-JbD$0|q|EO~2n~l+3arLHI}*ApR1Q95g``H~bKM0j${sr1@3eL1qa?+5 z+H2-Rl43tfQZ$(l3cSuOV9CxcV9D+Z3G460Ox^#wOH@=qhcbbNsja^kyLO+_2Dw9{ zi_?m$)Era}_xk^Y5%wgrlRAOoUp1&Ei$_ZTfbApQZsi5^dVjyww`QM;Q z0c21u*dSl9L0_8>bAW6)?hGmNJ(;b%m`me99menXy5IE{vGm$-S${9#ozTUjXT?{_ z>Sq1D^o#Z<@IXfK59<;Yky69%0FiDF(0TVVohB183Q&FkZ(jCM(ShZMHU4ExB-EJD4E-E&?EEhmmt@cKMx{CtFpdlxaIOr%X(3w&qpp`|PJ}RJwHK@;MV12Nh z&G>d_jEVuMH+-6bfkFGY^#$qM$~U`xRBW_wFyHFsx!Dc6vjQ|+a27l|rD1)zh^hN9 zcyvmm)Erd(NtD!d-voC9L8dx@#s{H&KR$5ZPog9SR3E;6W$mIOQ4-LdqoM$63-f3c zi-Q(dbXtPS!sdgZS_2dYDzAk=DH0;w2|A9-MMdMkkBUyWWr>z$jfz1r=xQ6#Ny#QJ zeL%$$=$;W!3tOO5usZR4n*g zi~m8+A8kHjfjmBi6kolb4Di@u2FI4{+yDPxc7y5-KK^Zj{M#HEja{ZC@Ne^E0?p@u z8jp~n3RO_0);*^SR91BEflxM0p!oC?>8@kx4wL8x#is!zJ{@{lK#ftGUJqD&)`0K+ z)d97=Km(7UzyY;nz}4YzP+!>kP&w#ea~aUY5hzrxPxCi}M&`ir2^w*{t$a)S1~Vvr z9UyV50nUezxYa?4TVqJvmO$fH1vJWl7OxSYo;EaIeL&rHjCh51-9hoHffTO_Ag6;; z?tdQ@gKoy_oS5drSGl z3$SMd_*=t3L)3AgW9K*!NfTV4K#wK>-A{w+A6Bq`YG3{T|8g>@iGtq$0r}%0NB0lo zgOKVEG`JST4C?IoOiSnvQvtC+-5$bT!#WNI8ng@we6jZhcCU%Tz2=STwdOaVJ9omn zZ*_kJw}+bR1XzlByN|ut{PO>Q@0UA3Ua4d0cH_`K-hCQWd0XEoW9vQvT5;0tCej_I zp?$Mgq>1?;=r$(MC+hoF23%0K+uygkEcSgh+HV}6>? z|NjTI23l|Px9Y-uD*%Z|EdFH$`}gn*kbe(T?q4R5*NlDI68N`eF?SyXmqeiPeelZ3 z2OP$rC6p}PE^P@1AFvv`tV?hL(Fc{?bQ&K*yxt5>*PwnZ3uv-I1RM(B+l6F0ZMxCC z-jCvSy=MrogVy7N*35!-_JWfxm^jYV;Ofe7+=(T?0Yq^;C~#$HsFYh<9Z;eB6m=LO7TkkN`UI!_%YrCsQd%Re&d0*dfZ5;c)X$X0VupH(2aL zG+2xUEGFOw7CR6NH7yX#oe&4!jdbQrnDMt49k)PBeM)$CJaBboSPYuUiaXqC3ZX&g zmU47@@N{|zbb3g1ddPqe@q`@TY0&9m0*O_y*T6(@xbbb{|CVtgCAyYzG9~O;j4veh z7#Vu~bdIxu=ON-mI^$G2;}l*z+Rnhx>!ccF8AbVrGkH;T(1D`1jTM`JGA}g_O zt`lJ>HEphwVJHzqm=3);yw}g*xEtiCgE+7aIxpC^F)$o=11+9oK=WW&_Xm)X;UzNQ z`|*1HG>*H04=;T2X&cBtEH7SdWngHolYrXz3loV-h4f%4TM5ztIOcuz-(6UZ0|un`iV z0{}#{PeI4$`M2o^@^5z$WHe@3-Tex*wz2sbi?&XCXWpMqk#?v5J}L^Ow-LsH_v?b( zV})YaYYwP!6F`fonfSNs2p)VOV0;whvUbp>Cx~g@r4Nvd0_TUuHv$|C48ftD;6oX< zs2FfCfcKkgp9584pk=zfAu0;m*Lv5e$gnUl^!BJIurM%aztcV!-s{HEy+uWXgMk6m z?KS=nt{*_h!(Kl4m{s|n^0m$w8-?zOKb=!-Kzh27gjKpFI;YsEurM%mUsk?$@G)zr z2xv-IM)_W+3{!Um3tW^DbQ(Qa6m*C30fEN`-R>d6%Fkd;k^YM-7P96AQOF5Kw}{S#{XY)LgEiJZxHvR`?B(d&JY`&?#l-s zu_|BaoMHnC*n^L`ly7v-u>l#@9rp*S$N;M7;A5`NDK?-41Xg4K^0pjUjffspNv8@X#8IJMyHGsDDICzP4|F%rVZkHAvX1MMe8l z?;1#sc@+*GdV-|TUMCLFw7&6w@NI-5XqiR@l4(FDA!iy5aHatbQG>DvB*%benPkA( z4K3q<4N`30f>FZZ@rFfuR%{J-2S*M05<gY|9^Lm z3Qu<&k9Hi(e-{;==BJDYp9(Xt=K#6gl>s!y(;3Us?dD;9qbL`&#Fs()1oO?t-~awI zGL*6I22tH^EX}9>YhSiLRHoP+7Seq}+b_UV(~n2{V5b{Px0{YbK)0JpugHWKo_GHL z?+r@`>h)&o^kwLF(*Z4x3R4MgKFSdq(96;VI!2x^pu2qnBLl<#3yg6rjB>sGB_NOF zZ(v|}2^yyB?au-6_17~nK*QHX1$@=di$7}-er*A50f>u@2CWl?q*hS>N+dWGv^=IC z)LH;-q}UDG-LE|#)F?21%X}NuUdjRAVao&db&QIP<$BOc;S%onP7P2ON8}I-Ls;`~ zCjK^155Bt{Jbm2{TFPa8g1;5C9lm!vXlv_>1>gSv@170{!sZ8z2OkJ_`!uoiiZpc# zF<)ptz|`3e($dSK**P6#LMPZk)<=t(n@@mlqSNSfVzKTAHFNlz13?{l7Zriy?I1^k zy3oBQjGackHcg;Cpze$e3~``EW$`fAb#DjHoX!Uw0i}JgyC3AY?ibx)-Jt%h^@$=# zpF~9apo8_%Vy5mF-P1uE3%U;`+JH)JXUNJJ&TGqAhg zf{}rt*JUaL#N2@Hc2N2So$F%}6wvF#@xS|8XNii-i`l~9y}tRN6(8X1Ol1!KU;=li z4r(7`1UrEdtd;pj_d)G;kjFdwL8Kz~sJHqGrtz*+`|*L~2$ zxB1Ke|GoYxFSyq*Fo1WCWih_6S7Ky{i-k3{!S3(A*xLk3tjC)`(FpSAi=ChU|L=9O zc)9WO|Nmz|tuu}nX5hU5@rPI#8s9W9f{w;VUfSPspp-AXdyh&7C{Mlyjcb6mV}R5_ z7tMiff)L!F|}HtRqIT`v##u)pqGopB0{KN%Pp8H%{$Vt24IFfc?P5@2ZF2X+<6 z5elWU-R!#<7y=kT>y10xKoYG7N(@*T7z7wVB@AdJ5OkZ6i;75i<3R=nCWgQuRt5$U zhJfzN-Dh81z6>f)A=eXuGB(Kg-ZqfeyU*Dv!7<^?xI7k6*5MQ??`i$9-1IuJn&I-kY(c6j$bkZ-%scgBH^ z*YBJM&hhg=1wiLKP@e9b2TE-(=3V{&zx(`)a1h1b$<_(#eCZr_1F2@{_E+ijljsf) z=?s(Ubx-JYQ|b2C=| zj$U_@PIsQ;?jT1nbh``K{{R2)f01-|xJ>s6ZGVNJ?r;fD?Sq}}0xy)V{r?ZLvHK8m zm#&);nFl&wgTva9r-Y^3QRHxV_sz)Fcb~jnwxdqGu z%|}?DF0$`_sr|0Y#g@T}z0|n-nD#*r@Fjc_ogOS*KDJC&{!FEU;5Ch)nQ@S-A`h`J zKpfh905mP-q9S2^xkw5$nbO5$X~kd4ul>pII0Hy|X8|aFK<)==f@H@tF!vksZ)1b| zpi+Q;n;)Yw$o+2k-EXrRHrN!SB4B;GNU!^)_WLduQwA%xQl;+WsO~pqvhrgpQN?tw zY4Tkolms*qvdZ>sBn9e=-*(c83Xc`zcsoEECqg7y!CR{@niy|J?-svw=1? zf&?HJ!Xk@yhY4thbAaT!&;7s9>(8Qn0@@$z7GdnJVPxqPfH(^oDe>bcS=3-hucc3{|}?SiMNE$Nx@$ zk>(#vMY7%O{M!Whw>dC&`>PnUOzifT=nfYEXNFFZ#%^~GbaS^r%!P#RnKPil>F!%d zF1ig`MCJ~+fw{;GYJ&$O|27Av?tB$vpQ#Mp<)8yax-S|Z?DiLEd;}WR1m}ZJo@t#u zZJ?oOnAP40FU?p`^WhiCc@gU8Wp|cUxtUT_hVNe9pFOX2;$`E%LtSTW5tjZx3NmW51 zx~dN;U{woJkW>jkR55_fIu5oWA;p#9xFh&-@8eDa7m7i~@GumEEQ19ln1);?T5i#O z>jmRm(2Vd4uebmI_qKy7m>2dS5pV+%x|ia3JE+@ZH#AO*a6CVP&Uo%6L-aFpYefC#_kSIZLcJ_f%|BSm*m~Vq z;-U}7bwmnu1Pbl|-4GRh_+ObTgHO3DLv*<-LuI)uLr1wQ!{TyRc#we48|ltbk?96y zh>xIY4ruc=y!#iZzrw)KY{v;Y*tye1MS{OYgNcFRHE0951ZbaQw^;Kp4*r(yp#Daj zhV}hY?&ca54F>*}-Jp|bezBD}H2-2RvF`R|us*@xvInHBMn%D~)0d$ObgE(gzyJT; zJJ~?%rmaD(>(*qDwjUh)tp^zy7+!`lGB9YnGIaa#X#ehX0k1ItZ)ULmS;W=-6Lix# zsL|Wy$I^0=zXLRh4%%Op3o_ytTdA1wrG}r3{8J8PG4%Qgyb!Tw01fu5SRXHA>pl)L z4Wu{<Mj3bE0u5fxj_1oQ^U^(LDH9;Kn|E}1#!S} zHqb8PZa)s|gJqzJV$htn4rpO|0H~{@(d(k36A%Q-T_W-?)`RqfsHiZ8GIaZCXohhx zf|lLXacG~`^aFLiLB|122hFIssOWSvH2+|RtaoX>R4UwhvXsC12TN&n>+RC=*8io& zoqV7rIPe(dZ?*XM|NrZl?hqB7;{(x9Q6CksC?lvs zMTmw#M43=TTmP4?>vmDmiHEf0jeeQ+Opa1`zJJ~>&wTpE5u~?npZ+QpWef;wQe>3PZ($=@7oXw!Lb_Nt@KiK$N zZi9j{L`C8yXn_W3Tks~3z#(n+Z*D9NrMj&LO3b?bc&rbWF?AobK3c}qeU#BngOOd+ zjfeS$_KR*eL^^mKe$0)HvGqWyprso}i416?8z^)@=lwVTWGm%{B!UKOhSD-fN?__f z$jHuoL(`3;RHoaHr~9b&OOP#~jwV zaL}rLPzU)q$N~oNe6xzBn+9l~5xDLGO;{cRtpWp`-43dEtPd7(f$zw30Z-3^wgK3H zRx@~X`ltvPpX}s^LJ1cY z1JI>WexM;d4ecM{%qIdvUpNbbuUQ6VQ5QxF=J(p?L5EA`sDKs+=zu0HwU`(fK-)L< zK=eue7B$c*TsbN-FO5M5S$HyZ*QkINWq_9K%XEjRcyzOY(nt$v2&)@j!YMHDw`>8G zGe6i$Y@2_umsnVz9&B@`I1lYqn!6l`uZg z@Qaau%7I=#fh>mZ3ooqAz~zbvykHXn6>QrOIE z1Q=aZBtS_IDMi0r3CbmQppxy^0_g(|4Zj{pU+VP}2yl9_(-h(YNTPcb7pd(a{JA#hw5;*P%sk-5-o^TYoNPhZMhud;M5C^mEmD%N_bM5LP^beQUe z=wz!V;~c}OYfre@FDIszHJd-P$JkH&eGctT2cAJ)rx_kBfg+JJj42O2^ZA3 z&iIVZ_#DgmAQzSh_VzP?#&>>qGB9+4g?hK!uro011v$h*u0){MZ%*&T9?+T3H!K+# zI^-bs`<6b2I2f$1`+v8X_2m*Cm<4j3aV#)(PrLnjx*b`%uY+3s@B?0(-$(?9cE9RA znt1@^9nis58pfAEV=#LpPOvdBbcP97ij|aDgqM_B_4dyJ-RvE%&>1dq%)Ny1h5nlV z|1;k@{QUpF@o57;1HwnO37ww?2y3Tfx zKRVk%LDSg|8qw`+p8ztt9ds5=XFKTTZsSYc&fuvc&`L>AQ4PxPmccG1+TG3`+Tb;@ z-QGUZ-Cw|q0gFV-*(_aDM2dJJ${b2rKvPoPc^sgXx1b9sLHp)HR6r%PME6;3KMqjq zK|(tmRM07O`*AS)vGlsACe(1dc)I<;ha0^N|Ns9#$QdvFK+{z&9Qa*5B zAilE=6zOq?TMv{db@zeHv-GPew(jN!?M!C@ofA+2sveKK)qtpO{_bfYHK0>!TMv|S z#DjYfafcx~JKZWe{c1Y>RC@cs3D!;Fm|H1hSGYl7_qi9^pFqVFv~+>Fue*gSf*mwj z1Zvrb^={z;IjtLXL-B3!*k~tvXFLn&B9vH` z@EM%$R2Zj$GDCMCh=ha-c;6vtOI05@gZMIZ#XZbTU!r4u zs8ptV8Yrb%gUu<`>uv*um313PZ;2GBxdU1c5q(I40b;lHG>}Xw8^mj%)3#$llHl?> z5E6lqBOpL?r)!L2*clkQ=NN$_vBd}+QXwiD;l}?vEg>~WcLyjfgAT6*1y%D;#u8T0 ziX8B5rIt0IUePvCyQKrYds@u<^n=!om^8X8rZUN0{X zOI4ZgYriki$zp)O-o6>2ayPgUw05IpKPdG^9+Ci6U*P_0G>8Lg7l3xDbaFwe9grA2 z96=m#Sb>O!x&nq$iR0j~2Bp;F;IId=j=2>uc7+*)_qwqJ^!k;&5c&Wf4tMDe%K#k_ z(e0OG?I%&9-OUHCYP$Kl!z7No<$!d8QhBFaM(cr6c5ph6Kiusn(dm~1GR5Wts8~ge z$Tq)m2@NxT8{YlFGDjt(M6CPY3(cSZ|M&KRE0=kV44@54AumGz|Nn1&l)v>Cs5$2r z(d`%09TouIMC%p;+I!j=qT3osCa;;k3mh)&Kwnm&JY!u*F2E<7vr~} zu(9+}5h+cv%u$IbQH5C58=@lcVm-t<1(0Uzqor4kPj=?0M1YL3%u6UW>2}NM_A}`Y z%K%L`K@PHK?95S-0OcX*q3muc)@MsttdD|@=>*T}c7w|a&{6CAK(6b4p`D{5WBsa( z4YV4M`H=Q;aKli-GS8(%uiMQ-+by6w%ttybq%%Y%!1$7Nh)O__7`UpCDB=V4&@ICp zN?5@SNN_0!T6U|^>!V@-nkZ8N-S}$&swh;LPXsbw2Zi^a_uy+JG#GtUL>T=dAm?~o z5X_6|ZUebT`#7UpKxc@GiC|s`$PF^xbw1X0A>|@P9Nl#u)^!2pT%cpfK>6Y|3uyJO z^;P~>(8eU|v!xu?NBLVoiMP2%#eflV4zp#R1GxXD!r%HBR6*vb=z!Kz7lnen+YJc< zaPIB)v(Wy*d;xL*J-FD@J`U+-b6WR-vlUzCI*Q#uylsWbbD}g`YCh= z@N|Z$bbAPN`hoT}fOb}c>X1%16Yx&JFwn4tO{bqlXP8ZAoJVJzPiLHq_2Cks<8CgX z1OYP7qZ?$N4`?I+)Df`hbaUv83+Rjs>5Pl$jEm`vOX!SC>5OGCKG0mJz{uYQs#z@J zKuygsmfk*4(fHz)J_AEXTtRmjq^SuhP9W{!&Uv7!yK^3>>b3+oj7vo!+4XoEs1XWs z#S5u=@Y+s??hqA|&OXr8Sg#vPFKB7&G|+rncbH0N8)!YR=F`;uCXr`=F zu(J(x+RAZPP1KJil{)D?f{O?Kybtds&oekbOvg4JAnFe0-cUJ#s@kBL0g+S!eB>s zyI5Z+5jyS&@()9|QD>n?cMwZwpbu!>QTNBrK!;Ayq23{#juD`vy&GSEGJGRwJ;{q@ zKmY%a15c7d+Uq$gD&3$&0KVPFpwpG1`(r12r#q<4D+1bP11{OzTuL;dMWCOLv|otv zCF_et;^i#XH;M#7B`&Dw1GP>-aR`bb15jPlI}c>xYaZBoL-5HTZ6K#uGncA@N+yO< zInef#unf>u879ZUav+`EjKTjefHvxPgN3@eLEh2^6{s?xHaMtp)a#?75*XASmH}ok zUjP@ay)G&S;0kdg=pL~U6&c29AnS}zGKNJ6`o%Dc3;Kh0LMbr%fh%xEUj|Jd6#-EB z+j^i>r1cViYXs=9&6E7C(ES4jpeh{HiUu9d3qFsR2Rc~m#}VFL$J2dN`97$Z(ER&< ziG;SFfOMUR@onq-MLgv!)(6Yjx(|XRK^Hi5gZl&`0o|ax5PVcbj4!pG;N_MUxG@4<{#|*t)N9z#@|{mm5O!qzqoG1zz`h=K3A3lbcq&d+W!`)}Zs*G(KSA&Q`*1;m*!K^?(D< zpYEFnUke;~z}oOwp6fyyC;nq0`N!`NaQDH;+y?pH8;`@OtMrF`%~h&G4O|!IAFIy)~eF zAA5aNbY4uw!|vUJu635*2~&W7fy(K)X~0y5GN+ zXgyhf9Hj0q_)-v%8t_s=fo^Aq?qY-PYLiZHoo;WJ?hDEnL9IQ|u{)q?isoPcOXRyR za9=Euv_43LWvnagKBnxVqR{-~e@R+*wo7-l1858&G(0fu zh43E+hM?{bVWHr?eJ`f`WdI$(BvZ;}9ipO8!qI$;u{lIVgTeTKrHhJ2xk?e6b%}~V zG3cl$k=AdepmG>gse;-TBK+%}K|8%bW2&H`U(gXP67g}J**>wI!5*E?0nyDzVqhKE zz~IpCo88Qy#kpa-b_hX7$lh9iEoBE^lpA?Cyw{K8g{n3KLuZ~xXP!^<+5eymO7j9b z^FliFB3{e}wbnpm%a=O+3Oe%=I`dLG!$5;)y>1md!HG(s`GA0D>5txh9fII=It?_m zvD1fvf#LJ&_|9o9pmn#PF*NWpK+yOZNZoFbe6J@%H)#BfuiHNd+^c~Mpfw+3@h*K9 z*Et`g6|s~DT;GD$2ZZ<5RqO^?4bsowda^{Q+pVBGEGOW_z6b_}6=wc=s(t4ixyj6jc7c;MW3=RP=)^dDa+Uv{l!tf7hWJ9kjgZ0-^3Crw^QsHjz zoNmTl0t}1{|1WepXILLCIoMFo!cc10&EFdgQZ51tm=`sA3=E)-M->xz-M>g+H-B%4 zioy$#42XCV69Yq6h>A={IO{QY7RCvk`5c}3JfH%Wk+Iv^qdORM&XGW84tOsss8Z!gWb3OXLZDs(=x8_X51_;6m=C>X?sm=y?DbKR2n=}93_3jKgZ0cbgR1z3EOH_19*t$bhQaX*g-8qL8AXbh_Nl73mFs!eZgm(L=q;xZayT4|jlnKho(3EMJqvFHg0-D`;eHt>L4@t2g zW#F+c2=^F^0E0s(BV>dNBGm1p64T9?#n>C7l5)&NC57St1<>%_9gt4Y6fD#NNM<|( zTHh=KZc=K1mRPodN{;aEJ?lUvUiU3f1Rrl%*8y760h)&TU#bo&Vjv|Xs15m}^?xaE zuR9Z@fhu!IfT0tjx7SBSS4?EptMrL`r`JF|Np!FQ@X=Ly4@2x`_F*v zgZK%oqI3EYu)!xl^;vutXv;~db@z0TyR}19WI)Z0xcJyk!DvW0LdO_%K;y|Oprm3D z7!(>17ToJz5&q)C&;S1+E3P>XNiaZCK=T_=cQXKdY%pkofTPzK-)<{=gsW}_3$r0?LN`%BoMwI%z5AKB?2Bq zbdmrM?|6X@A&}{I((wb$gLiw$Xuk*P>~>P<4pQkXQ3(MJ2ZD}40`(t3!-CzQjk2H< zQVf*u9em8v8Ka`Y9HSz^zr81t;otxNwxA*1V(<;N{M+n6+pr&Sa9?)=mA2hK4!-B+ zU;oqkI)AeTI|IW$@Qp?v558k%{@8u4yF|qxt+OW%WJu$&1||kjDX7EHeY}*txkkl@ zp#)^7OzX)~P*2mQJ4VHVe_M(2PuGdB}?#c_hSOzs>N6=cJMhzH|VH60sd|B2On{8Uv>vA z4?;M&ShD;0ez0?Y9(>Qr{4=eyjtP8H;cF4?nc_z~|S1n()0coc!B) zj3MD6$iJqhis07Id6Gs0a3PJ0Iv|4|o~^$)XD{Zr-9JGcOXai7Kbe2`+SGN{sEF`yw+A(HVIh~JBEY{b7nUWi zf^C0s@GUq0`uEmXi{-kH?gi(z_XppyGQaPxQ4ulrQBg?i)bG`iel4zjRQqZ-NJ{%J z=pf9r&RT}v9BD?-Iv3{u-8YrbgC_QvZ!+HnotxBa69=^)Vz)48nK}P9X=rY|47U2l z!PngU>+f4%E|%>+yc=xw{e!PrneT(FW_}B?T>iC~_F?VI-5?q5-=Jf1(mJhsb96^7 z9x*|!{FC`7^I!h$JaxS$b&&K#s1(qGyO}L*la-6 zKj^YH{%t(k9Xxt&&Hve@Pc}dN*L;v0RPcft@Gq@685pz=YG3RI8K?a*trOy&m!MnC zP{hHG^{EYjcp2Kfk%M~qGNgHf2vZd z0K_Ix|6G878z@LXPDc+F{$_bb1_sRVjT7iCsS_B!AuNs=!Y>zs8taHE7aY7VK~vPI z=|cdtl$8N~zBM?Z^caKU1`^@~5{ndi3B3obxBK*KF;H;|Z`?zS?Db}B{0V9R6-{q^ z37Vw=O>ls^X&U@Z1)z&ZK-~;*FTnBOLw5e{C7MjkXCdyuS5^G8zK-Z*`~x+*{-t$R zGVO!r2T&&iB&z*At+SA6A1FUSIvHmC+fBG3#^dZ{fXs$>GC-y<|4Zw%;f8iHKms6R zO}N3GjFDkluL&sc^T7iy7S5}iY0BWA+b8CL*(EN{uzeyX^(>&Mx z@8ZkmXN;cB=a`!R^YJ$~F)%P(eg5fq`V1Ap{xu+OpJo8u2(h1sMUrq*9<2fn<%`aKHp?313bV)D1 z(7w?9>)?C&@ArF4${Ce^Fkkm9y#}(0f4e`^!Dpa_FwpW#kbfKY(7I`TxmXhB)SIB@ z^Ubu*cz8bG+L z0(S#IV%m4pI%WKu53(T469MH896b!2X0l*0lY=rdUvj+WM{_6l$L4?k`CA@NKF|>m9qW($&8tCX zfR5b-4ZGH;$TS~j(mv1M0$R>%eY%LL`?Ph9iiz|$9Tpl!((yJq{{hj$|uZ(7AjfzYck6wo_gRAxH(yy;UR}ENn$>?>+=)1XFm#Em3 zG8upKEPV@7*X^SsW9_4oQmhAR0$Tg1WE87(m#Bnv=cq)yy!Q70|K=PO3DCTz2I$QC z*Bp&5DjJ|pDCi_$(D}06J}L>I^Ex3(fQNsZ9<yvrs0k)6oI4l*2*#Kx}8EOJ|^sLv-^IpF=zhp!-Eb z!$1dKfc6w|bi4C(=R0(VD|DBGwrB`+`7?p{V_bd=nr`)0j@LN&n5CCTn}2(Y2WT(~ zw44{T+yFGW&cIl#23jZtI*7iACmuX~2fA^TgMoh=$H8YDpsw^s(0H##_o0I?xIvS+ zBGw=Hn_EHo?*eEkC@Xkmt6m4R#!sS@t+`%&+r?sx(IZ86;c zcY-$WX`Q(Iy33ytJi&VT0sl6B4`p|a%MX}uWZq_AV_;y6QITl=%U+xat^r~DX+gW% zw%d3>9V`cPFn=@XAV2SVJMt10N>kq|j-4~cozUI)rp#7oOhZ9!KZFmV<)Ct-o z8*gBJx|p@wUF0>B@qzAo0qx(+Kl!)Gu!Bby!7hNT@61t==spe}{#IZgktipl06%?GOChUGgnJqRb2o45+4qwsr7t zvxJ)d9b)<^aBt}ZD1BIeEcWfLQBmOEzNP})HM$7x8Yy(wsAyQ%s0i>kxBUJ8AJn+M z$iI#M;4=>HkD$>?4bW9(-2Cg$f(i!kDZ>|EJ_fB41YL`AQTrqRcApH;iauBzNI}f9 z_zMbukTKx2i)@mQiiq{cVwUcUukHD_=VWAPU)25x_YBw}zyILWd={#e1*8iU$e*0EogoXls8_-@o&!;0GSUr z$^{fWsbHhfvLhsjL9PF8s9p@g^7QKQpQ=eVN_X!VAriwa8# zJCp-C#KQPMr=vutqYsKY*y0WFd?Mt$Q_!sk`rV-Y#0HQB4vE`Xr~RQq%vf*J(UEd<)# zirB|0a7ciGf16t%|2DrMP(Sk^|2Ds17$XGC=yX%DtkWswv8>Yot+e^`e}D0+#yW7& z9d}ds589Pd=Tqj&zl{xa7Djg+2lI&?pkp*HKVUt;&cIM2)qP?I=u|q;`Ljn4J{90T zdhzAw)xsy!KCd?Z4_ZMRX3-gD(ivvZS?ADM2f9QnMn$Eu&IKGmEuElk*X*G7Flb>} zoeQYN)_uP9WJw(8!io?T5$y}s7mL}tPqkhu@ouiu0qt83W9fdSou^^_vYfdyOo!1= zqdQEbJI_G-XJ?&Dcbx!e$#nOB>!Z?_ltWZx9JH@8U-#?^Vfx<@!v4SX1;~OZ(dvW`l!hCvSVuz{dBthWVBDW{;veJ#stcw;*YzzfRbEXEcjGS zXd1EpS^5mLL4x@vBNr%1y?hT|7tnnAfAfElV&!hossPY3$p6+aiv_wwG&(};0^D7j z|BDp8d(8@>K=W`C3?+`eAu2MxZUI5PJQe}n$2xsfR9?*d2Jt88_@nL^6&dY&&94Kj z<9zs=3jY89kL=w(&>qt|9q?+%UcZ1&Kbca{g+twSVE?|-esBGvjJa2YJuoQj#pg%Z z{n{PoqkXRVWkBogO5x_8BK+;#psf<8_?wvj|NsA*!}=zF>(77x|7)KDd6&^gMTL>; zxEpA(6L?uFXd|XRBLf30A-2|lis3pH2L4vi$O~w?7L=1fH2?#6cO)n$b^EA*)~p_9 z1eIwB(GZ9zD0-39xTu8y80ex63CnQMeU9!DplYr= zUZVSy_G#;bpzA?jv-gTHgWL=14Rx2OXaoj;_x^=-pMQ}9swF^2&c6UPm>3zm{RK2# zR799TOKdc{%O$iwGlOQvWWoZ2U$9*PuNpAWEK!kRG+@35+BzMhBGdY|RJiq9iL_;o zia?1dr~(3?4;CNSeH3)WnE=w>SP&cJO9bvd1X`gH#?gJE+X1}o4b+}s059zVD+=rW z)a}LsIutPWm_{a^=9l`wD4$VY6RHH+1 z=J$Vb9ga*LfsDonAeA22r4RzNz72AQNIp3XW@KUW~WQ?ApG1+>f-v_^u1AwC+s9vOVd3dZ_6boZSB9n5G3pq#4jidEIi3;3>c^)8-i|qK% z&%n?Kx;M?CNOZ^l|Mm>8rQ>6foe7e3U?^hU0a}OJt0VFKg7ORN*TqcTue-wpz`>Iz zQeq3Y798i@?A=$vhqt+b*6}KIhjBpVqvK~2v3jl6b)4hhujUIR8e6x5*r ztxd@Q4P1Z+F?v)$J6u2~Ef@rLUj}U==!{VT^@TD(ZJ`$%K<7b*sOWTm=oD}LR?692 z%fMX9+*`ob-2-+^H)sKkBg_8_-Nzs+us{xlBvUxqeB!_HrQ?jCwThtY#RFM79Su4i zO*$QQIvo`{9c93+Igw6B0r2(29G!t0oq-mefi|!vUH8GTZiCium8{_9;>{H-44nq0 z*3JKz>v?;9%ml#Augi~Kt2O^)tLN$U6NU+h8eeMu$Id_hkXPd)1_p+IjfWT*7+5+3 zSh@pPj89s7m=wvCvswojl!kClJ!!A=j6<_ZahS|Nz-a}RknKYGx7$e}Yp zqPaqbAr7R{(nExQ>cLJAndS-whFae40GaQ%q%SoeV(ko2Xs%FUC>8AvkT5=J=^?{E z<>19v&4&aozv>K7X|B*=sFehnQo;?g6uhFPloi~Q@AS}tg;(<%hp_ICkk#$IH7cN` zvY=vOE2JXh0bRN108Rot`KTMz*MP1~YW-Hi9Tpz^qUHhv zL-P?HcjkM||HX>#!VYr+-A8+{+e4?bW6vH&hOqG74I5M#7x6qkh+c#5WC|Gh&>?!#Gdd2#O{azu{-{N*b@>!>&1H_(S0b+N| z0kJ!5K*Vt1?ou{(VBf`V)VILHF_GBWH;0Ieop z+PlF(0UV0^kc2iUf`kGNFf!}}Z7T*xkuq555F-P4&EV&y-5m=U7#Mbe%jZYk9s$gk zg1RT{*u%&W81y3H3^*-7k6G(J*bR>SP7fVW{DWe?cLyjHz~evQI3q*v4p1t93Uz}c zzcaw18yxwa9yZIH6z7w1Zy1_Bu2~Gvw;F#|O zr-E*9%y)uQK{q(&JHe@-8yxeU;8f5Jj`>b-D(D8sd?z>+bc18Q6PyaV!7<+nP6gfI znC}Fqf^KlkcY;$vH#p`y!Kt7d9P^#vRL~8M`A%>u=my7pCpZ;!gJZrEoC>NA7?*ylUZg9+Zf>S{^IOaRSsh}Gi^PS*S&<&3HPH-yd2FH9SI2H760L6Uo4p1t9 z$NzyZBS;w9{(Mnm1+1pA1t*@-6xuVu-35d1XWp}yMaKB{LXGrMQ?nvxkkl;v9lR;DhFt&n}7bn_|9ep zCI*JiW(m-##+{QFFoE}UbZ-Dz>!ae(*{uSS?gov0MmHaEI2<1b_5_#>DnDIRSit)g z8gGD32bp+>je!Aq*Ftlh0Yj-)cbEd`<|@W;P}l2M`2P#mKR`RU4L~cZ8S6B<{S-R= zB$~r?7!VuRL52I7GiQQ97r=+{gm>3*bRXZS@M6tL28Qk%-Nz3;;OKPYFh0=f#sgkv z_P>bV`bH^tvzq{8yr7#%T=d~C(4FxTOs6|I91gyh=&WPubd#`llPP6=kpbEs7AC+Q zCQ@S9c=$i0gAE(cc9ZCkaDXed{r~?zW1T>^n}A@Q2)CO^>3yWS1LQ>T;%|YlZu7>o zpbBFGs1enD^xzB7RE}dWi(~h-gRi(jBl`U7FL$3k_>#T(A!GN!?>Ce`C?C@P!2Fic zoddMB>;!1DnCe4z1_tfJ%?IR_LA^tt&D2VUvQ)qVWnGmaN8{{8;A9{WPm{J)Qi1jy3T&iGE_xY)=;JkW*W;LtmBrrSq_1$?H_k8XYb?Tp=D!Rxy| zfJR+7x^MC~fm-$2?-yu=f-0&I6_H+-PzL_(BF-TDx{M&t;S-#&r z_?G4Sje{@2DgP}0_H3qZo_^I2>*6&27eH7+Wk zz4{ViLEU#>D1#~q&>dgXVt% z{B58Mx5I!wKNpyq7% z!R7~y7hm#kpW_Qk*57X&d;u<#9@HD(U>2F*{FABp4(K3CP~HO#WuE}~iKibNZq0{X zm`{O%j^{Hd=ni$dd}e9=RyqfC=mf~S-I~2RYY%|NNPjSv$@Xpp?Lg_R_#YY^_QLxh zxKY#y_MboKh-S#p6k6^-a|To$^L4v%{C6`6|9_#IuhUJV+fAT%S^_6{t7(V|&wkJ~ z4BG#CZP*X~XX> z>uwO$&DZV5^Z!Dx$Nydy&E~WJwb$&6;bdUwHIaSm~G8cSVZ3b(7z}n5Cp?#zETZv`!O9lVtR|?wqIvKl-JUX4h1bM0Nop` z&>gGM8Ka`p{F|v*BJOxA$Y_uoV!;(jbn}stLmUjyfaU}TG)Q%~FGII0&;JWu9{)ir zI4wYnRXcoCKvy8!goEnWUYo7p@zM}|i|!NJr#eGyQo2G^gscQhy}JS!tpXWKop*tH z-PX6tq2`%_5C8xF0_binPzncY zJfZEQk^TtS-F9jepa0~xN0)#?7I zT13sDj3-3k_Q2kqS~QPJr>eefX*^Ev+QQ+z?aq=T25RIQer6ah!Ke|w9sfdc5(qMlgL5ClRKsDx|j1#5Rv zaj7nPjO z-V=Mk+ffRPZy#@cum{wFWMJr=dIpqJTQ7jf-YXz7Mn$3fe|O28lIDL*{7s-UL%Mx+ zK#m4Ew)J+YHYo6XRCEr$U;zaR$SaV*K!gMH6mTHCPJo2Z3zlw(0LT>3Xi4*L#!?Jo=KFsI3uN{2E+PkNBLj?mvZ;KYFMC$(E&Cl$k;$!XcrI@eNLLsSg9g}S%2rf@PaFkc2QFLVFb{GYXm6@17@ z_r1n{pyI7q@ZbaX=EwEShnc6e8i+A4ytV>0Y?v58tI)nR9~8L!8q_d5*nN(F+Z^o; zI-pQ-?g5=H;L^&_{E(lyrT2p%IAu66gO)pKSO zDKF>_AQu%4YZn!j5}{@n6$6&;7!@D)=7S0^J^%mz4=yJ`bE%+nBl%l2co@L*M>Q%6 zjsHPo`~1z@xxsru9Rj+KzWDM3TnZ;xyBhE}f8u6f_zxYj{tl{7dh`zLVPIhX3c8V@ z`6pwk$-xJ#&HF%s!@$42MPtt%28L1r{%tc91k%y`i?P(G`6r9??eDjn53|2k>b`LB5i9@pDOw=In}4zt zbMkMSC6VgR@S2@}+bkZa!3Q6(c2Cg&WvJd3jU9U!7(glmKdcK}FBL8p&OPPdCnO1F1$MMUOOCjQLzCPkc}rnJ);EP<_Gl$U$Gd2Qo0Ru3%J+^?fC|^2rn@IfViw!1DuMDPj-SG+SvvwE|0gt z>VmY+zI&jO(gn08cnVT=04f1{z(z8I7Kesv?D!8Fif~Z@UC#_UzfQ;cLK*1pX`SZZ z?8TK`E-FG6E-J#M`Q6h%!DfA`IJJ2n$S$TL&gOj}>ljLcK{XDj=mlL3&A)w4EU3Um zsxw}*Ft^MF*BJ+`4;8C+wt-ACK45(EIM~&odEZX3%aL5&T%)4H#NQ;z!NAa63Rq~q+UNp>l0;6-6z0H;H}S<3H3TLYu^I3K$%O~ z+#IYw7JUXCNW{Nw0x07`Qz!rSIpD&!`_RD$po%6G6b6pUzCMkgLCF!+qfxQo-`?U1 z3J+MtaPT!KbZxpJA<`YAVgn5v(1KY|;DJ&!#DIhFfIIk#1)31LLsS%)uQ4CD3{ep& z2A}!`TJ{Plr~R1Eb@zZPm4lC1nNL{vXn}G-?-VdqEDBCAom`zo9LJr&(?e;UPM~8M zBtYj9g3=^trz0qRf?9d6`9S8regX(#k&(ak z9uot@K9DBsdu3w1PE6XTKXzA`o9!( ze69;9SAzl!(yszlWRRK_R2f4m)z=xY!0d(yfTL!6iz~R|{tvCVAyThxKud!8x9_P1 zRo>u@rrI$oDhJ<#`&y6djekRn3{ddHjAh;fsl3m3yQugu`=|tD9spO~E-Eq1$G}y0 zE2!%3^ii>ZR^OoYM&isDtpmOk3v~v7mRqQF3K(DNjQEq*8Su*+T7&;)D!vIm6rq&8 z*NqXBr@LJZK=o{I93%7LPSBBukYmVvR7{!=Gg;r@Z*KxE@%2%W=nCQf2U@sb6~g?F zzcmMxo3+d_=Mt<;Ok zp|Do!qs|(YkX~?+*~=5u9U9Qf;{`f#BI3orH~;^4gGwM7{%swg%B9;yB?8o}Isu9w zP#Og_1*d?^RM1Hp%;%V=fRkRgkBSBJDF1?&R;?R%r-7#N@mkcErn7#I-hm`{NM-a1Cbq!_d^1hh@rpw~uN`&5^>l?Z<+ zhqF6KuIQuoy5x0;B(d?@#xKbxVr@$gUl`}76%`)TDNF|b4m}GDi#E< z?NxE>jO0k`EM)6+B`1@H)pApg}FrIW3^0PA--i7$4}qXx$5HIhBba?#BhS zr+Q%RDF_47E^+8~QLzD?o@T=gZqvwsLKM_!>y81pD4{J$Q2E^Hqmt0eBZcsQ@ky}X z!N!&eG#_NLZUI|d{sko7YtswP$5Zq{4KmO|NJJB>`_tujpyNsTw{6h_x3G9XM>BXp zi!$aD2OokC1hN6`1%Q+$%qMyan3)eBe8Ae<18)8Gwtzd-psKi=li5cl0n|$Db^G1? zgBjM|yVdv$t-aR+Y41rLe89%+qT7!x*YWa$E zdVJ~i``hX9r`L<6lf(EVsQugP_t&~d9~8X&tsg;2-9<%0`%rhNL9dV4KhUil9@eMI zn7Tnn@2FUR5`GRk}qX*a<{%%^d58~EwtkAjWPPmzs<$qZ?E59O&{>7brSsBLJa>Z$NF@J zsKkKSf0#k1rh;1t%Ap>RoOSsTO5RF%vFIiEv}YOqZC#+&8Yowt2K7@wxeBx*3{l!M zpXhaFgl44;(5z%YTvh^2HDk$2pqXQ|tOP27RC;|3|DxuV?hq9fNPh8RK7`0G2AKIp z44hv~Is-X+!~QiNU`gu?1ZNr-6$?m;x3G3maVQDswSino*aA+TwxEjy!5sil!3XLD zyx`w9MFX5RS-ik!kh-XNfJd`@RD2pi?IzG7zk@8z2Nc|1mO)maDS#I8Dp-TYTwATb z{Qv(t4%|oS-U80az3zY*nPvH`4HHMvNzqAwXc_O zgBqi*B8;IX|1W^LTd%pgLDOTtDxI#N;SG`Qi=Zl?1zf9w)@(93G`~>rEdA2$qM{J` zBK0l!tS{&=40xmpLV(WiG`?*a2N~cI2tE=y+8h6;PEf(Cr2~ zK85Fa8)y&&)U|K^!BorzuD_$3k4PMb%qoJ8*5Uz;tH8$5{47E}Ks|=e7!}YdEIi?$ zA;<0$+FV@%R)VFD&`}&qaPQT!Mn$Ady8C5s0F(9$@cxP}E-N0bQVw?~>lzi2qL0>f z2F3o?H7YV?9H2k|ZOmzQQ4wHqZvM?uvBLcK4J%@E8mqXb8sjKckyT zx0^^O_z3deQ1I9dc=?;eVUR;bdc*%ShMDw+|L>d!_8w@21~fn;aoG4a=mgW|zf48R zph~N|XBx;@(4wQ}Urc2Ny)Dy1I2jnaJ^naazbusnZPo4OIQX93`e&Iy^DCz27aYD& zwdJ=vb5wYm|1y<|HP)yIfQqCd(1sz=)y)SQU_$mCbbtxs{N}$*{7v5(z$eUzF!8s6 z=8JplRKmNDz1Z;T|Nl-mh2|ejMIPP!(C`A;W__8z=?DV@L$5ER^}$kp&|W!q>)-rs zph;QlgZ$uI6+jC(g_{2|7x8uAuY>~V zbepx!hgl$T)%=&KL;wj|7nZmp4BD&9mXSGgf|77$_=swXLmcnrGC9C#9&_p6=j+U{QyVot^;B$@_FCPB? z-yH@T+6elAE6)wvF&(@lqeTL-9!4bEcdod#O# z5!CAz(dnntSr_p_=IQ_c-E|S*Tm=e`UKvo2-59jo0Jj5M!18EzIX(RUzt@?u`G-T% zuH8}$3=H7>bn!i7T>{8&XsSgX{{Qb?`VegIYcA;IWUnU!)P4gw@Hh+ToC9b8T>u#Z zonC7(2FatDc<2Gteu1K0opllMvEZr9?#2tCqsR`FhFUg)=ITngj)O%&Gx5zkuYl4^ ziE#5y(3#B)Fgbr#_J-!2XFzRvm=I_f0%jCQ40O8(sK<7=c|T}z0Yh-u@phP4317Fn zkFtvjPxtp1fB*jf-&-EB8?-n993I`rUPwLwdHvgqi}%5ou}1y>|35Aowr~_QpB)+& z4oRdP0z#nS#}!7Pg+k^3y6-hVX6(M)e3*$DTt@J3pTi6ai0`)=AA!1B##b-CJNTLf zJT(P6gcLj})%>*H_%5iwJ7og6^EqV(hytZ^<`@-`i|1YjZF z_zdJ-~AV@DP8+e7pG(BdCmrnb!U4;A_YXBE+Xi z8gB7#p8^T-TOhk2Ar9$6FyA})ilsC1MK?5Jul1HQb_R05+zv@Aupqzq&iE?WA1L;M z<}g7$@f;OomxDSbxYA1VGgOy@(i_6l$Z>=J=lO;}|{wrus z^uxs$AdiBWplxZ}St`0A2@5nV^|apjDD#{qP%8KAwW%vT3p(u&)an5pMG0CC!@r%U zvim2r;|>~(+XYe!?!tG0Sj@lOm`^jm=&Wfm>GWA+0y?m``JV%SljHyY|9f3jEVK{x zc7gf^y{jz57#MUxBgMVDKm{^*vuutE=!iK1&<04*f~f9UCm0wQoG-raj8QS*Zvm}p z0&N=E0lGD**B{g_)B$Y}0}mK6gZy{m;tT%mChiB{u{1wq1TO&rt^fGg-LnbgHt^x9 z-|vCc$bi*6t3UXf#rPg`&n&n!MDqJRkP+z87hiPW=zhV!oy8q=Nb76Wz;bdRwll z?*IJT=0MVy%uLXhr|uk$Kg_Q?LHE%Mbn9p^zwXRnX+Fl(e1HQo=3jIkbcj}Cj*0+i zcDwN)Xt=ZSD2UzszTrRUJZv8oQ1TPuZw0Lv0xdacJfgzHzyM43p!Is;#{YZg6@X4Z zINe!S(^*&X;#(-_N|PI)WIr#5iGkt8)TaOcn@{}j4N>9fK6l(jg#%RKbk?Zobk?Zw zfQ}>t4YPoH7@*!NXf_oz@DEy;4q7GvS~mgSNK&I>0Gg-ltWj}!aryfH|GjOXtn{Me zGKdL^{};Zu|Nrl-3+UVjT4ERvTNDS*nGm9zF>Kd`)1X6eyFavkD`9_O4T^w?}JwP5X)cmHi7q6wJrmV zu<~`gfwr8qfz^Uqu=_w&IztI>cN?e?5!ZY~<`4%%_qi9#Av@1n3pl`cCav26T0D4` zyKfHz14B4yHzDYj82(n!(G;M2Y&ia3YCTXY6x#jo#o6!w|HsEhLyhWnQPBYPfTrIE z9TU_BY8-aQMfBE1fKN=jfx4cj4;M0E%7d)n`F}~<&7|8e zfPWi9K;Vn88~^|R_cMVUx53vP26h2|%RF`lhUR^s6_yMo+%F10f%{z|uPwX%BrN@8 zN(DjdIs?L9WITXMD0D+Qc}Addq3!^VZU-Jm@ODgamkf0Kha0G&Bhc-q(;XMly${rr z0rlfS>xm?Kr}%+f%)gxr)L`f4Uw^Rq|9{ApjgSL)K<8C3-|YU8)+q&ALCRRnd+-5A z_m5t;h!@{Lce8_9_MLSR5TAkeF>ed_-z5P$kMg2&m`6AGDyYkky8QxrMS^-o0=xZm z__yr@4NP~|>Gak`H2-8T=I7sbI3VbS`}P0-U!G!RV9<86;NQj($iMAy(2GML!L1;{ z8;ouV-3P(#%NMNLC(=5(pur4ofIsGVkq&Z>pHA--KT!J{#YZgs&5TS84B7dnsP2hPsH=UOcL1zLH^hyNCA%39#h#zRI zxpxYfg1g{9W2qRXJ#IFyYq7WrEu{Zm0sE1EdrKH-q`G$sm_iuMgw<$=*D_d)?hbPR zZ66ME>Gref^mFJ2ZJ4#`bhALSvg-Oy?)1}nS-{M|06B#1CFl^9m!R0wLXSOVh|fSH1t5#I zHGz6$oo+gyYnPf2{0j_#bj?6(rNEXogDrFD_Os~@v-sZzYUVV*XX$iv>2+u9^m731 z0Cuxz{158Y7xQ)6^Faqt zdSL~%5TJvX2OqHa_83508!FxZyIoX3VWHA};ovJa{_Q$}pqzH1Gekv$`9SyOgRi(D zD`q7QzGQ{1^u3{c2%H@t>wLpfpvyDiD`qu7%QJ5>9|d)EL0iC}9o@$qFaBTp|G%+D zMFO;~r>M0vE&@EzEC{OkKwFm%U3}pI^|4~}BgXC%&8L_yKMD`%jf?1Q2?Mq50$!}S z`v3pS`;5@bF1z1rpJ+bIfB7kBDYE><*WYg{pJwy}_eYuEqNRf-kmaE3r#_TkT^Loc(MCEXt5t?aU|Gp7vD3wCG@)f2ZaKt)absT9HOEDSzQQQAbAV4K(Y;F2%0t0 zm%xi8LG>>G_7*pAZ|XE;Bmh(&BU^P)`v%OaZgBS(*D^^7=38l_K5j@B$ z0a`0bCo8RBR_25UFze>NOY`5bC#p z)~kTkckTlz3<`Xa1}fZP^=ye1s2a>K+&ymw z0|Nu|JkaW|&Nfh6%lc}GfaN++o2`Vyavo@#Qb`Q7>4ws{>&y%21S{)i?>-IPY1)0B z`7P)wnNGI=*xt_WumIz?ooyiVtgk|D=muRI_YB+=2ASSH4YUIVH0#5_$UpsHM_(W4 zWZqw(o4iZFx3@7IC}s2lC7<3dPzYF`C}z_Jt&rt`wGC6iWuBh_=uB~e4A6NBfxY`~ zFfcF#bf14QrySB?1YM)vxDR9%0|NtNr(KzFJzt?FPPP4`N3^?>(uu(Ju2qdS{SK-<}x zEWo4E@09FO!|OEuew03p57)6 zt#d`gzyJT!IyIUPFlm1;ebxOnt+Vh&8fbx2p+s6|p+WOOCe0cZfzkur$N0B@=stGv znE>}ONG}<(OKNrZQ4|UIUa8gHUEn0z1xljbRRPdLH>?kriFcns)&xIp10?vO8*&B* z*zn$6ph48ntD#|sWW5>#bdw%T4qcxH=+YQWeOhpRol!EKQ4+mPpcXf{sTO-2G{E7| zd;mPT(lv(xdSu4s2M~|!19d6mJvyCyzRgV z9_WUefFMZ8`6A^as1FBfDg{Cef)%gef-)%lh4aP#|Kp<%gVs~`fwE2bF3|lIJ3#5n z`b3$@#RJwS%H+VLG?$QN>Yu@HVOs_eb4>7-HZaxG$t6rp+ zMW{POg(tAH4Kxk{%GSpJgF3+-x6XZ_UfT<<-~azxA1{^azV_n%pa1_~{QCF*f9F0> zLD>mfZpL7IAU+PU%)k3!=Y$nZ3=GE`K)pavDFX;a=ZbwQw$W9FF?mF_ZJSgBr^CSia%{mUoI+o@mJfKCs zhmiKx!1O~Fm}|S4#2r4<{6+$_P6X5qR{@#L9d7&|bevGZZ}1^vpcymJomUE-`#|H` z$N_16y@b8{+Kbh{|Nnon4K(lA2CA33r-4GU+phvNfB;&W(FxjF6QUw=+znEo)Wvkx zC3M!Mbk=2b*5!ciSlS1Q^Ui(XGG!mAOz8}(u|8g+4O+==(e29+2XtXc`b6k|5unITH@L)VBNB3l@-m(0wD3&EUkqP#VyB zyTqj1tpHT{f~!>Hlg!}SSQvb7B(qzFuwPDKKsUG!4eAyS=speZw+ll}+yuJ$^hfLe zl69|H_k*r|fz=n>(6I!?;{X4CXELy-Pv3)ax?SH+y*jfk;_SQw5ofQEOv8bO6Y z*9E3aOqZArF*SmUweaqppv(mo1Pg;ogAP~l;q(d&Mbf?Ppc56q_j*|$FIMY5-s#E+ zs+10~Fof*`-`I4l`2l11x#j~*7hhg};AVZi=xrQA4aj*spqSzb3s-(^{LT2k@d4vY z&42%wfKG)J>Hex+$kF{3{~K=)T!{#sZ2@ z>)-sXpqOZ`6JY2T>%Ik&FR1`6y=$)KVJH;_O?5N=ztHK-(|Vv3ycXG_+fSg|nJ2Kf zMn&R5qH^4VCiGb!OMVOB=ziz$=x_3vX6Rg7c zr1e$)DWKI;Do`syrx*E|fG4LFUVM`Pg-Z!PXv!5-m0SNVW$vx!>23oT8ZIgl4xM18 zbsMPNSj5&j4RCG!#dqo_2d#-`+gn13>po6q={0D1zEd%ra3j=lr&^?|4pzuHLW&xr=o7P@r zNP=9;-wHY|t=mOK0dz>w9q@9=(yU%^O%VQHw1mN(p?e;v#^`RD2Wq&6cY;U#{)<*H zxHEvFv4j(RUXCLVc#EkDC@+JysCCzYFP^dJ4q^%H_R|RHW)J>FfaqNhdgb__xLA`Ly0HVL#@g z=fm)txiilLt`Fq4UO$r;s^B0m^=rLdqShOd%h2004dmn2|D_z=9IYoyn7V&Ul}XV?Jw}c5NvX3Xt%5fgF6GX z1=?KC!BFZO{^AK}yQF#Rff8Owa_zqG;vx&Ep9m^t1O8vO1}DB!o?btP7aZasCzkSn z480=?VwdcQkAt}M5DPKI+3CgsIy!_Iz2d?nh!`c|8gjL z*6HWa3+^($xFOEK(Ax*v<{tO*j5q_zhE~wUQyk%q$3T}lfqTl$b_^wAy?%d=yL|y= zm>1S!44@%y6Hx|+UcWyt?ualjbcg+Dy#%_1@J+Xe0{Ei9<8Gkqk{OzhN%)uU>n>5@ z>Gd;su~7u1#pK0GFzxVSp$MozM{AIPhW^7|l!1yj+X7IqL(~5C#$zA{hyA~fyn7k6 z|L!9w?}hjJ36!wE*eA-s@S637I3(sYdi_K?-8d{6OZmfg9bj@}cyUhz6#Aw7y?z2O zioh{Z${ZhexQ;^SxK|7E|tPhv5feP&I!=R)2 znR|U08N1m)t7<@ldMw4PphY3j1DoM&2L`Bk^G}~L(4r&(AMg=y)^0i_s=fQbQJA8_ z&@FC#wS)^)`hyPQ>C|sNF5zAJs+$jV&|H`dB&~Jk*}O;rW$QeLUO$Ht_7}%Rz}{96 zWni#AS^~ah5tGc!YPUpd>a=7!<$!t)Mo1x1Ym{JRy)iWR=}N ztpAoubl2Hf|1A~l-p9klz+nBil)byo#rkgvTiA;~pjE5KLGx^oxn<)6or0Z?9N+_u zSiol*i5#AQ1VC*!H(!vq4l-FSk!!#Dzh{tLDq03GeX0%{R< zyRpQf=$M)URH-Vt;FrI*JH;$kHRIAHa!XZ@^=y0b)0t`?;pxKY23gpya zkb>@8NKORVTFTrR2Qv?J00h*q2@@tjPF`!hR3aG$J9mw}+o;<^$mP}r61zr zLFU4AfWt4Q^+2g`w^+BINb?~9kh4pf;tqGZ#WWufKo2jl`7y1RO2oU}6T1CVtPhs* zcKd@&Kkgm_DgcASjKB5H2Y2?|BdkA^%XIgH`V-b4i`cr4X&-#eqJ5D0m}NVtcTvvX zefkCHSZ258!y3*16pGGvgT>=o4@8&pb^9lDyQf&6C}lA|5PullvyDGI0n`xu7~cJ= zyA5PQ>jC~2aQ_C}QD{EE+RM_=YjdpIm7(=ONo;pGN4K9yx77bYmTrH6Zg&yx6P@uK zrLNuQUt9(4O9LC>(FvwXO1h_k+}Z6H;naPo6U??gSju%AY%<7WkfA}49U=|AHrKk{ zd0G#Ya2|ID<#dMEV%`2C-SGn5Y~WkWIm%hA50^1@AMP#}(EiX_F3=q=(tL}dGh75T zW$n%p9~awvKp^^Xw_8HDUyAmL5^>O_@4gJiC*wQ)5<2}-;$nMUm;|B^A9n>=&CneN z3Uc0VKX5?1fdd+H05@`6g5osH_#5ctK^BJ2LeQFx&cc|^!i3Jkl+KNy@ailS=qwcJ zER^Uhl<6!~Fuv3aUToDF@Tb$`N2ft&fkW86zsK?X>Q z4eS2+0(4?w<1vs#*nd$_C4rPk!0B~2XcGUpn+mv$*#}Mw=U*s+W^9jZc$a?0?we?^ zS3u^27jvD9duj0ZKd3Se?{<^ut&?ayP$J&zr|`mxA5@LWyfESiEkS#s%?IIL<^|CT z@o_It@kf;tzFxu!iO|lv7*GYH&>bew+XpJAU$B8%H*OJ~ zbt;{88oeP6k`A425xqLsy3f9-2F+#Pu)bev((9}6LKk#18i=RX>nrm@9>$XheX$s- zu0*l>9H=E(%)r24eZP*c@iC~XZ9EOCYpw5>Fn7i|Sk_sT@>`aslV$iUd)}qCK8oKbaSt5H>F)Qjm{< zVM17V??zBK><5KI_qi83|Nj4PKBnPc`Z*q~KD7HySa&H$w;Ky+^W_0%l|L^sn;96o zkA!u)sl4C=Ejms869?*4L+u9-wRE3<5e)L5J!la_x4TA(bL)Xp=FW1B-u@>H3=GHJ z!Ab80KPXM~gLdA&VBuw80F{4rJdKaQ0dNWw0KNU-;GPaTvEmqb`+wsbP>(3MTQW4P z(?><3+f&B)TR8acpb{0A&Mn}5@SPg#_Xq3mAW{AnDbPR|Xp+&+`gjRTr@?D> z(4bRi0Y|T!fHmk2Oi=gQphUIXJEl80q5CLk-CwVdAjn}7ojEEV;1w%ADh4lKgJMCr z+nWcpFbcG*5VX@F;05R;OyiTF>JsFoZWk2`<_n;O37`ej!WTP17o~@&s90Yw1?@8P z=nl?czR($*(H)#4e9`!1XK+rpu=OGE044v_gVyIkExQut&fo&jQR>#`OZYmyJvxI6 zz(-er&ZYJNACuwGU8CXxKK52Z`g-RS6;Sz9%G&&svBQRo{cceKmmr`+ zULiZ1I;Vioh6J7D*b5bDQ30i~Zf6N_2h>~Uc#8@siGj+-{{r1pR6tF#?iLkL=eqe9 zXsbbEs? zmGEIcVf??-JHh%oe`_ZLr2om^3Od2k+C{~p6qImPy3MTLLlVPv&@q>9JF62qt5aT{ z`it0kEYRtqQuET75jvs`P8b56kdrb?Kv%t5z+H0?;+7L&M;QNy8V2fwfUZvkU2*)9 z3$!od7c=-OdGHVbXb%?nTtw@Gpc5EMxuLp1CrdW}VlH(Ag|hYu<_p&EJEuT0o{vgF z2@5FefzGf1B_?gqiR3EM*R9Wk#+5(`3$m=I(?!MOb&d7=5-#xKsTviD*9qOHU+{eg zk2Q0FZe;B&QK@+y333GVEKtx&ux`+GZ>RQwDqZcDo!%+Z|2m67AqrY|CDHw(`ylft zP+maxZ8s!xjQ?BKsHi{^G-wHTYFNSNd4P^1)&ONy z>*J+nmNhCiC0d}=SE>c>TRTg12eNc~%lr>u0jE!u5*|>I02{jksRZ9}4hcq3>Z?&P zus+^dqvBJV)9oD5?Hyu$u-L@1M#ZE=4^(~h@?3sV!~#m~rL6y*BVJ2(dq*_?WGv+a zWi61=plfem8+Lk!fXadH?1*j;7Dwx|(g&0ef*L$L4ZSRTSo@UpQRDyCKZ-z&tB++& z;KS%en6EWoWdLin29+xiJ6%*vO4-0eFrX>E5EYZ|YKfp;AC;8e5S0+nT!2atX!6ho z63Wd71i}LThjX-o4n|kuZ`}sUaV{z*Ajg4rRdDqVw`3s6`v15(7$YL7wV7?zN8xm2S=| z-H_S^eA=lssCWmhLN(!UwPRvnu*?o90rjR8Ub}(f2-KtPboOcf!PMy;(0#B3bbcFX zpxnp$Y6(ZDcR**bgYkdsqY$>Yh4FvOHQ?$BDqv&$-!ezVrXEku%(4vrTAC-Xa5S0{AAa>`dIB1{k&QWoZKH8n5QlkB}J4dBL z`f5;EKwxh-s7!rf|LOn#?hnRqU$b~vy zl!}1e!DqP|)FdyJwaih`DRF`F_(8W`c89TaP6qWxz#an~4Fx(hT%!8|_r+2+uyuyr zAu1l7ZlF$Sr=Q6GW{^n`#b9Y6&`eLShr$b9P^Ldxn)BKSSrUtSve zn#VGarNrmBGq}Cf+YM?wy|@XHwCMJe>C91a0H-*}0YIHODg~W6Dmk4wDkd)`fx7NT z`CHh(L$;DN9syNrhap3IP!71g_~OJ@@YIPss2%SIYR9vHu3`_{wSmWt;l*k20g|Om zsG~sOwjrp+2R_@aMn$CiR`<(pbNG~kRxfDr_vHZae1gRPP=;=C&{!|?MbMN&r#RB2 z!ZnD44zWP`FW~-3_pRQ2pymOr*WU)36*`_cl<4v&4G4gY)I$d#xQ>JM zf`>m4{se6d1^0fePk{XyqM`ux=LJIklz;>z$g>l`@f(gMFuQ$Jcv=sDyj&t=4YsIU zp@_q}Zvq1YL$O#Vn1*z}j)NTqYVSZpGd}JR2f_-__yk+)ffA*F|Dt~w+!>P*)E!2hBypc#Q5|4Vt{Dw&&4K&EX$w*PxI;jubH}Ubb~CFLs-fSmW5dOngeEG>+KSz?!%xF7})rASg(r; zM?e+>xONf<3<6C~zBpS3I?YU?lP#|GKnW}O6nePJSiydPkHUt9_qwR?1Z1&*?-3Az z8qib5z|j4n`G`cPdF!_lMbOknP?+)m|Dp+u?hIl7MQtD+E@1~xF>^4$P5&4VHXanD z5Ephc2K*P*00&#+^rx6NPQM4%!t$w+WjW$e}=>tcZQ6d32qE2pk@L?KuV`7 zs7VPL%nl3hOnq_O^$&<2_+Qk5!JXl_>mShIuJM6x-w!FBydatQxajVuv5--(!`)yF zASFA%LnG*_K<R9!c=u1^1Kt0-PVuk##NKeSp@YZb;5+v2Qx4qcN?$dk zSp2UCXEf0LKP;V&9BG}5;AIVH_d9?Nv}NgZ>oc)BJ+Dgtz$xTd8F8L4lXs(-|0=Py7duZ)*z!LzPBbb*9oucUW90S43I|S;ciEs;OXr+{%FXh5n& zMFcd94eIIZb>^`gcTtf54Wcyv;w%U4td;;bnIy_|dp$vGodvpN*tj%JQTCSGl>*i^DiTH4Amf3NhgcX&S)2bemc9p-1+mc}0kF*wqWe(y zMabP955NN5jsjubpN>0%#`GAPe=wJdG}owbFqZ1@Z)0=lbQCc@04h5`Cn`7pVkvd$ z7HdB6yZHx8x#546)(vuQ4Brkhm#Bgh07%`pLyRTjNId=$PB^bKPy%9D>!s3j5LT}z zLxG$dLyw#rn687;V242o;{(l=0?go)!_vvv=_pgm(R@(htNpDk#}RTk#}Q=m3L#Pl6Pa6F7L*$Mc$3!qP!b?jo*G6wtWManRKa4B+)_prr;pkb7`i-}1MBjt&op?2l#Zu4A!2UZSi0 z!}@O-Q}%}02&-@gPM_Mz#<(e1|(*gFNR zEU0%LNOkaw-+ACJq0D~JB3tb`j^-mgkb?cV8)!opgY}OxrtTl0?ohWMM|eQ*6hn}{ zpclHiV0{LR7K}A2I+~!%KacP*)^T*Zag=BVbYJd1_u|Q4&|Y@X#1IeYdNt7OCfC7&L6mqAV5B_bw@E=?~mB)bkd2HpOpq4|aBY6EN<1Ph9&@rT~2THl);~l9*fsPUe zI|ELHg?ImKt}kKe{?zLan#qfq@&Es8))%ESKx+nBy06D~pNsns$?9M|p!;?hOQ84d za4(_i-1V*Ny^~kav-We=dDAhv3koZc7qZHc$$y5TO6_%4BYT*J|^K^`n)@w zB`&)4QVCx-KV%Nv9i$v-X%fi!XPV!rfQ~ZiW()=mBs+AA8{h7f?34$O5{0NJSjI_| zaCf`OfVR%59Fk!O?ac#k|2ysqnu2ApjN{>N0j&e<_EGT&1&xAsyQlf=UVtlf>mVvSR258(cPNq{Fban_MXv$Ee(?`Xj z^>!(jWsHhPDNE}~(0nCmqbNhS9|vfZ2DISGIzU)xHcb`u+HNs zy3`$_V$sPIi)=6lV~L?<980M}H(xj7E(QiRhW{5j-B_#-m-59zmXkx>&>5rR^O_Ab zXl8ud_&?}G5725OP`2reQL%vqSRDs{TLvQo!)rFk`mA1`dj4LWbDcRV8m<3JL0eZ` zxPIt^ci*BEN3cc?C4?YlNc4J{aqK)0*F{|lfI zloGy9mwg$aUOjlI&jwU(8lP)xMM$qoUQZDPGrJ!3cMLGpQ3t+AP zmhynEIA9cD3{i1-&B6%spc{vWHK=$KCo=%s2Hk~>93_5-GsaPK^ zWdRMe9EV=_>TX@f!QZqEG>cNBBE!JnS`A?;FqCkE;^Md~11Ji*T~ushVTl-=@S#Ll z_b2{sVQl={+}OjrfA;#Zr5$|4k;Z*!7ieXAS||I9*P#py)@~dn9Pv8@85kJi4)5S+ zU|>kIW{;OX(ENY}-VlVE*X_pA>&Iezsrdk-@Fo5whnScTFdqnyw{%hAD7CW;QQ;}I z*aga@FD8dFFj%scYVmLLd?x<1@aEs{> z4}Y0aj}1$Wa>CP|2fF9uaJO zJFNA8iCeFi1a!Snw_tZ63urW%v-Ml4fTbhHYq{2MrR>eWn2S_ezm+Q#v4UD%lHGwE zpi8SjZ5&?a8_fq5tnU{ciHnXu92X6meFkBOhe7A#gm&NJ-=@v{HoW^MX#Yd^Y0!+! zi%lU64Av~#B|P!5J3x!(L5p7xcR4eLb+`+FH^U!i2Q_<-yMtT5D;!Fk!h1vi^?EbC zcmWrW$3!@NaV$Xnw#9+H(#%Oiu*V z&){#F1)i2w0S#G$*879Hmd%I01a)797~umo0yKib{Gr!HMFDQQAyf)Cq6>UKK=T`(VE%290-<5ekD0@}e>fYzh0Hs|bCia5yYpBdE#a~R z4a|Y^tP7ZB2O6WazFTJ2{rccj)?RmyULVaL;PBC~)+`n6&S0_5WGUr!YCgcx{8GXC za?$hGtY9;{eN+^T--5B@-w( zPak~9+8gfC>%;g1G=I^%9W?LGtEe+n*1LZVboS z6qG;>4VC~f#gU-o#?YC^)0v^rnE@)2RXQ_Dtk0GRc6um)rreG@lz_^VP7f911E4Wv zPznUaC1|9oIY&iA!J+vONAoez)_%~Ts}k0Si$SJ{ytMxh9vXzj9S^AO6VLJ5y&H61 zTXPM^55>|4mN^`MN^f<$S9E)nfX=E`ba{nPEn5!lTa1lpd|dZ087%z@c~e;g{9Nc z1ANJDK&N9!r(;B?V+`odc1M@a#xJ0Srj0MaOIfmY6(>d`6SmF;80|R`Z z2x@`xfzH5;PRE>1$AV7BicZIp&c+9zplJlny>&K%W{5f)H5eHfIvWv&P~fES-pY&@ z>EHhUhpwXs4R;#<@9oO~xvJ%*gmiVF za|Xvju44e5qz4g(v{#z#+4x%xL6asfDixqoPFtYcN2LHX-=J;S?V?iC-2<7L1YOJ^8bG~hp?sky!)&nJ6-P1v-llj7HrtYht`!T|L`)`0s zHq&?i|2OXksbVN)V}1u}0Wod|DFu(H`>0fa+cqVP?h>E_mUn`x9zlN@Mgzuj1wnrm z(51Ecpe5Ll*_&nyM*h}pHU@??(6X(3h3L+k&5p*|ccGqC+ zbZ6;w=MZ$)InEB+>ICv8DE_)3aR&`xA!~OD{?^~DpeT{yZ~er|z|f5)9)zsj75H00 zi%6~gRrp&^gOq_14Cov;73~+LoXz&^{H=#U!u-uY+42$330h4sNOfo6Z~e#0z|g!OR4g#?w{8aM21|ELu}}dm`fyRH`0vi* z_#f0;FL@aVI?HN0NCLD>Q~2Be|Hj`yD^ox>JvO_0FhT;Qv)n+i+^4hLq_bS3vs~we zbO-~(aduE1?JQ?`$qU*z`$|2r6;WOO&^^tb7q&ce*VAn0!b zb%{Gqr@O@quP6ovh`@{fUAS}s~HVtuT{RQrSV*D|K=uiY^!C1Jfi;1CK9e8C7RCdyf$nViu8)X)H( z6;<+5@z4MNz1u-i4zaKM+zYvH|Nn!0-VO4}wHNi!7LE!F0|Wo|aL`SL3=E9<5s*ZG zoE_A#6^xH*e#GAyFVPt<(;2VO8L#r<$E*MUE$4%ZbpF;Kpm>@ND!Czj-!&iM>C90nv5sfqZ)F5s7X;4Uy&)<(kTh}}(y4y2^c84IuOzbja4$Gz z^p=2b`d}%N=oYgUjHUSpOYw`=10_0Lf>vVut?nQ>(1kBufs9sR zjQp);U;(Bwo-RiwD>o+oR#lL|eo&fX;BTo0t<8dz3!tl^!Mz)Bdk+#|EY|)!#p>N5 zDiz%&DkY$ha%bt{>w>2^2i4!7v`H?aOt9#F($eX-a} z`;_!C<4e{TzzYjrmN9j|1R2%spAg!8?ZqAs28K{b^6b9W>7MX{I~?3>tzgt({>qpS zx}c<_IoyWf(w_eade-?*=pID?|AivzrZ34FUxNw<3f|F)aPHx9nwXng!1wD6o| zE`yf`C~bps6QclQxP@T34P&^0V7bXl8Bm|@AdB#^PJaW4-H;dn_0c-rO*+e2UWkM< zF!Z*A@>8#miq0<3>N@Qcpz&f84r>Gc)<>Xgyc@M2;lsJul=Q=n_7o9kJ4I%8By_*>Wf`2WAzJ%F*>-=sSnQh5uyhjh9-bh^9n zZ+9064C>tua!10IF**yik z>KVc= zwFOOA-0WuVeigp!1RvzsDC7Uu-%Hsc(+!8a&%HSL?ce|2K2S@c`&wrl$8k3vaCKTI z0J^uit^~Zewx$!jUiO9WSJ3%Xpm=9t=ya3lbkjKQCIfOxXPp9c!SHc69q_dW`~I+l z_Vb+KWnkC|O5Tw6SZ75@XT_gR3s%rodY+{pAUEzHycinRyZr<&0|R*7Ehs;TwO%R_ z1uf17?dL!lU2Z%EGQ+p@PF!ccK`hh=@chip@ZQ}Y7#J8{)Pc5M2bUPXwZ2-y-R&&` z9$4(mF6j=g>CCP`6|Cu84eGgBt_Haqw9*1}dclh`m;V3n1Pk@C55#i)x|{-jFsq&mFbKX=yVmajAh_&0gdx@ z#&LAU@pQ%sbjBHU#+h`+>2$_vbjGQ4#>sTXDRfUi!Op?tLm=VxD{SKHBVi^}vD$(ng(0%;{FX)sI9~G73ZlGmj486{bopA}BaVeei zzzZnmtpW9Y=7H9Bbj|~BkC_K*@paAvZH4Zf2O7laoCjKR(K#=KnSr5mo(Gr=0Fw#K z3=Ed@pRhA9lmw)8_k-?ONdxVNcC+a1I|1t6fKLMMgq)o*50u_J=YgW)#SJg;3F#`w z-4ejHy~ zg7Kx}E-E^pL8uo`K`W;~S1bB~Dg*)0LE)Wl8jQXijG)ae0-b(5pk`1ZXp_@CkeU1~ z35*O3U2Pi}85mj)R2r;sDADO|TLbFk^sNAq(<3+-7y<%=gI-vLGBEHjImF0(!1{8L zL^-RqyH1&4eB5zYP+yb*wChg*v^Q|t0+6=0C5)hEz8`2YFKGNg=EZE#k+`5PR9Fe~ zMdk~gVItiZzu#(p#LOJV1HPw71tciZ-3GF@(~X0FyIVn8r<+Y$XFDjyj=O+v zkP+l>0WDNH?h3w=yxZTP+l|BeL@`tMiSBlgKOMe5g!=GSIad*@rMpfsb7!oGWxPvC zQn$Z{c0cI!(QbDi>Gm(|3=GzX%SDS=t^GKP`Hs7pfD*-VR{>Dz-|fc1*bY)EI3J|$ zwVGutPf0Dfii_`bGl=VS6@Ud7NG2Jk%~zm1jHA=fpfePd0U>LDI@>`x3$k9QvmcbX zAUpp%!TGBjd=@}wJ1C2FLyBr}Dr!E+D15oIADrR9xeZd&fFcM~7@RqC22vJ)XPNd` zi3oz$<3kDo{+2$_2o|V#mF;$8v3BDqcEMWAc877aUMgh;H-j^Id18A~J22`+#g!OLW0+nT; zSs;~8(DHZC3P=Itlb!x7-C+uy!kykM$H9%w?l75dHy-Un)-TGqUfZKvAt_A1MEnR9o_ulw0~~l-70o zacK8}${NtH6*%{TR*Ppb26XzUnDqLn7z76Ox~SL$fHQ1oj*86-3&?LOYi^S7J@iEZD*&cMLmdmhx;3YKA*nsa2 zpi2UNHy>o{><3A7yB8Q=vOdJ$dK6S6g{Y`lhP#wVfC>ly08q)`9)i;0_zJmGwu}|D z^qjHV-vTr<*UcFA{{o|XKy!EqgY~geRmKt(3+;C$>Y(LQAl%zOgM)$Lh2?SZagZvl z2THcT=Gy^UNz&fq}6f z?6w#coo+Boa6QTo0)<6IL|L^SwH|b6u`wv?0oNax#L>RPvfZ0byBRDYN#dIIgDnFji^&oe|cFs@X zK=CB#N*!kY)^(sEy}SIa%RqJOdXT^QTjzt0yzx;HfLH+9DDxua7-&=rbWpDK*HZpi z*y@4iBcSjyz74)%MW@%3!TM&YmnGPkQm5{Ako&s*O+dXx&?4n-#-Q$N#<%}p0EH@J ze+D>eJUAE_1lQ+)_P(4gVFAs39B&6X1C&d&Pj_GCpK=Iv(Mhk5ibY@+BWPbwFOP8$ zI5uqHu>o2b{9*xUsKH0Ypu0rHg83#izoeBUvLRfp^1b+>+Lwe`73Tto3#kU(p?21MbJPgE}wP?h+*$ zAdPSXBs$lFBp_zgSRXCf)9o+O3EtA%xgMO$*EfLj`uY}7i5wo$4JzJZf{! z28PvWd1`D zPxlAQaEB6B(5WO0-50elgUmL*WPKB~w1cF4-2=2;R7|?VL!?1# zK|(+qBy1TN92ko9y4^#%!vg}k8G}N@z->0)ZvTkx@R)9QP*X*x+aDBW2B2MPpj(|l z#T!GZlkwY^n*aWTj;sQ2DR>zGn#c`N@rjEDS4{DpP8PAy1Y5I zj{~2<2T=n$ADW}NMn!=kn1AY_jsVa_gc6+rJfJ3=L}vy^cc4dSfJAqoPiKHkcVI+k zfI@d*OlN>f*e1q~0H*M?;|z?9-Im6ejK4MiXDQ|A4s_@)ba~C+`oEOBJCMcr8*`w8 zaG?w6<~YzAIM5cd*4w3)yFiU|%McZvQpwI36#>vm6CmxZErAXthPy$7zOS{wxB8W^ zH-i>ol*oYRTwaSd{}wD2uzpp_W?7=5Qo?r3ftk_xc5{UWLn(7-gobvG3TW;~McPM2 zBtEV)gCn-n19Tt?#~}&i`6`KE5O`_Y2rPEKQ+liyoO`+S1r_)cR+erX)DYlmgXio^JitBW< z0H;Ggoo*i$hw#oYlTJUI&Nz?GIG@fq7wf|%LdV@eBVY{O0-a$V-3~0BZlDWv47x*9 z96%@A#ub2$`Hl4ct916n`TIqwcA zLC*s<$2#YM+F_mG?b4m|K!-AQ&I7gYI_H57?(LihE@kF*fJzxD;{(lgDvX`;z}53S zQ1#q757gZ1oCj)a@VAvSF);M*1CQMtx(Ql*R$_g*gd21U0H{Rkj4SC5tLcoZKozX% zoChl7I_H74OHNR zI@Ol*KqEh;qP=~fYWR2?hzF`vUt}BrAMy&`NeWt4)Hw}Q!F7jeboNPrs^m5v&~{-r z6^O=8L2y8ClL1L>69JKJEF26BkO~X5R@lM94Rnr@On?oTRuHfS(<%veZVWHD4}w;Y zcDI3=L7lD~-F={zPp2V&Jq;w@-3Mv}bh^cKw}IOPVG-TaKuv&7zntzqP|Kjx zEuk|kqth=1JbYpOyHusSZw{!%aJq!A`)6mZ!Esk`u6@m8InRZI0W?zu>I{YjbcPCa zyM=VRigbg6r87pw!TNBG0;I#xJ;mSyXh(L70jRUk>ygmypwj80;__O@5)yqaD?z5T zfs#-6G;mUKQE};R14RX7fDv>Dbaxvl!mSUNFn79wwoy8On&%z?5FZD1PXl=~s5{Id zAgKH3i@l)31%H>?cDI3j?5fl4R$zU&g!8zo1*o0;TB&;*NW%JaiC}ZB23sk2_rK$= z7NAkl*PPw18rFwFhc$K9npnnKlrneLT7VV~gZktWhh!K)qrK2}0f-CAOrZhY$2uin zxI-@EwLo?1G_b$gK>q5kivewx><)_n<>XL~&RQPmK~BD)Q4ojjHc&^V(^aOs51d1M z6}sENnZ#8k4Yb0G@t7+UBV?JO@k!9qyXGG(rF`9epuTZ;8z>9CmasltD$(5s8Y?nB zzzmiV2FrAUW~yCOWI&5;x?NNpKvlB!;ZptP8Wk7jQpINQfd?$Gg0GbG8@R{KT%x=K zT=GHoX}%V1{sAiME|#)^Zr>_lJLbyFXnepjR-+UYE#NZ&T~sWjLEF_K-t)`p^wqIG zT&mbzmV*@B#}L8ot6_b*gsJ;rrznc(1kUj8sC5pAPo-d{?O$n(BY!O z3BD|Ig+qxjc;EoMgh1%Uw{!ph_eL;%a}#JN5eBW=2A#*!>mwuZ;?BAM|Cw*_Z*v1L zg(~p~4R1cC(EXy@?@xEwkHDZ_9~p@kJHTqX*|Hb{!2A{G{{Qc`W4;mI>&Ft<8zLhS z^kTIGxUJ88zxkMgZ|TAK*l&lKOZa*{8IHNga4OU1T`A8JiEY1owuh@ch4^eHeV&Lh}R8=*A-;55kvubTfnM0*>(R ztKFv|$Cj0H^tv;}gHA*MA3#&W*X_p>5E%YK0^+3ZFrL;+CG6eKEFcY?bv*H%c^t+E zK3L|z;{3ofE;z-ulnz-ulw(2A^I)~ zhh!MKV^ll>Ux23g!2L;(5XfCH4B9x>{6--xyc^^^3$XJ9UZ{aw5~5-NcAgH{c>*s4 zL4tlP%s;x_IJz%rU$p*Jrr7Jkpul|I`d~4%sT&7!k^n=%i!J{^^GKyK-F`gGek|eO zO;&*~p4frbkg)t`Yd*pQ8a#rihPeeqH^0#d4(q0FD4i*O;0IYos6s64%IQd(_n}~x!OFTJ3yR%tBK~23E$vO<6 zRjUG>po^&3L%~{(!nL%63PK+h9?<4$=38J2ousckGIgBGbDENhoEjXKn_xfpcUw(1n^#A{$bzF>Y zpyg!}@y%f}3~`-|-A5t2T)IP4Bs#6)<6wMH^nv#m`LTqzo-7du?Gg$Ab!0#rIt1dI z!$cUsn}^&4K)Z`-RCu&cSpO_zhi)GW2b~|qd?Dz?0UNLz80!SOkHa;A%?1(B#u|@h zoIHFJ*@f zocn2L`>Awlcf0BIhNy@Hb%!Z1hpA*S1a!NB&Ysoi^-<9X?DpdTZGuq={txPE$uRn< zG+Q&2g3b+OX+2QV0x7jYjyZG2_(1ci|HmD{T`%w&wUW-jiq62A&WYeA*F@0BOXoyT zE!Eiw+QbZ79GB4PnDVmT7G>`ND7>5BWQ2x=?*t!&`nk78MdtI;<{Fh8hI+245^SA5=Wn=G>Zs&r)fY9(4{Zq*EKmtGIXm%1Qf9~BYf1EB3K<@!Y| z*5`^fTThmP?wSP8$$&;Qx)1WNcMgc}EUt;`^seXxhh=Q@k&MHjTmw>oMG6uh5y9Oz zx`RtX!@7$Lx{oOzYCikl`e>2F;27}i6 z#dHSObO$?d2fK7S7j$};l(Ka?J9K)xSbCcjiI%fkIvbSnfr>ust0iom&IX;{Ch>7# zN5ytJdvrScKs*EvgHCS)>qF&yps+9J=>Dk;It7oV`&{=SQ0f60YS8WN(*1+`XQ^;! zwnJyO%M0PZ-~|t0GptX6$0UxG@hBg(K3c-oS?tgm?DFCRQ-#aO0aTjNnU; z)~GySWMBw0zTJE@0(68?jEaC|EJG=i@!Reel@Fkh-=lH@v|LfbQodBXdy2{*kXVn( z572TxH=FEfD@370^vLopV$;KqtcdU@jHya%K58r8iwVf|<7|qcj$|CmaW{~03@@@l z`F@JZ6_68qR6vUpJKT7>TU5?4f+yc41OnX{KviXDh>8MuB0C1WYedKTaEToi0`I>7JqJm_&F>CbcvUbO2ly&6@!ETut}h0GcKJmDxgbkeL7=Q0$%($ z0$xK23jgjF70^kx-C+fwF_Lb-67X;ds3Yy8;$nTcl)rn5$`ep5fP`XHT&!Q0Xmvv( zq1Q#lpwpeBx10rZRAk_bNk1X(VFS4bVk~&ujezy*(lG18r9n`mV05pKN{sQh7qdZ* zX@OYc0&%3}9B^oWH=U?}R_cSh0G~@_tzVZ2cej9(Me_lc*ZkmUdwl`qlGjYe2fC-I zya5I4InZQB(D#eVJ>XFJeoy*a;P-3F&@j6G{Z^RtCD67R1?3CfE#N2!>c0N{mh`3X zmq3e^lrMI3guf_u01u35SpP2JVfIlG5R6d)&A@4Z=AD&6wuGp7bgxkX9eN77-@f}J z$dRCN?9Ncoaz~Nx_j;$OfG*MQ^-+oFbY*FN#@snar2&+BIY3^9q|&r*uZ$NShyVZY zwPAy*57)ld>!Tv`KSV`F`#8M81zIuyTI&v)&(J<6eWBBrqcfBT7E-m{Eh-m4j`C&b z4h5}&ROo5}Cv~0%9)}JH6SN(!vquFq_5dm`JEy380hLA}Dk1^UBn3JO3Dmgn1bH<^ z#h|kXoYFd{sDL!RQ2Y#v;8IP{;0&WH2iUK!0)oCESAY^x320+n05tb@3V_`R*7bmoU_J18b$sWh4ZNVuMrVSzai+S{#kFofdzK)OUTn+L}Y~*3k{#-^-4}l|m*9}DmP*Udr_4|z9TK_HO z038GmIu|uKto!b@L}x}qqo*O4Q<`&0LiouK29KQDc8 z`uqR?pe8nSo*tC`K#8xj5p3T?kbQ?ZkjFzovo#iw9><(EP*@tj?QL-gXJ%js@3lDw zs$DwsIXd%sI`upASvvCttnZd;b@O#k0|h9!wSU9LX zK9FI(J}M$F%ojp-%kl*T_D=gDzyO-CQ~;gQ2bzcs0gW$#nh7eP$;pJ?FpeOI;Q@i6 zjjurYIjFZ8M1j=VWFIgI4h7xN#lXN2*atpK>@wZpuEy89rz;s1Eei-7&IQA5FFb5()eU=D@Zo1HhJ^

e&)2 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 literal 0 HcmV?d00001 diff --git a/3rdparty/lzma-21.03beta/bin/x64/7zr.exe b/3rdparty/lzma-21.03beta/bin/x64/7zr.exe new file mode 100644 index 0000000000000000000000000000000000000000..67ef1da639ee99f32aede6b027a1d075af9e9d82 GIT binary patch literal 833024 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

Y(;cFc0Z#egZ2dCe52)D#vFSza5726t-APbPp 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�K@{-(=Lsr#Zh;c_ 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�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 z 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%0A=TH*4Z7zM~q+7SotN3JOX*$UL^_NRaN5 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:-DABI_LINUX>) + + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") + target_compile_options(lzma PUBLIC $<$:-elf64>) +else() + target_compile_options(lzma PUBLIC $<$:-elf>) + target_compile_definitions(lzma PUBLIC $<$:-DABI_CDECL>) +endif() + +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zAlloc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zArcIn.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zBuf.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zBuf2.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zCrc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zDec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zFile.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zStream.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Aes.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Alloc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Bcj2.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Bcj2Enc.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Blake2s.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Bra.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Bra86.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/BraIA64.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/BwtSort.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/CpuArch.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Delta.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/DllSecur.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/HuffEnc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzFind.c) +## ifdef MT_FILES +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzFindMt.c) +# +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Threads.c) +## endif +# +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzmaEnc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Lzma86Dec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Lzma86Enc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Lzma2Dec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Lzma2DecMt.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Lzma2Enc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzmaLib.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/MtCoder.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/MtDec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7aDec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7Dec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7Enc.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8Dec.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8Enc.c) +#target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Sha1.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Sha256.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Sort.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Xz.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/XzCrc64.c) + + +#target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/7zCrcOpt.asm) + +if(USE_ASM) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i686" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") + set(USE_X86_ASM 1) + endif() +endif() + +if(USE_X86_ASM) + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/7zCrcOpt.asm) + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/XzCrc64Opt.asm) + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/AesOpt.asm) +# target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/Sha1Opt.asm) + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/Sha256Opt.asm) +else() + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/7zCrcOpt.c) + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/XzCrc64Opt.c) +# target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Sha1Opt.c) + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/Sha256Opt.c) + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/AesOpt.c) +endif() + +if(USE_LZMA_DEC_ASM) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/x86/LzmaDecOpt.asm) + endif() + + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/arm64/LzmaDecOpt.S) + target_sources(lzma PRIVATE ${LZMA_ASM_DIRECTORY}/arm64/7zAsm.S) + endif() + + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzmaDec.c) +else() + target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/LzmaDec.c) +endif() + +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/XzDec.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/XzEnc.c) +target_sources(lzma PRIVATE ${LZMA_C_DIRECTORY}/XzIn.c) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6514783..846521a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,6 @@ MACRO(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target) ENDIF() ENDMACRO() -TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE("Aaru.Compression.Native" bz2_static lzlib lzfse libzstd_static) +TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE("Aaru.Compression.Native" bz2_static lzlib lzfse libzstd_static lzma) add_subdirectory(tests) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8ee6034..f6a9ba0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,7 +27,10 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzfse.bin file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/zstd.zst DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzma.bin + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) + # 'Google_Tests_run' is the target name # 'test1.cpp tests2.cpp' are source files with tests -add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp) +add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp) target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native") diff --git a/tests/data/lzfse.bin b/tests/data/lzfse.bin new file mode 100644 index 0000000000000000000000000000000000000000..3ef34ed3c7958106ce196ae6991231d9b140c99d GIT binary patch literal 1059299 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 H18Lu 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 YwIixwAoRiR8_H2;m&2F@U==y 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