From 9abfa4f68d340e0cf39e0fdd15292c4090a541a4 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 28 May 2022 13:45:15 +0100 Subject: [PATCH] Add LZMA. --- 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/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 | 324 ++ 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.cmake | 138 + CMakeLists.txt | 3 +- README.md | 2 +- include/aaruformat/decls.h | 21 + src/lzma.c | 52 + tests/CMakeLists.txt | 8 +- tests/data/data.bin | Bin 0 -> 8388608 bytes tests/data/lzma.bin | Bin 0 -> 1200275 bytes tests/lzma.cpp | 136 + 679 files changed, 150672 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/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.cmake create mode 100644 src/lzma.c create mode 100644 tests/data/data.bin create mode 100644 tests/data/lzma.bin create mode 100644 tests/lzma.cpp 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/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..101f64e --- /dev/null +++ b/3rdparty/lzma-21.03beta/C/7zCrc.c @@ -0,0 +1,324 @@ +/* 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__) + #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) + #else + #define ATTRIB_CRC __attribute__((target("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..ed84ce6 --- /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) && !defined(__MINGW32__) // 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..6d79635 --- /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) && !defined(__ANDROID__) && !defined(__MINGW32__) // fix that version check, Android with clang12 doesn't work, neither does MingW + #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..242ae3d --- /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..110ced6 --- /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..5ea108a --- /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..a6dcf34 --- /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) && !defined(__ANDROID__) && !defined(__MINGW32__) // fix that version check, Android with clang12 doesn't work, neither does MingW + #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..aa6dfd1 --- /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..8aecff7 --- /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.cmake b/3rdparty/lzma.cmake new file mode 100644 index 0000000..7c3e7f8 --- /dev/null +++ b/3rdparty/lzma.cmake @@ -0,0 +1,138 @@ +set("LZMA_C_DIRECTORY" "3rdparty/lzma-21.03beta/C") +set("LZMA_ASM_DIRECTORY" "3rdparty/lzma-21.03beta/Asm") + +message(STATUS "LZMA VERSION: 21.03beta") + +target_compile_definitions(aaruformat PUBLIC _REENTRANT) +target_compile_definitions(aaruformat PUBLIC _FILE_OFFSET_BITS) +target_compile_definitions(aaruformat PUBLIC _LARGEFILE_SOURCE) +target_compile_definitions(aaruformat PUBLIC _7ZIP_ST) + +# All assembly for x86 and x64 disabled because it uses a custom, non GAS, non MASM, assembler + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") + set(IS_X64 1) + target_compile_definitions(aaruformat PUBLIC IS_X64) + + # if(NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang") + # set(USE_ASM 1) + # endif() +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "i686") + set(IS_X86 1) + target_compile_definitions(aaruformat PUBLIC IS_X86) + # set(USE_ASM 1) +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") + set(IS_ARM64 1) + target_compile_definitions(aaruformat PUBLIC IS_ARM64) + set(USE_ASM 1) +endif() + +if("${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang" OR "${CMAKE_C_COMPILER_ID}" MATCHES "Clang") + set(USE_CLANG 1) + target_compile_definitions(aaruformat PUBLIC USE_CLANG) +endif() + +#target_compile_options(lzma PUBLIC -Wall) +#target_compile_options(lzma PUBLIC -Werror) + +target_compile_definitions(aaruformat PUBLIC $<$:-DABI_LINUX>) + + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") + target_compile_options(aaruformat PUBLIC $<$:-elf64>) +else() + target_compile_options(aaruformat PUBLIC $<$:-elf>) + target_compile_definitions(aaruformat PUBLIC $<$:-DABI_CDECL>) +endif() + +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zAlloc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zArcIn.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zBuf.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zBuf2.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zCrc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zDec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zFile.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zStream.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Aes.c) +target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Alloc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Bcj2.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Bcj2Enc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Blake2s.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Bra.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Bra86.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/BraIA64.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/BwtSort.c) +target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/CpuArch.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Delta.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/DllSecur.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/HuffEnc.c) +target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzFind.c) +## ifdef MT_FILES +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzFindMt.c) +# +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Threads.c) +## endif +# +target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzmaEnc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Lzma86Dec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Lzma86Enc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Lzma2Dec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Lzma2DecMt.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Lzma2Enc.c) +target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzmaLib.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/MtCoder.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/MtDec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7aDec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7Dec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd7Enc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8Dec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Ppmd8Enc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Sha1.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Sha256.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Sort.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Xz.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/XzCrc64.c) + + +#target_sources(aaruformat 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(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/7zCrcOpt.asm) +# target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/XzCrc64Opt.asm) +# target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/AesOpt.asm) +# target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/Sha1Opt.asm) +# target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/Sha256Opt.asm) +#else() +# target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/7zCrcOpt.c) +# target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/XzCrc64Opt.c) +# target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Sha1Opt.c) +# target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/Sha256Opt.c) +# target_sources(aaruformat 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(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/x86/LzmaDecOpt.asm) + endif() + + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") + target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/arm64/LzmaDecOpt.S) + # target_sources(aaruformat PRIVATE ${LZMA_ASM_DIRECTORY}/arm64/7zAsm.S) + endif() + + target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzmaDec.c) +else() + target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/LzmaDec.c) +endif() + +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/XzDec.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/XzEnc.c) +#target_sources(aaruformat PRIVATE ${LZMA_C_DIRECTORY}/XzIn.c) diff --git a/CMakeLists.txt b/CMakeLists.txt index c454680..f373389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,11 +96,12 @@ endif() add_library(aaruformat SHARED include/aaruformat/consts.h include/aaruformat/enums.h include/aaru.h include/aaruformat.h include/aaruformat/decls.h include/aaruformat/structs.h src/identify.c src/open.c include/aaruformat/context.h src/close.c include/aaruformat/errors.h src/read.c include/aaruformat/crc64.h src/cst.c src/ecc_cd.c src/helpers.c - src/simd.c include/aaruformat/simd.h src/crc64/crc64.c src/crc64/crc64_clmul.c src/crc64/crc64_vmull.c src/crc64/arm_vmull.c src/crc64/arm_vmull.h src/spamsum.c include/aaruformat/spamsum.h include/aaruformat/flac.h src/flac.c) + src/simd.c include/aaruformat/simd.h src/crc64/crc64.c src/crc64/crc64_clmul.c src/crc64/crc64_vmull.c src/crc64/arm_vmull.c src/crc64/arm_vmull.h src/spamsum.c include/aaruformat/spamsum.h include/aaruformat/flac.h src/flac.c src/lzma.c) include_directories(include include/aaruformat) include(3rdparty/flac.cmake) +include(3rdparty/lzma.cmake) MACRO(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target) if("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC") diff --git a/README.md b/README.md index 4a51d1e..62d191e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Things still to be implemented that are already in the C# version: - Writing - Hashing while writing (requires MD5, SHA1 and SHA256) - Deduplication (requires SHA256) -- Compression (requires LZMA) +- Compression Things to be implemented not in the C# version: - Compile for Dreamcast (KallistiOS preferibly) diff --git a/include/aaruformat/decls.h b/include/aaruformat/decls.h index 4e46fcb..167748c 100644 --- a/include/aaruformat/decls.h +++ b/include/aaruformat/decls.h @@ -164,6 +164,27 @@ AARU_EXPORT size_t AARU_CALL aaruf_flac_encode_redbook_buffer(uint8_t* dst const char* application_id, uint32_t application_id_len); +AARU_EXPORT int32_t AARU_CALL aaruf_lzma_decode_buffer(uint8_t* dst_buffer, + size_t* dst_size, + const uint8_t* src_buffer, + size_t* src_size, + const uint8_t* props, + size_t propsSize); + +AARU_EXPORT int32_t AARU_CALL aaruf_lzma_encode_buffer(uint8_t* dst_buffer, + size_t* dst_size, + const uint8_t* src_buffer, + size_t src_size, + uint8_t* outProps, + size_t* outPropsSize, + int32_t level, + uint32_t dictSize, + int32_t lc, + int32_t lp, + int32_t pb, + int32_t fb, + int32_t numThreads); + #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) diff --git a/src/lzma.c b/src/lzma.c new file mode 100644 index 0000000..d81a2ac --- /dev/null +++ b/src/lzma.c @@ -0,0 +1,52 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2021 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +#include + +#include "../3rdparty/lzma-21.03beta/C/LzmaLib.h" + +AARU_EXPORT int32_t AARU_CALL aaruf_lzma_decode_buffer(uint8_t* dst_buffer, + size_t* dst_size, + const uint8_t* src_buffer, + size_t* srcLen, + const uint8_t* props, + size_t propsSize) +{ + return LzmaUncompress(dst_buffer, dst_size, src_buffer, srcLen, props, propsSize); +} + +AARU_EXPORT int32_t AARU_CALL aaruf_lzma_encode_buffer(uint8_t* dst_buffer, + size_t* dst_size, + const uint8_t* src_buffer, + size_t srcLen, + uint8_t* outProps, + size_t* outPropsSize, + int32_t level, + uint32_t dictSize, + int32_t lc, + int32_t lp, + int32_t pb, + int32_t fb, + int32_t numThreads) +{ + return LzmaCompress( + dst_buffer, dst_size, src_buffer, srcLen, outProps, outPropsSize, level, dictSize, lc, lp, pb, fb, numThreads); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6523ffd..e135077 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,7 +14,13 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/flac.flac file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/audio.bin DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/lzma.bin + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/data.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 crc64.cpp spamsum.cpp crc32.c crc32.h flac.cpp) +add_executable(tests_run crc64.cpp spamsum.cpp crc32.c crc32.h flac.cpp lzma.cpp) target_link_libraries(tests_run gtest gtest_main "aaruformat") diff --git a/tests/data/data.bin b/tests/data/data.bin new file mode 100644 index 0000000000000000000000000000000000000000..c1b79bdc866d95bc77d3877d549456dd4c01bebb GIT binary patch literal 8388608 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

6(Q-|`gHppF%5yv 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

E{7ej;wLie?;Xk}E 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®%)el;vvW!kK|-M6 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

+#~ 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�ebh)gjIiXe0DJ}p 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∋;O_|lU71k&=S9(n@Bcx? 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

u=X|UJzPp|I> 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%0AFff!FSk6lV(HfTX(m=F=HL?k@y1vBVA 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

gBa^ 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⪼R(P?Q6 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

i_{YGsp~2w?1Cs&hsyfhF6pWxAA!7r> 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%0D-!GJfIWbK*6A} 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 o9WPxvBL)aF8 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

X0fkQt44@051Ogh?_k-@ZQ!ofH_`&ec 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

qR0i6y0{yb_#KBd425Me0n%;;NLnH^3=16r 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 #;kc(FoUJGY<#1Ogl|09c}bKWuD) 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�ARr74EIK73kd070TISLz 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 z z3u+HRBNjxF*YcvHm-ai*V{rv+%#$`H5$wnVYMm4hFT|0vHMBMBfH}edFQOp@9c0T4 ztkFxusC>V^em;_Gp!dVQ2N(JDh*WBM4K!{G$}2=-a*A89Q<2R7{~x&oMv|Z@lPZP5 z`}%sCv|PYJG-wG@%G|*|tOuU8r~UpIXn_U3gp&I43ajU+w($>^^N@FM!%9{GjHWI) z3_)5T%0Z_yK(7s=zE_bI_Jxdsdj2B4`Y3}+%~9W2cE`$=ltGAIO)-nvEj z6%<8KJY?Is_Y(q;s#%2JhC2(^Xu~>k0L%Z-$Q|?x<-z?qS{J(Th9ixdU(nt?)ruL| z1P)4#2@}Nh1FS}Yv}3?4*J!_R3|0rg8`O|8x1K=&)b&gNU(7j(b0Vm?g@qe5ui&Kw z0!SLW#pZLo=F>wGl0L9GjYzTm2?oerFCujf2W5z26`tM^-a<%%V{y=zxsXatmCRg2e;SI(N__A9fPi`+5flP`O79kKr~0 zKA-}NI&hhLAKJoxFMxW7CT?@+FGFf^%ivJ3o*IoiaNG?fL1CG@-T~`$0{tU!0Bl4Q zt5`}@cxwm}xmZ*TfQ#{13GEou_I7w$w{!9Mk1Q!z8xm>B?f?J(5rr;VzW}bB_9ZRc zJBVrwmc+nit^;gL+hK5)x%>MANNL?tIGO+tEieO;BL|SAq|ALkUqN6b4&;Jk?myxR zENu6&(5KA3zkmOJD)llTQ!Wg&Ep*}ej7pA%#ssY>cpZT@S^?W~hIT+XwBBOC9Ce_T z1L4;lGcdptA*jslXMmpbI|$pk=jRuI2eODR^r+Olg~tJs#WQElMB>qlNq(98zFq+N zglD*yMhs)1+qv@tp#4e%YE*o%(P{87Ag$sM)+$38Af=UMR4^ABz_3Om+{FE`Diw89 z309WSeiRqs5_my@)XqH*yJ7i#0$Q~I*EcYX{q>|AmB7FtK+$9w4nM*}jDcZjmAUs5 z7#Ogum%-u9VJSSYWiFzJ3%WlBGF47dFvHuRXpK6G425fk?%rAtF2xGa214Pg1{(ub zv|_Gpn-2{xSV;$VIlTP~8(Rg7(v$%2o&%R6u&#pxg9EgsJwHK!fxLatG;s2LQk%C5 z3CJtpsOTbaXhDdfROapvU|>*yMKTqGV@Mf=x6FlRNl4TpI(}61;CVC)P#aw2SOXu8 zWS~KzyB~h*&3=@{q~ti1j(XrxjHQx*mb%Dex3FeByq`}8r$Qz_84z3OK=lM<<(LBl z1Llf0Iyec#iu3&mXvr0pFL2NX1?#bdIEK082_V@ybk>T^A2g9kUZ7J+7d%5^%VJ0o z3u2-)hp1pbWKkx_WEe)y`{Y@G$QINubU{=40zx zdPp)vtf6pFNPq_P{QCK{E4d&ZCQP31hYf+jQYr!3fmVCNVQxjTe~6U1@B0-P7)J8c z87%6M=FqT|QAiOBVnTBPTrY(TM4J?3I2cnthKOV+77tP8Vo>9YMmr%Wa~J{L;Gkt- zz!=blY6De$$TK3)iAV<2g$_`~w4y*qSfC7MfO??<0gxnzdUPzUoPfjJ{q>M|hlL_R zn&#y#$e~EC7!qaf{d!PUPQ@jVpg9jeRu(y_aJ><(mXq$s-f=2ITQ6h0OfE8c*Ia)e4T86!_p-0*_;yoph8@2gn%<3`nD^^!Mw21_p=q`$6L#phPzyW$xe`Pe6_ac#dHh z{ADg=fy{`XI)g_aJU?QY8-`~-Xas|jKU^cF3|IjMH5*3ZEEb5i57}VqmX4tDT(CQ- z8W2Q#jBJJQ>J6o6#cdpXaDnp3z-ATW@fCiK7?U_QPw7e4s{iCZkCGWm{&FTIDF4WlS8&fp~s$VjRdy6`5n!oU?q z#D)0#`hMiYSV2Q+pwJ+4T?pKtR1H1iTn<$wzyJy2_2A+bOh9F5PQ9N`^7;hI6D`TU z0!1ej59TuWeLZBXj~a{bNe-jIs)3X;mzu*du+>4(bOWcTur>m|z!YRCHH!^IyMM3` z>4ID22(N>=3=F78E+D7K^C)*-!s|oIM|zMgA%zXQo$o%lxCIlWXeV3keiFBrDbR8~ z7(QQs(l!(i-ZJ+-=sHyf28Pk8GnA-=_am{iV$s{VC>jx*{jha0_v;ht5g8q!02k~1 z{{8#c*Vm)W3sa%YeGjQxp(&CS2jOxkOdJtd)HtRDW-9e*XypJON`N<9aX5Rw0P0FX z*j6-XW0U$0BxoXR(ZqW27z2IE-245A_=P4Oyp#Z~_B#*^9n=$Z2Wy$TA6nHr3_v%4 zm>?W5HHgtqNM{b&Aw-tB_0S9pXTW6)y700KToT~& z&cKU9J1_8+chE8z*Q6rITPWcU?}Sh>>_`ih0O z^i#9fM_S;3R3kZVaF)62p(Tp~yygcvdldiw{~sDMsCTzOLk6|%f_3+xk_ZY~<`yt8 zC?q&wJ%<;e7CQ?m0ioo5?5YWiLP~#_snjbt;GJ$*GmNlP21EtS=kR7Ntl^4vumD`; zp_Cx-G8(ITdU$C+0|V&7Hdx_LTX)>=N8|!n(BY#E3I@LAhUC7%Smr_|&PJ!su;vv+ zYQvOU%E0x5I%GcbUrCg+n=9KnhNq=TivCX-Dd8OT7*Q^w#y0d3lo?LgXU zgn1ucG{DL(0W9{O2hFg-o5Tn=Le#I=43y(@~&qPa44YUIt9Y+B(Z@zpaTj> zzConK!M9cnbZ{8NeM9C<5~Pr&J(Gko7h8q}IS^dtzE=RR>iPda0L#EINEJSe)UBgR zJNN&6P&opLcF^HDD2+IL4k09ma41?KMMxtV^7qNVeGxj4#sK#>ynzlch2ai@jDDku zgGL*`!AHG50^C9(8RrWM{{O!ZZ>bZhi!^2T=ff)(ux|+w27~81OeCicvUcu$(4j3P3(P7FTKL`#!ARzz=DLr2g>kh!v z2|k8E!l3d#l2Zp&nG4#o4RPD()ETZ6NTo9OJbWJ;=(K5Emf;YG77^g6BCCwSVlL{q z2(>PBgb#G$JiGvlQ^*p6xu3`-wPv|7ACm-ZNf_RWMaG`;Rw zWiFO_3!Kdmk&8tI*uZ)Q0|7`AXg}zFD9r9FSQTypQNB>M^@!SYq*4i(1GNADL&j~f`2?mOcAz7)vLVsdL8knE zKO*`dp^KLcfZhu-$b12I4wAzMLpv98a2Uic;L4%|kE(ZxqoMo;; z!20vx!g7B-aw>(k)d-D9LUS|N4y0KhBzKU>q)DL*^%U;YXvuUenl^af9=re#O_Cfg ztTTbyQiYVP;QA8HP?&m{{ZKxds-eU^PtvXjfdm>}@<4@P17{ZqG4N$BM$|#$O6h0 zF_=n87C|p`QOX;VO@nBFGz~%ig79fX!rIeFLp7Ay1Y72YY#_uE>?4*CIR^L^7tpjE zmFq;xJVd;1(h6J$w8fR?$igTugX8NGRjs8j$BD-eODwS!jX;wrHa zr4Yy*_@Xgz8wxCf&mqV~E}<+<`V}o`g)Sir@HrGFNBtHk%w$v=bYl)Rul1gpX|P=j9PLfcJXJzxS)K%o@51e&@1WE^#ZUg#oj zImF{A{8Di5(l~{@UtdqvAw_Tj%K)zu|Ns9FDTWC}D{>)?KV$}u;l4&ZVS2CmEr@)vY$;e7#v04(9cTgkXH z?R&TyunnN|8bF3&$LFz*e_&UO5Pgr5E*KaTD2`ZoLl@sz3&H_|h6S6JL(FM{hYxU$ z{6J^TXuso*Rv|=EfvYeG&aELOAix=BAPEQ9!C??bP&{>3Ple_XDFHZuY9S#;r80NF z0s|uCz&RRZJkGM|JgoZ)Qbnjl1r>Ez#yIm4`02a> z{stF0W)50C@Swv|GQ#B`419h7wR1s@T;!00=2@IY6Rhlln9e|8e=cZp6gISo&n1|0 z@WLNz5v83VQ0WgcimVy{(|L3gfrU4`lm!*SxH}>6V~A0gm(k6+6j(&kI$VPxF=vJz z8lVIS#RD_80JR)MQ9O0_zJNMwiqHdTkn%xc2F4VZx#txa3{V#~f%XC_U@;dQ6z4&O zDA;Bw0WS)`(&z-Z0LNk0c>;s?;3;>gEg*{0`|x0e7rGk+y}FlVl&b-a^cxffi8XZL7mN2snExB-u_E#qUWuopHz(xTt0Bz_xQ8C>@r0pFoY} zM081ARI&t8;9(ul1?5S&Gy?Yhn3j~`zUMb zLY+gk!Vqg*B9@v9P-*`l?(L_^AT;r{n++k;x9A7#VXe8 zgZ}@AtOg@E(u*;aK~Yl|vfcuD@S5ro25OWFKg@mf0Q3P#LeV_*;HpJY(gyXB2qtAWzhCH^af4BmoUI)3t=O`SPdN%g7^Dj zZE{f5;>Sb3z#SxIZau~QpMC*oS{xLKh)#|`l&hG<9zqVBhOw4-#5ohqB(QNvgaOtu z1Gv$!A{Tbt3S0uj05u00Fpek$$$;>A|9uC_ z7nu!AilfL@L}^H{%%!ANhqj{)HAf(p^kVf2Wbgo_1=1x(Q3Pwb;V48vQ*THfgY2gT z83n~;*VN!?G`u6+D9$9E1D>+%hu$&wUx9&i6R_!km7&Bo@nK6HD2aP)?x3dFe&Ppl zhf9Gw7|LAA8yxil3>36_sF{T5YZksT7nVU`ZCWGT(sAGWY%d{q^-ol@4sM0I@IP|Ns5{ z_3N?JW*}?-|A%%X@T}s6s2eEqem$(|4oOUSNQHWwz8ommQ(!NWM+auz0&=z@#~+{x z76Pp;a*Q1UdgxT!!1g^O4c)-%9HfRWIE)N%Ok%z zXhQ(#r7pQm-TD2P4x(NHNMI0{|NcF=_w{~0nKKQr@oVVXFp%RQA;Q3b)X)X>1#q8y z3T^08XATeK0;=KjM2{&548zk?Ao&MEc0eflk`%Rb_bZUJwv=jVW>6ReFSTHIupqe# zAqS34q%JCwB4U~E(T_akB>B1>NQM(Q+%fO-sNzgJBG(!h93101DJ*EU&NR#CNs0Fm3-V?u0VJMvz zMto3#l06g;xppqNEEri^&yXV)QLZA3LfB}fBznmOQA9k6-o6wdJidl<2oC0G9BgC( zHq(UR7O3wqU5=Jz2@P;y7)%F&_X(f|_e@Y!zDEUk^DT=%3N@oMjG5A)$2oDJ+xH9y59iS zHHAhmX30gW=kNE!jZ`3}^#Pk913Lh-cZ+a4(tst3o1j?}>!=9obT?KdC}s@+#{sll z;QapmWR79L%UqNhMrawzfK-UWgg|%FW5hDFkfx|BN!73;e%j1{rlUVp^%ThfoF^az z>M90^80|@N6U2K^rX;W+pXAUOQW_BD7N)b|1tcT_$;|m^=I-CWem;?<2uhKQIraf9 z3_wGXXm-H4(1tLsIu&`V=wO^eC3K7g+@IJP@G=*vc>Vt$7Hmij-T#P|E|%#?Xo(DO zYJ+ZL3BXm$VRs1?MTuUDt55)UF%_*JG)6)4B$ymh?OgD3O|-MH22G&S#~~z?x%6=m z!WMAsfD;vn05$m#av&C>O2Ad7{s(EqdXxl6KN#!kp^X?~#un)8f7tX9Bqd?a;ULN5YS2JS3kIZldu*QA-=E+R z&_7@;H*8M&{~w$dg+wm;xx}zFx+tOYz8<_}3~Uv8c?vNG)-DEZGhv|Z zIyoG^BD#qifYPwXVcHNE2FKJu66BP*{h&lf`5_HMJn9fx8`C4807AqnEYD%8qlpM| zcb9>I0b_CpR&rp!$qnKpSm&CQ%I1l0?1r0Q+296>nQ$gGf*?T`2=c^&^ zqZbJ;bFmbusPRd97*pa0NZShT0+cox*j%JC8KXP~EBKE%z>#>TgQrv}JLeH*ITdKg zcrNJr4V+#iV9R}M^KamN%h-loKxfQ@gB)_o1Key#Aq}0xgmB2)qyaaPR0gq4++jY5 zixh0&c!Cf!XU>E$=t>fwsi3ZgBpiavL!qjNF$FJku>>J%6k<_8vv7fo86xaQD+B)j z|BqOEioEIx%|Vb@CZQh;UC%pM&QJ!Ix%(9usJ)aCIxK^wnuV3RsC68qp$pww0@|~Q z`%odY7@!IlbgmjAE#P4hvlfObE*b=eAO*vaD0BBi=Cfh50)rp~2h0hBvdo2MYecfb z?C!(ejq^yc|NsAkR;7RpA-cMNkEWn@y9X+EKxJ+L0}Yzpko1o^VDta~e`u+T8sd=g z1XyGHe!TsY@V0bSK!xGX+p)mN@ib0pf zkg*%ywOH@^hIDozD)6`qTvCuQ#||5d zAn9f|8pb?>0IggC=>g!XuI~3cpsf>u47$*}A$cBcR38%Im}I~(%$S6d6;db+_A(cC z)DoVYip#hC!*K-)Jn9BbnTwInPJ+|XNkmQFb6P%U6F^9P~1Zm6^q=GKR5Xzx8AX~A;6>O~&NFK}FJ3K1j zl?Jh8E_@Fx(Hh`(4LJsQ8Vz-M0$x9WyB74C(AW>nsGu0egGbo38A|*h1ULj{)mU1&@Y`rX^7vZcaL*B6gn~;J zs;|w$nxqC;5EMA*JJj$w2|R>Oe7hK*Q3T}PLzhl~q8ASydDCVn;f544gSX6uZ1rVe zAm=vq^$O5UI4Is81{_e%gTx+YcA|foi?q)H;wWsbT;!#>pv6?UV*%b!C%(-6zrVnt zU}Vh56flsMs6nBLuUCOP9!QcQa!|nmUu8>@g+o*^G=qSsL0jg+N)U1yto3M{A%|!* zVR1ITStGO(5Q}c=3SkcAVl8q}_DkTc3Sm)>r43JAmyZn7K%)`Z!uvhw1o!~zbc2W+ zR2bn+TySy&6}C`3NXuOKDtj`vp1n^Xtw8_|k|9FCizO`O5_qZ_8m(B*z@e@m;ZcOJ z5^H23R|S}Z(8z9rtHf->BP$za6Bh!YJ`t7xhc1CYK983;^DtBqIjAr^XI3ymgMa`c zmoN;=Bk#nE|fiQz*5(b7rS>{4_L6Eie?EiUzVO-=Q zO-ErCaInk-iCr2G}gS>XFRz}CPC9OLewK}DDvEFE1G3t{RgId%}bDXsuK@-akf zU+`)WYMk1z9?O}Mpb-a1K!YkKl<+5>L)5WhqocUU0SXCoFgfVTTtuIhoO-w(>og9s z--k9E-V{W>rV#2SaD2iET9&!s0u62xn1Q1_g{Mu6fETjU3NYnbjk{( ztfyrlKtrAS6tvnvy6Kl}I~*_v7bq`ti91taw26xvYp}#U_{J6x4JdN9p1lvia=|yM z*M~T7P?WidY7v%@aBX=7tyhAnA-I+VUK-#izln*uen`olz`&63{{MafS3>0tuA6eK5oY72N=dQZPBV+PUCf71&+m96@^D zV7M2#NaF_>W25jQ3mkqpuQR7S86g*>P`hvp0>N5rU{wUOIDEDZbJ&DvM;Ab*yN93_bked~hBZNCJDG54H<} zysc;d&kGFuBA0|Rmx9qccsjwxfE_x7NInj@=BnU@C`c_v-p4Q;J}n0-E-_?@6L5fz zxiEmogzK@as3Xpt0aOJK1{ygYx?Y-Kw*yNMtVeXSKv9YvCt$P&u$VORgpdMj5Vdn* zTYYg&ffI#cgBF7A# zwPHx~GGyJNT|ld&OUVyr>gz-*S20=>i1raUdTEnkQOZ#U1_s*nTu3nVBO7x+cRJpP%gvS-~y`{76ek6i_xAy3PDhQpkPoGcTl0Mw#8fGl3wJ( zQzeGaaJvUX=Dh%eKta6%g8-xeC!%$YVZ?w7z_#NJBFEncZ5IZmDm-{}-VATbK?=FS zF}48T1;M~T&epU4phoftC~`q9H(1zga>+ z{r>&?_s=gt%2l{-qr(U@tODRn3n2!)%th>iU?B7Q)&vG3TT)oVV$cf~I3P}lMM?n} z?uNuCoFrjUI=IMXU~qt}3`H6Ue&3&vK+f$|s6{T3hxae?M#uGdwpjFfbTUHY<%})IgWH$a|WI>w}_Y9MHfW=^81| z*=Ww785h$06M(cVAv;>Z(T8CnSQJ5E$m0~a58JdQzz|R%0G{}VsD;E08G#G#i$R@2 zbk7B%iL%k$|NBABaE1hU5kpFAAL8j@M?&i|Xmns%WQfbh#4J@9R)Y%X_tzIV!0w)g zhZh3_gMdT*ej-~AxB?SCLyT-LUD>b>B+@Pj2J&uL0bR&NdZ{pf$dtK|wkIfZ6bkC0 z4N?#fV>}l&1qGHQ>G<4!$n6dD!QG7ah~1*F6R3!q0Yge_D6L$=TOpu2A+~{5dO-!q zq98RCEDT1%@Zgw)P;U|=vDe&{(kI*Eoe1l0(A-tM4BAfwPJ`} z5Da8y4^UH#^dk5CkeP5pDZh}SjRE7RMx8YErsNh?H4S2u}Hw4Vgim2p!MeFECWs ziv7Qz0PEqBvtJAv3|OdoB2VEUVsRMWg@RbD9&|$Q@s_sW;RLF>8J?R4iUAs1KP6l; zLxS&-id>RTfCcYrrcPZ5E_2@(kac+}2|lHrQc&j&5$ja!lfi0N{7xrgaah8T8JolA z)${YA%fAqTjKUHK=%>E_kZc&JIW*8N281)n%531R|D+eW{{yHWpx9!T3Sx+3{SZNg z#1cqAT4R7b){CtjjN3Wq8Q{h2|N8-m{j!irEzpcDZoTL-NJVY{YMp?t5{(ZUx2EKv z1tjA@W$u0j@}>unj2SQ{XfGXfdG7vx1)_%oaJ%t?delF%(h&y!;>J0&w3PAqVP7fP{&`ps5weTo=d?c<_LF5nuy}@9`swTvAt% zg9ndE8H>Q}F$aeA1q>uLvT>U=5Hj9myA(@`DC@JL7_%>OrV(y z4Mc?kaBCN>`X;5!1ueIOsCQs602>DOD!3m3YUUC-)BXQHe4iYtCGLM{`A+H*39viS z2?quN^0qUg8#F+C#E3e`0rM$6((yj{2nx`F37`fX-ZGc)$zdc%EXWH3jtRDI85n3< z-hu)Enp;8Cz?Zq?9BBj1-DDJ>=gAn100r4VVBDj*pqN9(1`ePWDzXTq3?0~!Ox5)SwG?+2H~SfsED)iW>{kh5_O+RSBuT*D%Ob zLf1<}UFAUO*n$CcS;~Cyx)hvcF2NFa$PMGZhnGhIWtbjcJ-T*#Y3E~cJjK2B{8e_y!#E-%LzfacQEv%(YL zH_#-FNzr6I816_IJY_C<$q77rhFIQ&&!cE^2}5Ww_dj^WDrRCKQiO!c1*M%Uz(B-> z%aCDPgiE0D2wRLo`eEDfk!#A%ZbFOhA(`SunvUJ; zpnC$(|NjpksX|pnxWpyn<}_3*=*8P#kLWJp&M^j%Wj^$B6x<#p7Y*EaE_qwephrKF zQ{=8^K&*p;2L)~hIdeg{O(R`~&<8^8zGUd7m6R2&8^eq|rxNA<;!LDL`B@1C_bw z4Mv3<*w#D1|hK$QqP*FF@MX zQj!X2i0i0ILgu5W5(@@|hp!wM_V<&vtQB15u17vc2Htz6bafL|!*K{223eK^J=~PI zGZM(~CBYJRDC{`9Kc9&CG6sf$8c;xr7Nnd!FzsCOmWcg_^j=9nyYc`3|L+Y*8_Zn~ zYrP=_8$Fqn&7dJgFoY?Pfd5oF2L=U1gOw417=)I#EuPF+?cZU*JH! zHXjl84Y(2q28M+B{m`u)G%9lmmbim|slxm9@Z;AYi5xpg+QbIUA|Jcs=qO6wb|XmB zkE|m1e*$TPxdVROBch{DwP*n!bAlsHIgqyB?EnA&4h;1IXcKObDv`{Ska0NdKXhBL z0m<`nI1L=^66c{;P4$D<7|^85C0ODP`lSlz>mj3z1ab!vT|7D^2LcYIy)-#xE@USv zG(D0UPz5CJS|8}iT11hY(WvbQxIXL)yp?rVodX z2<&Xl{|cZTWHcyq36{8nd|>_le9-9;1TzMaQyFwh7zCY5YXxMKxzNKO$!qUG_B|3G zy8FqP1tQ*bB2>ak8tO-cKmc{-ZXK{rxb5Fh?J*hn@^-3CDG?F;1FEDRHXaThGN*c( zOSr_PaN`?o18>MRaG}A0l#^%9oQcGv7nAfdcRwWWk+-SgJgJ9}l4lJxbg4igmb%g; zMhs|hCNsspz7M*`9W;V)ANd?J#PW?1vyKej&NToHj8nPHB~;=H40I07dli(URiiv0Mtn%A(ZL|x=n>+akqg3QG-}W(TkI*K=jgG9N|{r z04g7GNRlB8ZP^!qj*LSx8d2twUQd(Ziou{|J+y_epTXh$`~vU*1GSt*u*4n2i^I-? zW)*R!XSf8#37cABjb;wqfeZ{oqs)cOo&s~Bh$!6?K?>HdDAR>{CL;-LdTSGJH4G!Uip9UL447z`X>fVge}#8)_$ zoj^`^1uar||9`&$^oRhEZSa;ob(_^7qX#PntwP@qJ{83wp?^Q}NDCz{CRE}M+LObG z9Z?{#9Fmf-qk>+fOgIF}T<|443=H5Sm&x#a0`gTS#OUuI=#fM0&0Mri8lbyIU@ak} z_#~Z4#^5e=8~|oCPW(+DKgH(E{_LyrPm|XlAre4C##-T{VN++afVt|hEp{V=+|Ni;{97De-dI@nzO|i)5E%c+W(nWJ3oC~iYu$7+s zVWn&Uc<3F*18F`F@*$NMpn=RCQ5bR-AI@|zNVlBb?}ztta5^1yc@$ZlH9E&Xk_QHT znF~ASkIcsBddyX%1OhvNm{uE2Ph)_WPDt^D)Z0dP|9NVRG$Jbx1ZQ8 z5Qu?UYy(UC8KCQL4L~&{ay$3`|Nr-?z5orIhla5jfjb}uXNgPXqOifZMgdz=Ldwg7 zz08FS0+Kzja9)6c#M4~&D-bh)M$0n?p=&gdA_>IAG4}+G-uLT?I>-)W5KfG8bvx8t z+!VOXy^npBE;e2G7a+Wc-uJ#AG{!)MyKb?$V5Eu>C~*gT_5xeHoF{6|jINe!a+3ZxF^z9*{Ee^1LY7i)itm}dU@e$d1}Qsk1%By=nTQuu?) z+}JFBsHefg%o?TPA+R57 z1r7;i1_p*f*v2KUz#Tm2D8Pf700SQ8gS*Uy5B!rmrjgbO#>mB zLJ<>QHX+3l@|+T3!$B9GB5Nj@O-!*1n%N2LrMr}OoGL(0|TjNAioFICJMMmW$xF{-@l*u<*4sLmoyPG z--$b{hqug7D{+Y{a7nsyY7j**QvMpWWiB{}f*dM9?y{`;3?y${>lYxV<@O#r$4-+N z#X5tgK%P~Ut!Ti%l7Xy#J>Ic^{UmJ{oUg!OKk}9p>S2ITyB;(Uk?_8rq*5At_zX|c`=CArG>c=Q2HB_raqDo0aDj_@8_ysubK$dR zIJSxs&MEf=NFL1nA3#)l@;ysk|s>e}aQU0!BL)xt*(kXCF&_y#r{=hyeHitkE(T5x)r5d-y~MMnVD! z46ZirdSbTr4*3Fi2$Z?-f`{xP_rC+_gSqbo@V2gCiTXX(0|Q{Pl+sv7wa6XOMt2O^ z<*owtW{RPC%mFlTj#_3y$8+)TvjCME46x%^Q1zqxc4YDi9IP;?O5F3r-1jgX3S87O z7o3LaPT(!v-b1q`>7^zjmnASTkX$qtfR2bp7=epbPvXWlT;^aEN8Fu@6emQDcwjXS zi{Sl!qHan>vL3=Tpw9IY1q`53ThJ|w|3N3^A`etU%G~+*_gOGFAl;cgTIOOza6hOQ z0Esay=tn!0;YhnG3o~7;$DLrhbsfefa8! z(J~hl9!MDfrn5m*;=Z4cb*>mS{SBW2caWF4&`Wqg#|449pGXOccqV9XKgk7^0a5G3 z{?}8r)rsyWtgRFZXV9>N{p1|bAVBGndFx?g)8I23QOnHz4E5^;7zppPK?s}|Ei(y>g4(>7+)Ix;>K6&@>fU+5A(F4g#XyG^iflR=S-;=r%0Jl+C zWDvfGgaMeuI}n4#5Tb?NuP5px5wIiRgaPOZ1EQ@!R|qd93qV_d;XJUi{R{$x_gU=U zzdwN?VLuFzc1$POn&C>|-vTjsO5FQIBswY$WDTaMhG(EbxAzxO0Va^$%6+du#$fJ! z0pi-P^~AM?$&78RU4D!?eliWms*T8dtC3O+0|NzP4E?YHoCIuTE`tNXCOwKn7)aX_ zjWqyx1d_HWP5k(Y}Q%~I52271aiC`UCpdcuSvJ|X{ z^kD`E^42jZFerdD!eW}_h(cQJP)~Ry0_?Y8Pr$dyL-Gz9Iao?uBGxHTc_sLuig=`0 z8AN3+V)l&OtIt4z3|bIQ@(AdA0piM1BA4)j+(8ZoRToHc17VWfWGBaFke>S_u4WKO zAY(KYG}aEeUs1uKem)rnz*ak)Hy~mp0_3gXj`1(Z9V{g-;mu}r+-N=!Ndl6Y!Q|j6 zb77b8Fi>EF`jBe^ksJ5x8E9GpVq3K!K-UC9;;b4Oa~<~+4EF#3Psw$*;F-62 zic$$(!<4p`;a!kR(+OYV{dK_)8ixs_p^z6{!wD3V}h=&IKKh0CN=uMK0)I8zP&m zNMZI~fyj#}h*?i|pZqcxsoH^s1p{px)<}VX!X&Y|OWHv=l$W^%`1h)zcx5&FknX@Aen%T3EHg!(EuSyk1Wu5E=hL+VROc?5W~MbjQES{ zXcriSSB6o%$%b~0r?SbA^ge(jT2@<+G~7c$ne`vEyp{BW7SA&f+1Z^>%-kM1Gx3n< z#d?e*-G>$+ZUK|;*AsIF2|O7QbLt~{nM=;u75nSKhl+unIC2U6%fk`~E_9}S$PpgJ z9rlB`NP!H`CWB*71k&so`3H&p|NkG{Hz$26+=0k-V*eG0SlnOX3>4u(5^x3Pf!5MRm<64;ljCi-{1a1dTNqN?d}YxFcZ@7aCh2 z3Mq;Pemoa>bs3;TA%K5**dW++MzD#iK<=g*VuNVVsT)jXE_e(U>L7}WTyVFQ z^uFqQ0b(cJ6o{G6!s7q}*DGS(gf@^v3rNY9lu-uoo(Cko7))@PdtPC5c`ZiB5GjCn zvBDrIaS5J7j{l}TB12(_DT5YqAZno7x!}cJAcruJetj8AsDlk6eK7Zb00WVl<}(m+ zBEx+=g(QKIYOE{822Fq90EoNnoTG zemMqG?0^oL#qA=x%bf3r?b$_kBQ`d^j8)IjKf1h@+_=Mgdf32kIwN$V!pIv_fJHP? zE*aQ%E@-1J%rWGj-3am)xG=y|;DOX&!S5A_8KebioDV)_8^pqg@p*#4iUw@W7qs;q z_-v+=9MOZjxR1dBMfzY^$wa3Rqoy@@7b_5VX*D&SgKid~gUCnHItBEwffaKD+|ET@ z!b8ysS$x@4Wj+kpgEDXc}Yl5$(l@yQr0c zfx!WL9aulQyq3I3!n;^uz_&o$uSe>$!c#DULD|8}Hck3{)0q z;Z*a9nrgexfXBM^_y-EG4d+r8EO^{PC8_g7EoC6Mc#KM}8P3MwJy~IZmxmEpjEj3< ze>g`NhTlNN925^!nTs+@Pg&XW9z2djh8gz-h*|yx4m|~;RQ7|~?_l*ycFiZQL2Q7pDI0*d%*DDocWCs;h$?m+hCuy+l&A(1 z6M3U1Mg|qYm*i;g3;Zh;Mu+neF@O|v1Jlk$asbh@SP18%vcSc+02u>X>xsX@P=Tn0 zV)yY*v*E85P}=>_;K8>D0yPWbt&wzVu zU>$&Wc4|O}Z1AoXW*BYaqNSU`QP@IUL1B>#nTjK)bSfaOAO!`T0#OUa{u|&MBsq__ zK>iO23{(>DUO5?kOa5Vuh5J_FuD(gCkC z!AJBUMGJ^Y#=Iche*?}SRP2rpG2o3Nyq)&}9LUAH#dowO#S^EX91X<-xK@nfA{Wv) zB&!SVK->^5C=5Zfbi}Mg>&M^T#(y$8G&WEu@>b^(<5ZBhXpRXTg)_QQ0%sK9-E}sA z1G)I_+Zl~coY4uEK+4(!SLRY&}M2$*m4x4NrA}q4F-4*yS~ zXk@O=RS*ckcRvuwM|8vQ@nurb!DBot8=x|m;vyH+R0Z`;iSjR+ zB2d$n*hOkYt2Myeko{kPcN-dHG7u?R7>L`2f#xv?7cr1JXqvnG@#I+shS6pcB;x-6 z$2+VrU`H#QhfJKHCQm4DblwaWcLZo?c!8*aDRYUu_7S%?psU2lGUvSl1M#~k9Ee;f zcAvm{G6%e6E+{6@F>cQjmU)jjdn91~;FwjL4?Y(I-IGxMXwC)4DgIN*$(vIJ8%zm- zZ^zl_N^7D+7MjvQ)WDRvWUVzo_8zq6C2LF=bRQQnBeWpw{L z6e22b zc1Uy}NMh&skQ|H7L>fpHNLW7@%C!4<4mlU7Cn})PJvm(X__v)AI}}Fc(7>}yc=T{i z(!v^%vj_4%G}7FRtQtB^gui8ptO1!#bTRt>Klm5~dec1Lhmbw2J%Dh7suxg{CTQH`UEap5_iSOz##Lx`c+&IPqp z85kJI8qECXa zJ3?Dec<0UrW>^8w;;5?zMpj;-w7&j!C^{N8;Zo>B0@RXZU`~-%3SD@1-u6*;tm7Q>^ae? z7*rM#rT9Lf<+KiXSCU~VfGC|pLkj_<88rq5fq?k~RM{iB3ilX;z<_PFLUJA*nRpM$ z9gtxKJm=U9$>E>-^ASUAL@lPe5+c z4A@3Kqy#?X%3SE^Bzc=EKudG+mVPLu7^rk7Zux)#p#{Hqr`Vw5(@3#G{Mo)J4kpAw z9@=GKFzBb+m@y%XamnLe$1qa%N#L718<0&9xR>J&y-}a{sO9Z|ZV^Js-2=fPx~Ykg zSwT}^3=9lp9*_f?tRlJv32NrzUyT5B-F*i9=Qx7aKfu&tp}`iRMFWjSozU8r3Io4# z7quQh3Wbp{orZVrEMWi!fN+<%19*TWmMlY9=>7Tvlmk*72DpWRl(L6dI~O!I0CGK1 zqpTPa18Ptbf2jnhnM>Sqw0;HxjpzB`OYJe-0~NqFg+jahcE2CFuf;I%#V*dh5<{ z1kvlnz^zZ>nwtiAi`4)B|JUQ)5`m@6C3rDK0C}|zBs`E;?SeWD1HP02%|Xz#$-ppV zS0zEh89#|{-$rQgGq{!mjayGOkHP82h=E>nnh{2$Kz=zO4v4C*U(ApCL9*$*T zU?6WW_dlp?BYsgYsF_RLLb3Y<4?uUoTjqjnLIVT`Ulm0z^+p)xv*7Y#19Xkq<+xS zT>N)AAS(wqbBSwA_7j})Qoy@>7fYE-uptkgN~EZyMDNm5WEgVDk;}%lCUl7PYl-td zzB3yI=)Zy*XNfy>M%CZ1M_Hi2z@RYT-8bZ<0B=Pw45@Z5xSU~NAims0_Va(xNw|2M zo0zJJTPOw^vLMiX!GF##YSj#m9Kv18`;fsviiTs+ujn1{Vi(7~5&^^w@t{WFVCKC? z?f!zJ98S=GNiNP3cgU3%G= zEGz-gf9?!di91wIlfU1OHlV;Tct#Wu@ehk%hM`pELJzhfv=SEKOH>y4kaL1vcDNpJ zf1kKfwSI#4=&Z-Pt^wOgjzrcCuy&yV1t%e*tz)2cpco#4WHVr%LQ18e(=~`2=ONox z`f0?sK#cx#XE;mTA+Z|}V?Y5k%|W|0KNKVqq|`iQ#&bdIyg=?Ib1?TmXkdcKu>x2# zm*7MeBnk`&ZTtmI-r;Guf=7-)UPHnVlZhbVmtRw|kO5=afWW|ZDzP_qhtgyYo|uDm z*N|cx&ZPI;8P0=jhD2DOuLrk`;GxGb2o^r#jCdqh4h)mX(hSK1;0Z90W67Lf02ge8 zM@eBef+LeSt3b_E0uAB-yxY*gP6K%jfr(o$0dXvRt0pA{CFZgLiUx`yE~A9R+Snah zix0jJ>HZ_Km42DaG6 z+Snc9r7qqDVgdB+6XPy%@$|{yseV8i`%$-;fpX1Y9KuBjBakDZc!-p_;C3hIXciQI z5YGX3=!k2#f(!)>MBu;p0i+6o4G3-g1+UG6sKrWx-3E;gC`J6ZGsHxs~yeEj!cYzqL5_hoQ|A3`|JJ1Vla6~qSFeu?d@sMce z!j>!$IMo2dpKt+iGnx1n8@QQEWLpz7GC-hHxF3I+3w9hdI-nF;bM)&G22rwn49mf` z19{#qY(*S2WFXYQPVvE$6-kWsgJyvk&JuS}FIB)Yf;*V!%+S*YB;kU|p-|?6SJr}D zOGfh#>~&DNNaSK$ka|$l74NJUND&Mh;4e@?%IfhiCPNgJAU}dJnf*-UGfF6!2SK{2 z9qgKcK9XTSxDJFl1ws$C1-p26L6DoSL5YiGjH|>Q)Ms0qM?JI#oCXGVx`EVi2Rj); z41qEicCZZzo5)ZD1iUnt$e{v|PH+|{awGy&J`>6^3HY}}U@3EnT%HSZEGj+^b~_|$ z1t>VvA4{KJU;xj3#GKz_U>H)RF1}-O4akmd)VL>#hqJ^bt7}D+m6R&NT!RZba%JGp z+$YUnkUR+{2Y;ChJJ^QIJ177D{}0}3Mf|<&pkkEh4aT4*G@(|h1O74>%jzN0q7y|m zeCZe{dMO!;#WI1VFn|dii*pPHZ#jVyCI9j5f*^Y(4yqMI@^I{c8@$VL@1va(21?Zo z1_PK5i415AWnhOxh{0dx!iywwn*-qWuf(qtgG|^FtKNX%#$WKV1$@OaBqC5qj2I(D z0I_roWF`eepV(GwQL-$86i;ALdmnMB706>CJb23rWcTAJ=s+G|pzAIO9P1_qZI5Ap z0ceRQIGhl~P%Lo&g9`ze9|nDy3-2rw-%v$P@BjZp+R69|Jyi9OW-gJoffN%u*Bqn< zpY^b)K+u%llZV=YRG?sEFqYOO!@wQa^d56n#o#Y>@ilVkdixFzhYZpZ7u%HCK(Ady zEhtFiA#(SiKUWOCkcv>rhBE}fCXk>TQpginiU6|>G_*jdcm}nz@vWIaiVY}}$gyOY zBe2k@r7i=N8@mbx`22&#In)z^?{$U-6$8T{FLeh?BNxYZjKO(i+x>nllN^Kc=o+F^ zHaxu!`ZI3etHg*uYaA^UAm=m?Uq*mhrTEtwAX@+$_#k99sL)5&gU&{Z4Jea@8Uo!g z1Rt?r7i2268@rT@6eHY74hwU{V-Rmn!_l?`#Rvmk8@bqv{z19Y`8?(>GX@5Rfn2Xh zPBKN;1CDYi(E+9DN)g+TgD+WNAa^hqbhs`4DJ-KPCd1$3BmDlVt3|tEYV~AnUmAarYB~TW_hUwVI#XgWb=t^AdL%2h7Ss2y~ ziIfUZS1}+-(3DBs*aCQ6Eyx{Y-Z=?dnoGhm07x^J;BWynRKcnV&9=Q~z&|{UrJajw zmBV>*T1QA*fQ1%fSZZ&C(-p2?p6g$)zjU_Te&6a=Zg(q>&(kUZ2pe)O8?nNfjt*fWjIZrsKvl zYy-Kp3nUU^4oT^GY^!h?1};${IgN@;Yzcv`V#Ks_;Y$|CAIt@B`eh(t6#%&5%D_OV z=?aSq(9its9bQAE$Dxrwa1;?`E~5EIaFPnAuR$vY7)ZIy z2hz+X)L3Xc!mWj=V{J~`JEVwAcR%%}awwo`(ElGZaku*hJb zEk$Oa&3S~N9+LpE{Vi<$d06DquaS#wAa`(;xHt;jfjrrRj08xW7Fhfb7)`j$MXVAd ze=rwPn&E3>q6HVY5M>~GT^gtb%YbGCCKoh$O=6jgX$V~8KB#R?*7+_Nr7k6f6PA6r zpcCZ@&L_hCK~)CYL?Ht$CWye33q<)3Tk8^@)980jZawDNk%OtkeLo-lwq8gW4VCk7 zNlm~I-+{@QGiQQn`Vs`oT*!u9kfTUxrlN%dxOgIEGXKJpzHyL2yjT5Cg^{S+J=Cw0<4s zJT=g23Vih(&H%zA0q)fhT(yX|kxRmeFdl~xA%(>igQvvBS>O)f`AI~CDTPYFc>_WW z&N3I$-~_pl;1m_kpnxfc)kIzVw4BhvgC= zveF8s$&`!WEO3X%&IjB9gp?QtoS5WjX3)D|aP zK!cWF;4Szu%Urz5!H$MzZL%)s#w>No8Xg9_dvV;~mr;JO%e_ z81Sv4fmVjd0fAuCZ5ssU;KpDnad8&7L+i>1SkfnnMkItmd9E0!n1VQwg27yfA;d00 z00kdpEP{d9Rv$PE5;h-XD&9hroH7@F3N~2-g!?gzNd*cvv}0YeJ5b9QP?uCtx3B?4 zB?F$*?D5@rM(i!ppoB;fhK@Wz@(-A#ZXl5DIGhFUaGfeD7cahW-=Kx>L@c+3miyYg=5JWmL5Gc96&p&$cZH~Jdb4{m)b)t zWVq`8f1CyGkUuYs*x*2WJ+DRmhrxIYcY5W~Q%*+rdBqhhHGjVi1)IcED3l!Bp{{8Rj`%16s#TlkJ`Qjc^ixeks=8*h9=*nF1+HpW-j4%2r!GmLkon{4QS6O z174qCmbrvWa+o6^yV5`rN#YSK5Cc$~gCJwT1G|{5IEZq>Bx*?qH4v1+@P+_kbIDSH z(vYW8sSA!y1_lPyD1sz6gm+O`_!pOv~!s4ho!sS=K^L zzmaSf$lFjn$jV&EY6Gy_@OH@Ydl}rgBz_Ms$S`QOA=*;#&;k*M;egG>oBA=!T%sNE zA2F3i=CCgIQkRkj68ceJ;J6&1b9Pad#Zjl!1x<;9yoA&r!YuAU3ZR%i$1A)CCo`y( zV2Z3d7?csHg>jq~#xRg4-BZhNcL zLhUgBGYqmjD3Ml)k#bA|dT4;lLsBl}fj1Y?$LY{bM)1Ky3q<5$usVb`EG!DkT*Oow zxx>1s)BLcsK}kai$J#N5fw*KA#dnm9Rzsr>-lBx8{(?_r!om%irq9kZjOEtkoI3~g z9W|);{oq8891t+}2pm&@g(xft23eVlv}A$kv%O$mLZYEw|06YX$Xc!YAEjIZxfqNoDWK4Ign%3%a`pDMH9O)EY6B#=t;cZx;KQBqayn z{Kqk{OUVh6(7-2|LK#0HR3@D#aK=5njue;=OE;*|2jdaZ3nJMk7#h$|Y$W763iknHgWGjwX1h&CwP7+5ox_+$aD9*A%yID--x zu|SFq2$PJ=3h(hUFpzU+8fZl`WDp$U0ys(D7%?>dk7E|C92d7 zAXw(&A5nn#k*p{r=m8W37#n@b8&yIvlS~etL0krd0T{t2(;GC^21yrSak(Mmr zJ1vi3uz&|p(budK&;@RcGB6N*qS*ic;GqR#Mt{K_c6?n~Y zaQc7{2?V@=H-M3gI*4%)asXB_AdfNQm~IpxVyPbXstMvN5J}c)Z+OEHQxa+76l5iN zr*2>xONI#Utq%+XbdoX|o}jrFa3n#9K~mF0jE`t?92{Oyv|0p|9$sAxnnQnr*2SnlNjY9(k4~1ORfeeFT1L6nJ z@t97M6!JC+Z0+~^#N5jZ9;JtQ0+Xi0W?y7)fE+-VB@);I`abrH(m`%w7{M#UFoOyl zA`oJ5l)1>O#K^yM@;~$x1f&J)n106;fi-i9Z_7c37KkV?AcZr5aSp1Lx&KkSn`90! z;5w6#qEZ*vblLz6K_VAdn5FJ~V#-{kX*5VKLLrG5=EqEgB#EF$5k*l$lFg`!-(x?p z9vm8@OwBROb@UgHCS{u|Eu9CajrD%uoST7o;&w#4HJ< zK?K!>i=tkc`~N@6rYLd;815rx<{@zcB`G=&7h@eM)X)Lw6eDj=L+?`*5LMBIu!ErzsSi7D72O=#Ti1ABA`i4FZTsA+>!!akq8SFIE~(HCdElasYM%B z7=W=EP@X}(0SWGVFk^HS7i&a$P_ z0x>;0aHEq@5ejnwH~>HdAq}V=z~G%nnN}xz&p-OaILKunOj-GeYY_we3lHQ{7ao_O zv`AFB39a5i0fNA^A6GydRv@=V#Yi)x2%N`xL?h@DX(AR-l49AgQHw|=gWzr+v20S^PbQGrmi8@ZVeju{HeT;x-4K<1GuZKIOCBNVAnf;tUKQC8~W8ZD;(h9!gtp<`O0J_n)rf&@LNMGOrM zC`Cd~31S3^B-*gTKrB|kH*H4$*dsCg239#Vk$|WHA6r0fFHn|hq3tK)=fXgd0Bh#L zdzTnF)M-~r75923{eG&3@E0&%tc+Q%fLY9V%`7$&m%_<)OlcvMx`z#7qa1x zH5{_AQWx480eKf!e4R(_Hls~_(tIupby#5l7AxSJHXE1=m|$^wpNJ(yFtr0kgL4gp z80az=Ipq?XY{DO0pe70f1L2*UD5k)gxg;zUgAOgAWJ_w7lQWsX%LCiuTDKi!x^u#m3E`hCO1`P(`DsvrB;{`T*0C79H zD@2HOC+e^QxvKz)wGE59^*9y~g1t}osuIb8pbIHTTBwAimyS$uI1MBLPrZ;*3E~vW z26LfBA)!rQXrT-%P>5-@LbXDiOvE{kumNU*2?FAM1W7^#0Cf{K3T3G-0|VJ}X~@U( zBHRdKQC2*H%Q}!T=$P))Y4_oaNx_3bILh4n=v!@|l|01x1S1(+6cH_ky4i*90rVel z6L%nv&VYp+sK8}lATiU!G}D!aBoi<>uJ@@+JH)F9T@u#JC1If$ z%l|^YJxt2jYl0s0Uy*!H}4`1LZ&{9?&uu zdC3A1M~gs%8Y=}YJxOdU!*UID1_i6hXoAr8G*P3*pq?rN;ROzmq8SK^KJOl)CAskcI*2P_#)4gB;2QoOoaF@AgX%w2~AYnm55&~OAJb`*-BaWka zh&PTzmALL%g8G`a?Rz|Ky$`zqh@$hC@K``)DM)yM$$>0$QAWhz!wqEl6=oEU{DQ+w zc%~s?kq=~Ofw(isz#&Yy%*80sa5$HAVdPVFL5?9m!{S_PKw(=Kcd0uN^YY-Bz>$W) zZD7=df>K#h)=k41x2RY8(tGL*?Tkxulf$kW~vr4Y`7IDFfk|L2&B|8XsT^iwDURLfr~XXo09zZ4mPb7w8am zkZ=H#I09ooIZI;D3v{xVjs5?Re)ksGtzd#yBMg+8OL~3+dj{7~J-D_-jT)4JPQnpQ zvV%|#q9^mJJCZGhYCt{-2pldb#DMka5iRcof)gcBp9~5LDf9-e%ta{-aJ4On3oh91 zcM?-QteHzxqZR5B=+FXDr8LBcxUw+RK+tk5r1$_cQ8PANA$e;LP`3gzP_S(5KiaB% zuv?)7Wu+s|gBU0rxqt^9aSZUX1)Qr5!G~v{CNXFY3=IPk7QYbZ9+V}yWKV$-XBVm} zyxYwf2CPSqI38W0o}2~HDF~fO5+YSC6gQ$kiw0D#5;Z9E+8eZfEzmu z3`9jZxTlIX?}E*5s5uw+(iZ~;2G|}|Y{uXcLv1V(x`PpyDG+g-dn6brJsk|^&;=b= zMnSquxDq2|kqv5nh|*W1^5_CeSX0nFfy5jsDTPG=8Xah3~b+8TUSKJh=nM+&&3NZ&-JQ5zG1u2JEKtvNBDL%kV9E&1A1K?yW zvxPR!!DfRA3eHBsb>J9iI|^!f1PTID@W7Y4kZ{6P=0f5gRTegP3l3ExhVDrS4_HG2 zWHik;xgom?&q3r23=9KsqY}t*?_tXnK$^=LP6b%5fO-q->4&}Rz65YnDR zUp)!+D^3dD%q69$hU7{j+O8mLA)!jdFa)&m3{j6~q6@sXj+`TFFvb_iD!M^_0v$LE zSpo-lEfRymwFbCL-2%GIkVA?&)KV4dX%GeRC~Cz5(E^bn?&w{RNrW-V+!-DF(YS7E zhWK!x7EU7uaT(~??I9dXB&dJ{AebDOcCG05+E0lq>5ecZf zQS%+#NK^)-r%KEo8EB;ejt~%mvuO-2bjg{$#u#59Ym@@&Kb$+rKy6*h3P+r!E?usZ zfW!mNEryU3gIXk`HgriG-GYWECWW%^jE)1j_~*?AXz#)K0z@TG*|Y&>K+{hIl&_(9 zV9H#mpknulavLR|?iGcxk%Ntzi zGLX~Mh1EO#s~oC~VKlW6E0O;N*@xIrgqDB`4$w{6pJ zAQ%6<8NoC!IYV^FuFf{lX{6z(Cz zQ|eMU2nBOIE*k0sT++}=6fJh(2??wlXBP#Rp_t;xeG>W&aCJqN63qwaCATa{!pd(A7 zu|X4Qps5U^R!*SkMb66*tH>$3VMe0vkAj#7BPkto!(E_LIA9EOJPsP_ew;xIl}Amn z@RS6RMU}*15k6t$1!8m?$XyR@;zRs^P7cg4F3Oe+N|O}65T}bAdYBF*AIBU$vEcw) znoHbfT!g9c)(I&M6X?(aF~bG_|3eSMA*QzpZ4twx0q@uaw9qA|yo5H>;r5WX_6!z? zsOJD684B8zMOkTqdv6*o`sv{lJqFI0(>M!LYz0mPQU#dJW{h$KA64 zd1+vVaZwJ|8Nh>dh>bWx>OdhmNHALZCFF7pdFU7$Q8z*&X+|_oa5id?RKu9iGKJlt- zVRa+wJRu@2fxS;$CkP&fs0^e=t^&@YA5{ybJOYCX1F{+y)lCC=IxnT63)c@$8-s$N z=+4Ri|Np~^D^ibZfVWLZD)XU33&iPxI*o|2Uug3QDMIj91h7Jvj9iI1zCg(W27KFr zDLsbaKmAKxSdofzbswxyM%(!fPfXw#q+n+RQX`j~#VPRoO#%b|N(EZ>DsVdz^;Y2l zS`duedF07}(*}f?Iddk2F(9M>rK4ZaQjmef#s#8jLW%=mLkq+Whd>9K36EVM90QL7 z0!Oz%<`R_5Z4GH9rw)$p*Q7%EFd z&j!1vks7&V^kJ}@iC+}|_6JIrpy0O~hb(FncR-wg!)25SLlXyx8rU+IxY7%^XJNU7 z$lgBOAb87?r2GLZuJE@)VU|GMhC2g86{4;11VswLHNEhI56HM`7P8z7Yz>T{WC6o} z)LUa`>|6)5kfH_`6r@l*pk*#`opjtjhAqt{SVo~4foPbZWgawjXk2Kc znwVL!|Ns9(_pB4lfY7oT8XpjfU_lKtoq>!#D8~7Y3=9GkHAs=#XAtKjlN7G-!L$E@ z>ZLBM=)^r71dA)QIv$apz&=N72BW1S99&q1PVtxw4)f84abD5^_QHT{_d+`!eaJ6W zKnZe4u!6~fTq{QDVD5jynFPh#a1Kl#k((Q!`d~u~Xrp;hSqutl38B&qTQe6=OABrd zv`8mw=>e?h0H**5LBR@L6{ZssmU#BG zp!p5XMHSh$Ae)J7zk~H-5{P00WEL8x zGz;NrmQk_Pg*zJ4cQ6rH8bCjb4w0n5hMZ8uyv;|NsAoB?1QYmMpvh42eSG$ITEknsnH9hG%RX>~0DtJdvY|NH*HM z*>Ej!2gTR|@re>wLS zACYZiq|i7I^ASip6qB*`49Ud*@FpA7I8=(#MW-|_brA^z_s|YP4O)GTzQ`K)+6UzD z`u`t(gcup4@~9>e=HclpfFf!D7KiPJ<`R(gU_4;gtPu`93RQr;2O$Qkor^nJ6X`c- zI}-h9J;J&X&0LZi$grUWyk{XG*$%aaK;FYPJ48xj6DiG-UR+|?lt#|lGbB$FSiwN? z>L1*cMwi2+Ei!JI|=4{HLz6rh#K$bp1l!()IB!wTqKc$h<>G{td)@D;Hv zjHx{OH?xU#D&^{+!3?4XsLaKas)_R+tOz7|T@E5=5nFmf90coC5-3C=ivR!r4?SlY zzenNo;Gn30V$#~}NQEvLM<>8M1+^MXQM5tgKmIKe6kjQcZyi6SBMgX?fv3*^?;D_} z9`uGT`rrdRVIVQ!=T*>tSOHHT0Tk=>FL5!a@`iJXI|#-WNGn&6QYoAXZALPXJVpW2 zNa{r@u*^ne;}}+&;xBWtm3hREEPw+8sn8|$pdZkc!_cY$l<#1ejItZ-5*UG}G0MQe zK3?zY9g1H!R*05hJvU7KuI5r@wBl}eFEbl z7rJDOFTm;&u;oyKq74%N|KnLt3$lQ+k`cf0l;m9aXcfi;87!zlm%)L20LJJY9`uGT zq1FIwIGyIh3It1BBAXFNp+F%M^R!+{;*CPb&`CQu%|M8O8C#&V%!RLNCHayGL@7to zLNWM+H8EXAP%OeK1-!$0u*NVXD!?Qe`$mxqT{7CJ$lAe90Bw*Uv9S&EF*1gCnqdZ_ z(iE2I|M5)*k)L}JWiFm2*s!{kfdPGqE^IUj?p5?c899Ld!>1c*J*JXS3SH6I0CWXd)(4NA5*MY+9fISz@I9I& z&o?18bBP_7g`^yKZo<<5f~bU&Fq`leqL`b|aE~KG&BaL}6$PLL`y`JqU~QCAyoiaw zTpAe#BWeI3o%0PV=ioHS%{Zho7f)4*qza>CMvVl}F_x@oXGP3b%$*esj`=E?wg zxPTe-E^)C;oRK~5j?>eFS^^yG5Ml_Hxv(}T>GM2D{X)`4E8#;6#1@LM*)fc4iJUHw zvM(eu@RrcXIH_#;^|Rk{-n9F2kHMfp`^4Qar4SuT&?o)J2XCbZ;Q|$Q31e z%?7J!p`K&Fa>^+5Bp}L;6GFHKJBz>u2rBH^!)`AwQEbCNv|g`)%Pj*Xjz|*&bjA%O zg$um=BX-#qJd}~L1m3a`t^v+~74ztukKhW>8L<3|w_OZheF2LPVoP*%+rWI(LYMTO zE7n0>2GR>}uwxJefw?pWN{4l^FS~$-C`rvZSe$|M;$Ciol!zG62N#gWu0V!>Ivj|A z0J9+D3S?aF0oF|%L8!!~bXN*-u0W{5c9a=O5rZ&l2(zFG0z?hDb}sxr9tJ#<%h=-v zshLY!=>{KKAiAiAS%tUEg_Y!>cmQEMJzDG@LKQ_VbjfIPC;Obr_%5iiXeL^ z?PcR#mqtS7MlN$PN>fBogPaV-7|8+Fy@ASO98m^oFHky8j&KVW7NHWC#Ku1s8%Ptv zvQ&ZY?QGIqOdHjRBr){bx$wpz$!%r$I4}dgjYil)9FkQS7>J*of~`ovTQ49*1DJ^? zqhoUwh8S9*OM2FZ4mE-ugCIyZ2hC;B{xrfwG#16pK5Y3KZU@m5HOOTyp1KkiwG0ec zu69C_gg5{>l|mNfQanhG7P=_h!B*m8S*kE1OWYwnhlUtV!`=NuNreawQjtVr=>~6* z5^X0W!{J~11#dk=6_Y$xg76xYh2%q!nWPUIV!0C-R6~*0D}Xu%nZh^f3UVpMxN z7vg&`ImE^m5KD7OTX+CkSp@bkm>_Y%1H5n~x>SS@`r#|2;fla+BK6E2Y>DSRymEjT zNyeZqnh6kd$QY+UcOG(q1~n9gqIgOLUwK2^a$RI6;u*L{uGlaVA;!K4@eyR^fyIE?=2OuFU!>oicgO9{M6+9wHWDL3z7h{-(fzrd7Neq#}r5uzB2NdJ!y5S8eMAMMS z8*&h)!5gdCR`4K{VPnDDene*T4AU}G8gwG8lv9E zI;n~|go)cIyfI0FB(@R`9H3Bw-lZK@_fVdGNC=U^rxY3$AZkdJxrkhWG&4b5@FEIM zEHfYYjerj=5WkiSRyW{n&m(*TiU>R-i1?j{CW}$%l79RGWDzOIQ7D-7DLFK!A>ICk zVlWbi;*5zkyTdHNU#7$38KfLf%z>m~7_<7u>?V*t42BVIcm?pCu?BJ{ol9KoV?0E! z9>MF?AuI`si2=oUQZ$}mMJ&xFT|ZJYm((^gtN|*%4>*5LX3?3Md{*?Oa5+4PzLMP=p{ib4eTuMrg%7 z#)oD-d?hg6+y)zffW!pRhNIbq$wgF65R(~5zBBIse;h?4#Y=Vn|0lF;jN;3C2wYQv zd#Vnl%w@p6zyOg98L;)4P^(f<6wt7tOR&VHZ~GEQiA!>?6f;o|c@a=TfZ`!k<|2A+ z7)x{r#t2d~m((19=yDRY1*QN#&4RbgMajE(+Ep-9iKa1E*^+*yE+Vj@2?ata;4X@Y zbsqkPD99Sp=l#&^##^rAoK8Y5b8!!^qr@9#Qbg3zAisby-eiF0c2c-QqQoUUc}a?w zhpbv~LVyrMr_4nxeI&Ki{Qn<0ACTIKhYu|fKcE3`>fmj>qU2ptU4=L8VHUcikHzAc zNh4$R8HQ7Fj2A-^B#6XWEMgdiO91a02^!S5i64`I zTZgw(1y==%3ex=qaUOOOv(Od5>lAFJ;3^qOZ!=?>PT;gL%5MiIaCR^DQy4(;0LNGg zQ>Z^s%3Lgm*u#4{aI>hervz#@g2KBn4rDWSKOzjEE(=GAi+d!8y4DYV(?C%I#Y3jd zMfCh|=LTFMk0>`8@ZF=0RXbv6f%tAUyakI_3rgN4dKns4M`8$K7P?fMNn;?r_{MPF ze?q5?QGTE~-is<3uui5yvjmjF86&7=DweJc=57G0H*^V>xb*GOV=r;B1~O(^7#Ska zR0X1jOqq*F$RxMe{v)?2vE&iFkq#ePAYsH66tG~7*JR`}m-KoBuhIYiV;PSnefR=7 z+`#^U64V%<#M}D^*+Y4+6#J1qAhSUjvk3-|YLGPMSqiWaN7Vixb(jOX*d`#U5n?d= z|NqBP#DSax!4$9lK-fhD3x{(?7b_r#9VBAFL+B;m zUW6XF6R2fvkaG`Yy=D;T(#OErJC0upuE) z115(^nG0WiMe=wo>PZVEPXQrH9pXn^;SC`y`4K4%A(y$Nw!V>!!NtT<=#suC4Odf< z8siHD57wo^00W^@9#8@gb@B^$$fm(QjRZ_2^i+9%t$S#VPeV_yi0S=B5 zm%a^c0&W}>(x8}u;SLyso-}Ivf`~9dq+-$&FLJYkV0dAQ-<&x z5ut)#36?^aj6G?XOZ*`Th4gs9bS>mSS%`VqNm>supo~+&;|<~#oN}^e>ei(9A;p^-KL@>{b1YJKzwT*YBQGEI7rf=%1zpwL38L?F(k9f_mK zP2YVOwDTTSO@^cbFgYa3T%^ zV-Q#Zp5z`DDC|)&!4YsA3y)Dvp&AcIiA&!#YE<(LtqlUDC@B7qa%%)skmeNrPB(`4 z5s92cjUbbd(?7}D5#+HbpzL%(RD$5Ffl?kLg)~~3i!Cvu4O4)PBe}+h zTZ#9~9+25|9Ye)6tUS600v=&l7@%kxP>d~^VsR%}2r2oJQ1F4ZqF=^;1H}hPVm%ZF zxiJfm5Qx`s6_SX-BZxX|(Sv1hf%HI!06bHG5c}ymb%twLd2}Eb5?i=PNK}EznKNgC zY5EeRl(~quCK>C*kXAh4J1PoCKp|SJD9s@ps$s&2))Gtv2My2SWYi@%jKm_0eX$qG zR$^Im3QaTA8DAixsZ04J5tarca$^<|-w?0i>Q+Hy;Uu=zZ0JUT6qD7R!BxhA3i63ti;0hA4xv8v_bg>WnWCGpbAaNHm()upHit)cHa5P{7{8 zxoHut5sR|O7iu9=7YSk(h$Nx21T}{6)EPa;P;t73z8f*1VKcNSQ2ayjU@vo#Ed;-`@OOnR~&Z8AIaDOr|kZcxK z=MvG>rNLrdqzVtwLjn5@=MXZQI;>0P5cM_KEHFWG3dFG>3v3vepm;$C)`-9%i0cGS ziqFNsVc)P421gf!80>4skQO_U+)VxdA6}|~Jd2dMh>K06CN>FnBW73#WihzxkeXV= zxr{_r*vAD7NVOLG&@d=y8AzX%!|DYh7BEmgc!@TbhScK+dj&=q;7%{^=Lf($GX@3N zyI)9&2WBFvXNBNcYJo5gXQhBOa48hTRsN42tw2=3B4UkUke9hgi_1yw4FCU+(#$2) z)5i=sL{o(ny@&#i(3mN_bjGxr$|49iAw@mu1tq?QC@DPw+`hwS1I+0ZcVy8lfsfiE z)*&kd^utAQIQIR1Fu);;dNm2muH8v>qK{3%rV;Ojc8Udr|IgpEMK`z7S z`Y`lp$Hj+58w0~2Z|5RSY7i>Gu=o|J#AYD1U-$q2f248>cQ+H$TEt)Jn zFzp~+1V>>>$cY#hAq5IjDgra9a6cu;Ieky&#I%LICbxe5C=&B{1wvtmE)R>p!9BJBYlSe7cSR#gGncq=G~{qXF7c7Y39%8@5*~tvs-;tz`ybb+ z0O^xoIA-L)>57z20lvV51`gOvTm;4aTgZeR;l?LEhvJmOT6_{3%faPUh&bg-HgLKY zLjrfTM{%%Y*fsnGAn^w#2X8wUX-z3P>%>r-xuh3sNJ9%G4QxQ$uAqBT2qq+Go0w43 zhoCvcD!^6flD?w>Ux7$+yBUY`@r_}C(=JuksDdW!XjJB6ubFW87AB08?qHro&~#iM zhU;Vn`cB}%LS^XFh)5i~YsHYuOmg~usHFnwV-rY23nW>O&_}qahW0+`R_6Xk8f->N z0}KqL_tKGSL==-i9O@i;gMKI+$Yd;-;t}Nc1=MPpqZbU&DizJqghsh=S2c9pV~cz0 zjPeyD=)p8H_(-W>(6)1t8VTeyLy(JXau$jq4=s?e@fZ1~BO=89tf0?w(k(bWow#7P

;1C?@L~f>%J{F61pcokk^dk=~5K(p_Vi(EbL=>fv5}F8w2n#4?Ar0D~Mm@<3 zb#a&9pxG^wf(?(aAWI8Sor=L5v<`XEWO!Q_h$wQUMH$;$l(gTvqiAfOP@{i7CF0Q>13=E{N0l+yt42nAg za(XD(LJjvyQIIuIJnRYu=w3WJj#lH|12KA~FSc|^iWoGNf~Y}R<{~$r$m*h^jscRM z^^u1bNGq{HVG6~>#0Ypmm(FD_>aoI5$3iI57wY0&zCg7_W5{Q`L0pQB9BxbXK~)VM z56Q(dkW0sMpO{=T6xARl*uhxlB99D^G5z%)ZABCrb8yIoJ}Dc2|05OF1ZSr~DF?hf zgWhE>&JAe{WNh8VyL^GHfgw=1U|{^#Koj(^YwFh1Z^Q)8KrZ!S5hGehjsP@?f~dh* z<{~e#A*(z>oh>HA2ymAl6g&(Jq#b|)E<+(23C>7yg$2jZ~OiF+V-bV)8%A{r^x4#F}QGMNu?Bca{tSOMxF zBT?;5RCAD8s|=(yw2_uA5Lf1c=G;hXNu#=yTpnr=LBbkJlD?k-oH6*yT;!#>0;CVc{{R0UwV6wD!wuzz2on2M zNW~8kTO$7d{|~BQh*L?$_(#1211U9tnWWcqc$=Wq%d|*S`Cx})CrEcbbwhUOnTBT| zcXaNITG5G=SO;I3i=2VUDveOvaOA9eKpt8kt>cfhY=KC(3owvatWzlwAk_{?$pOqH zz0^Vta;!f~{-01YH6 zQAj~MFif1K>3yWmIRjA})6s(jt(i;4ngHaX1rptW+(Jfo*x=*iYnzh3I|5(38MG6a ztZ^c2frk4uZREr}Iuwa5>`=t;jgC`qjUS4YBbS4eHV0Wd7rCoL`cw`mMp0WqWGoaz z+4DrAe&qQ-kYffpMjksyN)uov8HFyMX*tko4rGk-;0QnbqsL(9GYr&_4Gt#{K4CoT z!$xnIq<(b4QstmKKNqxe3g$TSy4+~ZTyna!$U_SxmitIm28pFL^&^=W6VXBo7W816 z^gZXAC!jE!eJ+Yx3e%hFhl+LMoOuJs-26x>6gqERH)5d za>{L#p#>6W@sLJFa1NhPKRPKe5qbC=DOG@(WE8sijH7PLlYmWN4=|8E6-Yr)4k@kB z^K&44pii!1rqZtvImCB+D4?|5J-wZCP{4O|3^Pw2-z$!oAmV%;5flX;O!lQEu(JB z8k-x2q!_+!XJj1bIV8h?{*H#F$U!!qi##qsUNaG`nMIBvC_@V*Zm2-EeyEhW_?H`y zUg#1y6@hv?f&c%!6?h~V3`k26T8Y7VF$hyXdq)rtj7=rW3mXW z2?p6VRH{Bq&(TH%+x3>9a027ub^tMLf{;8@!2t{*22YtwNdpra49M+F1_lyucz~LL zJhVXgvOuUND23clC%v$O8bWspZy`y>usUAz7#J9+xtsvGmV+c{G?K(xlkR~}UkmXL zD~vXBX&D*F>9PZvLoYVAPCs&iMb3Hy%+XwO7K)*i{Mej{FJ6!bM}|(B3qIQnXUvn~ z4?@#h)H~ksKcNF2$*3~$Meq=p!#AwJK)>VBhj=KG=X|6LHfY+pC~Z`7N=uCS8?p*+ z6lajyF+~bjQk%%+MI@DUp?DhE6ATOtWR$u8@sANRFi`W5Tl@z+QgI-IN?|>4#^7D8 zK*k!Cf%C~wv>7Q|4VE$&Woa&%trO&CCTO=QIZ=ah+7^j}%E-$WhE$o0XT=zKCm0hf zbg5YuqKv>JC2bIs#26$e#S9TW_?LN5aS`7T2@iTZ6OnP+{|OE+P<0I#&Ndu*V^ov{DCLzMR3kXi0Ug(QPAwgXEatsyHE^eXo0LWnz7K}22q1zYyss=L9&(`{Qr;M%q6SjMj2WdVL2B0 zOgB)}Bw{pSB8~Lyfu=^PphS&fP*c;R)@E^f8dY%on!yA`*&?E_> z21S{RvJZjG9z9w!mw~J!vQdT>$T=VfSBMVx&6^&U);XWA3T$IdC=2SC!GncFa6Ln~T+TC9oM=IsUBcC}= zl}$C3<{+Q_A6Bo3}J z7o|f_WH8WiIO64Vi;|h!z^eZ)6P$qYf>QH3>(X_@bMs;4Vi1)k<8txf@{-^7sNx z2Qm;=4o(*CjUwP2GTO+cbF_g&9YPHFcrNPFTrvwf^ky!3OAb(n7KU=kLw0&PA26S+ z$w#s+q`pS@?7&DK&c(kZcXZlpj7iEc$0+|^ey_rj1(Ty_5F|-a$ zAQa;xNgj5r8F}MN!y=^CqwUEAXLSTY`I3}j5lVFR1S0eYh=s@ws4Y~oh6FIz=90IY z0d;7B%z+Ovb+|$RG`>LQbSy3-hln_VxwFwm?f}K(peb{~^W<>Xkk>r@{~x`X zOWrCk)S(6PX5j`XK1Z#^2!Z$YBXVegz}y*C??u80^HBjjApkGs7#Ie2YyqXTB=2}^ zETg&PjS8c#S|GRl#}n$KQllY2;}9S)cSe=Xg*5iUa5a9gl)0!&bIEO(pcLE;3?v^l z4vl5hRSV>m+fbuMsnHM^fDnMr9U|p!R3?=+7Y=~WhJlqxQ8AG1T+}mL$?eT!jOLP8 zcB2k0khk(-7$l8RFAUibATW2vFghzdkWo8G%3S0#RTvn^on}UF=8{=lq7E&PHzYie zaXM=E$PR(?82JDxmoqR>d@|?A4qeK9j}#jN*v>_5ppv^z4Am5JubxC-wJ>_}D&?tc z)C4+)0O|rDqzn#alGpj8qX&k&RnT}CI0{_AqVAO;cXK>O^-kV`Gqj-vavR;lJ>`u0 zZ%~E+{xcgH7!=6OU4zoML()-5h3&w#b5Uz%a@Pr9G;_%u6+j(Y7~S|gB-8Z>bu^&` zVxy-v4uXU+7|PuHNRD7&AoD^V^dSLqubxCV2iy)H1Q9jrgwYTn7y_90W1wU$1_APV zegy3uRX|DzpvK7n@Ep)LGLSpmgj#Zg7K)K~N)Fo40=dp1B@#x}j)njgLV(Z$vC+N0 zR0w1$7=cvE4%FBJct1&0|P@5D+5C)I|BnF0|!_fL>!P~U;tqd8-^Jf85x+Em>8IunHgAE zSQuDYSsB>a*cjN^*%>%EI2brNIT^UPxEQ#(xfytPco=wjc^UZl_!#*4`56QR1Q-Mb z1sQ~dgcyW{g&9OdL>NRxMH$4z#2CcI#Tg_dBp4(mB^jioq!^^7r5R*oWEf;+Wf|n; z3Ft zwHb7DbQpAXbs6;Z^ceK@^%)Ed3>XXz4H=A#j2MiKjTuZ#Oc+c}O&QG0%oxng%^55# zEEp^;Eg7t=tQf4Vtr=`=Y#3~9Z5izB>=^9r?HL>#92guO9T}XQoEV&)of%wQTo_zk zT^Zcm+!);5-5ESQJQzGZJsG^bycoQ_y%~Ibd>DLveHr}x{22WG{TTuR0vG}V0~vyX zf*68>gBe0XLKs3rLm9%t!WhEC!xX3K$9t3mJ-viWrKEiy2BvN*GE@OBu?_${5Pa%NZ&vDi|s& zD;cV)su-%Ps~Ku)Y8Yy3YZ>b5>KN+l>lqpv8WRX4m^N)1!}RIX8D`9w!7y{?OomyrW--j3J)2?9oH-10=gwuAH*X%p z{Q2`47A#o6uyEl*hDD1OF)UuZm|@A1B@9cKE@fD@Y#GDy<;xjXtXRRYa^*^fRjXDp ztX{pEVa=K~3~Se}Wmvav9mD$d>lrp|*ub!H<3@%}n>I0Q-n^M%%a$z+Teogy*tTsO z!}jgl8FuX0!LW1ZPKI5(b}{VUy_;dro;?hE_wHrbw{IWA{{8zI4jeeZaPZ(khC_!A zF&sX8nBmBgBMe869%VRo>=?uGRWboIZV;;mnyc3}?@tWjJ^4 z9K-qZ=NT?sxWI7n;zfo_mo70}zI>VC%9Se&SFc`WxOVLt!}aUe8E)LT!Ep2DO@>>y zZZX`xeVgIVojc&GzVF?;$8i7teTD}Q9xyz7_>kezqel#nA3tVz^5hA_)2B}vo;`cU z@cj96h8HhhFuZ*ElHt{>R}8OTzh-#z<_*K!w{IEVy?e*-{{4G~4<9}-eEj&4;nSy2 z44*%LX87{u3&Yp1Um3oA`^ND7`*(&PKYlR${P~mN*RNj;zkmN``19uv!{5Ju8UFqI z2Rfq~Rs@XFqaiRF0;3@?8UnNq0n}RyXl>i5`J*8)8UmvsFtS5nw9FmZ@jvSO(GVC7 z0s4l(Xqijj@E)~oGz3ONU}T3t{mhvoI{-#~KN6IhsBNPmFd70QI|N3{+>sssqrM*vfzc44ZwL%fnY;i0C?Goo?$-+tl}Hr& z-;-^}sK((G0tG1P1ua#~M@ZfuPM#*xFZ&VRXJAkuQWNRQkTyb$mbs({-yqO2-vBwK z;A9Kbqvfwb;Pg=^&_4v$qok1as1A6KknBg584)}r?=vuf4xpipuSd&V+Jq}TP2Hb> z$SQbP0`()Y?LyCp7!r1&q>uzOCp*Ap4bWsp1Q+gm5QAnN@X<1NI3%X~1;h<8B#f52 z!y&pU@gV|Nm&2ORJEjySejGYH38~L1T@Ux^$13 zL1iIQvC6=}fL^j9YHsu<@SySpjU0ni8Zt0A(8!X}GM82XI}qj)Ij}og>JCKY3>rI8 z=3E2NoQ1Tk;XInu2;d^E+hAaz*@!k$$v(PnVd$r-`@~JBjh4DYKdQ<00aCHbz#xET z4AOF`0yL=+z(w*s4Hqtqmbt?$DZM9d#qMaSJIvypc<-PVEaB>ve}nbW-1$h+>t2fdRcWi_}q~RhdJ5A5qOjqzuBq zfLmos6`B;rS4FSS}M31Wp*BY)Dme(6TLX5g4KiF z2$ZpIS}j~aE^`OwEXUC@mlg?;sNHD-G+Tm53onhDNu>}#Dpna77|^ySBJIT*frASu zOMlQej8G}~N7pS-Ds_R#-pCtVKx%^0 zZm}4WC8O&WsGqzC)I_36U5C+r#(+lBKv<4ctTHg5x8{)cOpLt21tia7uIZpwRE?Io z)C$SLXbw@OZoo*~ z`u1O>6Lv@5-~!6TGmRFDjh4C8PS1nUJYq`S(P7=e7<0676Uu5a^zFaM{p%4oxPY=T z8of56Qe+^Pxubg`s1&G!&=_J$-O*v)K^So~aT0Q|iaBhFv}aTps|36 z9l;Kx>&6C6bkWiwNZB6q&_d)r6C-AD;r;pql=(C8iaE4BdQ^%Lq``~ESsH?@$ix#BSV(5z+sOW~lW7PZg1t<-FaCr+NXfv^lT;`6BEexJy zKr5FJKIu_`HVKVZ9vU^5tPntH)1hwwN18}NKLUp=%LcV3T;(mO%ta3v>Udk1;dbuO|l(|vRVv%rVMGd*f76}lECGy=p)@^2RDkw(J~h$I7R~JJxYE9 zRp;nfU_|sNM?zfV^drh@F^tA6Qi2%HN#Q)9oPd571`85qb<0(f*H1^wu`VtB%77)lXb!jM4EGGLel@caGs3Fs^9 zF-urnA_5Ne^XW9IgR)u-qdkYz2&B;l*a3`h!ks*L{LmyaM$6m*jQjz%`aRN`Ab2W6 zW(d$`t;_&>n^xAp-(MeqR8}DeBx!7i`t@|E?NG)$&M277$SpK0f{9p0|QMK=#G}TgEoQC$zlB{olK;> z24#*mb@4?6zFkbv0HlNx2%uSW7kQqH0sTD3|46IFXfu(7FHmVCN5pO*jHseXeS=)) z{{N3*CmjSv#};Ul#E3SP&>o4=rY?@4d_O;cKz&7(>=V#Wn^6Xo!4UMxBIMO#v}|qT z2wEBl6Pz-}7Fje|po?7Qj-IzbgQy+~MxG}ytUKD&#f-)K{R9FHTNWl)j3%vJf$FVIlsj%QI?+fa4^0Xl)BvS1kC+nIp`~;^V(90NffWoD0{;#Og@AgD?SIG-Ow|B~1{qR8TR(FqO%n_b!)f6w zsOLs0l0slTa$>`bt^@;n*FfG+YOI2ha1NJ>@%su<5MU+~~9 zHpd|k)Kf9I;Z}{7x$vMEWf0hyHqs9pBXHO%TIonDt^(DTF(A*AVcfX>A9=(Yy%9WA zvI?H%VF|eXgk0v*Vu9{xnLAX{4_(|zU0t!UsWSn*L*vNNLW^M) zq>vrmhenTdFxc(DzeQri-cd>FLIsC_`u_d6n^N#paDV^&`T*oiPE^@TrBWApo{RzA zvB<69A$f={&h`VL&_gN{8ECOU7s>q5G8di`Ml$0)-uB$cTs4NX!GxuRbSUV@n3W-z zp6>6j4?ynBV=)(1h$>fkpsb2QU!nUSd32vPyD|s{3k3>rF2qs5KScW;bydn}nM*+& zjA|u11n{q|8F?o>5?$gt6s)IYZ4u~TGUS2|wUkBY5hy!|iEZS0GRy&8<`evAv(Y2fbBb}kJ9b*LMOvyA{wyb9>O(4p>K{O%{N#8p69;)&lx zyt3!}iQZ7`K=G0v8=o@(+ zIX8k!T4Z7bO{L*)^FsnfApyFBiCXb~p4ffGl=eALw*R76rO0~&FbZU9d6g#S;Fyze zz_*p}J&tpA(L;p_4jwIYsSt?6(Fh#r7E;PM488F^vf>E;dU|kJI3RCfBFhr2n$U(7 z!B$}*C>+*B+5U?$po`o+$5&io^}xUh;@I4Sw^wi;V@v@S*cA6AFau(=%*70oQ4vrG z;7GcVv^XNB((tUOhlWA|O)qp-Nzym)wvW{`#<|UT9(*I+>8nh&qq5k_zf;Bub%xqSB5i zR}t0PrDUWBd6gQ*_yO|v-=VS<4f{wgzH!|B_~V(9(8UqQqh&6RfEgA3{~vn-hL$@9 zluXeN`p_jXsz8qd7ZOHTCw8Dw0Hr9{ABeL37rhQaS=KN#VtYTfbsu<2T)a(OaPW?n zxsY@?O42I?@EyS*Fys~x5gTd*a-slrkD4Lqs`bdNQE)+kPGAhh5;PO40D0pB14euz z+e@|;P@CvNA&-W@!bkvjsd=A>!5fSb7s@>{+Rmjs42QD`c$>PEPMZ(TfLo8eFcp?_ z5p)1X(L{T15FA-1dr}j*U5IfuIa1+3lMPu^4!HZ+7Te(7Cr!9214TLwHbo!>>*zi- zDyMJ?o5LkIcPY529wxCCo2MnzL7bVhBBaw zQ9vQLf(O#?!~_zSaRr>q!*HKB=1?&IJo07`1{&PJIa=o8kI(aizIw;+eyYe~YeB$@ zqv0{Wuz!95f%29C|5;R231$u1N5XlgV914{{n^~JHGH9biCqx z(3y(J%{d%NUx8+Kp5sl5Xp;9)N&|GKlC>!td1)%f`ak4WFviFOn%f4Hdmb|iaSh~R zFL4bDkjf#HiU_0ePq9Zw+qps&1+dB! zy@Vo#kF%3X_vqV?o;;DgK~78{uTI4nyF^*mfWDNB?taH@A?j!VC`fP}I*PT#4d_QJ zSdptXq_P;d14xn?Eps8kb$@-m19FuQiZ>`8+?^_j^J!1w+m?pWKBB#I2-$Fdet`pK z+Xot>BvN!<8b-itcxpce%;jDL4Ez5drMSXSjhrP0?`koOpnBx9>;G zT#Qsf1%dPZ0mx|!BS(%Fy5K-YPKan>Gm8cg)=l9naV2lf)mq?`Z2VIE^3Nd_#osm4JiCjHlY#%^r z1rN@d4UE|{95+;Bu2m4geJ2`HLcs_VPz+FnM{=3_ems>Nv`yUPM9Lu6gJ**TSxc43^y>Nf^;DZ8gG4+AIe6A8U=1TI zgOe~XkXGoTG-bg(J7oKiTfu{HwHSJli@lMH5mp5IFG${|eya&mqJU#-q?Eb$aTT}% z0ocy_hgNw+7P=Ux%@58&Fyw4SA{)=VIbBX7I8S){0ysHSM&LVdmBav}m2%uWRY)sz zk((bFF^GJgBLhZ>Oe?PuYc5)mi(^&+?QS$;Hn$)Zi?l6sN5Y6mX2a!uOmL zE_AVO*2mw6AvSRhCUtnG(ny}bA5w72q;()Ixx~BNE(4LTDTDNhhLfd|3B`jG}O8jSc@O*)*%n*V(g0ek38!^{h>|lE+SGCt;of(s0(?20|NuD-Dzl6A_pv*6y;nb z!-spB`ySi1o(v2OcnaMA|NkSkCGb`A7}KJ#^gkTS-2b?{wK%$W6eZOA^9zu3J}hKu zMN@X$4MjdBSu@UvAYpg`Wk46h1<3U)^_zSc){!89TIAxIO+XnOAvlf;vmU8fr2c^m zNQT!B>#+qKSFI2{@E@tn#l6c1&#eN(vdsODyIV`<`Bt#Rj!xg7pMX5xNKrWpTD|8` zj{vAGAgIw4-s*_#{`38a6~hV+3DC8N$SNpjV=R?|dV_(4LKiuJF_J4vnMKNw1?7Ij zZvtwOi+x<-|Nr|)n-Pg$hl0|AqWUN{a+!PgE-b?6Nn^w^{-7pL7DvZFf$)+;_ekwm2Al(0h$5Hh?hD#dPX-2t(K45Wc!4NIueP9xlE9*9h~EGI|08d`X24SD z;ye2VWYr*Q8o>QT9R}|41#-@}LUPml^|)5^fdUjiHgKr#$6wY$EJEZ)B=fMZ?u2L{ zo}7<$%mT?81_SCI42fK3B3navr47VW$OF2VYj9DDbYfa55JPE8qC_9giCcs!Vq+HD zCBUO)E{So8y~GtLAbyYrWpIH3eH9M=M(%KK=l=iyAE}dsoYyJx_5OO~h83Ez__ziE z_3McqZ$#~xLX4$G^ZfsLBCa(AS%-V8KZyw(q#Re5gV_2Wc|aGVR7DxkB|H`fau4k> za;C&NmIYtbNbIlz_GuYnLy>4-BW0UmIJSVj#8n`2!3ZP}kw@Vf7*Gpc+)X`Dz5-*a z#~8#_gM-AC*%=scW(0f=zmM+#3~*>-B?KJm=M!Dpg6+pPluKYKAXpy(;{ALQ>I(yW z%U}ptgf5M(3IPQbkyaoNvtYF9PzH3V5J>25Cx?&hV4SUaSmGphSOLeJ5A{a}hjW>W zqr@dLA;QxFTGveh(GtM9QU{dYp?FxAx&INpH>h{v6v?f|{p2hNQ-GaB1dlCZ7)Xg8 z=3Xj{fxmZIH=Osya!VxKqKyd&|cNn|4L6R7l>M@4L zp#vd>GTevkdr}5<$!XvUIMlBveuM})Xpmb;P!|(B-iK@qDjVBKAk=W&6mgrPP%XmF z!%_JmH4w1t1B)WhSzu10p~Ntv!2#AeAOw7CD7N_(n2Vs1jO+Arm@+7hwXA@~8`azP zNae}!Ds!sB2YxBR_fv?bctJOfYd<8oJ1RJ1G-3qeFPUQ5I4kyuf!!` z{Rd{Uz%GJZ<{m-fpd<{Maxeyvusf7AQLL*8$SiR&3tdou2DyKOFMNnBcu4c!pi+&y z@*yI{uP1rSgF(T1N*Y^O$|fRvpSS}Zf1bscIzSTyB+V}1b_5oWfovwKm4>|10wZuy z26S zuYpV_W~l*k0|K)Rgec?~7%-c`I0Bkx!ib>`+(j;=-A+_pN~px8aXWXo>_fvgD^2X- z7PyiMYN2ZYiBwRMM#tzfl;&t$4jNSA$axkeKydfk@Ao6G_d(HwokL;!77|{V6Z|;4 zrw|PUNt`9F0C<}*ai{!Jr_{w>=n4=q=#4x=ikV;$r5pppfS>1x80jEX3apHV*|^ z*t#5$k5MsJ|Kqu&164Par;tF=cmg~GF^gQ{cgVsGL1y48agmPkz@-H0H7G@uQujU9 z)eFRw8BkY%D9lMTL@|eN(h50PXvanj<`O7!@prKx4#d8&2^0t@7^0YZa77;|%#blyF%=1<^nk=fwvpCssD3ORd`yixeEF*1!da8Af@8>&R8GYC;6Yt%hK)GB6-g0;&l_6}yy=FknrjuodN~ zE<)xZ_s%d=EXueVat(@X1U=aBkp!9q8ExCeDXi|dFgbfAI8z#x!7 z-E(06W84snqdP-fXyKZB!F%30F(E*4sSDeF1rJFOgW%`_^6&wsViYq$aYO- zcexL0<`TS^2y1^B>U#*~fSip9#VVCo70DRAmR&OcxQ6au9fC*Nf#W|Gc< z)eHD~C<0iHxJI)HYexVYR`4M$J*J@SYl z$Wa(rf$YK!G^mMg9KM7NauAYw%+XR{!0;ZGcAwCFTR58pXz33* zA0tX)>iA|jl({IiFgRH-;NEkJ5o{<$3+9|Hl6vG(EnJI!G2DWrAH)QeNQ9CSxj3dnAF;&cX*1gujEbp-AKdn7&BnER1W9)KE#qwd9~ z9Zd|^+6S1y3=Bja7=UIfn2VIF;ieHNIiMvPNI8~F01}2_eC^+t=4bwh|XtaU~T#0+)Lw^+5oV}ELS(OXLK%XB`Uh8U2g41x1m43F z1=K`z3i}8aF5}?h*oJiRmsUujBmg%C&OjtpJLI2DTH;WD6y-*F^xkKK}s0t!2{-# zX9<=eUHrRtk%w$COF|UmNG^l+udlCnz;(i!gF^u^mxn@{xhUO6q(CHwi7idyzWo~< z_7H+({}ONwQUx{?+qp>2hlCFU1CbLXnD==H?8kn(4LAf5MJ`H_ejoi_ZAFps9ln|i7iB93VWD8M*;20`~7QPrga&Ua1E$Kw^!JuVgcmzG9 zKzw{73`j#UAf*_XvUUGNha2RSDY)(AbxpA~auMT8M7ssILIR~O;WUkDG@8djA%K6q z7}BU1mckjO3dXbzi^%@|02ECi7ZAb@pzR1)%=-TyVif-25v&?vf*5rWfnC-}P6g*- zm^oCSks69auAPf$dm;h|C4A0w0cQ^fVFCk#fI~fM^A%}b57M{-O6V&< zPIE@<$TEP29?(i$1_l(3gOfwVvVCxf;Tdkk7CT@)3=9kk)IGfhPZ*+(^^jNOVrk^! zZR6u{4o-l-)J5rA;WPtP0wXDc6CNB5AAx z{1DGTJB=VKNW>WTx)3OF|Nlqw07{ucqQ%&hBZc%(D|4~5q+n?i)RINbZA3;mLYaU= zLVf-I{rmf&XN^H*u(SZcp$h8yfKnn-a6&W`%*SvCC1X-x%V5o1n~z>5?3Yk z|35}LhnYcO*#kAbhf-9KH+_b!kxTgz_?Vu=U+R+4)J63>DDd$%bU{fNqzHB57v@fs zHITS+0a)?=0*n+7HI`@!v)BcffOwq`wi_3LUjGv;aYxHstU-xo9vOT%AIX=#5SS9tp?IC*zo;+QgaNRZM2xV9vs%>wKmBKDU_0eydoD%BbTbf3P|3n zM?b3r99mEU)|^06Pk@QOZIZwN`bd*#SQaiI$ucnDY;WG54>=4K>ShWk)Or~*(naQsWM7E6)ak9y`M{d|EuC59AHxE(-_hY5xVWeNyxLdESHs0?^09h)Oi z8=Fwo;Bg>qs;Mc4GPX`eA&+IJC~X_LP|xG2rocgmW2GWgCkBO5P=XD>GbV~O_>HA( z2bX(bBN!MMP!=|zZ7qVSp$-i$BtdO#`_$7zdjpz@2iGgovm7K9sD7l8FmxSI z6`=Lg=u-dx|3^vNPkC%*B$0;gvtOX=cK4 zN|_3zM2xba2B)c@q%deO<)aD+f8r`dvBVfi6E5Xc2^*9{Uhto!fz3WFPR2Q8jZHtr zVpv+)pfCeroWnTSECrWWAYCww+$}@XfTR{p2E+w*@L`5Pj=3Rkl?&Vqk{DzTEg+4E z;Od8g{DuYNZ}nr*K)euAJuo!dxma=oa+X5sN{|$%WGhBqH-i+IxXq(>tx0@bV^N83 z>=3sXaLFJ?1hQo~c1O^#&_zilxSWOTL{v8BcnG{&M^#8W9=`4e3B?Cep#zCE zdZbbn%lH>c;#PQ1%vBc<8>vE)H>`t*N0KTkP`Heixu8%0W0cGUiA~fjMejlvxdlsAwrJ^ETp~~c&wkG6-XLLi74u;#n+M| z=nGs5aOG%}LJ+Q*R)sD~p^3{$I71ZEt$52g@O-}lc?~g~ZU9RlWlngIK^Vj@pg;)< zkY?Ol3y_pz@eOgQ8)O4M>;T$Q4>~#*X-E$2R}cX@A7y@heFEmGDC8A;@F{I9-T~Q% z7bAQ@p5?d=M~c>=Q08K`BvD(rAdey?9Yna{VmUZC1b`2~0Ud_}$Nly7^#PbMkIfLI z=mcjzY-&)%kTif?J75^kh#`u5LHq9^=T2Y-KDt8mWkg7x!z{=^nrTz$qKvDPTI6CG z2*GCrdV*+iCPAhj5H<`D3tm(pk`{txFdyZ-RK!Mr{r!aZ(__o7AWy<_0Kys&ix!10qDu+h zDg&~dc#OF!7w=FY@--#2=)oYhi9o@Hgo(8cqX~k0G#Ftzwql0NfhdCnv{U+sj|-5> z{qyS`5^z=%AQiYUtmeg5MBvhcB#y}S*a8DdA<0anIISP_dm=E4T9H{3*_Z* zkWqLr&U8g&QpV7aGX)~GE3mi+d!30C?$nkG2th1edwU zc?lZ5&;kM_z`z_Vb8S#93<_kft_GV6y}1`=76bADMi>sW%o@>d;6?noAX;hNrD}FH@h%<$OsvgWRAhH<5<9sYq$m18_ z_<$4mTn9G@qyL3-Z~>_*h9?BLF(}uM!(D)tVSw|x2ZU*~WaCBi3*m`X!4yQQ>vn>a4CGz!9sQDDL z%>DoWKfW`z2e8mZ?n;wd0%9aFyf;BZ8&Z(KgOQ|KNmOj(USUGipe}k=fTvk>%aMG9 zrS}Of#b7?gK`SJzr=(GX?j*ALkdXz_i`@OlBU2DRQdVGK`T!}I2lu)KdKg7iLd6U!m+x-CYOAJrY6f2*l}3>=L+|<7iXEsM!=}c;UX;05i`*+=G4cj^w-nF$@cd z9630hjYS`*;f@qbU?x6S;Vc9hNWahl$vN-Wquy)-_X4gWo`IN?#?Z$=;HDzk3}Pb1 zI!64VHk25Rc%GcO~ip1Oj zwH=c}b~lM3jnR(7<0jmleNaT>4lYawBa57`hjfTRW3V2kfuf5X4pK}G;xZRYloK-* zhD94FeUNp|6e4huW*VSnF80P7#42=>#F7AEEj3u!3p^~V`H{;md}Z$c|NGG!Q7{h= zM4^jZHN*Sm#04Bik&9>V8SY6fu;+;=1+lmZYa&7}9kD84U|=A;ByX?A5&+Z{x-US|#S+MC!@yobB1UGJi`kkYE?whnhGD4!3ve!> zK}!tCBZlDh!5G;UDZVh61DQIp=31=RhNF53Z^I2&n-6CUVb8!=VgxPRiQpnd4T~03{#PSxvB4QMytkQxJ^DPX)QQlTGp7cEEwRzv9^h^@#)Ye~Uffs`y5uw6L_R|sa{Xn^5t z?$M~wMNTIqG;;p`|BvAy^wa_NCYZo-_c|y+qG4Rs4cG{DA^{Y_Xf?M$0@lVWuBkiR z?gd+ho(OT5BJiOicu|UTfDSaQL3HO3?2N%kpzVJ^i$^dQcW9C4A*9STSj$|D3_)~@ z6dWX2w1Yzut=K+K^a&hb-7w-mz9JX2sSAB94eX|YAg~p=*c-Y3(XW;x>|CT|1Pd8_ z{d4SbLZILvJb-AOTD> z5*E3*A__}AOCW)vnS`q|NLs!`7>XPc255;HSD0 z!L`^Af1W^VMdMw$47u+e8gy_doiMNzz98V0KbYW63-C&dUOgv_P^Jh$O~(>{rhwk1*3RIXq5L$uU77K2F(OU-h;xLF8;Uu-&Nk|bmILlo08k&It zyjFm;2m&=F;6Vsy;G9{b^|16Jbx|BpP#NS532I)+$DEJZHf9ZV=?t^!fE zV6+xN0fKuf3yX^w7zoe6<8%sAIFnc>BV_@QlW|U^65q(haf>5%w?iC`T@Je__C5vv z)0@y%Mc}Gd&@Dts2jI{F6T@Is0n(ZW`-Tuf%QE->e?qp?LLO&R2ps?D6*QhxvBBzb z5ZH4#F>8D=48&3ipa%`g4nSP z?Csq8fl0+M?^A&$p~M|=V+)vRnSt2kf*Lc}+XlpRLP3K*$ORNyAqq~yC5uWYbJ2&|@T~eI5VhC`5HTAy?-LwQGA$%|Bb5XwO+YNc6@WT@ zg6ablqY1c}YSNf}1$;xfU~5tQMSOvPt48-h!0|jKCFETeETb*%Oc>e#vLmV3!o%=CxC&$ zfJmKC0|p^QVu=f`QmN_z`@)^p=><=_)1vBagtCOf2p7KsTCUpf(Z%3RFS0_Ow=5s{0%&_zpp;EEmG za)Fu%POHd`7QDd%Y4kv~f+=v<5v~U;L|+2=3<8Kd@Xnrr9f#U#Bc(vVQs^QF9@umQ z0V!}Gu7Z<N$6H7RZT-xdkYr0=5>J_n8sQ*k;b}Ax z5gu3y1oWwLaLXFGu>;nF6!hRi8RQf!7|UTXsMC_9b|H!I6Cov-H4R479@7X^PZFCy z!RCO&3pH%;6oZfw2UR)ABlgIH{zP~V>`Vv&Su=pJ9*axy3@f0FA|YiYh z-@hMMSfklYVu@=&bX1_(Lx78vR0ds{i{v&)GRA+x6#<`uq_GqT=q&>U1_qRFA*lF4 z9wG!6$}s1k(wL3h|NoJjV9-;@Kn|fF#_%#Rr4q=~2)|(|iSW1|!$Jn!3&y}l?jbCK zv50XZk_#Zk7FaWBbuxNC3Ul5I&yrlkazLSKxpkVPp|okle?58Vl+O;CTVGMWXW=P;P$3 z+A;$<4tpyAHK`L>A7gVnnPN!s3vwip+on<5etfhLmuS zZ~+~4fZj^NJ&=pK91t8;s6obnYlRWSPNWcpS`TRzLuBz3Zs2_x5Vas%(Q6HeVb}{@ zv_cD{od}H7X29btEC%g|Uw9!v(S<$d`vb7nED*0^B@GHNu4E&v#1)|J(LG2>WssG* zNG^kgEK*X%63e)R&i5zaDkz}_laiXCTF@z6Z4;DcG4dD%F4t039HaM1T#<`*cqV#T zM97JlB>~E44VrdL)u6D&U-2Osf$T-n!WV543bng~_qI2bfn2CtFp?|wL zFN8Tb#uY$1QR-=YB@ak3wJ~bZN#s~A$Pp+t1p`QgG>l%J;Xc0{WG>cngUAXNIf{wY z0Tns@$7s!ZVpBXKDG*iWu1B6Vxe;@bdQP@nR%L(jAWyqi^ zbCKKy3mY715qo5=Pe4@AFaz+>#2SvA$6@B7WLH$@!15SGDG8&LsK$`TL(64EuMa{S zkwwXC_X`{XklR@}T!wBnLA&?whb#d~0G}V*zaLR3;jjTBjNEu5txiU(kC2BY@ZHpc z(#V9k0YYLXSZFZ{k%p0wREd;gASnayh&MKn%nzbdg48K}v|N{}CaK zZ-5Bo#Q*=#7a*D#6kL&pYz)Y$6k$BICx*H34K5Jx(27J#Dub!aMc)Mv8Wv1Kke#vyv}yYc;eMDb=o{@J?s`ytg5#7a7n)ZgQaE4+|`bTE~%tdR3fC8Mj6uci1^&m~8VC3E<&Ok;AE{NF#N;1?WgfG$Jw31v2G^gUP8&EAl z9T7oFiekU0aDT4{M=|K4J^83FaN*T!*r$2WJ3Ksfqi(9$Epx z+((pz4K}xiDd935Bc!3mc^o3M#X(sG&#*bruZnN@C1J+e`@AVYMG? z$psEP&`mTr&Be9932!+HHw|Jbz7h~ROoQ+s_{<#y7i1K~6sTKa6j~XHns)Ko2r?0l zVW#2Ssd68A6qo!YejckI5Vq5fMVE;)czB{*HaK|7T%?Ks7Se>{5^t7)8H1NbOQYaW z+K)04iN2W!HQ|Fbpb%*433~!XHzgeOW+r;02d~+%!W9x)a96_yD~L1;tzbjj-iOx# zL`kCbA&9Ay;ijTj2kZa;M{cTN0^H-c|MAR=Bif~Kn=u)XP{N&%plxWRMlN_?1Zq1M z`gW>nlcxq&j<;6 ztkI3^L3}eG5F>~nF*6Bhr7673`Trkf&IbK>9AxJ}*{FpV)CCF-3H9qSt%7Qy5`~(< zNIZ@WDN!JeLc=|eyxJU}b5R>ssK;2~(?^^fYO@F_k_c;uRUXg?3HXmR8VMCcrtp=x z;5H|+VgwskIl6y-Jp_Pnnua71oXG)Fz#^5f(EBPd3`Y$Ph$|rNcUX9!#wx)a1=EIz zMJx?>q-;mY92Al<5SP=9q<@J!INP~ck`MlDPOX6;%y~3WC61IIP+f*30ZX80G-@(O zO-K$2{Uj9>Xh!4bLUJ$&P>er9(H(?^ z4{0C5j3?SnAd}GQBL@6KQuuNuzAdHLdQJb)7W#ws5QDsc%lXjTQ;{0Ekf_172L~2C zAoE}tCEg)gVN$rP1O*TZ24w-LCRj><%A@!mF~0|uC7v3v5?7#};$%p?FA*w{B4V(# zbJ5BRP<&$_YK8g&CF(({$;TK85pCZ*qMwB(0d)#Gg)JYTxXvJf=%uLWX5;0fjw6#c zzl63t7q%q=KCwpZQs(o-jP@8fIDn7jo4+4%UKU=TK_%ghZb)#Fl6SDAFNh&nNc_2S zJ!&u`>qqO?LtKqnxHy0V8>?c_rbkG6L+rwU4K$z?eqhs4hqs|_LC!cxS)I7l3pN&c zA2>=I0p;3Ud=(SK7@Q<#pg`SDYl@PFIZodYBY_kVgQd*HEU5668B{EB;oII30XM%M zc~K7Patfq{?FbF1EJ&Uqlz0>z>ibD6aZqi+$Z}#!Nti(>F#ubo0Bcxc)Jrg3 zaQgoK`UE1+fdaV>2^%;B)c1qC+;GFNGtfq4k&71W8W5uBBi%^WqcauoE;Ge91c|mY zaXn}V9J>4f#gc^o|N9wm?X!TyB2t?cB7p1O4y=VP$YQA9VG#&%0O4rF)P~e_M>&cX zmj|FG;G;%fiHkb6(9i&h4*HTPl_#ij$Fv?}@CqJ_)Gcw51~1_@ATv;h7LZaPvLYll zTFHRvF;o!)2M6R59?2jQnP~PBQ8}PmfKpY!GAFE$iFZWhJ&^}opn4pGC*Y7!kFOR& z-&;&dGZ%ei0mE{bKmvNoLAeX;Q0`xy1~0C2(Quq@$IpOg(Yoh3L574y+nj8 zwCV(TY>>2bG5c$%Qvt}HBB_>ia7d`H2OTPpHiZK6I~?P->;M1%C}j}?j=X~8KGc>4 z+zz~q0F+%yNQRNXgydG3H7J96M41B938rCfNT}ygixU*%&e!7$S+HTG5e^0Ov6k@Y zMJ}jPc~9gG3#fe+obFM;Khy`?rGQmG((o%Nd_cq64*!vgE`%mn*n*UyVaQR>NcWFH z6O#d+WQS$)8R?`8R2L9k<|0+#&@vaL#AQHK3TQqc$c0V^B7%c%tbr_XQQNt9@6yfF zNERU~VsIp(4b*`YLZccijZC1%JxC>1EZ|U3kJ4X7Et1gm;8}c%nq7%lodjzdqFF(R zOX<-@XhDdz*g_6RbT(2hLkzb-hjVe366XsrD@#HiB}(3*9{n^_jP~6A|BzNEp85dh zM^FJs*jfSy5aR7!f#$_vwt;C-DyaVtbt1xUfq;HIF#~A}Axdx9-eOSo0yY&ZfnFJb zY=eyr{f8FXATd(LbCEVBf-@p&uEX8x#_B*MK}eKAT|-xjf}s#3_mj_r#4Xs%gQJ~` znR9V8J+U9C1ojD>5WsqDJl-;w0e8kl9a_Ly`mBc^=mKpT!kt4j18q2vwCF`ER&e_V zm$9e~BIpnbq{6}BX$p6v5DXWCdZd~eqsV1ofF>Fuyb3A+30S8Js8nSTT*1)yXe&QA=C~2fW_E zmB2va__q8(+)X2L;4h0uiikl`=AyOHK;aHfub^l`!O(?^AO+a5LISRI4NmyjHGz&h z!P)viEkdDX5sITg98d=jk`l3H0G!sMO5iBlK;{#~r~`)t`;hMq67HkUgQGTxprsu+ zpfT_nq3*aBc{r?|-iHqe(25@v>Ps6xe zdLCSdAjU~y%?o_v3Q)7K6d;a(<~E}#a27gj)Z)uWZTxMuUl{|ALH(w+u{1Wpztp&`Zn7;Fe%3RD!3rjN>Z$1Yd4G;AjE(&kX1EndfqYJ3*N0defsO<$$6^PpmK}L~| z$sZyE`xkXE7Lwb*64(i7XB(xVixNI~O~5;SPrBDB)PXhHki88py|7tBM6w}p2n(W+ zM79#TUICsuP~@<2KxqlIXAdR^-HOIQ#JB=f3rh4s{0c5$QN_VRP#yRwq#^=h8id3c zxW;b^T$YseVc6$m;6|Y^5Vs6N+=oGu-7H73h6)^{038JFTrAC8%*G3JJ^>?4K>|b_ z-HDp`K-$nS*0C<6kOC=3&fp*e;c2)4b~ig}=?Bt71SU93LMYBr+kwcg#HJJ8*+w2I zL2)M5uz(tcFD6h7p$muL&;n?r9ji--C~*JdyF7w{fdS|0BS<+z zDoN@Geoq8uGZ!|T2=^vzJ^>Q-C?v7Nps2+XiV;u_wgidlHslNr?tDQfD&X!!?~^Gw zI1n-RL~+7Et+n740g|&&nDBgv>|OMT973?Tq48 zTw_YaEQo$j;PL{TB`z!#5L@QX2aQa@D((NEO=@6|lU5T$%5AVl7y&v-1jdHY#JcD| zw51Nw1trOCU6*UIIzAgAq_PL^%%Wp^-orbswLK4@= zg|AS7Xd;=!wz7ocwhYOxz@q^vArAc50=(4)P9|UiEhFLV%@SYY{zqEm4YmRsfn20Q zLJxIf3AX+QBG>PLWnvm-{1>HFaUaL^LBtQ)L9E3>B1I5M$GZLkwmFl*V-;4-VZ3 zVQdFZK+S|x3I(_m9Ks|5ER?JVGMbo(CSWENrI9k}fR8O;VW6=BoL8y;{}1WHAxbpJI0F%qA?dQC_viK@ZdsH zOo$2B17VO^fDzHirL=_$_XxW8$!(a!4WudqDdP-yI~P5qkf(1!p2j(Vh-1naqz8i6 zGa!wKL7N_s1Oy>bM?pbi=;ak!ip6XPLo7lfksIw8agJrk4MPo*S;R7tVv~V^0j-aK zVF-$!5S0vSiylK4TmY>a0)-k3D+EyGY+#ZO%)wnbfL)B@S%N_W)`I^ebC6#NmALS| z^Ud6*(p2yrBo50U$Y8qaEZF z?3m!8A(M|NV#;N%UmpFAxd)+OF9Ba9ub@Q6p&lYXq_yO8UHbh zd(;|C@nBXY(khKzVegrYgJ)!vvVlp(uQIi%#>OUk& zz*`T{-MZD`5|nGeJNG0St* zw1wUfCOiy)tOH>;#DU0i5GNoO2SHSjN1}uvMnR8eCd$YH@~v+W7ePsUc@xtc3^>n% zMYEg~F3vH0s1qR+{vI!CZA7q&gB#e+qxJ@XUuydd-ZisHI6$W;F2vJxK0x<%UBygq>!XRQ<=t+}c zj1y}xHPj(x(}6B?vCPRJ^%o&sFO29y?2tqcjReGC@O%cOBklfUNsa&iV;YZ=xX|2& zuOx!H1G#mEV$1*FeimZ(3|7tH z41MHb4;+e+ayAwZU@P~b{>Pw@O+x8;VyMI+06CWuiz~oF0_3js#bFy*7(EIJjkAF@ z(TP9`&jBuTu@r^KMH^ZX0gf%aThRB{!xLiy%3uJJm!YPBuAjlk+Q{uhbhn|D$5>+u zx#U92WZ?V-vl&cNr^rRVMTLO@+4SH?LiNT9*hv`i0uC_@0{;ve zYLw%Nz5B$CWDr~8!qx;sQvjs(g_-@K3l`uK5I-y6yeWA;N)>{ux9r2#11}*~wLjb%_ zfUF(L-XDNiU;7`e%moeFA{w($4gaA7TZol{kQ9Qml)yMt2yPH61EU*)6n-Q%SCNAc zH7%oBh@FRbT)}}rGR1Br5u(U#9uDDegF(!gAXOrxm8zEOnWW_^$s!I(f#7#w;? z1rwyU1}89NCn2*TW4G|W4s>b(v*CUp97mXkji9D4B$Ls5XJGe32)qtLG6Kv*u3AYh zy6}xF;Jd^gY%>J}dcr}UQ=!0UO0^D}G8f4qkYs^5aDWz!EK=CZj{0uP`shEcd z5G3F4-;b}Ah@l@X&KU$i#VuGBlHKqFC&3aJ1d5L^TkhxQ6TcLg(Ai@U=OU#KhycDg zhRh_uRX|E$Y`q2p0nk~JkQ9g@@eOl;D*%L2Bo>kjF@g(I07)aJBz_UpUK5f*3=Fg^ zasU5Et|&m(;_nIJ_XL$?k;;JjBS;*OGwFk&SrDbffY^*tr$Q1iL=r@jcjzIeP0&&i zsci}}9o|;NXo5qXj3+9P3IvqMMiK{G!9cZE?tc`c36zx>`*xAK6euGU1lmJLEl6xD zIo^Xd^wuYUrq>-D5G5a^io+9n$Wrh3*B3wxNT{E`AITP^Ha7l1L@jwxEWf|Lo`egE z1q$FJuE;J#WjB1p+QY4kL)upd=m# zfgFW~5lI3mouH|~%Eh^&o&obd4Xg%GAc#nB5I>Vv%}`)5L9LK90e01ZjxC@iCXj=W zQZCFJ=!Gs>ORPXjjVo@{kfcyan_BKb9pE$g&8t z$YG(RF#^q8q*#ae6rSf%))f<80FMY7v|RiiUulL>nUdjOly(e015xTC#DVnt`wLJ) z3=$4_NTQ|)A@Pn>eu7*Hdrg9 z1jphjq`C{N5I=zkC_FyFVg#hkj>UQ!w{gKvfdnPOa->KB%MTm@P7@G^4QQE*$h;88 zpzlG0h7g7_(rYh_Rx1MoECr%>gdhbXh6bz&4;;m?On|HfCiWlOf;1vVhM_(uM4?n# z1kx9D(GonQk^AN-<{%9@V7DJp@&J}0m&*Vtx!i!2?)DE_M>97V(0w- z^Pq+^qUDC_GF&_d0>|LP?1YR@AtexSa6KowJu0yic>wK$rQ zD1CBx@E~V3um+MR(!jX@tQAHeQXnF6LFB-NF@}}c%6UjB3zI<#RiylfzE*&N>|I9i z;6N}?TuC5#VU&nSxg0f@66{PPLJVT(`ULc(4hcyFDG<;P4pxNI$zh=+7^G?q-7K^) z7r-1?LbwbUiu zYmn9AWFwL@QfkJj8YY37l3-Rd5V@HIW(xTt|X8*F=`#;O#-N+p9F133QdE0g1vQz0$lfk60`_S0g}CVM{^;a zeP~>eLlJYlF0$LsBab;lZgj#~P=V7jd@2|+_=zJqLsBN`l@(@}1{4Tr13}2{$Hqn! z5+sc0f;|Va3>D*>^TTF0`C=$p0^|s+`Idb1$<~PoP6i|<$c6O6;E+Hnq+s^qN*9=M ziD!c(mTrSJ~X`T6zecbH>F9u}wJ6e8|;T`aCc z655Z{jztm%F~N?5Pf0-5h`~!>kOCwONj%`Zf+R`=6EfO?=0zg(AuB;j&&a~~*bv{K zS8FMqdUp=j!fa~TMT!}axCDm{5);g)69Gy`NRbM&6?ct_+{A&XCTV;D zrBDIu2bZCcKtt)Wf-k+rs4W>FE^`1E$Pis1vfjY~eg`2qGl7j}0JW4s(pZk$$CbSx z%1I=Vd-U)^2)h{=@r+WkLYxgH5j_BqQSa*!z5(&U7{fHERwRnb#VyEMNV5-O2P7NA zH#ETd8X#pTH4#KL(WC)2PICSK|34^wgWQ6F!KnmRO+z(U=2Dli=isY7c65 zM{z!8p^J1NU_h+XftyZ<0kIuK5|wJP z2D}1FVj^TCRpilqj%Wc<#dvZJ85CtMdf0%rcjEOBmPo}ps0+=Xut8hoUMVOMA>~o9 zm1stz6lM_hC}k8_4;q1_2i}`OGnTy5|IzG0a8W!3sS^;As4NtvAP=E5^HI;qfiI#1 z8v*eGyqExsffm4l48g#pPCda)BaTK&wHP+TS5HISiz$ysgg)ghXtgakjljbaQsm-` zIH;q+!2|XfqBaMM;UmyT(?}g!K;F7ZF!6&f!+<&#nWF1JE-WxG`e4Mk9;TUgG*apv zxOOf$0V2l`W+%2EwPON1><&p2JOQHx7PLTzjKX5smH?B0X+!UjAXx!nVj0wg=>^l^ z_8>$lJQrb1ACr(}z=q-{P}-XK+Y{&+5N%W$r8$l?0f;yX79*U|O=Mt5SdTPBj^Xn6 z`|A@Npi!0qEG!^1Oz_kJS;z|K!c-yCP*;P) z6&!YuCNHuQoNQ>T18M|0)jcALi72m85+l@7vM&n8=_#Tl(4B&spoubq28xi&+=06H z7o+Kg<@!Veq}eD?FhE)c&=`eKXr%{86$rzMKoA>IazM0zNc5ymFt6e-)BYom0K=7{ z6lI{h&!DcM4uw(%!O9%$M#Dk_L@8y z_d>%ta3v&=I9*fw3R+lrb!YE@t@&TB`$z zd{_mIyr>E+gOP{`WmizTM{^!B7b$&0vOi?6JlHNMLBa$GvdK8v;Lax0Y>e6pMHjl? z&|QMsFhKPw!WOi(dB}#M*oMS;KR*B?31KaM!_)%1u2%`B_G78_-o4lutSN!MuIvVXmur0NMmE7L@Tr-fK44PF(mz{X#!mX z#Ba!<%z!#5h^~Rge5B$H;wWfj(b!u2#v?gupxU|Eh8ED1U_F-OR){Qgq3H#h#xaJ~ zv5bphsRJMp1|jjMy8j5>uwov(asr|kOyU>>!5>k0WFZY7u+f-R6RJLh;~>h>lOR%Z zz?k2L=m3*wK0q=RYv8<}k3O~nHU&x`)-|KL6$g*No!#I-$I^3xS_Y;R9O~zz`y7XD zgoHtbOu+yD?+Xw$64(k5fxU18=|GyV02jGv;fcjkXgvcSQFw2_fU^yaMJq@MIsD0( zy+=x6U>AUl#D*a&-avkbVcaV!vFWF}7?Q&wE`k;VRJVu}1CcV>K$W@JG6;OWAL^F? z^yLL0acqSyW|DvgJG3xB@8zQn6N8LJo4bd^6%q+G39J;8K(YWcj;a3rr_gcfq%gr8*zH3CT=+TvoQrafjAhP%KOAY&BueLe2xGT4C$|NleQ zVS#z*1gNydAAj#jD~v%Qs(={4LbeZk_9m~$g;m=a5eAJLLKMmzE*XX({Dm382)i*e zBz-qQAY1}xp(JRKFTmX(xb%Q920@vN)Jg&c3J8N6E6Cv?fOXX=w%sn6DIHuS!P*>1 z{smbCI+GOH9xxkPN<-u^N&I;h+8_a~PX!wWzn=we5T*-Z3dy9A0}x-9Kwo@}xTF(q zF|tt%sQp*e9s)|s40#R@wL-a%tA(qOKu$~ZJg8d@4@j(x`Twz{3I+y;gnHads=-}$ zNFW#x>MB5#!ANj)V=HqNPy+&{o`fQIe?kDF{D)R+WE7VWn~~E!84X>eRy@Q!Y$QgJ zJ79BX2-hJsfgs5RDXI~w=*vQiiveoqLQ@kYM4%+BgoK3!s1$^;k!eT@hH8RRm_^$D zdc;OFa2|oG1W_2JJIHv9$`Pazj`7ACQkxdm%teoOye(0X^(12G;0eTiFiWwT0cw;% zlz~a)qirDSQOi}-431(A18PebDHS0ZdcGbhtAcHW5M=K1dOsh#aS%gc z)U(bZK1CrD5C^=0D`-SfhoTG{2W;(sl*KBb>K50k1xSL0CsA;Opj2N7J3!%$NSz=a z1C{|cgn9xjN+Qe#vGAr?L_-YTnm|tN z45YQ9&|Qy}kFb)^ZNF$P!K^%>IUD3ljAL$5K z2nE!!FbX|6;jM%qmVp8g+NKA`Jl+U~Xn~QCDi*{$54z2wpuWDoem(AWXOQFyPjmQ+ zT*x7m@B$868 zP{pw9f!2T7dWFD04d2(#qjXJy)1Yffi5L=;(vnu`%%3shV0im#W^g%5jh&&b&(vZU*porjvm95B4K#*a$-G<#n zf}$vC9q(8(S~C~khC*0@(o{i<1&lHmxzI)TCCH~3n5f%r5RQSc&STp}fnhW*0eJZa zF$^0CE>56@5U5~-7Qfh(Vv0c$3Z^)A5wL2wlfV|EuXToNgrp=y9Dwy=T?`4=f}epL ze~2*){CeQBNSblz#Yh2zVr1bze3cy{g<#L}aIeyy0f}0$g9cBTi%~-g;2Fun7`exB ztq(XXAt@K^T`++o0U;$ZurgEvY!X%iDdE9dBuD`aG6jc)SWP2N5V@ShYdScOgWLeY z@Vt*?4RVti{U~s3VFE3xux;;ySb`uG;3r)o*@vG=+6|G|05(6O*$Hk3K@%LfA4*E4 z2#s$vBXM!Ti4X21aCG1-a-ppQ#OOF!IYr%dwOkQ{N0 zW)?KE$uWyMdXS2Q!Bgg?YV$^3?y|up<#l@d?YDwsRXqO zI?#i=$c3Dzi!|^6i5uKW56L1NOo$1faKSpRghLlp7}NuRXvKa<9yBDNN@y`{0d)w; z6iNmGxsUYGY?AH7uK`g?4AkCVP%xlj^x^;%p?C@_EQKzP4kB{01KWu!SAz2gSOpdW zcS{IStif7cN?Vi_7ho4ag9kl}K`q5eAvKb*<{6Odphkl! z(!vp^wbYP6ayr;)h=u|+Oeez(q%vX9v~w|f$e?_MI<2-JCCw0B=zIHMRuUlvFUSO}O$0PUNaI3tJ;-p3(Et>a z(1HkSx z_5_lR7}*6q@gS+CI}@`tfUUhjM`s}w3WKJdi%~K;FhDOMg9Z#J$)YA2kO(CG!%1w> zjxkINH4sY8uZNexh~g7sAc{^Ll{mr?um&eubfdZ%YAIzD!cGE13upx#*4zv6DwITz z1*BXDRRN`7Mxh58=;V2{68HT4`UFy2v`|}+DMZT|r=y4}Ji&nnt>HmM8jeNacwz|R zDm)6HQec}XDsn+bzQK|e)KHQs`r`H5;@O+JcO;PM=ii$et@|NRTg9h3`4UoxLkpWfoQZg z?)?IkiVLKIENp;q8D!%CrYXdotO6dAf-Y$Sk5Q0bRDgYi2>1Q<*uoV$VFn-U0NV>M zfMMZFkVe17ouCFx1xTp{;b=@{*hIiSg@iOB{GkfL^%X=8Lc+5VRKdVf7|x??Se#Y|BqH@VHiNP0Lowm zcx^4FRwBb0>|Nx+T&xul#QnHPa7hF!b0IFl%+C}Qx$pPSuMcntKu_zqoI_9?sp3P) zQ3N$2S8wP(L`&wN>_XT)da6M3H6)Ip<4N>%1Cm`x;Wb#wT#Nt#H6T&)5h!zGjE#bq z{Xl{gMxvD)$hACF2~tR)F`){;RKb7bBnK8^U_fifA?>V%rDpVk4x^Mtvyu!ha%w{J zEsANV&2}sYih)$4GzVaw07*bF)ZbVsNTG}D8k8*+gbrZDY9Cx>%b%pvLf;R0;fE%GX~B2T(l^Kly|6t z^Bs_mxr2EYoSGqCfsv@X&3c(~9 z%_vM~p^3mPC2-~xvO0{@YoKPLrcCt44D#i#VDF$3;6fKQ2Ealfv*)APj;fP*o&#EG ziX}c7h(665T!ui4SxDuG(l7_P8w-A4;DDkGoGhRb3pNq+I1Wf#02UZv9uYA zSh!QsVj5%&)TPv-P>M+uzoOcJG6cbZ<2*amA`CNRkU|9Hbus=G0C7;N6)dJ9LIms| zbOLNBJYzy+9UM?wYY{el^E0FZSnc&!k#t7IT9AN_2 z0A@h5E>fZa*Q;=Te?97UUD#RX@W2F@TcB_P8;6y^R^n1~w<=PX2fstmT?h6m=Jl{J zVR-bCW-7WZG~%PAZIDy( zc@N@4I?x0f!w`iyNdpH5hx+>Z{{8zwo4e2N2LT+dF^mODP(!ge93@`C9B|w~+p7?R zh)Q43@J8yffDM9|xnQ$V2yn>5JF>bnFw<|sWfsM179LSWHYeiuxDXp!?52z2i6QH z_G2w{G4dc>Jyr&4Axnz?krFP7$!KK)RwE%*Gqg4aSH*aWO=J@wsQ{WJKoa0of?G2< zOyRp9zys#^>ja1eNFEY!=*J#iAlu2pU{^qFAkAb*DnhHAFrooXo-8L)UlTZ2Fch0MhXUp7asqdhh`qI5+wgX0~eOakwIi`{UFLQNa8jw zKzx8nVy{6#mSAtiqnH3L*`P5GP8RTr8ATZ;2Q&qSvU&m>v`~{Um4jvBl>oQ^Mk=o{ z)&Kv$AM7*+1_N+=e?6$Rk4+gRVvq_46jFFM(O_BuP9U({1eHcI3~VBfRftg414x0! zCm}9`k^~}xmQF<~qXx+w8b+B5?$hE9gL+7(7N!8B^#x1w7!u&X#~jIk8U)TSh+V#5 z#S{_!xUb2AT1hg6oRH8m1F~7*%z|(`jv5}NR>7JgQA4ocKX|P_!dwt*KJ?re5SswT z<6vaR<6uL}CTw;fSHW0yBNww^KR|};v8qKAeBX~&b%Gp#%R-3RFj;Vd!Wyn1JMKHc z(*6E=T9mXPJD?bm97r1nn9sm~v8Nhg7APR7xV{4FR;p1L4uus9RI`D2g9cxji$F{LE#J81V8;4J+S zenn%UcnNnu5jqM9b2|=uP#ca|Lj^V68vMsm=%NoIjaG25 zL9-mF;fiIGI94mM3WBV~D)Aq>mJODKzy&bw&d7Sw&)30WEkR+h|3U61aRu7@dW_l{ zHPJ9&Kb4uFgK#N$zrVk}o=P1QJ12g>{%4**?fAX5fMZVKj&}A6rQbl0d_F91L;}7_Z0KEc}ns zDn~OKXI~#|C}cpv1rCRsUB2{lN@7BIX3 zZeC%C!UVt`faV~u7$i@DgB41E8@kB-aHu$h0?UGR;vv8tLx_4>k%XFOn65)k@py6% zxIjm^8b`JOhcZkR_5u+t5I{v6YDo>&J|AfpG*|#TfycoxpS~A>@0f)N!D(<+i``@b zCkcW*3bh?<3U<%JZNkq`zr>p)Y``HMs!(3q~YlEpliUzM@tY? zZ04Q^haMt+6<~E2E~gL_M>7!PT5Ey^P)`B4$b$H7u$H-?G6Q#k1oi-Onfo7{ksw}z zkf4SxBAr3RkVq8GI6@X9bs_1e5)-!ylGR|UZy?}s20%k@6+X{9W#K{;WICVgaS#aZ%_`zHZ zv;KoOL}RbSz(qT}oeoOFcr7xZ$znomF8&WXi5DD96c4|Gd<8QJM1wLKb}LB}eGl$_ zfJ{VS1!A%(9&0cYD#gV(9^3Frfr~7N&jv@Ci=+mX-eU+sybK}X zSp#M!CXEzK;M{S)0N;Qj#8?tZR6k%k0Ye1YO}N7c?H)8-y-Cz&D2@^wt@!~d*^r$9 z_40hkSSEz$04i|*|3_(+<2v#I*^kg1jWN8BtOm=BDa2Box{!-mu*>lm>L`|xzya6M z@X8z?$7^Dq`=cAPtFmWi2+jLk+BLx$< z%>DoWKbC_?pvI9$k=)(_`y6T)S^&VD4Z2Jmssc*kYS^H(OmT$=BCmo?gJxKa&}LwO z7rFuS;q6(l7C3=xhy(6&SQ8ePTc8SYWKihf0aOu!0>>lNZgA6{i24?x8^*d1-X;g* zVWGiui|~dmxXp_{dchS8qN2E;0AD(W#dOMrK+PCPR3Pjm*;KUDK&`C9w4E#|-l%ZrPLUKv{5hM=CO#^~4OAnAUaOXU5$%Cc|)M^0ff@1|lB7=(| zGe8AH0qQzm)X)Um0@nd6xYkp%wTrhMgz6dy5AGaXhckkep%qFXpMu5F2xP+$w`HIy zLTjrsK%I;wm&|`}AmD(ywg|-r+*ZJ>gr`NQB`|Sx8Z~C%mcXJ2RXMnrMcMO9a+$Lp zvd9EbltLF-m=7o`^OTVFV;Zumw2LhCvmA0}EmtE)o{5P#q*t;AlZH7Ne{o!88h# zBBkwm^mz^x_tA@kk&MA95SAQ4J_R=eV66zq6cK762s=U#x040X5{$rq@Cr(tSrBc~ z6Em*f@2{uus92nKgS?ClgDV@T7cu+~*ML?^;wtJ;N)z148m$C}j}TzVEAY`ws8hhv z2z4$IQ)oyLgxfg~qfzP$xD8n9A#gDZE&jl*PojzmSlNf=OdoVVLfiuma;P=`!Am#@ z4;n+VAw)m)luCFChl)~_LWCK#3L@Ebnly7Ui$z3y!dQfo15Te{xESU7D4g1;F9C^c zuzv+uidks84qRj54mN~y_CvOvzeky51Y3fBAs$o@xMYXB8C1AoFPfpsArvGV zLR<8Zpd!X`5Y1$eh+YTD{VS+#NR=WuG_YT53RO%b1a}?9UQP|?tqw!N*k;ZtzC0bazy7J9;?80<=9 zX@~(BX#%VcO6-SD6hpZT1pB&ZMGeFXyyX4;>+9#%X5WXbX1R}gLsi4-A3s zK-B34kSsX5;SD9QE1_8lBn!o84Lq1MDW^&4gUc33EQ~Y=hb(hF4VR7C{{WF%P$C|Nmp0ErX~k2o$=g zL5R?X?i45=xk@42ZAJAa#2aW?3S9g_yZqpS5v4|e+KNdPz?Yq#@2>|%UIOG65KNU2 z5wJI5Aqbv%fTvW50_-Ft@4@t8S3^}%a7zXpP-HczG0I1rNsDM#V@W??_hBIjjZERN z6X9o=nIz@9_3%0ohxx<`Ln0gOhWeQ^!Suiq7!C)!5V=qV2OT_lf?bO&4Ke`#HZgF+ z1DprJn!yCL&k54}f4u|hh1%$Ii;z^hKL9bD3D!my0ZY6jr&(~#19m#jt-7#20aO)k zb*N#1x9f&d7BVm(51L}hG)UzdvU`aLIF!K!Z2#IX46NXBe`+q)z0iy8$b~>aKg!yScxUm72 zz)CryDg{qz(9(ct{V3@NXUYLrPayAs zF={9wSp_aBz)CPyitR6OK)F{Dr7UD%U@(}En0W+`yu*xv(1=18!iSQuQVGco=uDCZ z7ckE?f>?xzMsRdNtp&Ri%0{;qjSo_aUZJBYLFR&z4*Y5n@G5cC@eO3P|KBGF7{JOq zNH)Y7K`8pD!$EWn;LR7}4F>xY62uUagfPNk3vzrz%)~>I8BmyZfSX@9T!bzRs%PL4 zhAv489}?MM?+uDF7jwuF>_SXom?yzbN1jB&dT}a56@-MgJiyb~5D^dwFSj6VCX|{K zt#Jo30Gx+OJoFjnWF#8wIgs^`dH_j=028@1#hn6C3R4E0nF}Q?f_w+F{63`if``q2 z$l526gAo`}u3}_G#PP(S!V95=h`I_T%#j@ca~mp+>QlH)u#y!VT+neqa0DYtV^nj{ zcpzhO2QQjp$jQO*-~jmmk2T;{Fs!VCrUP^XX~+k;4iZcV|DE4IA2i;DlJ>DW0aW}z zG($;Jn+zDHf&v<97BLhN2?)aq=3JF7RBg7kk*C(DWx>J5l}ufvOx|R6l=v` zi4f|%|FD2U@X=Txmm^Kwug6FZ5CupiEPWt(9l4VXDIHLP7Fxi<%&13PKm*OjXl^2! z3yDWibCGB*P=&~j$DMFc0|VBmf*Jv*;I06B5XtAT(E{X5h^<_On}kIY+R#H}agZgj zD1d9kWS}^T@Hhax!vHcK2}5jx)UQx)fLnM_Hm1F(BH-ExRR}i^;s%I~&{?8x)=kopxAb`DTi;j#-Oni0h|E-eJaF-!zG0}sYim*KGq z8p=rK;%>`f7y~I6NS$}XFa}`TzesBHe(!gpGg)Gq}A2R{Dt@wy|EcpK)eT!WJA{Ah< z9~_+Epn(#2{E0<7rVu!=pk@(Ak(^;bmZA*ELF_@v=O8sWF}#&S+2yIjr_2Qh9k!#6 zAt8%QBKpqY+y|F}l>^|2fn-%^_@fqG3=I2`H6o0IswRO#m;pnR1Q)uf)fQMO0Rp9EjJF7Y7=+<2 zklP@I8dwVKjQ{_^Ox2=c7Ns4PfWiU5vY zu(K3M&aJ2c15S=$lNg3_I~UaXT#sB1LA->Gg!TQ<7e2x3YEa<9IiS!&$^8rr45&pJ z$ZC)((lH{bk=!>!sRnS`jL24?fI#v%st%AO93#8~3J0(-tTuw^La`bo53cVZa@coW z8@xxpngDhdCR_&&28um6-HxOgGedz~$FLt-MnE$Pxa@$kku+mxLSmkX0{{Pi$TS{& ztO-<)!OCB(WT)d%- z?;u7+=cAqd56VAyj3lN!z#1cnq)c+6MRqxSR0P8klu8Ka&;qhqNDGyrO)vQRRJiE~ zXF~!7t(%7~4H~U}kD9>|*%@vq76x)oBt{30(FF%c)dqDXIK4yJSnNa-0;@*qN8I1P ze?4NI28v>E_ZU9R0xGQWH>M%M3$M-~X^fs_E{@=W#3_h`g*oB24BQteAwo0}riv=G3M^Z`$M zkkT9Ly=LIC1o$Oypdf;mzc}mwc@I(7Lfj6w35Oo43WLK1C8W?e;Kl@6BNt5xn2Ttw zkmWvz*TE){LXZ}8=QW}Jx&CGR0h0f;cRZWOZRASa;v zAGv`FlE=WrWfySy2-8bct%U9{m}bOfiy)_AEiIpn% zj5EApR`mxUDS?y**i42gr#cOGGExv>Fctp)e_szt1{iY40!ZE0B2{Mhi`X6I^5d#G)b%%VJiy4Zbki?16VhTBz;;OC*rcHE>?;VIaB@WcifjSds zsfjZ^A?E~~85PyxxSH`OMH}M86G%4D)2B+oQ+c*a>0yy zxfQq^g82%Of7UZF2n3*o7R)B}Fb6es?<0jCCVibf8U*3fXBbWr_Dol9$8Pps`uZQ7EaWTNnJzSDxi9@osLIJL_0UR0- zA5uh;TDzcl2C274sv|(D4#g}YIFK+wv55#>U?nJ;z#I}PZ?Fk40?84BdTaq_#G>ba zaA<%Cg@pOwbPQs{F-BGZ;ufKnZN{Q^`45tIT0WK%g2N{LZ&AJRq# z`vB=CP$aD=jR}K-e$ZJ=^U1j3kK`5uk{iHBx`W+FI)T<@MK%>D8ybbkmO;`6P91Ow zs2=13gB%y2b})ujnG3le5T!f;oh5*gK9F0C*n<$=3~1ORQ;0!OPz(`O=7JSL&46WA zkY?gAQca1wm;~j0s0|EA>k-gwKrNYxbP9S!2fjlAxowZTmyfaD7tKA$T;zs2W=V&v z62``1FJv?T9OgLd9+(mD_wR=&hmYaGWT4wYFf%DQIADnY6rhCW&)_B^G3GPij!GnD zL^Au4!w$4`1k34@h*BBZz2`Ce--uL%g++Rc0m%zQG-$9`2@yh0Z%9VsWunwG5Myw* z=Fkj+sAd44q5)+ij@Cd^i=T^>dxue(>j2Fc;9Ld^AnZG~km@b0k%*;cL^2SXB!0lY4O=-i(GZBL+$+7n(J1`Zb}L1Z-zu@a30)lX1k$e^H^9L-GpT&Rzc zY=gx$etqz>1<#|TO0u>`fYS@a1%tZG#Thc-HU`84FcLA>4$fvUVQksuKhg!Wh{+P< z;KyP0kc$@kCHSYol&T6OvT9dV`U>+D0ucRAuA%|d>gD5!vwK}3arq9 zDgm!oh58VUB08^t%Ri`QVygozE`yx30}gY7BMZ4zL#Zj1H)k z2y5~}g90CQzTUy1A7bQt2!&5Ik#gvbT(CDl1V*v@A2gtVntK1^uP{NzAY-H&iAdKW zl;IzOLbe4fn~aQu(prHSN^HV{s0J<8MsCcIGm|z{%3PF$kBBwIX*19u0o`4INV{lV z39OkNDFm@ZBGwii!Y(L_V7n#(b*v7QF`-%+;JFpqR|MEFy&xLlTU1S`en%8Xj7fAzzi6vOj0~dFp3oXzfCgCGdynxFGXa-;(T_}Jah=#LM05t_%FoU)lLinKY zg)h2=2w{*A3t_$oLailAYSLSYs-s8$G|l)0!aKr#|7G)TZs zz*&r-1Po49D2bYc)PveSM!N?G>Um^mg53%saMlt~ZAcVy`AKwzfE1q)3qhm+xb`L3 z!Un5ifcHH>MiD3v!KE}Tc)`tNXnBp~4NNB5{b~f=g=qo~5hBhq1qFuzmMJx46QSV% zQVPKV_3PJTThjpZIkILV+2E0Hi0P;#@?Mem^PznKR3#7|8Nr6qb%K~esKEsF4n#3@ zG6JR0CH0^&q?|b@#&a>tTxhWe^*IKGI9jO*&Jobi!d0R`EdZ$kbsSJ^z#MW1 zDZ|8Q)}ojJUf78=?t?mth09fFMxbz!{S2;mQDmVUVrV;g2dq%6k!xiAg94G&ai^(2Umvz1+aP$ROX`eo8Ssz3~=)q z-m(R$Cv3@o^ovZ0Y-z#l#7$$JJA->4l@Tx>PohOhJPZmjr6@%W*fpo9ckLl2??H;I&W26vf@6cg_Q zkS;7kDlr)llV>mwBY6*=F<^3V8d0#K7aU01p+Sy=!r!)eUyt0ILy0cJ_bbAkiC}=T zHq0S7(;Z6U!qp-`Zb;%jU>9LCf`#5n!5X|+3tjX;Mwp4oLPQM-_mbg?HDVgr@Auau z&60rv8Y$snx({XWoBC0nGM}VRfq!$TesKF`#)c|WTpyXoGR-7P3)8H<1 zk&*|ff`sQEq|||>xcgd zIu^GOA%v|E6~LWI|L@04OR(~f2;1OFK!pd27qBl^f~$u!pqk*rh$zk>DG~==nTydP z1Eplt3kOI&Pggh)&>NERR!JaE?<;Li>B(GwF|T0=4&Hxs322eFwrPe9Zn%|@fT22X8) z?ieJm4~}*&M!OAKF2EWSu*?ou2MY`A@dcB`HGu{W4@Bsp1V1=O!3{uV7=T+ia517| zAFWGHPC0kcw zK+h>Uk8RNbR0*i;hs~1Vvlx+0U>ZqIGH~OO;}v2Waouy&<~;Ux7TgkS3@n8`ap?-; zN|a6XsD&=k%NLN6!Qd!!VM!PfUJ%bB1q`UFLZoikC>GW((tl`M6-hV3U<3=^Xhl*7 zp2CLMjY;lDFG`5a&rs*U3`8#C5w0P`LW(oobu@BuimN$-nu#z%{=NZ&0$vxwgAL{% z$c`^m_oFV;fT$!sucEZXQ4Pk&10@lNRY)XKdqHfHl5BHWC=jMGbBPVv0Fp z+=8dXMXbO8jcVbV{s#vU*2XTX^=OF~b-)i*DIp$mvjJ>91JTn^$f=*mT!-Qsh;_&$ z&b}gwK5%TK`5Cp)#b|Dz=tppnd@wlnL||reNbn$M7z5Vu`Tftl8f|_aYVj2>7*h_pgdr%4x#12z5RRp;(AA@YhSBfI*0Y@ghjse99LFa*k%ON2FzWx{4JhIrhOI%#-R=k4@xHN&? z2KF#=a1t>93)YB9fCB>AC|K2nsT7L{B5&eNoLF>%gg`NcY&BZb6{G|!hUr6%Wwb&U zS9U}(5y|(1qs&Fm`v3n!J&WROBo5pMNMcA#P@v#zt3i}P?SP*cgNRnN=mBxTPDClx zP_~&tOvFN>8;aa?$D$mk5OOhuYaAJ6Fd9cnK+Qy`LksY0u<$2qc({SW1?M~!X0wLS z8Z3n0LGcGQoTRf3(dtBq5d;&$`}xoU7pxxN5F^A-unY)Fgt&SWP``lIL7hh&6A2Zi zh{9ds;%%~?FF;N~V4org?8_KH&V*LN2&H)Er9nDyVT{?=09?r!y9w}&gg3vjTfi)cpq|B1aQuh+0K0)^CFMc2)ig&3a zq_u=r<`U7(!f5Wn+SH&JB?W_$2^3=t2*AvNhYCm`Oc0GmNiJv}fEPWeMKPKQ|1ok8 zq`luSfLdI^GYQBwP)t-p|NkGk@<4MVx?@oJ&}0L(4MGtx;68d`1c_=?bD=!&;03Ih z1tlK>14YE8L#W|IQCJqNLVZcN9lahU?jhP>B+4K#l1or}MIgllLK8_V8WY`ea3cmy z4PGuR^FeYeUZoh4SSn+pjDe*mbj4_%fz`qo_96t3^5)=Z=VF$*(E1fu=7)^fVm}-g zmVnzn zu)kq`1h;vySNX621=k%!r9`+6{0z`hzQ{g}%vWfWBNP+Rmc-B233*a1ZcW_Y3| z85G5MIVe#I+OUsTHC9Pzv4vj#VO5JJ2rI9lUIkIGsuN8mDi>-c=2l@)Y6qDD#e^dn zW)f&m!QH!1Z39VRw%njj#1+2qFeL0*)Idbx!N&g_{$p9UjvOA)A{Ty!F-(ro{0X8M zgX$nunxQxknFIGQzT}GBD8Z38;FT5FK`8D=v;_#ZM$u9nXdVGl9-+44$uD$~eL`Gu z0u3x^x&iwRM!-r*s1gMA9&>gHwW*F!3SvRp_po9X)aJ#NJVB~K80;E+MLtLovG_gK zt+1fYF9hQY$qIa93<}UgeG$qr8zLmd2EriNU?D6{NO3aU6iBKd6zFi}NDSoc19bwf zMhTKG#H2Z_ne!eN`{+5FU^xU%3J|LYM>`kukQ=BIaaBf;Su)TXLzEyQl>;q13<#Ws z2QPA=%Z4FAhcOP1d?O>oB~bI>>akBZLDb?WkrNHhM2D~k=ix9YE<&jRU=f1fx(uWlmJ_i# z1S|&j2F@ZMtb|ws?NBnflkuKfgWYiS({|uyF)*M{Awo(yWChrbBq)lO5{OC!7=}U& z!4aDns!;@xyZ~dO$m8HZiy?SBcRu3aC~(}u%wj-ZRE51K^${%D;I0BO zU{Q)>A^em^kUSKFf(Lmh2BaLlz=0}-QQ#CmA9hM^@Rw5T1U~>`eWrzY2NTevk*;ocU0c;TiuH(W` zodha);BJ8C3Z(NV;Zj%_s0KkS#WtaYO&xk`7>n`9qkotKPgpb{gg||Mh*4Ah2Bl+zNoF1&~(4{(yujygLETrEng?$pl!~OGt$RoJk*a_YMIw zF^-l*1Qy~HN7&{fBss!<#%eJ*@ZiSa>b+vsiYy3DO-PvzSq?uN6kl-rAq*7Kp@u@dr`{9wcQhM%xEg8ln^nP>+KsNNOf>od!q)b_@zD0vP4s zGPt!6O-P9clGTxI0VfcMIw(n269-}>Qk3B=bCK2HXdI#>J=7Wk;zpwPGNL6okZ!Dr z7&8<=qrVVO;USSbwWI|bWYiVp9wdyOj0~W)()s=U_4W1j^O25n#NjB¶F02=3n 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%0A%zqs5R;HP5r`1S({sgQGY%ol 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%0D{BdQCipTQKo%!Soo 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

?sg|f06~mU@`^Zd4MSW7`tJx6bm4? z(;Dypf4=}rLfk3t*%!-15b1>^T!al@ML24rx>^<~CmzV_%Xhkm8CMIe! z$66|b?I)igJc)HJV}9}5MH=}jHN{Z zhf=5$o}_>{5bjx;ETe$ffkuMM0fqBur($3aG&HRUF4iRsST5>D=m4`2RXGK1UBcFY z?HUXOtc(MtIVc9#_VCIFDoCdy7vAh9w#@ziAEi$;fMxFg|NkNDZlEDX1U0Zl?*IRo zgZ6|9-T#REL4^M>l@Kf`apnokDO3EjC+O-CooFO0P+Ar=SwI3_i3JS@VoOlO^d>E8 z0VMAunBXGU0o3q?m-k>tlbAxWFJT~993oZal$5&o69mGu1I&V#ao`XJ6Og(Mt=~zf zBKJQy?m^BVA+;gTr44ME`ycCx&LHn##Uv(Z8YC6e3x{uBK{X5hrQGZYbi zgAe>6jK_U=8^)=hSi7x6ENdXbVfd7w6zbp(BtF$pIk+Zbhkv2^$fv;B4w@WM(*z0m z5Ntj6B@7INdN)W_IqpP4aD;(j@E-OE4jc#p4s1js2C*QAdxBU946XqoI%rG6o882w zPmpuqX>`EOazyIq5>6PfV5L_*1_~lv7&HC}7rGeb8O%cjXtD-!ksOX(x5BJK%(^2f z{ExX#A6lNEC_+7;mx0)hKbjeMxhSh5AdMNk>cNtTngDA>0aim@0-Orqr7LO|mt;4f zjrKuf3T0yu7S|&+b@7~jLpXCOka`m=7Prt?2wuiPgN6Zm-#2Qn6MKrKfzuGpZlqF- zpgn`C%q6<5I~a;w^rKTjseo{y`yWSR2BaG&#!)&Fj9g>|SjP)7mc?TkSjS%6AyONu zlk~`r!pBDGEn*$rz@i&m0)oO3yQ{J2pil^0$Rd@ka0h@KLB?Xn{m26V})A?HiDdl?i8kczYQs3iti6?PvXhD||= zh}@G)Y?=hCgC7kBvH;S51dHP(5VLM*sS2+y3M9dU2}ngQ+F8d$)WH~*V_(8Rs5C^% z$9OhW5K-z9Tq}X$U^)t5NuQ9UfmBmL?i{0wqYzy&><69Va0F6Z4URGwZDJ3U~J%kk3$TleytpET2{eJB0q;dEMQNc4n zk98v7Sy*+V)Mvy_p#6upjftN|#%eo$!Ta#NQ{Z+NN|B2;=z=5o@S2ZfG7a}wE!Z@a zofWue#0ZzV1ZVBQ)(s4SYiI#c_`&YhrHlIz8H%LzhR`-pcTi%sNHA6oBbN{iG{4}8 zgy;e{b5LDJWG-8eQfi?Zf#3yDcZ3ZkUm|S5!@}Vka9IP>Ms$ftLcsn<2_Cdk4W~H> zXCXD-ajGUyVm@f2Aawj1yio_;ai~k1Ny>~c7a7Z&mO!-v|gM{04A zlm`Z9nfo9AT2?}jYC7^ixHJP94#wa`??jl7NXx|PAi_{&CD3Ctpb-pi&|(WB zaPt@Jau9({1+t+y*fge<0L_!c8S@@=&;tCV z1qBC(`uhDe^&QcrF3#g{5Is3ihnJ+}MqHSnjw}${tw9vj#Off@H85r1LKbm-E~uM= zy+B230KpbB!OS3mhP0{SX&%PFd-x67upI6Z8ntwWnT^p0%%Q=&g>Uqcq+$(bAWdl0Mhzq-3?A2E^)gYVt^m%03zEVi zKBdjzI!fk(WGk#5K@|iq+X6X@CIif%d)4>%BOUY#>gZxGa{vE_JB2dm;MhWgcWD9I z5?|bM27lf*>v&s=kE!>1| z8+g|z?lg!p`a)VO2-zkalWF+RhC`W4V_*ot*=r)E)Ww|+kljfiHm;$C|NqZBkaXu2 zRh)~|%q4M3V^Ej5IF1&Dlxw&XJXL~}ctel_AL29y60T<<-X7|z#CP=%-sM7|E;Zbn zL{D##;&_x+BGJRe@M4bWhA}B_LRSlFbKyyWh;a^3P?6RQLa_?RWE$QUDC%4q1D@C< zqSVEs8^xit=b-d{K*0*z5J7vZvDknT!=#O`4el}*Z&R0Mlhe=;CffX=S?K=%kK+O$ z1NceY(11XpPzG~p(u+q~^-Q!42wixJLKL4+!T}Yzc+&^MIiS*k5+`BbnTEeFjXqk7 zyR}M8sT)9SSA&ueC9D?|=Aght!W2|ygzdwx0;%96=8_0x!;rKNw((quGx3b-;!X4r z-4u}P8Hm=5wa}$Y50_{s;!ucj50FDY&aNof2-LEK7MT%sWP#{?obb^#@_X`N4-!Ry zvOj^;hm^5MoK?ke0giG}0p9{8^r2wNN?qKe!WfRFodE8k1(2P{L+v0wjWJ>*i-F|L z#z;wHaF)6Mk(X8=RdFCDfn-lnu)h}|zRX2CIThqI(B-@o*-t;s=lc^t{c;C~f_{Q! zDC){wnp7(&BMU^2T_Bp@1pPp9$by%Q5lnlaFomWB1_m5^ONev|u1QaPMIlC81!t*? z%XGNoK@2KwKqu0}*p%TPS^&qtKmxvM2%Di~i=o6W{$>h>9mr*FLjx#u>5U2J5%iuC z!i5AAK8AmZ76>4z$AGn^OSco{i1rkv3L&edVBt@6fk=wAs8fAJ8TwIsK)3PnOpTuJXu%rkEy6*iZoKC2q0%iV; zCg+s@N7-b8$W#Ozk7yhdTS^l!5T`U`Qj3^&E4&;4XD3RAbU}_mTLT6*6GY(IAB478 zmw^HI%o~xVE@^W`AZJqzqgG)cpF@vv1lxdIC()s?i|QDn$G^Z%Md`Q?*0BYUOTk?S zNI;{Kgxeb+?WAJ`1_si4&R7fGLBD21Szj2jt2|U|gF}2{{u|-^|OGIr03jpfT??EAmhS7$Rz*CzjN>C1mrk-0+ zCz46r5b=M=j4gly40}V8ffj`>sQ4sxWc)w&)e8*6WhM=ElQYrfAt>gE#-MPA=NbXR zElH@s@O5H1R`Z_Uzn{cT3)EmRh5JAleCr0lT2aetqMPktz1RtiB#zpy=8(kYDIt>Y~s=@c1eTnGb&^1!wf#shCx%j)`yaeY2OQq01horYaM?*tNeR}7>b603HUtSN z3r#6%kxQM@1I>#6sB0F8?q?thHXKb32L=Xm9gM4436Em}H^HE;T_C&QM-3^=A{6W# z+@})##~ff_z`dgae=P&H3bbMfcf%UhwN&8|F|+`&2dO-RxfFD&B^65u^gK@L5af^= zTloL~KWffL1S&b@BP5QnlAyjSj{J*NJwgyYLZD8h&EO}(TAH)a0-nm@4Rt=Ey$T98 zqU}Je6T_afK-mzx4Afqn6!Horkdv@t{KK?}**%bE(%VE>-G;FU3}iN_M}^y)SX#%p zM@De0kbv3(qv*LM7&U2tU4SElVveMMRSP5#ou04;Ib0AeCy+C;2}+P)M=>ze57s>q zaR2_tHIqj9LL4MJ{)4AJ@Mk4tl|xDKp=N*N#LMJl+<(f?R{gIhI@ z?Z#j~APC(0u}2m8qNqctU>D$Q$6)a&SOZnI(jhukU^5v=UMMyw=FmvXz^FT+p#G+G zZzWn<0FND!JK=#=Ji%N@pbv`Xf zb_DL~3!6v5S_CNGq=r%akW-r@C5Zu=Lt{`N?V?4rA#8A9GLW=Ump~eTL@)tGxTVj7 zMkb)HLZ;|^aR_b)k}QMPb|)v95n(54_mSu-4>4kjeJMpf0|SoL40zpyWdsyCGEv$1 zh73>_=@Q?3$Ll(cQb}VHCYT5t?K8~RUh&|Xm3f9Fy z;WgUe<`~2z2uaSUHgcIeFk=g#NhXr&AMAxL&aMU|7Dyn$OfE(ODLt_GH}4e(eo(Y2_p(ziQ0Q4y2eAaj8;aXyVd*Lv)emCy%2!e~{Ai+Z0wk}3lN7TSLo(e+&@3H*2;sR1KKs*c~ z@eL~BGG#EV6@$1QL=s=>VlC5%pLW3=9RL4=?z3ZHAmQv>tcIZ$At28|umI7e307n2 zE{Hx(LaQPdQFemD32(CzB@7S=0c-LH6?eoN1~nN=4hK03FUH%)L^u*`2EOtc>I70K z^wY_~b}%sDNom;n-MC9#;+E?Yu@jmUPob(sj2}TgN8~Z#IM$7U48iSRRI8DAm_;s` zB@U<|0CEEZ!$7xlL9QUW)J03iAiX3WzK9fwV|DHYH-AcjSk6M=D+EVxfJ$2P!#XG1V?%XMkh z*2U7mLd+_huMfai-~GoGHu$%YUK;%KBZ~_@iVk?)NaRqS1 z;vJ=hOv{4RfeGrzKd!0*=hYBcS1>T(JfDong=4fSbwQ_}fWr+zAX-=V39b{xQ(@q4 z+ao0-FcVaLBdiCr$nNwFx-ypm&rWc#?_mVCLYMgL3Nr_Jfdy41H}^j1;aQCcLw%-~evctly7!tO%q9FUC2jOZ}9I*BvBF zVlF|VU6BhK0zjlR;(KgJQ!Ch7v!GTmN&Oz|{qq3qCjp}8Li92hT;ejo&$EUnEQm*m z_T>Hj`{#oi*AP5^Ki*LZTytF{4lv-}Bmwml#1D8#qNl=%Ntf7;6hj_82UV@eWiSpi z*MoXJ*xigfd?03F46=cY!8)1+QBR0ODrN_0JQvGo4QPCuh?YCHt{_E418Rc{6tbW` zWjzs2!4=F{qYGj%15xz~E`w<*j@ig%peS7NI~FxFAZI6H^y(;Vj z3=B9+AzZ~el4W2f6-!;T>I!T;a!UxjRUhlv5>kMIn7C^U+~EV#hjk?jdAlJ%#tnw` zx%+Xn`|(dlf?bc1ltB|zU>R}$G1Z3GVQ3^LX*`2YX^`}s)s3t|lcvQG;| zU*n2wI`Q+SxExM>acor&4O_WLBLtw6H?WNoVD%$xwiC3l976##RTFL4f6V>}!852( zXVOqdXy1dbtb{klu%%KQUDNXggvwiJ@I4}zKw}G_ z8Ux2t6v9ni)Eo=)1sMy*&iA9{ABZs+B#~2`7y*uV_dd?mIT*&!M*z#P0s{jrPya;? zdR!?V)ANXg3!A4xsDTc)5^or0hly}A4KafUN-22qJfz4)FH5l$n(zD36@g5~fpO;z z>}4ne?ky5H8pk+$+;}$CqBs`MRyg7TYBvaMz5uFja6}N@(!yElVhtZ$V=t&KAd!bi zx(rB6u-E8BfXdwe|FL_Ha8nmcHAK?H$$z3-7NFx2aF3+n4R$Q)1`)XA7Ug(tBv%q^ zex=ohUyvhF6CIA$A4nk@Mr!_Gv^k)`O?*1Q==&2hmyP0bJPwBxx$}`6432w@0g?NJ zdRky@2m*KBz)^suYMl%=6>Tsa91)lmFHSRY zIv%s0#X6Kr&Z$W#jsZIu?2~~lbN~Ox)~974JkbQMom+i!y{Bp#nBtO3`i9WIVCP= zaSs;1L*0m@48=W^g{yIlGx~AZ016EhOiZ5v>S!z!mVARYv;etEi^S!!xJq5LxJT6N zNM53}$o-F8=FXgnWHQ~DNa+UaV4?sh!D5LGm=NYz95ELIyq}LXJPG?6cb5+4AnY`b zrU%SID)hpz+e@q{juMxgJNAgR5@pp4s0e}2IuSAfX#x#(4jZZwRFoqXX;4w@6r@yy z#RHyUPgL#D0St&foaH;ja7YSM(dnsTNxc6I33e=S&PUpaN*Ahd^3`YJwm635`EoNdjUxR2Fsb2Lr4- zjAQ;7YBC`T&-5maS{`?!0oRHIoUI=0!-1Gi#xtgY2vDpnP=^KGJoL&GQs$C=`YMi6 z7o{2lr6d&lafSs}=VKQ{O189XhiSr!t8<=4i7{0qz#_;!PUQjm`s?&U4)`{Bj9G?UW^Lc%K=vkW#C-G zKGW!a}lz;iD2VuNFeNRAlGOjY{#KwJ(dA+sDo&@ zEEnV$)M&#UWgxXE7%?n_RTIcul-3H0W)u#jRD^n$frK1|QW)T{3}QG^jG}jx=i`_- zhPj708e6pk^(2lm6i>So%YGQJD{##?5Zy|Lx`;FiRC|K0MxhbFo*?_(K%4;fiB);XF!SL5fMzm`M4El)%O@c7kHJKmj$XQes_& zcODU?!Y9^5;?)jI2xk3dyY7Vz;JEnC2}+x>>5%DEIn8TjKL&msN$)5 z@K}qz&OjMqf{!oYsjBeUfGIT?%UrCZ`FMMt7(->)voMYk9MaP|1-q@W)~u*5Fu;DS z3TEU{DDr+j?j|k+0|Rv`b)0TQng;`UALld_h5<+#u@)9ba%@AbLFu5%wY_;6XB;3vo2OL63+w-2I{d|NmpQ*w987 zu!JkZXwq4bj0JHksU%VD0)~M3l-PmaO@xn^KuL4>4I@t$X@CF}`l#(ed`2Q=M65+C zXq<_-`4o^!klkR6nV0c60x8#^?n*k}pP&HgPbo-P))cf zq|`I0%H02G6Ncb;!&6rxbvQvvK^VCaMCB3}HKXAQTioJUcYlD~jEW8F@%R|G=>%l% z_k+s=RIAW{FfI;>7YY3Gxar%)UZ?@+y;9{^te z0j?^+hGV(|MJHOAQ^bY40;^YXl%cpvP~3}kao;C^qcsil6j}=it1B@C(dQgN16~-4 z;9CqZWk?ahTt13EOx|C=9~`x$n2J^Hpe=K;9QDM2uki(|?O>72fV4A$>Lo4%u6Yxz zVT?tP@CpW~KLiq}+T4A=J^@QYhT4UoQ05S@IG=JMv|^w5#EjHF#w^nQ{|DE-M45&% zwn0*ni+br2Yzzjr9tLa_I9p*WXTTDOfX2@faBy&NNGJf21Y-^63>;B|W1S+NF?*aY z#Wk6Rw;@4%KL+6ewB_62umXoJLJ5ckb0~;S34V`0_=wi<09W=71(fGUn1ewBT6gb) zy+vmNcRvs%S3q2aCCFjHjHw#hJD}Rk8N>-tlAJ^Yb1H}?a=I5}n?k{QqDm2vv3T(P z`2{GwX^_!aG4ZQZ@z{o63e*}!vYSAGfn*j^LlNr`Fep7k;~hyC7AA@d@FXiNT2aaZ z*hxAdi$Uk;f@2D7IMxXWq>&LM|6?#63i{C-RrmMz7l5-phGMV){)X=V|2S%SJk1y! z3(Xi9aP3UPH^2Z67A#?jPYB#s0DBHjU>l-7u$VexN`@%g#(WqFauPa6X^4R)saJB&Yuz+cb%9cPlp zy1)c#3r-3=QiB>k*t#~b0KsVvNfIdM48kf@unC~F1$T`?0jO{Ri<3-1t7ni|gKIn& z>=P{KedEp_;FJ#X2plWCC!sY7*F_|QoSGZ#DFi`k3)~=}em%A^OoWLTtoQr->m9Hp zUfiCfWOqD<^*97jN-YND(_XM>I1ek<{{R1vR8*qm2beZckxa1g`TzevN}-QCNx_Uo zp^-*67#QH=2j>xa5WKbsSILi}8zUAJh*+I{ANz67L=f&BwgKLijb}Ps_ zwFBH)Kno#ksUM~UC6XxNAQihPy;-!V6G%WrIZ4(H?lKqK#TdAA2q?qBA^<`YSK2th zdM6-F4*U1_*Vh+dy-*t@5639cK~k6_DJHel1=+6PP*A@fz2}K!CYbpi~hFLE{N?6*bG8ejK)T3?qD0= z0C%`hyQRoRKyAfB5mVqoOahnc=q3>14;%;IAcru-0yv3d92hi;g0+2&W44Y6x52H1 zF_3d5)UVj;6?jt%rjHslY@Qi4X<}^BQ>Z7WpY2VDgNyCF8g0sG~JP)+zKhxNFY zy_4-dY#Ko&Ba$<)Hdqn*5|HvMQelm4oftSCQL_oc9Ap;qNFkE($VzasQHla=6)(82 zi>*NhF%qfTKner~h5)4IJVYfP5?i5*EkrPkz$iArZot>n1qUiv6&fLcC8TkTUtn3` zh2b)E0c<1RSZqWrC_^`ZQvUh^1N8ABEbV@hq7C9Cq!1m1V+)|0%D_n&CAx9u612uY ziY6=^1K5}hQXrtEj`!n;PvQGdxBOzNs!hk*8pGfs9+$d~5gx7&^owQ_NIS)#K)C+2nLTPZ8 zx!78|I8!vPHUvD<5DerEw(w|Uz_w5n*C8;tn=+(EIt@pi5gsPMqFafJej*Y6RR;Hw z%TT1|DVCxVB8xL^AR-01osGpDghDJV;{88i9e1}TnFc1SsjP9=!Q*JU|Z4vH;kGL^d)7u z7jodR6}il9XaI!|y)nUd36|jnTp0^ne*~LzN*4HzK(i%^WOgnSp`4)zFxQE)jkQI|s*_E<8#^q&a6pqX zYyx&7%4{jv2oQlS$H6O5Y<&)>S(H(jS5RQ~Oi8LWk;~k{wmugYR9F%!w$KMDNAeCR zlCWaTle>_VVXXnMH~_S^4rC$qFlP0MpI9(j@qspW&E zYJ@Ca#g#DNCZcQ;CuY74NhjKFR4hd+cs&Hx<`~!*Yzc|%qf_9e4Ja7FnCPAt_Td72 z^QSnMjWK{Xv)#vkWii%b2L1<;0!D$)Pmb4PzBh737nOnD&Q2=BbiDEO~M^W97CW0v(1P-6sRJK zmY4ANI?pp86|P806>C`uibf)udXV-oBy5N-q@Z3$Ddw=Wk-=pu7ICQd|7auG3=9n9 z9_9@)5!okT|KJZykQO*b3QVw82!UsvAdUqIAbk#a=bAwy5O8aWXTXLGKo&qTmOAb~ zB1lQ_Jn^mosRXUj0MRHI%ZRb196bTe(;vLSjKd5t;NAehtT+fQds-Ypv(%D z$F&#%NeNUX0|V~n3@Bj9!Wi2RX%6UpBM{0I6!QLTY~l6Z0BPg_x!%Ltng#W3aa6@f zh7&XfNi8}PWiS@G1rAdPs!(vHOxW}qa+Kmcs0(Hwej0soBoQ?Z+(7J2U3~jtFxz&> zUctx4wz>oE5bO+W`50T|B1RLDYG>?5k}C>ISC~G)*1B^bt_~j>WiAPYE>Z^+JsAk# zSWSnBH>8zfXfcGIyg_E8DWMJ*X+bu~4%%V^tc4eKJc88}MnyFZv4xT^5A`UePR3bxt0HMepR)89aXyif6 zBe1yyrVC0VWqqi25QV4c!qe0R>BNnRD~h1bf>0>q<`9#y)+mU4i96gOCX!8pQw-)1 z7}kkzJRJpu{YU{nh}*f)vr8ah4<)g8;V{xQR5jkoMR;DqJ@<*NT0?{)by;}Ur@?(g z4F*DiY)dGG+$&|NlS8Xsi+t!=NNmdMCM`f|9l{TRxCY za#+MMtp70Ru!WbMsOs>xaltVH?I&Oj zSFnQr|DiYCA)8FIniXv2{sKfDj%+J6*ko@N2fK`H0;$9U`vOnq29JIs#RsAf$$)ty z7RW)MW-fm7K&s$98mtSwKq_!zlrj@u-|t711Rxh+?|gyGL@FIXey4CG7i1zBgDeG^ z2gP795(w-~U3`nz$Y|=~Y02PnDwd=V4{~HZ2=8N+MpjBT8(Q#S&F$D0(GhIw4xKU= zW%m#yiJ^6+aIR;8uOY-8?)T@{*JBM;xE4h8LM&%sz^@*zk$eVh*Eh^U>d>?~37rUE zqW40uwpZcitVcQk8KuI-I^qb*7+44V;O2oCkR}T_7_s(LL27Vdl=>W6w7v&zQiRzG z%1OA}&M4X$81T(i;cx(UVYE&-=}8jgY;b@e6ZkGbevg?EkhNlAlinW$#U{EzXqg=x z97vTo{=@`UO(p?tZQ+W69Eq@l<_ohl%OOrKroW`O4#zw)98>GHN37d!(K?Ft?1Q?KV8B+TcX(Zgi&n^~cTkhS#RSe2fn+l%TJSX_kvv5V6Db3ew`LrBQx|K+25}EcP=I_x z07C-^qM0}nGpA#}BmhYrQeq*_4&qfom#yK5Tx`QF$eSlI?LmsNK|Z$dA89QfES8~( zALK1;UI!_oWC0||TsX!o`fx-7TnE({`$;^G5#(=7>;OC7m1^!H%^K;#Dg)pKF`(Z}1J{V-v_^zZbQY;S3asOJh(j~s4*CBd6zeeCXqXwH zIUh$u7yHa2K2IZs_uwycQPUSFwBdCqmNm*Cd1?)tVJq;lk1HZ2392&B&o3bEWJ-{? z(Xm6pd=d*8s=6I)7<%O4?+mU-9=bu!Ti8=RsKJA^Fa}!$s!YOAHs{4p@v6qXRF!MlT zL4)v9B?w%UH|*HeHa6CZ)Q^^eOnpwL7& z5nFkOTovOPf5v4E(c-ZF5x&|3TR$6@n-B?c5TCbz6gn7HASnN!P0m2$i>N&zNJisl zqGTMf4e)Ud{2FO03p%WPJ^0*m2r(ZdFo;T8xaZM3BKUJ+KLgT13&;&QP;A4^gfl=h z%lI+`SRvAoENLSP*o$1SnNR}Uf`*mFP%#9BTxB463!#8Q7D^F?E1wgz1M7T<060DE zpI@JVk?+7+0F4l+NAW8}mbAbIxf5G<#?r4xu?uVW2V@u(Fub{i*Ak?X6ykB5OLdV{ z4*v06)C;koJ~P063Nvh=jS687HUh0{OvVCqurWi0IFDnWG@0&4Ew>1rvv6Mkd7T(? z$YU>3K#3T;43cvZ%|X&e7EqmzwPXbujk6L#sco=oM{*=tOytF^IGsV*WGww-Xci-q zDtM24r7cVomeP`dTcGO%U`0y{v5jKE<7 zZ)GqrFkl}t1?4{c!^5bRHA$ra5k)Sj?}^=IpfmB15)SSmKCn;8C6EIbOW{PcvDjCQ zL30@q)O(b3GNBr<4aDMi5lZ_NY6_OR3fb3KS2f_bg%nw+BM6;pg{7;2HO7&Oup!aT z#j;=w79vPARafJHV+W-J2eAoDIshvj2E=&*>UM%br4l62ASC|QSUvKZCvd+Vq6^pF zF;FHY*vv%?{t;A)9DyjURLJB3vNVVd9<)Fn-31B4FmjQNd&C!}nmigMZIWjMR2ND) z1`BjzX;5*G+~kJnBfVvUh$)B(psR~8hs%(wV&p0s>JzF`aCcxj1JxcZ8ziul5<{=d zMM+`s&_H3JjQyjA3b{O_aDrKdE1QvP#o*BgDriV*3=(iUs38gqH4u%zQ3{G+MA#x1 z12_f+KpCCTF?xtBN>alM6cQj8gE98iQ{cmOa1L66h8@6~85n3)2$ye~$*k0a(qza%eb8Rg8VZ1QxT&6oPsMSDlY!DweJSW~GBv zmJE@0E|#?m@GyZeFnx&>Dr7P-=Mbpd`6km@G|>hsXs9~9j^1*?pAQX?PtpJtz>rvF zU_d(Z2HD@BW-jtF2V^-o8{q`J6CrT*5C$kD;I`u^GeMK9I4T2_dnIsahgd`ziSQiq zs%Emx#J1EF9s-yQ1*GEsKI-M3P{ky>0;xoT8iCDI$b=d)gVPz{ShP%+!~rQNKYh?h7AsfVV^35`S<<)`Tzw60uzuh#Yi+}Vj{40 z6-n<9V}eH@Nhz5K`47FmLNB4-qioLxm5zukgq$ML^+D`~s37ECcuNqwArPa`NtASk zYxfwaQoz-22bIUrWJ=2-7v=OPEaQjh{vyCXkEPUu`T{{Y)Pox?NO22_G*Dn5)PPtZ zQ3Cd%N+VTMApKyB(Y!>m7Oa5KI4i0ZB=f*_fC!@cwwPT7w6RV|k_DMJG}h;W!wWNN z!5#n+IJb%a|NnnK{N5&_!VYW|ltAi2fouT{>qBLR8wDNWq1vR*E zE)zr8ikj!Z9;GG$as@bSLAyz*VK7or3NsglhBrJBUIdkUnAwD2%%Hm#rIv--2{Ia4 z9a3EeQGs5IBP*r?8!31ZNfWQR7)y0g5&&|U`~N@03-l$4^ahF_k@F(5YjL%A&Vvp* zMJOa<$QQ*rjC-dT2+rA{>L-s!&61B;7eGoH^o9koy0NH3&xhzG)O?h!@}LGOB8#D9 zeeCH3od0k|JIpy~8QFn|JPI}!o?>vu1gM6>?l9!}Gn5<$a}+gcxI>Zm?@?j_{_zEP zGZ$$%7ZeAO#DnA*(g*R7$|JZrXwiilHFVgVgf!fN<`kSkjL}sk=iX&2s6i`Wkq#wjY?hoS(dCDa2lRN@KnSCJLkX(bahyf`f z4I>R{f`ScW3VJ_^2&mJD*xn0X_zKa5dr&|CWy%e^;~>6*nFQKf0V*M|tA&W7uKB?k z9-!ONLvQ$;7eEAIDo&-KA_p{GkHv)lNEHULjidkf_tzIVAo*Ir!J)pN zn1hOte23^IU~?4-Vvw`|FJdn37}YI!t-z=o;K>LnWRaL)ztV{ytIS12Hr$n1huknqTm~|ZcSN*U;FggP z_IM)(pJV{t%Unk4$6$U8d)GYhyn1t2Gxa~!gDUY zLI7^3LJWgg1SYB10bB0?1_kw?QXf>kfX!z>UOf#8eTXP17%;<`(=|T)dkSNiM zS>%FS*pOhL5s7dL$~YK7+t3SCSVBM&M`9w`LUSge^n}f8SXwUFid@VR7cB!}GaFM3 zv%iBrD2b_u3L*mZE_0!U92FBW)I>xY0%c94pb0=(wg-+?c%u-^gXzQ-;Gm*_V8+Ib zKZvooZWTuvia_fe3`X7t4jLwei6UrH?I7$5G!+P6 zqB#al9VQojDh(QoNMTt&b0)$k^kb1z<|0xw%$?YZT+B1=@vS7o3^J$)X7!C@Lljg! zm8knPJ^LPuBVkPl>Lp^N{xu|?potDgPPz-0~8Eyxt2r3~tHBg?MS5&+#s;gP|aAfBK7~R0u6;QFu?SH(if!k#jqF_mV_Hd_fc2WV0R@*6xW^%kln~(g(W9| zl#q_^BR9~I+j@v71J!sSw?R(cM0N#Ol+Za`m~O(-BSG$U!R><>4VjiuNS3+ic^TU-|M1qSF%+4o{;KAuA%u*Y9@E8%QNTGyWG2k?pG6@uak!%!NQx_CcNYOQ9 z)`}sy84~&+kDvwyYHJ0oiqr%EH4rl$(4lGt+3i5h;tymXUJOsrm|=-mA0A2MJ{dR$ zQ1b`aMx=28P(_LuwneGwaF!zqL@X3TDlWjTKqrtJQYgD`?n zsKEd(n?d&APb#F8xS*Yns8tq{mB@jGGpvx*6T{q(k`UlNLLPuebT`3)0xy9@!Ikefl>AL#N0kS)jn0316I=OKxMdM02&a5_aPSir)ta0Qt_48}A85%<{S$k=j0 zj5E;GfGT#dcfbUiB$3?v$eAGl$uC2s%taYq0S(il`x{G*NOnR5l?>pph7(9>4&7p^ z@LDdpL2O}Dt z(5o-r*CRIz!ES@hlpz(l1TWJAxfiL%KnWIjQG}<=!IDP7E+If*_bsUWhigO)W)z2! zz1f&>3o?1{@L9a3wWEaGL@KTRF zMOHy`C(T#)kw`tQF-tSl5D zTt$Q2i=#^bk^-5DXVxA^5dzkQpTO!elgr0c zzfeb}NC>6>=$27+R-b@FKpBZT`G6B!q#o zHUg%cNE+La2ckrzRsy|`dh;8oLjiRkq!0xA16CM8nz`^27^;x;HX+PBxB;*kG>j?| zq5^jSgPlh$0;yGs+{!22`1hbJ4RJc091`tZl=Ov}=djd>C~ICw3n@^^01qB819t&H zn#qJ!gW6|=RZ&9)Xw4Sbb2zTmCC3i5XhNS31bL1D(N2Vv(BS40$TE0K5#%a(Neq%f z!JvYVh&c_AArOoxbN~NG8DWD+LrB=_TNJC%IiQ4rz4;CC3dks&6(*Lf2U1TQMk@2* zjzZB17o~&|04YadMu4kCh%E?T!wX_a+Z!Xsk>VF-4qh5dLmARlKuHb|SAa>J0gTrg zQYDeP5UCZXGPGzyUSI^$0~!>7TLFNYywF=uD610nizxbkXS^tm>}I!7$0?H0kxb&b`yAf3|Gm9q!1L4koZG03tMg`s)h!& zWpOmWAzlHU7mDNpWG0r57{qbJl9**Z+)j`YI7U2>oj{mvfaW_y5F&*SY$yN{1+Wqr zP)g>r>c!&`K@BibRY{b^!C+suQRe-uQ5Z5r^K2VedV^N2-23MJzz@UJ#;Tz;F z)a-~+1Y(JISVjivCJ|$r#(-4IlV}*}%0cl=x-OD+AQic28I5G4;2J<>63F=oj1moy zScGI%kRC`w8(x;6G%RqQYyp|^A|_uWT!B{R{(q0&kwNb^fn0|LgR~(PK1eDcwF#&} z1aABx$v~NiaU6uR&{zr%4)yi*^#Kluk`7q~W*P)J2d)C$k5GF_qWYmLJYbrTdi{vD zE4*O~@hPkXhC2lP)J~XTxM(cdjR9pTE5c+Di(W-8lHVB^(3=0ayh2DEDZ&OdutC9mk?0EBoHHUEI329g{gvZRurj0G|S13SQXf0Ak>N$SD&lca+z z#YllhwPXyAIOK3cH5roP5IGXUhZXpcMleh_yd*~R95jm)GZ=!DXkZ1n0%GP3$^Y06 z?Le~@!UYwq*vnM7&rvHGh&Jpe5yE`Rz>qK>OAUhB69p?qA9DjWPQVgi0v3*NJ4t60 zpoavase@!XEaV_n0HRn1y8_hGC(UA1UqB2oz&gGMlB1+CMVh-nkqxpDj4}Hdq!|WP z4N37}69-wD3(b9qNe#4q8QNxdSQ-F(1x#Qj{C=b~1NA=+3e7ICd2m934$WQql(|TO zMzxhUum%u3xKK@oNF(9~>`_Gh2`{$5+HuAg0|RLI554%o7MX|w1KwjsJ|q(n0>swP zph6sbVGr>NsKJcQA^)*VH-J3}CL9oz5UOU3wY-R+gD6BT?yy$|5S7G{=P~a30|hnM zkqk(+0#pzhYDl3BQHfq|6S5l-4^aJ(88oEg2_a7C(%k=swu z(rQ0)nfo6e1_Y7@Od32`4RbDvRZy?sT$zhnI6?ylLOI|oDnW%jL>ZWb`T}k>YH;z-d{Djlf;JghskfFYz0m7g!i95N$+-3ky@2D*x)J5BfoC9||Mv)7?$`n1pVh zMJ~u116qzUfc#FSt_*fRq8%)YyLiK?9lHcdXABffNE!A2e`v)Cj!>|ENTz~C3%u9@ zX~cVeFsLkrjTL|m!a;z-5n>p8mCJgRG8f)Bg}DK%LGuM*O>vNev0Dt10b7NU^uR`< zHkrT*p#=WB+5V$td~|n08=Mfc5S1C&PBMt~@Nj}@MwIzT9)o%o+RVjLoxpSxM`JMn z+)~C!O`ydCNUd$+OebFzO5hSx#}i`}QkooW?cD!}E6(fDTR`9lLHG|N%FtTDu(32u zVT2h77I8%`D3Kdr8-qg_L;(xbdLgkKyuW|{{`H_KZv^h&zaMm&6?S((vkk}}c#Aje zx^al2)r<^i`z#=KB8m-2a|u37gsK~R(FU;?q!LkbL&UI$DzL=AH+&?crrE zO5K2J6nF;_q&Nd92Q|P@6@YjUuYk$~5Dx?6PE-UAF#C^`4?uB+2t2SIs6{!n3^JaM_7Y&QW1kJ zA*Rf|4=QE@kS~jcrFsM{;1EzhAEP?~4iT6lw2Vx)M=-+<#a@Usr1S#W0U2q4pLGK& z&|ogY++zsR0LKc%ZMO#%&2ST;niHTcx%&d30EXL%vsZDy0My!nc4$F`1J=NTm+sh0 zWV9AM+)WIK`3k7>uu#xof@ngs9Vr7-V=+@b#tKZtMeazo610MWmO@yHMx-V&77w8d z!6O0UMKB3UB~WX?d?*2`C(*Ujj1P)!sJ#r-JH-qs$_8IM_dlXrgYY?sh1y=lh#6Gr z|FAACG}{n}AxOCZvIUOO6VUzj^#O<#Iy5PDLB@lM1YC}N4=(*ds^G39#4sqB4{er! z3`Hq&LFpSLNGV2Ck}$`hln{_M8B*+kY8J#AF0^t9J=BpM2QrC>+y@$gfVl+Tesh4X zvrYhuAhJ8M`ABR?dVm}~2A&3kx5|+eLHE*u?7}|ihnjmq>cE)DJ5iBxDZGM$+Ky^4 zMq2}_idgEt05otA8V~`5}eBS`E2Lyd!J2GgME#}KDvj}yX6#Ig`x z2f2t^Lkq|Y;09rt3%-^R~G3B19VDD`;^CD+{4qn3wPds{*2RjN$@R4r=Owj&j_G4qm^93>m=-O9rSssuBPH z&#&)?I|Y`) zV>=hQ9S-t07^9?X=u9|R0!&~Oxsc62NGS$Sn4y+MAoD0VmJE+Qgrvab4^sBp-(LVv z`yf|Qgar~%y-BTxI%@t0IT58$fh0A=YF%iv7gmNrxgc#I3@eGTh7_ovL~oB_QHT;` zu&&{JXzzJHq-21&3S=X+1i@ksObDC_vDyo%PH>I+L5nDmB}kaKeizhkctaOd7D2^8 z6x?F4!H6ydNRD)DfMp{a*kBNW6q%s92T|)`#yi?ZHbM@8dk$m`6oYDORL?<{FA*|} zit=c=glZ-ulH8zd=VCj;7Ij1mHC`APFpFGpBobBRVr;<2k_4$1@^}pbM+>CPJ>L%* z!T@`NCIsQa2CrLTl9(k6N}z+Q5#$*fXw1QEhvZ|J2l3Yfpxi)s#1LvD)JT|P5}-5R z{gA0Ngtah-!2E+rgUWEMy=G7y0Ja8eLlfQz1}lLPq?M2GCLdDC2b!pWnFgULY>M?` znYe@pBCO5=1q-B*gasI8-wSIXfiz;paKAx30VY9dAEo_F)ES#tjVD(ST*HDL113m| zFMO7QGdI}G!CB^FnMOlN*GTRM`+}k(7bEe|cgP+ooIo>mv$#WmW&}3K^36e zh2Vpoh)osT>nJ@ixJHB(5Wj&);+D|Bjrji`GJ=Y-UJJGY5@a42!@3Me+DKu7yn)fZ zfY(W|It#u_0#q!5j7KY*KrSJze8Lt!pxy+$CSza_AiSUsybu%&{H2+8&Vd7#~{&@XJ8XR1hni!YeAxx3q&PzkYU&{ z$O=%G9z_-sZ>Xatkii64ctLn@uYnjSF^^Mms&8xl3}fCEoKV9`laA=KnU>M?2f zoCf#T;G9GIk9o`ma=L~#o=Qsfe~NDNvCK+FM?12dEhjxDhL^dU%VlYm`^ zjR0j>R0pFN3~snXdh-z7(7X&&gsL4e=nGMdMuH3@JhXsX9zj#aeF5lU>GhEDNTdvp zQQV-}3NBk9+fE!n0O|uIPoovc5dD}#E@X{ZL5+ch7sPBN*MppaoHZZ{NFhNsV3gYM z{yp;00@&wp&w_a%>){wyzY%9UC^q3*p$u?y8xny636yz@I7eWrg4hmq53HibR7Qr# z;4gF0(iJ?aL7qjAZqyVBJ5_|JA{R2#1`lFttS<+-kUWf5$0ECm+H92YB+s=VU69HR z*>NZaL!}WDK+rN4)@(!bFgVMBjKz+L8d^X#5?Ty^W?aFgFQ~Q#xd!Smki)Ut1s4VN zyg|xvW2`j=S_2-Wo5)4EaGN0vP%9gKXaQUefQ*D-h(dBnP$7d+?|`}#V8cOy1vMFx zBVo;42oJ0VMj)w$YQaNc4Og%`92f)~>Y>)G4{*SG@ERV2DU(7<7$9$9R7Mn-j$Gyr zw(}OC-a;){!Lb3Afo5D#n1C^Qz(B$cYgT}o0H+{I!KOe6jDcaeQaUh@Vg=$F+L0u6 z195sCvy*@rMF0%|LVECs$`6*6p*adI-$4sVT(*HqQ*gnFO95CMRD>Xc4boNu6}b?@ z9iaQzpc8qx4+8_61tQQB8^UZD3%$k%=|Wp{3{pz+P%hXU$dMvwDI8J`gA4^>*w8pc zJ*gxpN-#};r$nT50?sS&Diy8V2RQ^uEn!z+(GQ*FL^1{%_yPUr|KBIv!y#-bK^15z zlEj4=_>G5$>7X53KuxvCEg(?d14S_m!;=Bj%iy#DU5yD9!bM^9Z%A6mgUeL1#Zk)( znEz-&lhh=^=^s#8hUPkGX$sZ?lZIy^P%9Ip9%ehDp$eo7vyvR6Gx#z zJ!Pgfz#GWHr7tMigItKzNJA^mPz?M3|38vSu!)!itj&(16FrSGplw@6QH+-Z zO3f%08S;r=VAl|?hwxYcZjXb41XT?zB|>T{h#WY!;7U=OL?DMCtA*&mN21mnApOWg zP!OFcfiF;i-0p%XpgIXH{HD3sD@0QYJ#B5n|As3@bvQF$FV# zKOE`}a;XG&6h_Dp zksRTg(HIKo(qAh`r{U;xbkd|YryVAdM&yoVGz;8GH<6dJim?jY?38&ExntQo|{ ztp4Ec07-)|ZI?2jSCtgR8kRsuN)&^&%msC-K*5Z5n<|npSQeVEV19&lUr{nYOb(R> zAFK;D0!q+*!wcL!`x8KI2&gmYLyz2P81?@@v?e9kq(f=uqLV;*Sm^x&Qk)D{ixGgRr{2L@WAGvYCIE{Yv?3c;5`)b~C!lr_Y|_E(fP@)Z z+5k1pzy&+9&1h=i78BFN1=)hxHv9h{S}_P#ngFgiq0XWrg`6%x7U4=8WLh}{%3MTA zgdCf&)Bp+-v=%TZD4^2tv;h*siZRxRQ8|FIT8c$*KGelf|Byg|){25L33`x~QdsCh zYd2&QQHmC*zYuW;6@Z;sf?7P{pYntjxzK~bu!JH^2q{^E9HxMrIYAbJBN@a1$$~Lb z=NV?m|NsB@V=EKD>d^?SH3eEj6uJQp$#{yGu*9YI07XKUai*(Sr9344$`p& zBo`t@23l2w-uj2uiUiw3-~&-%5eTBu$IM6$P_i_fCvi+c!6Bf&e*OOaNC5)1_x}F< z{q+eBBn?qeR_G%2&p`o*zUm4Z6X4-fup43V2}{Xn`oX0kSRod|fq@|bWFV%$(G+9k zPo$&4>lp$dMKH3>*vm`|W1v37q>y@GaHpV;3KDJrz_k*?K&uY0xqujBKx)8og2j2T zu@U5a1gc07NF2A^sSauhnoatAU40|TLpjnGXYf)8sH!2AVCEktM} zQVBS;A%+jmG8euP24%qpdR2s0w}R3IXk-bgdd40eNZtnr0=}VK1;_*pc7rGoeLo*F z;es85g)ji!_&~740Xb&>e55_8SWH3|LKKJ~oupy(5JbCz5mq<9JNVZ}90mqOzoY9@rj*s+h|a;R&NOngtuP!FONk7NRh1td=ABN>B(32JXb zdq^>9CcRup$vTdnGVHcIJW&L30GiC0K(3tQZS{tx`j_3{}hf`PkG` zyVM0$>L8E6Fhv~*R1ZLSNa>>f2oeWoA?<0*)DCeOl!Qe)1IqS0v^pLwSYTaH+_48W z9L*T~$C?X3muf@xQi&qA_iB((kEK~lz!B%?CtypZ7?Db_5W{H?T9FAd89CI!xfwK9 z05bqySwf=>&Ijpaz+9OL(+8&e`yp3k;cW|pRHC<3z=or(MnQ2oW{HJ0dxOovLZElE zKyLUC^E*^MNo5h(0Q>}6W<@kT@oU2-3vTdZ3skTK+L^iv$Xl0@awpWAsHgs6vkgfM zB@UnlAjU0_6vCPNu|+LaOI`H(8gDBA?k-XoNHI4!+qsA`11ZtM8%vOQLJJny2qSWj z2y2+27rD@K0IOQigb3EGg+nz_!bDBb2sqTQr=a6_e?Acd7x;aS+b^)%4H6Gv5-FPC z7e^q zqEDD0@)Q%?v8bsFIauIIC}5yfR@hpp#F`GyO|S?-(FDzW$f@H#%6X5NJv5RW0!t0B za0JoV%6?==ftP246e45lmAa_uf&u^h0t zexV_ZhzWRdgW8AI(7~GVk?e!)1Hj)Bf~bMI2z^`|eryqHk%ivOg*y{!43ts`K&|~i ztk`#f8=xS_oFXM5rC8}Xq5$OrH!64z}_<`z*ryqA6E5a zO~NQ)j#3k0bu_7h;DQqDGBAN$ERtvxqzJ$^^#P48lo}}kd5jM&BZ6E4txSn>14}a49xUSu2K|WC2UGSRvZxg_ z)_@Q~uu$4?)Gu-oegylAl-4D}jbIiezhE^0I-7(N-Uf*11P!-=ZAT(V8CpQg#}HGn z=P>ltNuyF1EnSd*I0iUmaS=$_28jvrK7B~6jRcr;5fv#?qJSm^nDfvKfaNhXVVH?f z8a;H0$Q7VmgyagSLF79(QedyrAc;R9PLg{Tu@Q3G3F z3#!FHx?mW4enasxDDF`NuyEkkKo-Pe_}>AoR7H$7gABtM(1UIm2FamfSVswK$RW4k zP#XWJW{}IHUNaZsP^^A{co3!W@*a7b6RAZ6i$dfCK*(>{3LG5OE(1n0oF=6%#KSPZ zV7cgvke7&(NAfok6JaauS$NAvMD{@_1C@P9&Vsk1ApV8<0!QRQ6#f5?*1{s9$o>Cc z0cH9CW)i9N{Q_*mQAi$wGf6cWt9n>?z)i))ASJheZNey=(8gY1K@5*MNbW{74AI*; zsLf5V9T+_3&NVQNJgT>1uQwi zyM>5y0%{YiP==a-Xb*$U$4Y>TGD4%=2rt7U3+r4r)LK}h8)_e<41&oqz$e|H(nu6E zCb5r%gVGAj5JC<{GLu*)T5*Lh4-qgD(yD>R2&!6WUP5hRzDKePq8H{(5RFtIqnd?< zhe!_~oe+#mKlU8@9+t)+nxQ1}>J%*2;ub=VGq73k^n+UuIWkDDuAey*Y!jUcq&URz z0G8|nA4P*Y6QvgZ51-b+UU9=LKnq>`ieZ|-d)AQ3ez-W%4B}2yfE7g)Sp{_ymfjyU z+%PF3Ljh_sJfx8fLLT^om0j?f1JNvoMj86Z0=|R*vlNt1v6c@o1^*GZH8LQNE#h8o zi`Gwqxf|>)(AY1M$tX;iLa1+0@6s z;9x=!@Cp`c1U?E{XCXA>S$=`E4Fko<`)D~CVi?k7 zDf^&C6BWF0+xB+}96VWV&mclRJ z1Jn3>mne242Q*kOh`O#1g}u~G!0l?NK6HwHMK1C(zrokeg?4UGjzLC? zD%9pbd@v4gF$$@_K~W6Gc-5jr4X7`LT(F=>;^z>x`yl|5v!S&Lv~0p}E&*B4y|nf9 z2@VcWGeI6M_z&N!0OBGrDScqHFa#Nb;$Bctfdt`ZA{+qCm$2qMNEK20v_W1KKwcdR z62Qa=bI~&}wo(^mI0R%EQu;zfHK+(h>$1Ysp(a3(380}y#E?CP1yCiFP$1_(gAGJc zP&q?tP8m@iwNWhFeX$Vg0(>jh}B?iZ~|vm6u`5+4eQo4h6421hgyq+ z!fb|MjaVGINfSnjzQMOv3{jCHsx5FrfJYKqB*XI?LOo`1AR0noV{pbZrcO{t45`J9 zsQ{MycpI#$_70;^!fk)`GNS*6N_+LO?RaVOWU+4nYWkQnw4ge77z7L34~;c#=1e1=FwkQxT1H3&_IXbBK%3`9NH z70BZ)P+3YTc*_E80rEluQcZ?>7R6%-Gr-2}lFwTQI20TzEx_sEDDd1R64EITbDm&+4!+MWWGy7fa4WQjE$3 zWqC9!Q59h25wrV20r`$6XmTX0bjRufEP`mE00~cM3lxiTG$CxdkuxW(%z+PAzy#n+ z8=#$9h`orV3~2VCbHS+<*&=iWu&bUy=3@2Det5MEQi56JB2O0}48IR9tPy1}Vr?$= zA{Cx+vCsV=3?_?()5U+A7m9LlYR4f5Qiu|gpwPrqW`fkCVnihj(F!7Q zTULPcv@wXO*t#$zT=#;$bA|y+!hl#r4HBG+LH-?tXO@E_9qcwlJ0IG-0E>dxydwt! zJgMW!mS`bf)nejuwU> zttjmfc##bA7hC|IEg@b6>jV)fjbxmbL&k*hL@r{O6<)Yw7=|O+~JyuWPk=r zz=4P$h|M$50tcZH)v@p*8CHfv%1W?u=*R$CJff7?INcAqL-W02DDD&?p-L0t`zoU z3-SY`=L4F|2l2odwOa-6x`O2pRVVKH@;_=^p~Cpx4QVVB2z_|`qNWXG zlVPnI>_skgBLIQn4rth6FOm@DKD35Gww+=&VweUTbh!OV&?acrfGf9vq;Y3X&<-K6 z1CR(3T8Hp1DUx;6f7|vLFI|oe;8ClLmUAiN$@VV zG=wi-^%FN!h%{~laT1s$v~UcPvcO6~4Lr43vWl3tSBYq{vtgY9xRy!Aan1;v$(sV~i*G&;0oC4tyhOa+P$Qr0KaRdW+kOd`!p_+%56+te-(@sUzi|ue6e48)+gO;@7 zj8GJ_vG4Q7xFZBb&;R%R@XM?e;O#q9CDh~%;xZSWy5RW?t&WF_g98MS2ymwqxRIbF z!a!Usf(?fe-~xqE$#kBG6BY0^abcFxoQCE)a9}_P+(8F(47BWnD2I~BEk<}8!CF0t zsuNy{!HYGBe)t#!%nmFxXo>{1=#@aehL`WS;|Siw!qJ|A4jV8aRrToZff<24wBR0w z)-dS0DdMA7SL7EF(43Dmpzh;c3XSN5LgEla;s{VI{zdl%NH+ua(1hqNAnKe?uv$tM zj-4l?NB~<(5&;c)kf#UR92z|F!)s!AjsiIs^+s=`VFy@d#|#H>i3!omKzt;km;=i9 zcnjdh})zw5~#~Y9Q8wNtgx1R3%^y zq!4fqLV_O8_y++~VIxa8V|+gYzRo^UxdCwr;j@R390Us@m{t&t+JZt-3}QNvGKhk; z)FpBW1IRL3W2CSfY-KJeBET44e?rqbSP<=&CdgDjSO#}f2qnSdjbog_4o)pNQ~LY) z=;aC6MW}=WWVabkE9fYJC|{sX#8HeOoP?nR?aoPfPXb!#!JEBM3$Rc`MMS;8e$c8B z0>ioRaRWS!CRifE&^JALI}04KsKPkeI3j5wOIu5RL;mfPuIrc36#u zCRE%3y50e2ar_^$Y7*=O1c6UEsuK{=gwTz*Ap;s)h9)RflW_2`F4rA2r7lt=4ze;A z-YA7PNZ_3|NKBz*8l-51W);lnKxrnE*$RQU0efy+PsGJz0?3;mFr7$e5m@N~2~Z-o zqJgU%xM~OkxqAx<9>kq1 zffkw|m!hOKXsL}N1~nb&ni2v|MQ9*_1$R8iO`xSlBJ)0IhZY~8;DliODGyN|K~#fCc=RCM3;}O|VQChF z^dMv8A{(!lKtYeY4+GW;Pa(L~!IKrP1b`TDftJdkraN+T5M~1QiWk%*19^{vCMeh| zSP7Jl8t!c$SoNX^!WQe1P*9@i#}cnt@&t+&1P3)Ef&vTQa%zx1P+fzZ&Ol;>Fo~sZ z00Uz4Jt3nhlt+|R41=tl3wIeTbAa+3G=e}BO2vp2jnJHe87^=GLAr^VD#tY9Ke(}l zdhI(%6;TB)%Kl!Eu0en?3Q<^KV|5#r)(y(e4MeLJT;`o8YNQ3LP1poMwxiUu7>W=n z1V?#@d_N_IZm0mF#{|vgU|%6w46Ubdlrb>vP|Z+7sY9WpU_uwu8>0sZ$x6}Sum#HUF-wo_XQBlF-(*~rsj;3Ntfj6e=< zcr(-B{`z`Y{J~UWr%7lIfz$cu^ZRUca0_F-RjXONiy#YI`6si$I;Y)YmrDDWw zRYbE3YpIKUxh^d2(xKQzE^`|iApWN>iK}G=>qo&-KCIIQa~(<<25oyF1`^Q%|34(& zV0!Tn*kkHN5`pAvSYo|TOjC}50o(pwBr~bRT#vJfkJ|!RQiFvIN==5U4W-h8sz=$& z1ubr%Qp8c<1~IBVxOfhzJB+a?gO3y9HWl6!h9@fwa}bpUOzJ#RD;HL1;|eHfvLz!b zV7B3+VdDX?fTf^Vhj|fyNr%fJ$QLWa97Dp9Vz5dJt`)>UuDUVp1-X|zw-R6Ku1D0h zG@j%}E^`N0I~NoaAPfs@^jaP{mJnlbD9iJaBM+s-z?ET;HQ-=FTZSN4ov(*xFpx8G zV}%0bEQ`ZfiiJU~ZQSJuPUF$bN!&(&yV&TyL@rv8A^}|)PClLnDTb3lT`>$n6ajdy z!O?&Gk2ntuPZ@#864>GmR$}0=0-8!mX!W7^03Qclqd-FwS7QaA84x*`A7Cv9h$!(S zOh42iURNEGklmyTZX(ZAL5|x1ucV!@R`5{`c z!Zre6I03zt1@R$;Bq>Xm0eZ3_5MJOw zC#xER+I=6}Do!k=?s;$=z+9I=LW=-u5m6KNF8Kc z?GNO1LT;A|9H2-626YJzicSSC^j=E=Qi?CIN1z0HS&Ac_fs;KBpOP<(!!oGTP$>tz z?N^Xmc!t4aETl|C>OO%qqG7l>SPCVmeq4nFG?kKGKEQ4!#-$TuWCxEQ(Y%Ash2<== z&r`=%YT~RbaN3TXYH;})su`R{38;Z8#YJH~atceSi<-R+kjKt&8BMY{k{yGy%!L)A z@X8q)SICi!$Rubd>LP*z-o7C`Du@T%??*NV>Jn^}0A0p#|NlP^PL2$u-u{H-MWp%) z>=Eoq8@b8?E29oU!m0((Y&ZVyG`xL^XD}762G2${M0*)CHNmPLTzL_aop6=NNWqTA zgy@5&&3-K9DKwtp!A^X;63r&qYDdfkj~EJZ2!MO~aECw`I2XlZn1SvQkbXQ72G$R* z=&%F|SdwT0+qqMidHe9z19YwuJx@fGbPlF`gVL*z^FF`kH9t;H@60pRks>=p9?ATFNQn zd&r8MG3Ta$2sZ^k;fW_cq~M0TnDWK+0VeBfIcXN zUNe$js>7{^=Xh9a1};M+16!$y-0Q?^47LIrvuZ;%0umpnVr224eL_gwLP-bY#v9mF zwAP&fCAkZ1AUXk$fx%klLenoK+@axwwj>NGkdTXFWUs>WBgUz_$f|I&_Y=9?lmWCZ z3`e<-+jR0|AOnC54CG9mA#6mhjX=Q*tK$$V{{M%ahXRtPGA6pv1;rpVEg(A$i489c z@Du>>vI}Ra2{I5-zoTVHSOtZv!3`-_>G~Unzg(w`uy$aC?CUIq2m?m(f5pM-d8&-Nfh64mJYI4{(57==a0<$%Y)ofw~ z2fob3(My6QGia&@hdapsP>ftOAhHO~Au8mMCNZtOCw6&1$Yl=wB$`faJYlGVEj*<7 zz)z5~kuY+=LM_D@OGHvm3R9tAJyLRm>Ljwz-4AL(;tyMRGJrZ88wIbP@s^8lRp=`Z zVI!Hi`nix)ijj%2xdcfJo;blp?*IQ_zk*KIfwguKxF@K-)aMq@JJgJa}2b1|b3 z@1c*VF2Gh`6Wr|pihAT-DX2!0%ELT|3S;&e^TG+r+BIlSL<+(Bf!PzmfKsEwod+v( zp#tD=ho(3Xg_N$5;}J&z4jK#u=>lPl{vy-{Y}EPr3FsDsjKF~dXuOsh$%U{I7qgN^ zQbZgRR*pbDg{90TAqb#`V4(sawGpVfiYiM?p$o|b_}fG9WPqJ6< z5|l72P(>kfU=kcs_?-z>heE)MTn2ap9kFOBpnv~=j5-fX9HE$qhl3cH$6tZrGy=ZR z3^^8Y)j=4hAQd-o{e&9rke(R1RRo3;K-XuY?_|PgxL`DODeO(6xB@8<251fq9QFYi z^9Il|7gj=oRUr{bH9e$p0g=NI`G`!!Kxps?7CJ=lUWHhUz2blwMr9ga;!j@Y5!}%r4%)aHezP%T5qsIlEyFM?O@ix5 z5U#*lVB?R9|ImfWnCTK>EE%l#^HGR; z7gqH{yp14{YH8#`1FjvFfk@X3M2rjVpI-pKs{>&p9u{2--2bo=mw`Hi`^douoj6Ac zJVZwuPYB?VGC*6xfjJ*XsL+M!fTaZ#=fOGfPBV^r7pxHOPW)LI5hln*6Qsd~XTl#` z9uaD`f!%>1py?cAo&h$%0CzE*L81i+tN#B79YG8=2Pp%gs363FkKjPf0a3W>APlpR zN*jX&Dpf=Qhc^o&Cn+RLVIhTc zXaSte2sPVKU5*&4#Te~C3@{)C70!zgRQ_O z$5_@2dLqh%f{m|qA?WiF#3s?p6 zT~&w?D%@lFNO27{5IxfNlT+G)+(N6(D(DV`@DU|0(%=e2id+&Y1%Uj6R^}pyE=ZaL zj69-%;y8@)Nt{!kU~RBQC;o9#XnMhaMGPVt;SE0IdIl*xV5taavkn|MNQE@m`FIIL zP+(;F|NrlU%W$xvNCb`qjMo~NB%(b*k}F}_;YXPwIS2PuoJhK$OyqEd8-cG|0@4Rb zpZIE0kSg*q{Fnu#n1-5$rK!u{K*+sNy?7{ykH7&ikmI>v2Vf(hO@8#OkJKnY?)&1( z4M--V*U9Ji*B6j~UI2Bv_juw5Sqib224kibSs96Jq!a)OCe)M%>(+y0NWu>Fc+%#3 zSTPDW5?^BnG_(mSERf%V%H(_+5!^CCG2! zK!B!mH2L+gVjippOyCPCG~F0nco^ZY$2Ygq}%}q5u+LkRZVk`$#DT(J$Oj zQDFem53l6@cJ2%3_!vNd>_<`L>^i|Iw~1v1J3p~*i#?_5atnJ zAqqiAl)hh&mV)1-#SU@@kAT^j(nzsMZo);+hoI=g86M~^z}n13^Dw%e|Dc!$b;2kbf!J^$9i`DNYAxnajW+5P*4RB2t+P2?hv>-iQTz5jOJ) zR#Nc){Qmy>0Mh2jz&f!IB;_xtTgar4N?dRyM5ZxVw84rJsQ-{lHbl=CDoL0!NSIGl zeg>CM$j0F-bnEwn3Mafnu<+G@csrr+A_Hsw`hPzGybKhY&7rP?HFV)6F;16)>O{QO zqlZ4CEdX^7mg{ZL!`%#V54ss7@DV2A^a26X5Dtbo223KS7`*zCTSs7>pqX>LI{yEM z9cPC>@(CG2i9Eci19LKHKp_JT17w0&!;o_-Tt6thVWwlFVOfp%goVu% zip1apzHmo_>Iy;*$73Z@wi>MMTx72z*bW8r!QB#gRse0gMT?pHpjBT8EtIny>cMux zudG0`4^KFQq(CdNVOa{qCl(`}L`SW~3P@JN%OObcKs*SMM@k$JNgSktLqR_Y#Vy2e zPyvHt9;AB>kwhmQ7zix#gC_%Qr77GrxP4f1%z4n*DY)PlU|&~`%s()c3EVqFFXGDoz)rb7Y%>`SO4NTFZ_AjA|XNp!;l z;a#XsP|-!mdT1$+Yb=P6cIwEZ)_PFalVABEWvii8=0bgrg)#u0qV0e!hOsCnUIK!Jg51yaihB!vS* z8)+olk5TAiDF|VPf;alL2)T1G-YU50HHcQ3M(_hMbNA@^t~?*cs@EF1)9aw5G=Cu z1BU513tdpR9e=MK)JO$8315JKi~%cxFZ+h82KDn5AbAc{vYdw$fDpythAzQ|G`M&m zREEIq`wyFt2Q~I!VGdfR0CoeoPDd#jQAZUa6U)ek5o9A3c~ouY5?#w+E4IKPi_htx zxBx{0DcuKr=HZqDucg7=d;moa$RQ}0%tNb@+qp-OI4EY*lmkj+gSgmLNWj>Z{Qv)d zScstH3mg#&J5(b8OmWbO}`A76%O1I{0vwD2nq!_Cbq_f z#}Hg6VyGOawJ=RY7wkAqA}9f_=I}Jy!K3}iZU?i;Y6l^utbuChLV|<%(`mt;r3V4p z6$fjAKpY7tVU;%F6bG$N1nNo1ju2~*1{I(y<{;wKCBa1nA~eyZS- zTny83m;_3tNF@`dk+6;jtecLh0we-gh4TiY|Np@U+<=;^NaLRj_mP^tAcL@BP?A6o zJ#6ZrVhH2W3RhSQ7-OmqZGgc5Z-78;fm5Imghn2y27!x{z(BYdY7m$rHd$jWuyN!r zxT9d2K=A<=qzMDMDg|F>3hS~l1~O(?km6!s%Un=u@2C18EI3(^LpT)RUGoI%X%eV_ zA%nOK6b>pdFp#}GY(K#)0jb~NL4+|{iBT-Vl_D{~tuu1+0*2|>3tdp&!)rX;7ufYf z^}-W7zGwp(1r9Z&+9=>ZEW*Ky$)LueQlQ`TGb=0@A_3Z8p}qG}1FC zQb5)ty3CLup$~~#U9T^IcjD+{J%%j;4)rL9?O=@pcxu2?+MI{2Q6qhOFzSK!)ZjQEenu9_D})L< z6lWrFus3rFCoqT+s166ao^a_8i&cEl1u>pt657tiaswW+(b#umlRChFT;>kUc?%es z?EU%zSYSirhF+9GKt17xAtVl9X$V(m1YY2hac48?-Oyw%4f_B8eZ2wU_5m!d!Gah| z9wKIE1oaACY$kywxS(sOAfb;z!kmw9&;aRFEj*bR)FOm7mJ#J51ES2rNUl(~fD#0@ zwkcE^oq`*PsR!K5#Wm=PDEz@*HXyE)N6O{63`Tb#1|QiBu-za6)Abnozyk0#3P=+S z6Ds||)fh-IG(Ny4(TV`sga2w$u+3-#JWySvvR5$~@L09W^PaRLK_ zK|uX_;*u{oc@nNG>YJM#r_)dx^7fGK#ohFFI+M-FtM z3!ZAj+U^5;0eRUKp2GD1f5esuJjx1?F3iJL_2cT#gHkIo0S<98q+A7sIcD+)nS^J% z4O*#-H(Vf=Aq_?oI9Cs<9vg+dnM;iAAk#ntHXz@kU;-HqKJ7 z#s=vmX$1pPL5su$8AC6Ondo5Q_I^JZCo7WZYypRa`uzkVALbqu8kUMM8it6;Kr))R z_ra@p;eH^0-SvJ20SuR+xF5;^HP7JI;oNwDrV2>|oQbV{3blg(g+9E1ZW5$?!s{FO zXe<6w4_=1iDRT{wiX|+qGhDM|pyn~2S#Pu;Konq@E+On)r1m#xBM{-#3->pkvwzWC zh{45PIuPzifek|V7oJ`SpKb%oVFb>q2U|cn0d*J=-AKB@nFooFp9wEcuy_mH%*Efdg9ZuMK}4*$g4al-oV$qT0j#Aa(Z`d4 zLkH$u7)>Da!D|+Ri+ItTN*)*LDqM9cilJB+>oOGJ>H?wYMcWfGb0*Ycx>5v!9_nDw z$u!j1Tc+R;P+z~F(HaZ7l6T#s)xMOkmAp4Q_-2VTM zS<>JNAW*9SSA~V{TJUl-h+8m=a7c_GQWb_~kN{eti+{ZmXfzyR8`Yb+#N}Nq!ANjl z;eYtZ0)3jf@D=x<;3bH03@{)nYrG~P)j;)wxy*%m;{5*k_4NS`B%KQ;;Naj;P+z~E zqGm130Z8=yeg_9w?mdrm_L%_MZ8S()a59k>@l(?1MuN`6A$r9;dQpnIHHntZ zL2g9HNJS;`Vh8+fPq6bb3SD@U0hILw6i^C6unrUgF%gI&jKP6B7#3?7DnKV`AeVPY z*#n{(M*xAE$Heahhqt$}44*@)4?=x*wAjEqj)bs{=&BeaTreviP;lUHjUx=f2t|-) z0?7iNGU?OIg_pTFA{gNr2n+iF195X{NWn2A%3O$#!Q}h>`}gnfuLlFr`InGm79iy- zSP&#nWK9e*e66hJi9fh;Z1(lu1xelYO zf!c^pfddCwBf0`)KBOrNatvlO7iE6EXhYJ)${`)3o{MEowAR<0|?=-o?6v1u6VsOiHB;C|3^B+1`=sx zoL>TSBzPGS(c=opi>Dw~6PS1>;_wA{p^I8p5mAOnKba2hJA|! zK^G$u0K;gRizj$7q~5QG&JjT)OM#3*-2Z4x!$3xnz3J>fs0+@(fFtW+xE~|{Uf=|> z6p9J8)X=jzR2wn{D|FG$d?lvPMJ?Sx?c4wV=Ys}nKz(t%T|T%@kZO>}uw&e1F4$x9 z|NjS-ooGcDYUP2W=m)uw*xU-LL7*W9Zsvko@vuX8Ak(r$E(ZWR8fp@V!aAsnGO|Eq zA&C)sSW8X9+sL5ipoSpGr3?)Co4H8!FaEL_Y6CSWsJn=bMW~hgL35`ttuUI<(B5d7 z3k^L|sQ2hQlm*CG7>1>ZOUeCqpv4Ld3=HsIDlz_n&r?8C3&A{zp3R~9kSSQ9i+lhr zp*#k0E4tyxW4d_vWP(ach!fDtONhB}5@(qUwi(n+#TZ(E9XJCq9_Q)2;DE$iEx;WC zyKDxrZVPNSSRUpPB25B28>|~jVAgCXBMVe+=7ItY>}&!Ayhen&5=7x|$%BIvq>T8} zc?r0IpfoJ#i5N;pHETX{PZ#25+#AFpT1U%VNH`EpVwATGh*JQGHst?*Y)xDW?%jc% zG>4-dhTUOEEiOo6A)MDSvN=Q}G6^qqQQJ3|u}r1Wx%6_WE-)r8-pIjjNLWRXa7Q#=zR(D3S7)lTu`$I($yrxqoCzspcoV&TxcSjj+C}Rx*3Sc>*)Iz zz#35raOnlI2Q{~mQRqV3-3kQGdxEE7SRoCv91BLc2Q|xs!U5uF0c;&+q;?t(3&2AQ zIONdXfiMl~yZ;Uhu$`k&IaJr78-UEmD0E?FLKUHmEZ}cjLUmxH;NgoB&%~q_kZDj) zq3Ffy6i{?PRSS@vB|tWlg2^v)F^)EdxE;?938e5G9nZxVN&EXT4}efeAhNDUH5hin zBP4R5B>CgG|6%i|xTdaAZHMzPnz=+Zl99&Rpf1OtAmtb6a87Xh4<=7;p$l>+-qr`G z9SpVvHWLN+A}Rxs)=^3|(5NLSwN=o}iZ5WSD}pfj>2&Hn$#Sc?meBP=EEe1m@23L;z%1B-)~hk*=%^iRQJ zL=nh|8>Am^;{#zL-3wh%D-vHOh3u9E`2epfq@x^BC#m)`z*bcjV60jIc^f&4fcTgg zT(uBY1|gMSn3)?o5I|&u8R87Qg)Y=UP|#4Y=nBdI5RcZ_}7%g+L1n&F&^;oyO8DP7x2aA4mq5TQq{0WW{ z1c9Z*{SVp^g>@zx)kt_;6QLGWC#ZRcZ~_tA_F>vdDRfcQlGoA&VzWCJkR7=B2Mr!Dg`=s9NQa|k zE^0{LUytiJ$pE}pNT8a6%)8%@ZEOq2%o!vH;!d4lgAsdS2(3>6D@P$v8bP2WLiEW< zs0ArVD+Y!SFQBT$C}&Vy1m>WZAqn7?621ZrQsjZ0fPdM-e?(eGDRaTrf{6R*8zMl0 z;K~nVI0$3608)?=(0Y0m?rErqR@pEC17>1@&J$9&;KMQs} zjuX+rT^B-Yo58L^s^<{RQLqf+JRJgq(ooe%6h@&7t)Nh+dkKuYAeo2C#L>*f9)hS^ z|Kk|V#hIp2_tudd5E!=Dj$9I#h=EN1k0^gYb|7IQM;J&cbW!XgqDX<2J_uLgZA8KwkA$)dTp{){_dWI_ z+mUhz_LdhUC<%t=qFi8@J7C;6=T!08JP<@9eMZn@j1Utwi42+|hOXNZ^ z%$UU8iaF+Ox!pHdOnA1hciGqA7Uv=)*~YK zqo@a&hc_dD6o4_7fP&Z$B?*+d>#-ko2rCP5&N4!3M?#jPb+j=COJEU>Sr|iIkB>t5 z3>**)0Z7Nsf<=fdBQfnjDj&cGK?x!v5o8wDY=ynA2s#fBYB-o8(gu(%RKT!aCE?pE z2wMi9)&~0nM4&Zwk;1gTp#h|T-k9v>BVpg;RdIj+{Q3j}g)IXEg8=yh3ZRR+aEvJs zC~;8-!qAi7dXy|iPA0`MvH*>G;*M;fXQ7L)%!TjTBsju?2sW(d6=2y$K2`?0p&1EWp?gjGCj6%iIyM5AFT_{h&k7vDUz#Fh|A$0c0)- zgG3SHDoSKSL2QM3LOn>_{c*Hvl&su@Vmin{1^erfj_e_Bkq)es0O`k$ky^TlL`~F~ zE?P?$Uk*ex*$EYU1j<|m2FyWL)XER51<+u?Xt+Ys01}Cm)vz4#0u3M{OEV;6!Aw{y z85R#v(_mb(o4HWW!OVftL^SF_&cd3>urzZq&*#EgFoTSw4Mqw+BE5#+9heKpkc~x3 z2*Y@6;r@Qm^%4oBT<$~3cmgOw?)M{gN?~agLKAcA4x)Sj=|L2%XeBOrqh5$&3S>B_ zF%PZ+KzDvZ?8R(`fxLu{ab!rSnIH;L=%TDfKzIk;NH`zOY&@+$MDdIzH^a>XF(7^e zxeHr6_dfQ1C31riWC%KjwS&>cG5E+$M$D2G<_mHQ8^nMl$baYz}w3u@!mAUglcbS21Guyu( z?^V6`!52i#2i+9`x;p|T%8BAQ6s#vMRpE*h?3>LXb~_MJ;$U3h09jdt8Ifc;6FK)o z+=No3y(ipcgZdk-V1$^3LLv$`$_iaPbqgW|LtTZF!cpd~hxoT2`+`uU79-ZyBCKG+ zX)8=ITGuySzZNrg&3u|AIZ(=85UNR45cy`IcPw^LuITG zP)~*XfbkW$3<;1X6;iz5Vq%=%B>>IbNS=l?esP(AQygP3m+UP{|54Z8A~_AgL=?Ix zThfSVPQVLOuwk$Si{UMJNs5x4F_fX)ih-mQWDB?q5n#Yp;DMyU_T#uD0#+;`nTXA5 z)R2PJ4)5W&qQc52%$_%P)3Asl^^ai=hSCJxhQ&0n5VGf?W`QUo9f_p@i*f)l`XzuM zqd^#FOoQD-3j!AUAlu36IpT5@TB!^5*-$ETk&b(&GN4Xz`~UxXT+0+d?iDBi=WSf^ zgC_pI0I63C(vFVFS(OX2137^~%p|%Z0BJ|VII<ySy;hu|iFU7EHwYni}e0p$~EaHOxaY1GUtJ4C)T4 zG8b1O0EHE~*r9;p!31a!<1KI*2rpHD8Uv^B4GJ?bK%x(>m}mw{7atsGl;m^N_8ZtZ z3<6OcflD};JYj25l;a!$ftg2esTk5GURcWy92k&RXFt~U6v#shSeJvr%4A5n2#g0_<`~=zy6FSQk#=v-0u%eyFUOSTak(tQNHL%$bg4{HY zs|+V@nhzc_5Jx~rXt@7Ji&%&xm>hssF6?L%u>F+g2ITmFu~AChe&jPn8HT`~2;6Z6 z4lp7K1Bd#4DvaF1g7iP$Ni&d}0>BvyuAT%2%Gq`xqo5dT@k4~Um;p$xNeIhGDRhww zF+6J#V1}dB5ZDSfM9Dy~Y=MRyqKoUmz@PvtL9m}G25ZKGwZdG5M8lhc1X}GVVFc^z zgA9d~vak^f0;V8YjE#v>u!9T-W3o#TxZl9WzzM9YH!z)px0#E>Xzar~m}XO11lg&S z#Q-jcA+KR5Ksw)UNStwl(oljY17aBt0rmY@vSba!cEB^mSDs|Tnt+55rrgh|637iNB5(W+l_5FBP z^pYFG=W%a*fVxV7xXT`}I{?Sf0(ejeyAA@P7^NdMid>X(6zXks3aK@X-*bCLXvZ51$VKoK&sjA8>x z9F!^o>}Ko}e?%FIBcBltW{~M<9Tccrpn-&4l7T@0DLz1k&w7VM1wSeJ97I>iCAjDYARhD15Y2FY9^ zN-7-2qhx)MiPR}_i79lE*0mwIf(Wl5ZOa6;H8I*D@C1ydNJI+;kdGl4Q*8j&;arq* z2dUnG8H_08pv4JH0+mK-=EAP~MN$GQx+!kvp|}_9RkEA8SR1N1&-p>}444Uz6|f_q z1T55X7)|c1FxW!!36#iz4E2z27=E45O{7TOkwL#F0+)x*uP*@YHv<>4kZo$XR8mcx z(3}}4mEk?Ak)TUZ2Hru&!7ACM1PnILHDNjFkJ4icuomfTSABS|WG? zCfrCwI0s{1=|0w_Xs9+Lc>op~u)-2+BN?XXKWfp9rRxK&Hz@De!WztQpAt6`0Cy>Z zfosT>a43V!K!gk2B}k`PAc?`5O{C>zk>i$%{W@-5)owY*CU<3 z1y3;;4DwehfZTxXW+h}R$SHI&r_YEe?m&(q64S8IMa}I`#Pq1bhlBsaZaopMiQHqquupf&K9V#Q-Qiqs_o5U#VuoUpPbtB1OZ>SP`c`$a} zu<%1I%%$P1xsfg5qB*Gmi`2y{92>5C)SeC{e7+`OM35+tg z0A*Jy%m~yl!xE{8I6?2awyg zfY^?+#H~j@s+`n9_dLe%91%qw#6d)pn0W~rB5(?+P(dnmiMaR*)o7IVAlz^)MIx%x zkviTOMTY^_Ensl7!3z&xVLT-0VdmN8pcz9;Adu$_1a)H;HK!);Kj39#=W1W``J zt{YY-B1HqlOaX$2N#pS{rBcvg9f(V?Om9+ZJ~sWMWiGZ*K@)qw9@~j?(0D?jC~V>) zFXKZom%#y)+L2c4l2+)VUZ@H(nfgU8F)dxB>IkXOCBiR=!VTnj-C<>dnxJz7E=L>0|mxzK2?0yh|6vltd2_Rsj;@S~{vBsk~(n zNTApo;H7)m0^9+$gn*aKL>8P_HnS0_ll0I=YmQ>^4RWE2w6T}4i%b%Y&=Gt*TPzALG8g-9K$Rkf`*pd2q%$UgdhbJ!ZZ+z z@@6h_Tik%6)s#ep2tg&tuA!ukB4`n+0%&}LLUgp93k#a_^NCsz1`0GVc9>6Le)<0& zXNfC-u}mA@ZY5k${r`{cC^n+>!NP(xnudigQVET`Aq^Y>MD344G_f$oAsiU6tr9}Y z8#qPm{M-~(c zP+Jlh#?V6m&7(wBDO7M5B)-8RGg{_?)>Q4UcYrTH0tX8rg7Ps1JS8pz)`g3(rYqsX z6XUuGEV~M*kctpS5K-tNC2gc~lnB3|#0zY-11x&5HA4~30POgT_gVaG{IrXrw|HqaehHcU0d%je&WL@MtI^ZqbXk`&d`!BA>a(fW1_O zS&m&l$OEWu#$GW%B9pKOK<44X5Hk?&VPGKJJd|}7NG1}OaM0S05dE;Y4G?fB7#!v8 z|NsAy(jLf_WDmvQiV~dSNO3ii+qviG7hp{+pvb_91ro?k*GTb!yTrxb$c1RV4{j3QnDvy+P+fXI$UO8A6bhFX9@GBV6?f>k%{@GdO9?)}(HRHVGY zfPM4;W;yOM7g5lI)FL(UkpdKA4@JXMn5|1l=pflbEE6@5L9T{k?2bn>7TS`9YJpJ% zBL~eCdT`Mj2lR6zB)-96GeXN;GFrFb;0mD1$`U*!F3v_SBt=3N>mrw55OFw(^{ipS z1shyHxeTOY6dX{P1hS)%R1@uw8gJg-qs6{)-I&z0gG1kw53otjff!*%FUH}{ zIghlw8%MY3etms?J-KBh*dnA{3~?<3aU~>JGb({;6x2jeV52InxwG}<fIq|Al#u{J}I0}N?X8M57AB?8zdoIrsKcQw}OFR0~6TU){AVJGfW)Re_;CRh~9 zZ~#`)j}rVE-Fi-Pdec2EmGNDuyIJ~YFL-K=Rt)n)>;^x zqKG4?Gie42cbq5LfE_|qBNt@M|No%5G>kIjKh~jK#6ALuR$7wSGauM& z!}JNP(*ccR2!$Nem|6xz1UV6b94SE8Y5^%-4c{_10Fp03p-VniD8MlsM|!HkU*ZxT z$wjeoz5vGH9oC^-dKS6={}V2Bkr!+s6}rg6DE@?TK>0-hbng;$uQgggw%U(n`pa)RjkX ze39KPAj?@u>1z0vxhNCRkTgUhX+XtQg#=1m5*oRX7=NFDR_J0K%0-^Gg6N|yi8Ant zHMEfjmyrrxWMQmMJdZv`vR(n}aS14zk)LEnei68h=PO0EOvp6q$P=#UkejrW z6}p66jNI!bx)4Aqfw08Kk>QYb+a4um4EnTuQj zLG*zfLv#&C{jkAqB1VzR0Gf)$u9h~UNU3HRw{!m!bBO^woq!ku0rRPzT0rBDAhU5{ z1>1=T7kkD;%00B(@c?!U4gyPr zW3L@>=tmYt4keUWA}+|VIEC1If{|T8Yc_^6iSr#borRQYhIcy`$7WcR#0A;|m_VEI z77}Oh^TyGwWneI%yoZCmU5QexL7YK15^1~u)5l;Dlr>&R%BfmUASH4J?1d-R5J4_; zvA5Sy20*FaFT(056hY+nJ2*HQ7|8D_BZm^qFfdJ2TwodGAnH_O6#vkJgFekb^pq;q z9ETLp!@bP?4_V0xPDWS>g97T0C!j?XXbS^2yD?8DN7G0I7wf8A1_jE?aw6=;r3B~V zBUm7yw#twST`JBcqx5=7C>fE;kyPgX|BrR$DkzO81k}@Mj00;^H-YSF4@9J6_Zz*J zLk2snwFu1(`?kaz5!^GjI1*EKbCtF1RUzulhF9V8I{CJU^>Bo z8pSGk0`mQRntVQt_BH0hfTsoQuu$2sO7h)C>)Gu_`Cpb7bkTXn= zT;`&A3dV(d1jL|5)d@402pU@#0(Gc{2t(jXkUb0X3=9)zA~v^RIoJYj+ki5Vmc$K6 ztuWHcT6}H7k{S36Mo6L-pu%c}|Ja)EAmiyj!ieNaI1^WH#xYb#{X!S+ z5)v6m4#%}S6coyEOy4#WN^=eB28?b4(LTmrXfiMmX(CcF26YN(KALFT>8lW_6)+%W zz{o3e|F0jw(iWDu>Y;m46R6V6-VZemk=#Knsx+Ws4yJ%c6rvzkpqOPw!#Wm!yU;`sxYzEVfexmzpdB{O$K6%P4t~z zkXXhQWcZyz7g;@c^9$7qAw&4CEJbNFIfhmk^T3H4A9<4n!}pH0jvua7zD^Rk9HcNi42LtZx?9HZGe*oQsClrE0TXeBh)z6QB?xf zQYeptNQat$PAL%QXr!q|BohWW?g%)YVIcDeQh*ImnTr%pqs-9|7!85Z5EwZjFk0r0 zoVXtK>1YUyhQPpwz-XB}3PwXaE0;3@?8Umwb?r0hq4S~@R7!3jXg+Togq{X`Qvv$;`(GVC7 zfzc2cks&bJ&K;4_KI-Yw5Eu=C0SbZ9GIxLie$?905Eu=C5g7vY|Nq1Ny?+#phQMeD zjE2By2+%YH?o;b5MMI5{~PxVX3&xVgC*czAdiczJml z`1tr3`1$!61Ox;a1O){dgoK0`goT9}L_|awL`6jz#KgoH#KpxKBqSslBqb#oq@<)6 zq@|@9WMpI*WMyR;_O)YQ}%)Ya7) zG&D3AG&MCDw6wGsw6(PvbaZqWbaizZ^z`%?^!4=_3=9ky3=It#jEsyJjE#*MOiWA| zOifK0%*@Of%+1XiEG#S-EG;b=tgNgUtgWpXY;0^8Y;A2B?Ck6q?CtFt92^`N9334Q zoSd8(oSmH+TwGijTwPrm+}zw4+}+(7JUl!YJUu-byu7>^yuG~{e0+Que0_Zx{QUeF z{QdnI0s;aU0s{jXf`Wn=f`fw@LPA0qLPJ9t!otEB!o$NEA|fIfA|oRiqN1W0qNAf3 zVq#(#Vq;?&;^N{M;^X5P5)u*^5)%^{l9G}bl9Q7eQc_YFQd3hI($dlx($mu!GBPq4 zGBYz7va+%mva_=pa&mGQa&vPT^78T+^7Hc<3JMAs3JVJvii(ODii?XGN=ix?N=r)_ z%F4@%Dl01)s;a6Os;jFRYHDg2YHMp5>gwtk>g($n8X6iH8XFrKnwpvz znwy&$T3T8dT3cHg+S=L}+S}V1IyyQSIy*ZVy1Kd;y1Tm>dU|>odV6~r`uh49`uqDC zCQO*XFmd8UhDnnqF-)F3nPJM5DGXDmPGy)jZ5qS$>C+iz%$UJ2bLLEjS+iy_%$_}) zVa}X640GqsWtcZ_9>e_k^BEQ_SirDw;X;N*ixx2~Uc8uL$&w`uOP4NXShj2#!}8_J z8CI-V!LV}WN`_UdRxzwzy_#Xonl%h-*REw)w{9K7`t|D>Hf-3yuyNx?hE1C`F>Kzv znPJP8EeuQnD-2h!US+s;?Ha@N z>(?1>+_=GT^X5&4Teog8+`fIA;m(~q40rF|Ww>|m9>e|n_Zc2Mc);-R;X{T;j~+2R ze*Bo>$&)7xPoF+zc=qfW!}I6Q8D6}2!SM3sONLjkUNO9W{hHy;n>P$^-@avd_wF6T z`}gk|K79DV@bTkEhEJb9F?{~~nc>TqFAQJ5er5Rf?Hj}Q@821I{P@A}^XE^7U%!4a z{Qmu$;m@Bx41fRrW%&2+AH)Cu|3R3hC(Dc)J{kg}Aut*OBR&Ke7)Hz55uXS~17I`+ zMniz+Auwq|1I_IiwO}*^MnhmU1V(xYjJ9h>dI}iz|7Zw|h5$W6Ah&x7J**kEV>ARt zLtr!nMsx@S-6H=k;t?Hiqn;lPfzc2c4FM8DU~+;2393hxj)uT!2#kinXb6xK0(bA; zB}dz+p3x8(4S~@R7!3guLSVG4B_Xgzm5zqMXb6mk0GS~$TGo;oaHHBrLtr!nMniyv z5KvN5qUoO4QNu?=U^E0qLtr!n_U{L67KUxqAEie_U^E0qLtr!nXcGdXWi4&Ob=1_+ z5Eu=C(GWlm0dQHXP(KPrLtr!nMnhmU1ZV{m7{CXPF*uMgz&omRGz3ONU^E0qLx8jp za2PFXNei%1)uSOW8UmvsKt>3RmbGLA+NhS%5Eu=C(GVap1V+nR5(8{h`Dh4?hQMeD zkP!l-Wi1(jHmYSb1V%$(Gz3Ttfzh&-!~h#rJ{kg}Aut*OWQ4$ISxZKsjcOSUfzc2c z4FM8EV6?0yF~CNZkA}c#2#kgR86hxQ){+ruqgqBoU^E0qLx98(7%gi_46sq_2#mICNeQh{wWA?08UmvsKwb!p zmbK)C+o-P55Eu=C(GVad1V+nRQbKD~?Pv&$hQMeDkQV}@Wi5H(HmYkh1V%$(Gz3Tq zfzh&-l+YSgI~oF`Aut*Oj)uT!2#kgR zc_A=b){+-)qq;^zU^E0qLx7YJ7%gi_39V7JqaiRF0;3^7UI>hqwd94{sIE~k8Umvs zKuQRVmbIjW)~MRi5Eu=C(GVan1V+nR^1^LY*JucghQMeDkP-r;Wi2V8HL7+r1V%$( zGz7>Cfzh&-yl@-UH5vk=Aut*Oq=dj|SxZW2jjA0Dfzc2c4FU2(V6?0yFWg3TjfTKz z2#kgRDIqXg){+uhqiRP(U^E0qLx8*x7%gkb3%5~SqaiRF0;3^7N(hXWwWNgBsM^sG z7!85Z5FjrEM$20A!fjO7Xb6mkz-S1N5&{kk5a2+Hrct${Aut*OqaiRF0wjfi0|UdP z38VMuk`!j6ibq3WGz3ONfYcBeZP$_-Vx#IuLtr!nMniz~5O82%$n9Rjz%V+7Kzi7X z>KF}y(GVC70b)bIfq^0DmccMAYv1o51^f5!zfWvJAYC14;Y)!-NVABZswwak>ES)9 zV~B@<0|Ue41O?K{+V?}j&-)>Bej}Z%r(Il;7PJ&NgfxrjshR>$(Jo#_O&+8nK+c-4 zf!)Q1js3C=l9bmWcKeL5-n)@ z1O|0%0o6dGfl8gQ95rP$1V{=2a?0BO2DGow?}G+57#I`^U{)14Ag1r;J2;$2^(CeV zs{APL|NsB@69m8=Y(${`|NsBIgTws)|Np;ta6s-5_d7W3|Ns9#a*c z6jQ(v3A4q)VMz3t$no{4p3xBa@4&#Iq@+aJcaMK{y{=D1Zn7Xr^{xV1V0I z&%gjG3E=$y|1m|7BuAOx5I}?}11wPg|Np^1_n^`7dcqb2Ef6Z zAc{#M>p_u#S_PywDI``vib%u#3=9lN#(+8~ zFk42;TGE1YRQ1pb0rJY)dIq#UJas+2pMgPOJ;ccK0t^tlM$1}AfRIfpFbKdR?Y#nn z0n8j&S^FMZyn@9G7#P6e4=V*hf-r?3HYM1Bfgu4^Kg^cVvKBR5MtQ?41js9E-wVL= zDlLM;0kz!)9hIdt9hQMqYEo)&RGD;7}5FoRxeJ_AMJ4MC7sfYGpAx5re zU;vE{kCwHN;2@WrkF<{C|9mWE?SBQN87s)R4a$@w)ymrc>lqjXKr?SJuZ)(pu#gy~ zhjR#!S=Rn9U{FBLE>sO7);;vp1* zcogA!1_lG9)C03+v|US4sE%qLfo6*#6&Rpd9Xaff3t(90M93!~I=~3Q zQ5LokxIZ7XxC0(}h$8ep1A{|72spsw7CE313bC0=npgmAkOHg?W(xy@0d(gVQb7z> zF-nYvz|ao?a?9HP2`C+Xss;qs_6^>$7PR&grCUl>_Y5Dy&i6yMh#)m9k%~|Q=<0+3 z_|Pt_6a+36HDC~cx5cRFkl|(2`+CT>F$M;KdPKt!sjQt3Szh;^0b1sQra%$H@}T+* zQ5urFl>r*0pivCaT3;|1OIZuuU;&mMB}PMFScCxCWi6;-3tsO|{a_%utOZS`B_O7I zsPCfTU?Qk3$-uy%kkAiXW()QeQd#>RQeVx7Oh$raVWl95P0e=gfAIVm%pEXW;PHNc zKJso0kmaLzGz5lx2#{aa-iL4LqIMuSKv#F7n2To&0W{F~|GfaVQC<`yMmDFOfkB{P zJ)%Ji4GpBS_J0C62m=rcZDFM#NG-BL5T8PfG(QHj1zy&IcMhX%c%aa_QSGB4Fwh}D zepw4TN2yzj+9yA7zynzf>3WAJ6 zRtVx#iUZ&q)nK+Dm9_t|&W}=R<*5GA5E#G^prEV;4d8*dbWz*+^HEC8{g5N4aF@07 zAzk192Jk5zYCC9Hn1>vw^XuVrTPQ`S0z(35?JZmqRtkaw07W54fIq7Y1iRFf4p_rco1L;wSL3>l-WeLuPmfvlh%)ikI> zz=46Gp`ih(ML~*dLC4G@^-M|8ieD{gERR9J!NCBupc7o^LdsfjOBy5w!~fqafG5Tv z#?_Cuh9Cifl?-5D5D2KR2k&M8_1$4%2%|ykT|qGl+O&rm(4a%bVJbm1NHtb#2nm8} zPmlpnjB-{uR18FoE<+#`kfZWLECeWO*FugfAv@RM3o7`!d(dIhAcf#D1k56!9y&1w zQt}_<9-6oYV){@g;RhZlfCC9sq9J3D;Clv0cwz=LeaqU>ePcsCv5mSPBLpZbYeCH* za5oUcT#5zWudjD-C_t>cKfixJylV^YfP#tt`%x}{yuW`xc))>T+lQwC_xlqZ90Ka0 zK?Dv!Bmz7ta2^t#(7_snEJoOaRg)7;NMi^f0;3@?8Un*G1Sl+PLAOVZZjK#>>0;DNqaiRF0@Muw z3d`E};Nwh2kJzGaq>P$28UmvsFziBr!m<{0azDf9?EkP!7NZ^-4S~@RpmGRMTGm1u zwvby_sqC~-<3>YZGz3ONVAzBJrDZL&VT-h z=3WS@`C`IaCKw|U|8uXwU<&TEIXb6mk zfCB?V&@BTZ%i7D}ViruiK@YlmP&o_6qleI-hs`K|Gz3ONV8n-j0|Ue41O+0?TBLUE zL-de?UWNlIZR^qHM){*5Fd71*Auz&2fTZ=cuw@8GjvRT45pIZvEyL(hwiux^Dli%X zqaiS|Lx7~R_6K3Gl@TLqGKq*`yg&HW~u^N87dN#mXojO9+tGuKoYzJh)|h3yVo$q4V{S1-nDx zDBJh@_oL^M^ZWOYjx~cLa+DYifzc44ZU~TA*8czh^77^D7z@6T-SmFFg8~Bs1&7e| zJ2>1&82H}7A>sf3`3^8p4=)U{iT!tQKpMYDaBx`v|NnWIRtP;GZ1#O<8(g6PZr6MR zNN+I!q5`aJlo$~3i9nR32gfB|yCxd8)%!uG|MxR6Kn@ebCWcbh?uVDP;I=HpKrpGm0N+XcUIEr~A2OhTRIdJq6^q!!h%0NM zg)rQP_y7MpFd*G2p#U1TfXI%LqaiRF0;3^7jS!%ES?fS?v-bag1H>Rg00RSP@(Q_J z1)Xn>ON_X(wjW|BB>eV+o6G`;W-X}TrGh6QrjL@NAut*Oqagqa0cw}E{R~v-ek09X zL02@Ol(o>wGi+igW$k(f2GHOvN-GxRXV9t!FbyW=gUeb62ar;*!2kaW45MW&G$=-? z(GVC70qTSRmCM@u0!Y(ZWV`S^XfXf`gUdjaa`iu?0LCVUQr0?vOVR(BWi7J9&I>Rw zAoKtK|DOOE=S348<&K8HXb6mk0Qn(6<+9cQ+>#{UIZ&OT(hjuh0JN+Ny#5NcT!l<$ zVH5k$z+eE~$TZ)90WuVUr>wm{AGEO;X+`e;|NHAfD;+>%6i~N}QllX-8UmvsKzRsI zx2&y)lx`F|Ydr&GDB?V9bpUF)>HuzvViWrhYYl^G2k=T<)HPq=W-`cu=leltNir}n zz)#9~zaF~ljXD(u$dXY!8UmvsFd72j5TI&Vdmb`C3O1NBLIJYztN>c(g7z|imcv2~ zCAO>$0Jn)z_cB11f4#4V9o-;M4_5U5|9;5sV$eO8NLE2@9HmA>U^E0qLx7?Xpk`V7 z-he@XBF7*!7cek@ia-UJf!Nxx*u;>=Ywy=Xmga)SYmxRcfZMguO=1cO{os}_$X@7t zoJ0M3ki{U8Q9K#~qaiRF0#pkDYL>MH)SFYf4{jl!hcC26EmsA=>jbcgA(ge@jlH0f z70Y;SJp+S40ZO3?I(^pxQSwqPd`Ar$4S~@R7!3hX2vD)C-Oqr$9{^-H1=s+zn+vgl z45eJX4;jV9CWcbhLe*g@YYiCC41cJ2P2@AtNq|cFX|XBR1Br8g>tZzwa6}=Uk_^h)`O?pAmMbszJ7Ea0wgF#$xW(5o2M zGcY7TmK*d#8_E9-U`I9HcYqYp)bPZp8KWUE8Umvs00{wVm9?P7sqjMyAx2Y3DlkA= zoM2->8_2-h6F>y?C~s_HsCyY8dlFFB*FsLK1r2xv)YpS|Ge8b-I1k#@P*4xv%>X)K z9Bl0igVrW7zB4VxmBs|KK{ERX_hVkl)T^w4r_ zW$k~E=^!^VD8M!@oCg)|V4(s?lNV&iC>{-g(GVC70jh)mb;{cNpj}whZPxyOk9^PK zefSsv!q?cu{=?NFE@=ea;fN51UFUeeKf%Ev0C9WS|NsBj*E={k6wDtjX%S&O${G!U z(GZ|g2vDc21&ts;I_Fe!)~GR~Aut*OqaiS?LVzk|Ex0#7dgSY{N*JS_84ZEa5TI%Z zP@}8`O)Ei;ilwU4MhzPcfzc2c4S``30@NsL!MA;nHfx7Xni%!SXb6mk0QEzF3S}*1 zN*^|zPkkqjnm8H)qaiRF0z)29Ue-dERE_Sm8uCeD)B~d-Fd70h3;~METF{X*$h!_` z=+;rAM?+vV1V%$(sD=Q=Wi9B!F6hNxLp2OW-8~utqaiRF0<;bRO3PZ%ku#&sT3W}_ zsQIHIFd70wJp?E$Yr#j(j5ceBdMX%o|7Zw|h5)TYfWopi0DOP|(rK`?cJHY9qaiRF z0;3@?6hnZrvKD;g3{}qvABtf(>gLf97!85Z5Fiu+6qU8$BWD;!k9#E)$fNS3Aut*O zBR&KuDr><<&Wtu|M|>h04S>-Q7!3h}AwWr43qEp&0e-JILAyp3jE2By2#kinNDTpK z)0BaX;|w52&M+V@1skbhIO^}w5Eu=C(GVaM0uBrelO~XNk1qJg83qOhDxVQf$i<`b zqaiRF0;3@?^g@9Ab}i({nbBtL(2Mg?7mtR(Xb8|h1RNL`a=Vu>kUoY0IdW#SSxf&Y z8?|vX1V%$(2!?e7!85Z5E$?fAal(Z^vD^8(W`F;JO)P{Fd71*Autp|fV{F6dgRP# zvvw#%@u(X|Ltr!n20;jrSJpz0oEdG_4uTjQb;4)}jE2Ba2muEM1|=mW5{F&qLr(W% zU|=vn_2ZA1Pd}iFjPgc9U^E0qLtr!n{{JVZT?;#M2IGwIdq<8OIdbCR;0)LI`$xfO z2+$-1-Ve?cKkBN%6$0dxwXppU=x2n#0Ts1JjvP7vWpMcs;u`pZV0fc^lrb6tR0)C6 zJES35Y?Q(J|cqNJ2)i#|6c%-_z$8T&V%I6JAmo)4k!R&5=hM`9u0xf5Eu=C z0SN(;%UbB6wE_wAF?vqmsWC{~_5?)@Tcn#FKzo55{{LUkz|fBfpZVZ3a~&XuIJ}3Q zpt~Qku>x&ewjQBvlrk_f^A|`t3nt&7OOnDzDr-Tf ziGlVHD=;V^ObB3LI1gGv0h0I+T7U+YLzJ}&NG;pZb}b^@Mp>gFFd6~_76K%eweJ-a z64qlhXko6W)*u3+tOXAagNoDwaPbPU=sjdzFSK17z~BIpLzK0nZCOY_jgq4wFd71b zCIm<=Ye5ZKq~1KLKYpA5w`oBHMFX~ovetk>!2mo|a34Hu0I_a9WIzE@*1l(8SZ}~k z@c;k+(Xtj2Jfq}j2#kinAPfN#%UZAxu#X^sq`trl+ovEdxfov7)-y2dhZL#*4G@C} z0g!8VAQJN#1pfDfIL6-)IPoh5*e&fSj`Sy#vlsgfFK-joKqes53WqUw|Rt zKcq+n56gm<^n!5!C|n>C0SpQM?}G;sM$1}IsEp##5Eu=CK^X$%l(qlsL0xw2-ue9y z)U-WK*=7b`^i*IvN6_AutF+ zfUL6iJpkvT03{X6}{EJqRG-~c>2#kgRDIq{!S^GZ$THcXj74d4p zW$k`23E#5t|9=5w>_CA*0AdoTT?-jP`2T-Cg91`nJKC;=gwQBC8UmvsFla)+fq|i+ zp@GD+!vFuj51O^2nI}M{?0W?U$Up_CNCn$;pMhci|NrOV3vEFX4h#ukInW>iVhmxl zF$)fqQDQU%MnhomgaDcC+W!IIu~ZuQ160-)Ku$M6YS;cZ09^xt*g)pM;BX%{o&Xv| z7%gjQ6dj|+j)uT!2v8mZlX%wdIR_%1!$-MV*GmshW_)Q zHZO$hz~Ep29YO%FM1Z!0VdK0IMWf_s2#kinXb2335Fop(-48hch9-VsU=Tnwn-OL0 z{{#kw0#Mr)VyOdz0(=Mov=Tu9GU_l|)0%a|E(8YKJW7m)z-S1Jh5*43 zAiu0#&j8v$K+pnm6oATF(1BuLy+~#4e+A^LdqHI_VzV%K4=-pt8~B7>kO>eB5(1ku zN{oiUXb6mkz`%t7`DHDr;4`32tC0aQD2qHd23}$d*`EsvFi=?wFOflm2=FlkNGS^; zN6T7JSdHS*5Eu=C0S*BQ%34sb9nr3&ra$&0Url;`KcYZ=zaNQne*b>tg7iLA7utQf zw5biK>Dy7WMnhmU1V%szP*B!_8n)mO(h(3$qh1^hfzc2c4FQTmfReHn)Ubu@?V`vD zqnbxUU^E0qLtxm403~JZe*p&gj)PG!8UmvsFd71*A%HssC@O2g_m@Ks-NJ3dsLW^x zjE2By2#kgRMP==KP{USWboOa98I6X(Xb6mk0D%yosI2`DZrH+i9T2c;RC+W7MnhmU z1V(HKP*&E08@3EM?=T;+p*rgE(GVC7fzc2^4FSr^TF@n63^Y812Gy;jywMOC4S~@R z7^)#aVOe`0yg6%h6k(`F|ERl1Ltr!n=oA7JmbH+EEd#9%p`lYCj9N1q0;3@?8Ui#9 z0ZPkSNW+!^v5l6-?j1FLGz3ONU^E1VVhB)L)=Z=~`8UmvsFd70wG6WnL7$!|1{T^K;zd}oE=KhBGk0FB!*a*Qms32#kinXb6nd5TJO?*Z=?jL1%`8MtuWDY9NmKdo%<_Ltr!n z2!sGN%34^%cJvS$0)ag$JsJX|AuwV?fGTAztYIr~f5e94sK-Y`U^E0qLjYe0I503M zDJfAlUi%;3uqA)x7(O?S%8iD=Xb6mkz)%kXlH0YvKVb1P_{?z7knQLpG+07sRA@8= zMnhmU1V}7vzg#|YlFHgQ(4zLpkz45IgBpvVF$4yNp>PPzeg=lo zQ3UiT9OaLOz-S22Fa$^{YahbP+9SWw+yp%{oPmL1NE||Az%cmR-)JE`${h`X(GVEQ zAwW`DdmT~MVys3;fV65E7^u}fzrTM!Y7_bW{{8qGqxbidFfZ57AV5m2y+?D(c{DyL zW{s*H4S~@R7>OZ3QdxTsQPw_04=hB(mKul9><@qx-3I;dp%$$-0Es9-7M0C+fUV?p zaF`EPuwDUlB18Xw2M44Q7bXc;4ioqvz`y{}2i6QF)&~eM2n0Zn&?#_$w|vioPckcb zUjVV|eS!eUDFG0RkkmnqsaIf70Lz^RA2b2I(fzyw!a%6PQED^QTmv zp_2dM%3%WU85kHaPH%t~?@$Q`_%V~9U2zT$AnU<)omXIBPypE_04`7w>Yy$HUsM5V zk@thbf`Ng-0NfhiPw9RUsPUuJXb6mkz>o|9lFHgIh;}W;7{Y&~hAl=hMqtAJR02m!S#J z*}nG*;G%myMEd{#`vPDMaCJ~SL1it7`Cb6wCQuRmem^PW$siL(@n{H)hQKfi0n*A^ zc*7QB&Da0`|Ib6lF+n|N%C-ui3;`%&Bk zS2xNS4S~@R7)c>OVp;qD%k?8iPTay#)Pe%;{d&;sJGgrd;*x_=ruGv+(_o;M?tU1! z4=WBqW`oPW1lR}z=%Ps?#t;lZ-FpR;CAQ}g1tO$$g_WW6LH2`ef(}VAFeJbn0$%t9 zQwLFkC~F146KP;k*yse9GfIqxz-S1J$Pgg4tR*Ip5CNT1V%$(1cm?&%G!SL%2n_}Ckg`;RAw`Pmh1L|R$MuN0l1L}Eze-( z7_40UPh7jU06Zdb9&9qqg^&Uk%!4ptW+JSDl(hm33Sf6QI4FQeE@0}wT0sOfVZLT2bYc@quzu2`t@)= zxJW~quL4Vh6oN2V60=xY+z4rpa9hn;;3Lpz)p)Q55D*NvMTKVwb0cs|q`3qUw zi&(z^nI(g%gBk-LOGcQEs2JdCMj4|aFd70QEd;1u*49&@S$iJRqBSU(4;zUHfUUTN zG#Be(4e|Bhauc#b0JQ9k0j;csoH|wjS)>bUVfKSoZ9x__z{*@ml*3mr><1eODr+HI zG8Dkg*Z=>a>ucevUWdW z`knl6bYNgms7G2)0A64V+Uoiqx_%ZkR|eikW&mliCO}32z-2U&KF|>f`~Uw33-|y3 z|2_b$S^!#j{)g>0fH>3ux*tpc+^hw)ZW$cr?|%>4{{^!O>^G=g`=Q1-Fc?78K}@;7 zALPXS??H2K;KdmC4H&?yjYs$BLIP-%91VdH8Uj= zpu-NpOL-j_>Olh;`@zZtK<6P8KrDyb1@S3D9oQI9EdXs?2SCqg0B`99&DxnF586%(GY9?r+Vd#q*@AhfWi43ad+0d?=x5M^CDDlUP_;1O_n^Um|Ns9( z&c=nbYe91N!P^)>EC`0F1M#5i5J1fT=<2|Nqr_+kjE2An3<0W^weOKOOHmS*0`PTJ zppzOQ?Ly+r!&24~r;!*{h_V)+YUHvOpSn@G(GVC7fsqsfR4r>Eb5E29Ujb}L^?d?>%Vk0Ql4a*gO`ICJlnJmPnV5DjN-f(GVC>Awb2l z)`42hT2KU>uMco=Na!bJtQMs0{eI|d7KlS_j6OFXo&i>$ONN z8i#MVj{0mg1V%$(Gz5@CfNEte==zz_#rnuWJIWpnfzc2c4FPxvP_3**yH*iy!6;)i z1V%$(Gz3ON0CaT9-Me>5Tv>%B+(3I%N1L@+0%lZbGz3ONU^E24*9tIDqpaNzS~P&X z;dL}{M?+vV1V%$(Gz1VKK%FrJ(1KXV@mL6xM_HpGFd71*Aut*Oun?e5Sz7>V){Y*} z3JcUxdNc$^Ltr!n&_aMJWi5CFfeL4Yqq%LAI~oF`Aut*O!zBc$QP#c(ooC1}+N>Qe zX=2nLqaiRF0@M!y*k)Kt)(}8WmZiSiMok%i~Hg1qa#;7w!Lx8p+ zKd{1C@gD1N6s)%^NjG}8`4;OhE!5wktIe5$pqYGZ9hXl=yG*1NsOTc)KJ+t0=A7x zkA}c72?5H=TF{}jpcP+~c7=yYV3O($q>_?Utx)wyCg3h>&qG?z3I z!An$yVBYxxhk*T1bLIy)^uGs-B8+(7AAmBTdB4CR0OErC1r81n3-8xEI6y31?*Q+P zgN*>!G$03nUGg7dPrXCI|NsBz!_0+9Ba{FC|F37*KObs5#O>=791`w>nP@J8bHS4T z|AX8QVj`K~!0^5v>S~ZR5Lf&MG5`PH4>H$*;XUN`He{*w0S*QC|MxqrhpL3h!2$_n z5y%XXWgr)WLj`Ia#Ji*9Xb6mk05KszQM(p=_;A4+|K}>^#KW; z7hrHOU@&<9|NnUb1_K8H#10Bjs}9=8Lsf|2C4kLwU{G*iaDa+Jjkqtspx~gukN|Vu zdUw7l2Kro&tR}0>NbcRB9K4<1#&gWvj6}8gSh`en!v`vd^}2zhQMeD5DWoI%3AP| zGYkw2pzKZ1B9au~Dr*fu#oByOp$KNZcYqi3XypM|8mtghIwXLGD$fgm%G!Dmao+$W z3RVL)A^}`xC%|T^?hAlQbCBSB1&Df*uLZp#Na9Im79_(4LdIg5_paPd+|9_C>|Np~Xgy4eJLCQQ3vmRW~gH3P% z*Fj+afvkZPn&1+2KSRKKkYNn}3&6t&NKy&{@Bjbb4-OfSCb;A4|Nn;s5-6ZRG9b&K zWi7%uh<``P(GVC70U|5E-e2iFx>wS9uffc`e7RX|NnmX6G?xCsuBcmR12WC7R}5PL!9|NsA9fZ_jnaNUF? z1##heP{@EZLCac@8UO!-0tp^`NcJL(1ABLr7!85Z5FjQ5C@5>eN6s*iIn;~aZ8*wW zNFn(D{(f+ohhhY%q(GDh2!-&%0#b~;hm_VJQK)K|Dfj0qfQwjA*$7#}cK-bT1PE(A zq{#h$zFvRBuFKQ3BvzD#o~IX4gU)m-h-J?%R$aE0Jmnrq6(lv1SBbN!yHn3fK*}x z5-6a+8le_}>_svTbwF2gFyhe#ShX1@f=hh>>Q9@kPOIJ=okV>2x=TS6h?{B z5Eu;sB0_-dvKDgW3{q)Fgk?l4+0UR*4+5aRJfzhHE?)W}-Q@qEZhrrM5CF9(!KR{? z2MC4W0s|z8QjEN3aQNTP05<|O^^~w4yu1NqSO9!i0FoZK;=P!1P?xtu~2)Fj01Uh6px0$Xb2D!0%Vu9kRxXp7$Dtf zVyq%T4ZKANnxxtfDNqsPwe_HpTktsLdC;U6*j!NYQV-#wD1;Xlkg^su2n+6WqZk3v zcz-{%w1tj91Qb9=ZvPiBod53tnz#B7T3ZS&ivItHjUTTE*$Z+2*d>s<0bDjg*DDAF zfXY0`Vg-;DaHSA?!M1?aLrO6a6Cwk55rPY0fqjKg2Q~rX!2bd8F$7Q(7Tnx65CA(& z091u2fE(s;sr}$!gpSvOTnO?UQXqjX0=XB-US#9I29FY>Aut*OghPPbvKDgW3@CJ*26Cjv>5H0F^%b8NkD(ASQU){Jns}|Nr1c1pfoTb3GulA>{#RK>)aDMkoYn z14%;4T4<38Uh{=80y6HJ04j?>X59zr`42J&vLfNUfB|S4A5=^#I6%z-se`)Wy@9}e zP+lr`}eh+diSUuQY@Bj#!ix6Chmh+(M z2c!kU1)Bh|;XKF;kbn0xfGP*DU669JA2gKlA2f&nk@^n`M#$tJw6Xw|!1WNvf{I;m zAi<1-SOf}_|H#IHy)jCRhQMeD5Doz{%UbA>GYpVokgzqxs@U)FzrG$+T!B{x{Qs{2 zo{KVIFem`Gu+9qz6x4&~u)r(>_z)|&{Z`Llpio~R02*ijOM?}{3JZ{-^`LdRAQQlA zzQAh0M!Z)LD5!Tp7&e~)WDckVg|g0r+OP`sV5{eY7R^Ha12#f|VgCQ~4gw62l?o7h z3KT$2es92#P#*xkVAz4dz@grO!9f5-f*X_I@md40q4S}Gv>>-am}o9Sa6x_q1;KuZ zIuIA+Ebu}I1Bdzo0njQkNLgzD@+oL^0PKte(E3`CH$ann1_BB74qzz-frR=50gzY0 zE=&L)L=5p3IFLY20vQLk2oko)#zDhjlo}0z(GVaM0%Vr8&?9H4-mHDE5CCe9LEE*U z*5dyE=N;y+S8#wVx;h^qz+eC##l4>(zyRtHLp=yu6*b=hv`_#d4Oa*%EI^X~LFRz^ z{Q(RD3E-i~{|F=AgA9X}fS@r32L^@!P}}bRdItsp2481O|qL_valL1mG6UcQ{`F^$)0#3i0Cq`3~p*|3`BX zoLkSZzaFXuqz=i10*ChjP*;Qe3l22~1+ZNp-45qLqW}LZ%m)o}tXF_a-A_<}dJy75 zxL=`x1Peaouthcw8vLWwXb6mk0D%x7udId7;e&dd1Z*HldVK(c!F*853*N4!bWa+n zu)uTzc2P`q*hD}>nwa9C#vhU>xa>sY6Jippo>+A_?JEcXm9;pfktINZ1j5K-qwLWT z7!3jPLV&EY7Ix$e0|R8%g*>aV=-RJPz>r{24_osE8Lx$^1MSR*GOkJaKuvar_t-svW(Lxt1AN9|>KYXp z4S~@Rz!n1Jl(p~SBM6`&KO|G%oIY~o$gK}ZBBV1xqpklD>ktslTKvT$TC);iFLrI% zMG?C2vA|_1hJt#~0SI7Ga8ZW4AOx$yAdt#X3^`;0By~tkWEF&#z6z`dI}l9^HZCZT zKp1D(V$(D#HW~t>A%Ham$SG@KN6w&Mee>lA1l+@F6On@8s|xOe7T4C-*Mmo9p&H3- z*J9U(T@-2)c~n1aZVY=_Ou$fL%Vs2XNK7=t@is*3`-ycRD3CxHuW@Krk8(#tU^E1< zhX5I6Exgf*e)Y{QNKt#_$ob#cEgKab4S~@R7!83D8Um!3wXj2L8PJ=x|1ZPJ+9S6{ zXlRaldo%<_Ltr!nu!n#H14BbY1Ncw?>Bzz3v$dS`9u~B+71V%$(Gz3ON0JK?vw6Yd* zXsts%c%eU90KS2bAsjjK1x;?0I~oF`Aut*OBRK>}9j|p@P(V5n3oYb8OTM7x?L#!F zQSN96jE2By2#n+qAhE2y-;b?93k$#x(1P~Jkt3sJEi6z*>Cq4v4S~@RAbku06lS=K z+n4adcC@Soh14h>4S~@R7!3hP2$0yW1#1EyrUGVR5b(nG2Zq$Bz-S1JhQMeDjNA|) zr>s2>zF`r2n00puL6!G=~mN?hwf22_$UsBBpF3YYgH4erlf)j&N!{l|6_sdHA!C zP6Zm88E`PU8gfPQAWSsFqvuD}79(w9iP}XGd1dW?1<(yuH1Q#|JxCKr4pKu$%UUWH z)}v)D6$2B~sL`^P*g|AJ=nQFM6_ccHw5%m5xKI?2mbI99nrxBLvX<EwxGl28PkOF)D^7 z7NbVXTH^D0J^Bqe#B0T?at1_#(F>0n8OGv4xJh(F=-4v?M3pgIF2n*ee(RPsC| z))@rA#rAmtkUXdz4=(fJT(FM+?+qZb1r7}LAR`70kCwHNh@c8NIPyD|v@~qXT5vux zU;t%UaIVARce)B;D~c#_fCB?V&@BT<8AP%t6E00Vg2F+}pc0JxOhZvZLf z6&M8O-~a!Ay#a&5|NsBrD=;X`fB*k}Jp%){UF-l>yWW67V6?2IN-;Mm3>htJX&Mb! z#t;%180z2eX8?6iX|yR7S|kuj!HO9ol@nCvz`!s$L4nM&7TmDK5@-Z%#iIb52VrIH zeE|kYOL9H~xIJCZ02)X?&j3B)u^;LUNO1|X!vU-a#skrCd2m_#UVs5I5E8&3@E_JF zE&vZk{0B8z4gUX!+i)LjZ#@IFf|<|2aR2}R{gCn)R0NNfwKUD2bTxdmtfgsiV-_3l z!TAzAH>Lp1=b+p=a2Q)rM2Tz2UtbHd71Z1Zw+2BR>R@ahgq5}Z3=H70ga7{xz~v*P ztc8_z|NkpM#st7|26qjivKCTc{{R2~KDf+;XcmC9SpS2@C(i%xhZomiSp}Hn{{YYc zZ2-j9|NrNMW#JanpD{XyK*i!=w5+9KU}74DS=O!x_fo-SZ9TaENdF9kY9qFy2vr4X zJj%*iaOMV0N0DYJKGoPf2rFwHz$Gk5H>C7~l(mTQS#UcQ)-(kv17SjCZ2>%9>+8=$ zHSY&UJ4p9`eR@VLpH*BeT2n{w5!pd4ixd$l>A+htnfPukb{{Hv>|C3eLLN&nx z5!^O~6y;zcc=^7+9^_ep_nn%o-R1T=mg3hm0V@N6T88MmAvLv7rH5QG~_CL<><`*3Jh<0~HUU z!RA3&SqtyaLuadynx7yK-xq)so2W&e0|NtMHv@Q$7Idi=w9Q(N+Ft={h73`F%!G{B z8Za;vAnFqV@FED1tN}y+|M#FVTo4D;!lh;lA8aN`#AsOyPL0$dM$202gd+}9u$Q&- z6TmCk1*pAhpQLOAQ;e-Bg2|CXQ(D&khphPrmto}CkD&*f2VrF`_H_vV=R>!D;T*3; zL^n8w8DO(v;NgSwu&J*1;00aavi3jfI)wkQ()oNns4xwHtw^~KoiXLM2GCVr zkTnbYVJ+DJaG_lQU2Y3H_zYAOgKZrUVzjKqm%B-n8!c-|3^3A^V<~Iz3otM!1i+Sc z4oD6{u@qZTgra~%4#j0Hv|$S^?MSp8i*jrpgq5`*NyNUf`}-3Z820af|Np%JgTeX# z|L=oWWWl#1z|6)rUMs**|Nj4Z=%%p!;C*B7`x(H^RY=i@cnWS%*BKNmpe7z3WyDJ1FKeMka)E~e<~xA)7K2X! zyI)|yfH?jOT3kYH#4Kwa9L~S52b}={HU_i_0i@jka)=j9Gx#Vk_&Hzy=Ldk!`GRQx za|PhX5#28U9X_@nZSVqWKOL#jb}c9&QVEZiwNwg7?8aazYr$C$T-Ns24~EdkRuoZ^ zn<;PCf;#q~;DnwLK#5~Oda-#B(XIulKwz|W2rvn7oWVGt4nLet1Ortw5gL$`P@)&f z7_yn8Wi2QnQV9=++>SLRK>Kr4^5#GpgQcuB01e`S%38$I9;^XCFF|ZY5hZq0p{#{9 zY_WtM87{--!O^moxPTljYpGarjFz=j3`|U;u#^_{paY*kWo-iZOef;fJPlQ0D~c$w zjtXThtYJ%?LugPu_In#O4_EB=*8h2l7vUgTFg96 zwg_5UBPk+is(9G8Yu_6%2=w`NwwV?D95ci;V^mF$SQ#bB34zhFmYh%{S`YTJ7IgCdpviR9E{dp9)`D+&1cx%g z;ZTABNo@}jv~UuCn$%720c5%F@&>ibySMUtYg_>jQ>g zz?b2G0u{U+07IG-0cv}Y6uXDI+R?HWlm@AUN6T6&1tfN3aFw-#C=XJ*C?c(_{eAuj z2weY-9wM-PRg{lvQ`>{+E*;MN(XtkMz9vg_w5%m7*of6MGRxYAh6ZBi#;$`(+9OAf zTt+Xk5V@SvBsyBwqK7T}QMT0fAi6_`Gk>(K#aVKaE-_lxk{)Ix=op#pTH@DyJ%yLGr_qZn zL^g+90FEwCG=H?LB|4}u6e1#lghW586nhAambKW!g-W8MWi3YbMG?3MFKdr{L6Lwg z)P=?ZWrxs=mbK_1OFVzHtc4~)YEYwPEj2+W;p1MMbOcN z_zl7%J6hJ_2^<1aqh&45tWCPaXjw~on314kw5-LSnI9tBwGS~=LN3Drg*HXOI9k?X zge=hlqh&29`B4dvmbFw0NbJT?R7en=BPdcx?V^aJxv@8hvKC`<>_4JmOVJ@T)b=1n zp*_SjkCwIA^EFwbqh&2w!A7j6(XtkQ;qvul*0b3Uh@R21mY7^lq?*yPmdJo2 zPuXZ$3(2#Tkoy_#Q=%PoDen-728z5$GtHxAEqVDKtFF zL?Q8BfwE@pXjw}{AmdUpTGmplBw%1*7%gk57?_wwjh3~zaxu~30TecCN6T8GgBnxe zXjzMyr^yx>Eo;dRI$|`AmbIAqmo$;}3=|$;J6hI~7T_qVN6T7baygM|M$1|v1ByIl zqh&2h)+L?uUV!4R7qtgTNcY6h)iGMul9%tX>KZL;u?7pZ1V_tS3d

28x4lw5%mR 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

+Q14r5}<% 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%0DE|;_ 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�k?fEyhGik+-L- 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 W27_Gt5( zJu|~jwJiA+*d_Dob*F4?lx?AC%;mi&@AG!gUc9!EyYPO(l7%lS^`9+#`^(FMf7gy% zi!N@~QSYw4Dkn92pKe3#<*EmDT^IBXEu}ZBFfC{Lci_L+?qdbdA{YAeW;WaWoN%O8 zox6XzKpwZU`fCmN_FO1+oEBmrEz(e< zoU)2*>PI_$*}6_KHKRKl((e3tzEh#9e^>7Hd3&QlFXYQas*i?4vyQb+y`}^n0ehT=Qn#zqnb}aH6M>$=S}Md*<7>4II(j_PiEv7e+WNVZNRH>|KGdG?k5~3vEKgF!u(`Yj^mQQcZE-^`aWgC z$qR>Lb4qJW?C#|mFSS`2P&ny8eYuDK4SkiMOVgBH-#sf{e5&@#r3ZpDp3W3&xbW!J zk}py|uDcJ;v3OO%AMSA0bxP`g56i1pW<8!LS)=Fi>DOY5)=AcWf8?XJ_^bYiOX=!q zNWOP{>GELGrWX@;GGBjSQFmZ^)rO+OEmH+kXQ+pHxrnc|UiPW-zwPaQwl2xLKiHa? zXWq(tzxlU8$iIk-6QX+$7~Vbnis5y2ykusWi`{~+Q>GjhU%oKFQcr2Rfc>xDDaBcv zPw!vOA{r-qsnMfzDbuXNrQV8Hu1uZ!+-H9%=iH48qvebnAMs^!cA7gaOIX{$RC)IP z(LWbNS`P30_U`SrFYexpS4SS-Zn31WGn z+q&e4-?D!XeOu3dk@HtEv^jtLNS4yeclPB%zwTKqSeH{a;b_E5Hr8v$ZO$2#9CXyb zxkAI!zwSj%jMPVe?adp@&$YYT&$U?hnx}6=@4FVqISem;$W2u`DY$y^vV2B?sn!Md zYN2*A-N{jRjzkD-`SJ6Y?^6H&$?Aoh1b(xMc+T#8wp(3ga`hJZ#4wT9Cp5LMD@Lw8 zDSl_F?af!^Zyp3+yvepM{rn%iXN;$6D4nvBm%#GB-)AM|t;YaTO z`}!tZKD((SY`yg7dh-+6R+sPb7`316+&Rg7q4|NR_(gD_DG&ksdojpJMZn2ZB zq`Lov!e{%c9zGFJzqez>Lzcpx6fJX);vGi}{?;vD$!UA1zi&;`Rz>3rwzpR>_qg)? z$=tL3@bA;#f&-^`3GBOiUX)cd;5(0a@l^M^rq}yQr_RqTWXM`jAeJ}laaC&SqWopo zs*k9jn5_2m@lVNZt2rmObTgc0eJ7_G`YJ1VQTU|3mPP6o={Jo!cLqs%z1_F1|A2X? z!j>EVf~}t%H~C=|qVauNUn5(4e?@{(sGAt~2eCkr(zG(q}-Wjn%?RD!uEk* z^CGzo>qV}}=(a2@I~%_8L0{G;4c+rc3@#maewXFRoSqkBe|-1Z6K+P8dGonuB z>2J{4*f>=&@l2xMtNp(>#itxtnmILR^0lkKFP(3GCTf?nYqcDArgXH|662=Kn(dcf z-&cQkck|ENy-XXrX5W%H&et|2(p`F2!KK)B3oib&>ie1&5!BirqZ& z?(pwW@n(tZ|Jj2r89ArUy6k#+tAkeliVerMD#u%>=$O>&`ZW}EPBv1kI%u*h;ZoSr ze<}|)WyL6L-Tn7*#B!}^v%VWuB_vuqFG@eWPui=2>9u%Y?UZk=ZVJCc|3|5;{I{Ct zQ&8D4n_2&EuHAELdtcClP@}A;8cXX$mObtHE%C8}qrSd-yN~GCosEGix9?=PH16** zZHT<>5Ha!IS#hCnmU<<~3U{ybPE)eyL*H0}={PnFO^3ub{e3_C?uUASm6 zX~U$h>e9z2?s;^TH0|GYIsG$3NOwl|stn%LAM%g;V>M5)z1pz$c-79R47Uq^jTJ=> zHN3g`+}`v0#<;5H=?1e@e9fX3`+NN~t>ofO+F00VYJ6AGbo27Nvc6mwmR$_L{!D!T zO4)aQwF@Sf-@Ntf=d9*$r)7_sYA=wDi~HYhWp#39T;!iuHpk3MS1n77PPu4xPGaY` zXFpoJKSdwf8+)!fz5HDOS8&mOrw1Jomv{XN5%^g#t3WjEX0l*+XCz;%^~q_^RGlyI z9F&@}E3D2iMv?Q#{#`6;sVxPsuiP^zy}Q42b!A%e$=yYLcatQJ%})BTc*^P@@4|B# zwwCIhRE~TaSKS;KKL5Wq+w}!vzP^*Ur~P?3M@G~)x$f=3;J!O;jdM3WyX|sPYT`4_ zc{_LBbok`D?O9NCL*4A8i`l9YAMdw>A2Ip$;>x$>7DAJ>qE6Cfm(Hne z-LW(L_q{1K3Mt$X8z;;CbByB%&uvWFqx*vGv)&$7b8Xd&`=M3$ zKZ*z}TV=?s`d>Qm#=&_#sdF^m*X#*-`9_0XJmkalOJS02RxRa8sdA1?UdK|OTKsR) z`0w^k;$&Lolpz0ka|(oA4xIm9yx(@$%8K;7cL&O})x-tvuT602|39aD#*`}ej?=c9 zXNu|_M1^l%H~MTVyjwxk{7d@XMe%k%SrrTn|K2o&3F!S-`r0b}=j(spg5>3Mcf50` zUKO`-UBc9^Vijj0v!&uezt>Lidg|o-KT%=t<>R5Z*7tb#1tl5IIk=QV+T5c+>d<1d zryc*FE%=~*Y}1O>>T0cJ|E$gwn>Bg_M{$bnovOQi%fE%&&v$sPEiYxbu=HZIN7?zM z8+-!pJIMD|-SjxeE_7hlNz-q=SLEC-&BWCv_gjta7WV47H`TeRoG$cTH~oE4$D#=id^b-o zHCnah-wfV>_u;prY-%n~3%9u={Qt<47ax*aTnY(DBcEH| zugiXVvFt{*-wrpICRKNKMA`%O)57&!5g%WFT?+Mu}saYe=_HP)teU89L)9m zdv5h1ey>o|O?RtjOQ@bIS#y3<)_Y5zQ|C@sEDZU4P1a_KoVNO-9_`P^+p?NI{A6{n z*y}#y(w$T8r)uZQ-Yb50`A6rwh|HD-l zndyhbr*X|(*ZBX?`nOyT^N!}o&6swb@sPW^Ez`yKth<|T-S08qH#62}Pc}p|JJWu^weZYR{Vvj%#{%hNP zrd}*_efaszgE<$UhXvTC-P_W*dGTwzvl9v)Haq)B=zst8dcBg*y|haw*RNQ=_VD3f zrkmH*?G>rH^*;GA+qK=oYCO){*$~)^cIH``Q~bH)(t{-XOmImCLq}NrzjrbC_DOW&^gQAc zl-V2W$kK84{j`mNB?pfvHTf&ddE3&u(Y> z+P%F$Wy$`BzrM7)Pc_|i(Yw*&NP^nqLd8>hGOOcUE^n=P9CYaJVS)F&J`ByVMixwWa=skInw&a(mVv zUT$VGPyJ)l#mczlZebT@?=1GZ;w`jw^Rrd5?@~Kz+t%M}@8uG@ZGG%@&h&OMR~Dt5 z2NL{0ZET{C@GaARJAIngp93YAb0bdLNUnVy*SMK=z10fq>QI(b<(WZm_I>&>*?e8- zCT0CX@#O7AAEt-t2F$&~@RPM}ci1;Khsrh8%N#&cA#Hl(Jc}Ma@tWdNdiZ2b!Z%mj={pWFOgCj;pLB$eg*hXgQ~bbd zfu+28exC0O&s0h*bE#2wNG@Br$Ed6Be&JpoGrodzZx!XYwk|rko9)}tgx44HZT*v0 zF0-r>bZG4`_bu8NZz&SbA6%5O{a@f7j9rW#}Md$oYP3szQNv>f$hwDmV`Qn ztG$Z#=2}|6&rJBaX@1(3rda?7KFup`7mE~D#QG3|Fk`QL?_(aTPO2_|DWWio3pMJJ(-#NA(?IAhX`pM zp^!}eBVX>mox-zHEptn?((ll~+Buv~qH>llhs7%xTkW!IDr&=u-*Y@RtWW#9K%_@_f9e$PGwgdgvK#*_(lJTAyploZp4bb{zM#;o zpnb9`56^i`pOR*rx#C)Cuab0$gz*>Nj)kjUapw2k*t|XJlu?JH%86gE6|2tco9Mn5 z+T3uhWP;Z>PlaQNW%YmRzbQ|1_EPJ=t-@yb^T>q4r&H=ga%!_@=k+O>xgFGLZPT5+ zW4G(Ccfa3t>5OuQUjo4kWyeCC8Wy(mPf=-pb!%$zr-<+U zC)llD#2hv}x9`Gz*Lhtl&i8lS{-vpQNT_fvM@-3LgN5gp++^(fr*rG%T$W8u(XmB| zf3@nDpWktpal+>BQ;n-y*-qv({0|L{KF4@ta(l$rjqy5h66fm}t?u;P+sfpz;LV); z*QX9MFPrOM+|m(v&s_Ph{rtsKOag>%t^B{W;@^oy6Z%4yx@6sns(7{Fhr*o$x43?V zWIU9v^9*wPuvoxz^XXqtE0|3#$*ueBvwI`s#d@D36ISGT$ew)sCEurU=d0Kgr5WGX z2t3+(t^G>vzCBmpoY#NAswgt|$kxSO()+$$K6&OI%fAh!#ocX-O!ofU(^J`2Hj#PB zl8(-K^6xEP`_A=Syg032`1QI9PE${R^A(RZO{bnddG=X!Nrp+zo;%NuMP%tZrl^mN^2-%(&8>~!rdsen?Plt$i&ET*!gJ?OG|X+u>y8XiC^2HBZue>y}{J!+W?h+(g>GMcxH-=32($9L9r+FqKgB6exVE6ZW5&YBcgtHOgQxN>nRCwSTl2+Y{|_zk~m_uvIq?N9;-Mk_xiV4q3&2li|j% z4>h4SHKHL74-Wk*+&}xurKGZ#jw|LL5r55{b9c?@1$S&0e>@nO`D>5h*Olwyr*|wn zDd%CU!#hLrzt%nTfOik~A5?I>*l7LYPUG)gBBIf9W+iT0*B-c$dFHQK`Hk(*Hr!JX zvU=fB7x!y%hS3v;>VT>VY07Jbq*txpwMj9%`w6>-Ntxv!45QS9)3mQ&^p@>X%b1WR{Avn46zt z-z2hl`PBt!?4Alg)K^W}aDidkwVdbE=ZWe3Eq&mBxopmf?*(_)`Y$|oB7cJNm*c5w zDwiu~eyZNsvEW-*WA~f=vzEN9eEhrh%FO$WS0_H3(D`Skap829N{Oa3Z$ee2PPxq! zV2UcxtLI$*xLlf3XX5?9zF(}4iZ!*D%+ePuT&i4?zBR2XF1zr3851|#*Vi`>>Sw#8 zK6>}xNcO~yvV-LtZR-M$&pNE|HZW_h(B>PTFC~YDO$v%uU(3t2>z4X{AsO{)8(Nb& z_nWFzu!@2}D_>vf)WOx2EOP9-kgP;=SnM!CpVql25$ z^P{{(svQ?Cd7|vMc*oOqcP$F!^b}2!J3l@AaZu#QpRl|Kh8k8IDy`95>fW zTwiy`)S~@H9!u51FUu^|Yz%fQaC}+`GEht0F&{%!h21bb0fvK%-(P$vh82&h1DW`TOVmK zep++4$@7J`%;h4}zu)Jy1y9ORi{ zj*3KPGauc>B{rq-W1E!XWjVEmN9Sw}FDvb^zIT42cINT(Ty1AJyqtIM$Z|JN9i7Q6 zRa4cg)w(olO7Hqt7Wj9(eXUu^)#1Ssd&}X^n}GSxbH1})6VvQ4d+K$N$#jR;vzZ%= zRvt9-7ZTaBfbI9r>T?Pw;Dk!q1F#$1mDkmJAcE=j4mqw@c~A&K9|o^jkxh$=Q7S-9m;9OHNI%X1eKC&gHaS%>9<) zoDUfdY11q`e?R73aWh?}vESbE9nZA`&kK)U=>Ei;>nf?Q{qSF{wA1BJQ~uw$bNfr_ z6yqSSjohu)llZ$`r`N9J<$Rd^?Viidp0og_EG$v6-Y<(rY#6&LJPGGrG@@<<3}M$isjA%ad!U3;VUVK!~vD&szr|w%#-i^=i+isnm;p(c#e@5L;X!ly~>v`NvH&|jWHcmgj zey`ufug^7Nl$8b7Mn=YTK9CIwJ;(4laF@Avn^fcXyq|M~U!5+$G_Ut}-3sT#z7@J< z+P%xP6Z_7^vF_inarZg?jR&~r9OC?@mD%O{A#oDd!N(Tf`=3l@Rs1PacbxG_PY2J% zMh5Ba9GNpqD~o(5XHH?}vW$s&-5sEJ*Y5BR0nba>_fW>$=FnQ^X$BSkf-@EG{Hm9A{GJfeF+tU%eT&f{85A$k`PPRCm;P_^|Hq1nGnp#t0 zO8NC{bH8$(<`u6e^y)rQv~T1UR5|Cju2Ai;(Um(D31!-R-x~8W-tTQxn>5MjkYK2M zR>y_9qBcptl5Ojk-FNceAb)(P?X(w4zN?en%9bq@P`h`hdg&^~Q{I!=?%y<7H80rZ z?CXniVyWA&Pq@1O;g%fhwO(^l6+H~j2IMR}?`M0)ty^zOboTa(e{{un7*69+O+D?m z<*Df3)U1+U_s#d%?9|rX!jicAb@TZx8`iRVGd#1J{O#ux?KHVuhCLfLiD=6CFx~vw zd-80@JIfYV&uLp#q}Q!W5YAL;kY@3Dyuj$gGN;>X-`J!uZ*`E-)>-7A5Vxa@hcTt8 z;=NeukxkVW)h|BQD@N@6K5Oa>LDq|RI4|zncH`ZrSlc~uXC}XQ*cq(p%z5Wwz_hZ* zyGwSl4d&lc&CP# zME`lU{VkJmN2%7o1nzk*#WGA&rQ=wSr2m_f>U%jX>FTYmwGQU14t9Mo{#)}wLbR!U z_G4GGb;%ahtkDfjHom8g=2i&C73RG5T2(YZvqtgagYC|zQ+=Y;Haa^jEMNRf#mdq* zbI&}kRTn3xy?w`~zaroIR9dLW=cUpOYVHc#XRcwlRJz^s(Av8)W9w82g$vVMHTf8l zS#>i`{ONECdcg5gXw&qB7^}bXMmNq?Pd{|D@`=(XzJ{7SeUIfmA(D& z_s-9o7B4Jgyr8!~{Y1f}Pn+qKhP`m?vfk(<-*MgHScb@$}$C|`88^Os&ecYDBT(`@G3mCotg-psiVeJ1QRtV_N!!#D7Y#m6i2Tc&o@)(X^~ z-FU4>YthAPD{lF=`u?5f+>*Hbiv0B(eP>Qsi6%aL?zJ(BKm4m{HoJAf5B@u|xqW&! zcK@(WQz~X);PUZ)E0IzW9l?0*XP~=>Q5y*-v}`&su*SE}E&cE+T3?~ZpW+O0c`_9@-{ zE5Nv0M=R|{*0j6At1Uyidskn4tKjbxePP-@2l?9{yQdooT>Ek4!~&+%JdW8A9RB=ChZo3jA?XGC7^*fBzb*ew*2>e|!C3 ztF))>d2QZsv3~AG#zMPyB6~W^+n!q3h3uZ==CzBD`L9Uh%81)DOMWa$)8`I+W|no? zc}jVZsrZ?Ne%m?(`~rg-530P+&Ar=jKl`6zWba=cxucsm&hh#&?ZxSxbB*e!_EuU+ zroN6ZsC~2S%H6;EmHrLZl^SbW=h)2@5`Sa!@Vc#@IWw>F{x13( zX4{gSc1p$`J#J@gb9RgL!hLy5riUyQKl^JIBa9jE4E$|+vxbiLHmDGiR>x6qG@X7C(rntNw!q3%ysgT zSj`)_WW`2yrBz2KJ#Ib!jBhSSx?0w)JKH2SEQv_;Ik{|0<3Ims?&8je<*R>3PME|^Za6=yuI?*m zl6jt>yJwz->XzC2R(!s`WWI^4R3xW!__nV$Pkt2Z|4MSy_AzTXW#p2=kojHoj#B4a zSDo28mzuhE_f`fLyqKa`#2NK3t1K;egO$DHq5$UoQzuqrD(_hG`-8!mCrmB9cP{WM zZRVd|ec0u|doD#et(1;X@AZd{RpjW_7CcJ(^6@ES$oIo{bZ+XtSvliT;DKoO?*eB_ zL$3P0xOmOp<)H$Xl==a+qfDBr_hb{8rQKSfG6V zg)igHYY99%Or4?<46-*~SQmBWwSCq1qji4omn?O?d?@c5;jcTvH#ep+cqLEvtv|WUGg1Df*`<=ibG95&k~4n2IO@9mljMKJPiOb_ zZQuL4`gfg+#^$#Brz6`=sXXy~zx~5To}(QFKFb-`-uoDQb?aQ8a*yJ!1E){xM|3}m_GHeEbqgaiekZi{s&~1iaqVpp1#y)Q_s7) zV)2_MKVP}t+Z;N1O7s7RTid*Dnuj}Iw^=^5=>Ds<>U}qSQ$9H?duSi>_s!2=nNKcS zd_NR+!25BtZ_|lATY~@BUbyhD?w_TDc{^K0PnR%rc(s_6NJLWFa~>C~dg&J{YW8li ziBfuh??=g{tcU44*3Npo?V4M$0*`@7@s*9=UL>yB#>@Fcn`P;3jU}3#TA7b7v`^`t zXZB(R=khC_dIgVv&$uC%klgX%@3x6+rrBEFzsb@AjgInlmk+PEEfe?OT%4kR=Scj%C96srl$Kd-oxb|O{N}J- z;Y)Px*!3S1D{k?X`Zjrq+2^Usr;G1Be#}z*A!*5RgB=N}4`2HnP4;^fvMAZ~!WvnD znmML#YxM!!>yi+W0*Ib|Iu{hh-CGnbR_P=! zl_<}ZT<

Tcq)9t^(^GzXiYkTwM53Z1G1Cw$1+cgk=MmeK($GdN%t?K=ZR&m$eD! zj|n;6PFZ`eZpH~=Q`1FH)_KhTyv{A&J-ywygxc=UR%{!laOk>`D<9Fxt z93JD-6Bb@{vouiBU$t#|ci@VK{>7_4bt+qHG~IX+7|fKWtoruIsqdn?d-j5c4C*=o+ABBoeED4Q|b?yDD$TIn-nPf+Zcb%;A%~~r3E0aQ(z}wA% zx&fgN_x)|x7547m6B}O9A+7SP@POHuD(}+D2;pUc(~h{R?r3_F68$88=RDi+ttyrqIJ!uN?{8`EOZ`rc$yclF4gC*RWIdJsS@BtMi^-04cHfw} zHY^YmO>+JFE&0hF#;D}pF76!-n)FyypOPRObgv~@p*Sk(t+#!%bqe` zR~FsCE2N{6-}+NK&(?SL+n=&N|7_$rVGyP2jlgUgoL3)x5koh=IZU-rH^~-;9ow)pi@_$6cH` zxhII*a;9eEq|NIXNnr758J&`?*D}hC#m+|6RT#u)9MhE9rW!SNJRjlSvU~ zKPFs{em(WT>%;d_#1i{D4oDpRDf0E9I1|r$FTUdsZZB`26aDdovvW$^n$yP&45Pn4 zTobL_E-GVaDl^M2|HUy+#=_s3zn&~P#**liaXVC^T{bble^FJ8O4a%MHjiGtwcg)x zg`xV8yRdyqxkxQ*<}3lr+jo+^eJ`tf6m3``HrKA=QSRecTF;G}*fSEeu4=nqm=WmuRX3tph%+esgXjg#2&2BuB2M;)nDqj`u-yB3dY^C4`Hp+LSE?HPek4%T%;ZUN6&G$eXif#m;UuJr{K%8ziimAZql0>D;1LSEA!OeBNEZJ{JSax)&3^wHeS$s z`23k(UiP8=-cB!d-!r{3_;tFUtJk{PX0hSU$C)iFywTRlj7JfhQ=PloyyH;{ySET(Ulo_mr?>|u3b2;<-^F`vP z*H;N#{8!Tct|fNMt{-d>jFbHK{Bn^M`Li(d!D8OdrzY<4l{xCuHoP(K-NUQ0I#ad9 z?|D`-bKK%u?=$j~jqI3AcW&K2{dM{CIdWk$cc(}GtYEw5%dRO{>%|eEdd@OWB8%m; zbL!$HZ_CprdwtANdVjII$??#}$4}gw*YMb+Ry;6Xl{=NqW#z#&$I^Nx@=QK(bCbl& zX~u!hR~Ngx{*JH=ogFnj%Y9uWYjDTjCdJntoQ$u%S+5BkYcu*Cx_5!aMVH;PZ-(=^ z9*(^eAgi|C!Tf~q?Fk0XYi+M+1n!m34EX+$|H#HQ9p6vY{5~`5ubCGAdsw zVy+ba^N3H{E%Q9}y=NcJ6F6a<7ZAudYiFtJpCx}H-`+{Q{&cy6ro;@>OWw={E8gc9 z+c|7HSaoFg@-GwDIeq#*_vga-%d(!^Cl@3OGMv3y^}A-RUu;!~^Q1SIF2BnR{r8G% zYrxqHcbAF;C#m>;>pd9W>v~Bk{YjPU8$ZoOvgW=a7fyJ$hdwj!T=1f0^QID^1%WAb z%l2HbXA-oGo!)+L*OuIy zH_zeTVYKm2f33=jbxALx^XtP}j%6Qb)aPDSRFkTr<9w=HASGt%-Np8sgePxOaZh{Q zyyV|<-&?*aXLB1Dt@!D^z2@xVDBT;{Q*)+%X_1ef{jyP&HDub^g<*{MPXwelztIK{K{!N&g6 zR~pxgP4e~?+(?Vi`)yD?n7 z8}DjX*v>q$zSLxz{E3-CVG<7%c4ogduhu`TE0yY|4q+}}l>Ghw-Q?`FE0GMLp>wLNm7Ht2kGR#EaD8}u zx-rh;*W{>#?8-fdq!comccrlL-fGlTSvFB|?%!0?&+G2H{0uynmukIexvkRzw_9$i z0bBP}%Ki=vc-(4oUFlQ)Y5%1s13zrLzH*zftYuyOzMX%JJB}GBx35`O8uVV~qt5@f z1tqOBTV`42Jz5uX=;bz^r+Xc*ufFLKutn?e^mv{G_G_Vn*~g9kab1c1l>RU>;H zL(GD_MKh+&HFa#|J0+C3l{H#gxM|vCufG>d^v=6XoAlHE-ownxCP91s)xYh$CGcyR z#3}Rj9FLdoll1to>SiK?ZBH*de@VR3uh(y(wDJ`&`vcbW4qVvSC%RQ}U z^0YVBC{^%mFVB2dDp@L7I4^WdhT;6rH4`tj?tEjjY~P6gqoTs~{Bs^Z5d||cI^=WD;?!k_?>|g!W z*c&JQdmY=R-aD(RSU3eO_}JtYYBTFIIrpnw^LOOlTAym5$JD+*a_L>2%M)dOUwzNZ z%sq*((OXs0HaAwma<-wpp?b6B%^s0Bn0(f;^;xyxPm9-wqjzUKkI@Ur`LnN5=w_dCr$_wT7ia@@?9vGZ*& zl&XE@yS%}eZ+*$~7ku_dZ+Px8TV7 zr>`))vsNr^TOfb)?X2xxpKgY(31(lNRi^6ec~Cs8{rJN(PtPs3nEn4mbI_*njJk!n z_ndm|8|3e3Rb)kEze`%xlIUX-86Ga(ji@x$=q+InAHncDWU# zxxS74v)o%@7VTXjdDm}wM^0G0MRDnJ;WPOL(YNGRZM}4lD`dqC?mHW2m5JqhGyBE7 zT)M$Zt8MEVef>)5%LQL$i*oK4u+3%Q4XHcE)w@bSg8ihP`%4F90mWnbs^-7=->lo# z*CN=-?bGoNrJhPL7=fu6(6m{*}iECt! z+wk0)^V;uH%)L)ZTtaKvVv~>UJlUI7+jK7S+H_yNLuC^Mw}<&{SD(f3EiWy5edJ94 z-FnM+i3Tj$^tx^Tw&|-aW9-h=o!M%;WTQ$%$b{x)rxS$d-gM3?{2$8nzW8M3+?!?m ze6AM?I}FM+uDsv zyXo5u5TP>xUUmbJ~8pvwv!89eq}cn?@7`*k~II+ z44?Om@;i=s9J{_(=3UR?4JDs^q>uaV3Jo>YU-dPvnNwYO(c+hW|GB3ve6>_Wa{sK^ z&x&TX+&}c^hW3)_0Ug{&bQn2rMo#Zxn&lZ_EfM3of!}TU%r_rzGWqNA#C5G+d-}?k zeP8S2bqs{g#JqN|jhuMOdGao+w_a7~JKJ&Rik)XNo7&7WH4k%Jo@MqPJuf3)rSc^3y<4*C;kG~j z|M^Mt_@?}<$d&D#UaPJ)C1l}wtB~)}={qm8z1p<1WkrKT zZ?4;SM;(z37hm+J$ljPA6eK&@$2Nuz|zu{0<+sQ!eIHqprwX&TZvi`%--B`R4o4 z@;@CJ4)wn|`k_5F?ux*S-##3-9e+kY&(`+hb)Mmscf|W*^8P()EH0ig4<2l@d)n6a zJNABj-sB0JlG(4ealD&!w6cpmc0spv*1RKMQ;lcsbANAc&3`Sl+3}W>>9x#Mmd0X% zUtgV##H5~G@|dtZBqlWT%av5i0*5)hPvdrHtge{HvE0e$xJmd%A8&mxFF}!43;bv4 zZaACDvfFrV(XRheBDojm1~BEu_ujm+Jy=X3YAqMa;XRicJo@5&$si`?5*Pd$4bWv<=0So>hn zy&HO0nY5lJZwa3;vwY z5!bv~j%v1EeG50UoSb!;pSkK@TJgjlJ3bNM5^cbtoVvfJi}ebOn>s_xl8|NXJQyi0N=%cmt( z{cf!AV_&cO?peiYFQ#ccX&Q^Yd#^-BznvTHw!LN=)7F%8!7H*Gf1Z@MX2bK;Y{%1M zr|ebC_J3ltSjc|s%i4d&m)jC2`Ci=c!i-_hE4)58ybYB1W!c=&8BkN&eG7aL5K{lBm4 z5PyEU|L;}v@PMDE>yv-~(wuFv^smM(b4kmP0wG729ZNPpKXW3|WXFsdw%=!p7kmga z{HE$?nqx9kymjfT9$Ta7;`4sZnVt8~^^S+_1h=&36BGF4GwsN=u-gYm=r4@rk2m%mloy8Y`Bj_+SG9VYIv-!qTva@rBa zQ#b9mwl!{had?-*`wH<)2GtbR1pB)a7qHGyT_Q2@fV)Ua((TnJUeD)ybbpP+`I=(w zg-d>aX57FyeXinm^W&H7&hm2y6I<*Y!7~}0Qq~5*o$<1&1Ee2 zL`?fMxp~Un8!x|ptz9-R%^-NfU*4a)!XteBK7~7FrC-0f>CpGx=cV3UK5+Sb>%=90 zox0a7$`ZI~Rulcc@y)w$?=wCel)ioY@r?D=PY)?>Jb7KExtv<4(diSy|Qtiyu3^TXte0cQ!nfQXg z5r5|`(v!Jz+uk^PWo*K!U@=dIa~+Fix*ZmzH;P}&+RZQJ$kK7dDBLHaZ&p{DxWPWF z{mj3rFDit()IRQ6zU26pqrWf5@Epn6eEw9%2acMQL;oMdKDc*#cS*vgo8NXt_r31P z%-*iJr8za}%dEe%^bbt1k#OIyx4n)d_(RT=*tI+-@)%adzqtBXkh#PpFaG-r=DlKx zyjF8Mew>JF^{njp^WOZ^<@sv2|24!f$x(7=(~%3^9amFc{Ot{=?8#ft*Tx;5nWW!k zFxe%NU*v1m&YKTYTmSEIZ-|k*^{I*H)XDCyM`FruH!~*{#~p8Hc4r1Z@m9r$TQZOmoGd0 z&9ZMDX$SRBnB}FPUbuFLn7~$Ld0YR+Mlbn&|rI?}6z7Yno0i+cMF$;9KmU z<*FU-B_@gO?QOBsEv^YYn)0W2TJSo}KWc)XZ@XW85TKOWxASgU{f`eDxFoJWidnr| z{2{x1;Oxsj_Z%_;%B$GFpJymb`|`ZY+i8-y&feTze*~lW3`?R6EdD)Ncqcx$IcwGp z7u$6E^@4em1&>cwa6j94{EF;G_fj{z?=r{ks2OxFiu)ZqyY1o8Fp2zN&tq@1B5Pk3 zoN#pc!?9(>{X>WS9+v%CC}1dbN%hh76SaQQF^8GzTjZo>bQc84Bt2hR*Hn^w$>-CA zs+KNm!-z?bPdO@Nnius;{@thLCHAh;g=5;()&3mT_pRzbg_>^`eCC``QdOO2TdDCN zM44yu4;3lV$Jd{Bxjz1&tQ_CWUa|4Qj16oY3C&w(O`N%OS%xj+#~|@*H&oI&^X|UC zT^PCaP5$n=Kj*IG@~jlkwtUm`@x}yc&R1@)y4vMWN?uQz6*MoCwMTAQBl~^R={$+f zclm;f6wZ1b3;SBh>1+QmV@Yw6j?9LUm|Dwrn=s47VCMR>FJ3d%C-wn-R9Fc zC5!R)(iIP@)D}HGtaN9#QA3TI%wJwcnIj)p6h0 zEb%u3#F^y|2BYpIVDGJH<2cz8U1|BJM|F?j6`3m=V-%m>IQovq@m%hgNc~{fS#LjQFy}sK zIwoB3SZ9xvpH{oqA;<2s>@)Z8R=0k2bd}_k-R=hhE5aWZ*Kp=;=j7M?RG}%KKJyJr zDVvH_msxP>#n$#S$LA#e+wKo%AGOs z(&_aRmxS*)w|dF)dv!M!WCt!5KI<$lw!dZOwXN&t8SGA&VI6vQ?`@ZF8#Zq^`&~Zy zk>>lvdz)rU`W;U0UL`sCwxDOko33}P#j<&34zWi*x<{-ln9#@nN@I6U)AaPV)bO&S z3$=Q5U+nv^I^F84N#|b<*5vDJlfIY_45b4_6HS=9_gnlu2Ic1YjSM5q@u8) z{$=>qP2VRhs_$OS_1?~M>6sqatVPmy1-8FRnqm9s>kh}&;jd=)aSE$>@AxvsT3YCn zp~08K?DZ*OKLw5-Rgb)3aAzWm-AOZ-X~+7~-$gfFQJix8>#}y^)h~>1x>>zFvSQ2J z?XTyToePmRJW;v&rHeBj;0DmnFUZl9KC~*(XW-s#;#au~qkVzwa`8AkF$_m800vqXNDH zD_>6x&w72i)Xuh#z6Y(W8=lP>PrhhDQ8FJCS<>%)x;EJy3ZvR?#RzS|`?|E09F zfB4S2;(k@FQ>K-7RCBk_*}Chrv(kjco0ojrVU%~y`_zS#W+g>Z@=tBI?mDF5z2@4U zTk~Ho`4=z!aaTn|)QW4Fx@~tR7C&+hkh*;1vE+xdmnA=Kahfns{xOT*tkNBu&M0Pm zZ$7}F9u%$3Bh>e=wD67g!5^RZ^tPAJ51f# zsyy`Iq5Xf}FWE9H`dYp`QMyqLUre5XGYjMI0_{85S+O_Qo zc&lY5a>P%1hmKlr%W0X66CF#-^>+FCb8;&z*1LCF`)EbR*0_DY)wbJw?iYUZY=>Na z3}g6~#>%U^J}>((`>plAZf2YQK&Qc}z$yIG0`;`y9|957) z%tOY77r*t$x`*Z{^vu0`I(o&ogAhH;dEzNiFqI$3nL|ZMHwQPJda=WTp1zP2!Ds>61Uw{nsVbRNmI*+VijT)xm|X861hb z%{7+nT+Oz6Z@|pA#T$w|ofgcoJNt5$wd&H-dP;XIJh$9?G4tW9)YN#rSA4r>Gls-1 zQTkvO@NXf@ZQmnin)&}3qU;aE{(tmWDrgs%iC1^ovSsU|xTm%pKPZ-&|K?GnZrz$! zpI)r{ps9aYVRKE;&mEQCojR3&z8~@3vUvM)t&K`sA6!~4W@%Da( z4=0&#o|4XNta^Wh{!3 zmRz{LN8_mcUIqEhkFLB3f0(RgtKXf%bKob_!ea5f*+~H+!t>J{+wc9>;`@K%UgN80 z%2lcyW|MtawoaVzRCP~y%&v{E@4Bw~-5|f-D{*!m2+D2}t z7fUYRZm8PC-}#|ceCc^TVTlf>^yc>lOE2ycW%f@~jbnMNBQop6$+M5DFB?a^yn{X7?gwRll>zHzCg;(^AoewYMF< z&Pw>U>y`!mj;gYp3zGMQIHs_6 z{cQY@xXa;Uak{wgxo?luyYC-(d*r2jz~-10MoxW4=Iyj}zOet>S&=874$V4xbJy3M z_nFq$N+>G%9m>2qq4k*Z#a0 zuG;u3?a+OP9bcwqs}x?h-v99Rgb%*5>k`+zpWq($^2v;4GeueqOmtK0Yj#XanYTN> z$H##x>Z1PwA)MZJIF&HScd zb*H}O;*K@jL#>K3{@Og~SyDbtUugF8l4;(ijg0nv`J(MR4qM$hZ}x4@zBR(v1C=)X z?|Z!?(7)rk2|v^6#PWCj*~Qb&2Jhw0a}KdeRnDrsd&y4m_O2i6Ru-)`x1PNFeM;Jk zIA2Sq+sUmro1+DFempt)yLZO<({A&(OcwvR*-=^dlP1;~7{MzU2 z%aHokGuZVE5w$XG6J29IF&iAO@I){h%`J5?&c%DaUoV~)-EZZuts-6YV9F1k!0gQl)Aq3V=H&vrNJoSb_5W6zTuhUg#eMqO{RAKzA-@^W1iAA_@`Y^{me z4fpo~UyUDG9%0S>-FN?P>4R1^i8oHZYuilOLyi>&?D-(wxQV;mYiP7t%6`R`pjbfBv zGCscjdt$iOvkgYgQ{Sxqsl;<}RfD#}>nk(Ax-;>=Q8;Sy|KTUl0 z@#a2m<=dyu?N~gmsG=oj(nLiepQ#4DRkp&LPN_~jFzx7_)ypIs{N`_Xr53d;)cFvv z^{3RU{gbY;6kHHj_U>3_qBT)JA}FN4YsG}^5ALkz3zXj79rMh@;!_OE@uU~4OA4d( zN}R0Y z*|jcTK1SF?7T(wP3@tZEi?wt+{FQS?$*XC3R$p7ZGNX4{%k5|0nbqLM|G>)hq~Evy z{d1xo>+0v7ee+mBW7W>gdoIT(OfTHB%O@fHQoPpX&9_8sRYKP)3Z6>zQ~7-FW8N9% z=O)7Le!WKvpNM&`Z9iLmZgSeo$)Q2ItG%anXFqN#5>r*0eeQ>X)AySRx{PZkiS3;p z-0A;wb*$FI(kC279&e&P?wFcAd46E4MPq`5@Cn_tl6h4eKlnH4_&X?YoI4eA(^U7A zzEr%N?y70G{;m(H>bPXibhEd6;|cp(c7eN}nSR|kG^Ld1Sf~C8v8V(6#i6GU-#;g) zc`|XEE!#2eOS|^oJ0nwTrFH%Cv$_4hS-gckR=i=q{>@bJE%VffCC5K7Fa2g5eOgZA zkWr+SV54*Ku0xTwM>2|px+jKxUHML8sj=6@Kc?-P`)>(?C zFFx4zWWSJw?kxQyij9wo1FyVmYuI9Iu;8_01efUD7n+XuZ~A#H<=Cis=VP`*J!f#! z{(!HaHaqppuJHeN+46@F*A0UoQ&)a^V|tuRxcYky7yDn*bl(|zCj9lRg`eCv+?`SmZ_&R=+){l7Ov$i(OSG3|OazXf~Wz5TFz)tX?-dx1f>%-H%* z2|GSH&TICpzjn5h#J`J7!8&RGxNqtCPqR7uhR-dd=Hw~ik0l-&$2DUAa{pl1J>Tj6 zt@B40d{Hi4pV-+c|E&7-#?!pl0=}HzaM(QMZ&LVU+s2BetwGNYZt4?MNIN3+{jCdQ z&!?LKt$VEF-wJ#(oS3n)H&UzLMi&H z4wvk93T_uYfBLQn^Mxyd2Tur|`+lo=Wnxgo35C>92G&~R7cQ*(^9AoY6l$M(cwnby zqtyM2LdzuXE%0gYIp2%i*Jo-@;^e7ayD@$p^NBq(h2ALf34Oel_bR3-*OS$S&8hFf z4e5EigtyI(7XKnJO;cEt|MTi87Sn^Zw-~#@1_W59Be)P zQFd4Jf4NWk(V9{rQPV@d=N}SjuQ*(Aai6@Y>C4Vs_w+X2wK~g`(+;d~d>%3N)pbkX z39rq>L)7>9*PU3rV4Cfmoq8?7>t?+;`F*LW_-fbn=1)KUX;HrGak>2P-0b~^?>uWa zGCL-}5Wf=g{mjpUbJ%lP*shx1d(HUg)-`P=!<(D*{|ij~`%~}8H3r$em7!8yFAnpX zYb~+bsb-wkwO{OP{x3EyfeFvN+S&GhO8C_JAlm3cSs(A$OEPDzRL?DJU$QagC<|NB z$Hwhe2Q|~Co}X7e`D2oH+6=2VN4rY=CO*iv*Y$RpzlHm&RQH^V+PV@qT2H(#4AWc`B41Vjtd_-Y`-0N5vcq$UH!i(f5q*UleJ6Ktb%Xt z-nf``-JGhG8#2W=_`Z>UzlKFoxQNMOX5q2P7v=H2cZx1y@h*px`(O@{5W3OiZqvGni zjFZd@IJ5sRY381t>F6eTyZu{?#EX+F^lrsI60lhI-mBe7T*L?#X+Smj(xXC`tF8p7o&4um170)u(#5otU;hHa-21 zTBoY)zm~QQmyB~Ngx1$j6}-4Ip-wX`YWmy9pWpUX)`sjm@4fL$-RHa`H;NlC&c1!@ zM8fi#j_lvj&$qffYkaZ$HRCeX;*-ClV-lXlbG}^t#r?`tv9 zRGO*s^5+Zd!Z((lp0oJTg>Tl?e1ATv0=`;TXLuCe%r7Ax2??fhsnQ?P9w{OX@W*w33{u(n3P=> zeEa?FRB_89GwZT!6GP8eVdlnSN0^Fjw+dQvZIC%ud`7P(&ee0rsp~7`+g&{FO=w;mpYZFsnApsR_l56234ELMdTDpK z#EIuITSM+Y&sh3p;ks|%8D9g zc3fY0Y2y1XuS2`$9j~tLX^UAfB~;2Sp}^zg53yWkUj3ubx}Vlu*#68)YUPDfp$Y%h?6z zGSB&LkPP_$Wx0l|#~wRb*~eXhtjF@(;vZ@4eW14{@weigDNE*j$ypdX=bhArrT$t1 zi;Z{Rj?nwn+x7D~&!vn|KFLdV-M9X~cd0Io3w30E7R=|g=F5^|(?qTkfAKqO7Yb>` z*46c?F6mL2G$mH)G{3%pOGie!=49us>K445%kQ1M)pt@O`|{?)Ti7gpgr`1EwrvVD z|Gc_+P2Dz^Q`^oeec5T3kyf|1^61lGndo%p8+jR(YjT|3HI`@1uURD;^=wIBE4ERJvGd}2z70#y@k{?b*^w}>Q8>xDJ~ngL z@%tv58!r0YPxe?4`1`fo35Bqusz(n`TJbrC?H|AOf$VSFdA-_IS)QA$3>M$uey`c(T32&)u5UcOOs+7gz}$Z`Yx9-!g zuJt#B%QG8G?=opV_Z4T;wiMJUoLH|m)&6YmDJO2lp8Zi9xON$@{v-RoN`O1PPUeiP z!dmVxlf?7nE;D;Py(^-YwdL0Y#&y$z45vy2ADwbD>3{aL7q8r)Zb2Oy>&BumB6%}j()|rCDZrt9`#caxyrUh za?`!(jJe+1Dh;1il!+J1O+Wwg$LZ2sm#Yp-N)BzAed#Pui%g<pVC6a3-U}M`hV7nlaOMlam9x)Io-}#!;uS7|GgT#QlK1$`b7-G^j_uMt8?{$!yra@z zH5jd*!@5T?SMx37Rw2o2;ztkMbiP-zP<(#4$-yP!O9I_>j?Q1$U*5ZIW7_$nuQ-U++T-K*5QvF5yWIp-O(Q_PLrYuT=! zDxNdH>OMb1_C)jMWhb`%T2-OB{K59bZ1aZi>05(cR{cA2dg<(*>1u0_d~+63T`^Bm z_w-a9m->noQFs0<>otVm1_qK0ixOTo~i}5L?$p#`T=7?1H?b-W)E=CEYE`8GT8nTnQ9qy(&OCf%sU#d7`OJUW3ZcaT24kydv#*f(TyL% zPiQh-XnvnP(=>3;2^DEu2Q9w`m#b%TZ*S_xyd){<%*H(FkWGxbE z{k1f7&)42+ITwSEulgJwG@E32{#4@asK4_q_Dt-q^D57U{-tj@Z+~6BCNy_Ryti@Z zap_eu;#*x8x~n7~ycQ~Uf+_PWUw*4J+kU?2oBO;D@f`hiT*0DL__Aj82d5947N{tN zo{n{L|FG-QnXvO27mMR= zZP~@U=-J1_%0&~!9j6BOvd_AkRIXQW_ssH%w_9WoM$HPij>ffEvf4$~pWBu<+Pc|S0C9|yd-4Ld?B@&HZ_Z;2lGj_E?8YZl_{n4SnZ|{ zN2fR{*}a{2#UN3)dfv<_jjTI;s}7|!9%FrdtBBia+HvW}o7?Ry zk6lN1vgA*z9jeSesiF$jayL z{3hD#%lf-0@X_PWT-`RF*lnhff>U-|zj9%fitjnxB=<{kk)qGimR(_c4*7A;OjCCM zo+Bp1WOZ=o#F$1oyuLN_3cl1)(duvx9c?J zE}5D4cukIHYkpia$24~_zk`a)|E?nf1^X=;*UMIk%&I$a_bkI*N$Hv=7mv+7`AKt2 zptbXgBQ1)l4DxR#R47dkS5#GhJNabAP3JxJCz^|ubfi*unbVl08Zx7hDcQC9IZ8&)%fNPE}gSVMu#R8407p1F@u54RZ;>tNK z@WhNQm)ZNu4@x91RlarQu~b-jg`(63=|8dYo(}|qHRlT^dw2SMyZ7qTA%|_|*XCR} zuzS}kpP+f`zRZ>U$aX*czxC~J&o55hI(7H4s2*82?~)g@A5T}?w&Z9|d4mam++D6I zLhFt+hOg2&{o>{3Ro!jhPi1-i-TUNztxQ3Qg{sT9_DMfkRs1@*5?_}+u~-=Y$L`%+ z^UoJ{3BLMr*h#A{vO+qqYTdzaU(3romdLuY+@E42v?{6UO4{j9-y#zuF74h?;;N=r ze{SV8!+vG@`OXJ zucHq9-~8=U+09MfleoFRPRv}htY9`GJf2BSzN3jxzKxh!7jh3HubjGr;@A+{%YSoe01BvjT%yNHlG;cJb`%Q~k7Xm&NiVf3cuLvzTwJmWi4;`Jm~y6V(jgf8V^A+i>hmYbJ-Q*HWVk zLg8n!SePw8nEehr@Jh^}eCm$0$49=0yvRt?e|P@Dl!gVn{!aV(E@nwJ*O516>m;^L zdl<7R=}>jSdao;c4Zpu?*mQz1_4J9JmRG7dD?=xrcR6Gu^7{XI<-~n|)bG2TP=1+W zr&BWhiT)<9Vx`s+!FiQFhaTLI6L6`SB+@^{^JVQ(1`D;;=NxZ?4n{BZ=eQKHQg@2a z)BFRkQ;m;xoWE4F&qAvAg5;r$cqYN%mUYIKuHw(0*kvrZ-Lkf7DPwB!mZwjj)R~&^ z&(EA&H~aF9Ml*M*fR7ixxjcRK;hWII2wSsh3z%A7&$LP4&|Q9R!H||=)L-+r zA$Drlv+muIk1M&Tmhs?o{;M4SQ-agmR5v#1DZhQNFRb|B%r*CmO7FQW2x^tt$bIJz zk9L!0+r-TWCiAsU_9589iu)}B|0i*lOo{PL{2|CWDQuYR&m z(DZlbxXY_&_IJmr+d_8vwvM5*4;Y2CWu+dRG;6Wpy^}|mxo_H|_;G1|VuE@}>U=9s zGktFP*a-gzk*8D~`nH*HJzSzb-@CG6S|$sJ&+7{-9ui@ zOy|&9AqVW{J@EOedCf~dhxKRq_ew39Qr!nvpQt*cltf8RUJKYp{?lN>?sW!GLmnNxGBZ^``ccf}^fTl32$20c8q z`{MLV|K$zkI?r@B&MEsXViHz8V{XK%k`meO>9zCbJP69~{krbYIn6SmB;}vy7u55Z z_{?R_n#hxKZt|uYvDTXHjj!E{{ur4vW-YQW5C5*YSYplP2L3F?T8Ry(znPQ?Ke%ES zYaPAr#E-f|5uQq{o^M>g1f8FAmSI7UQr~oKo{*OMKm(<_4Qcb!mVQ6vx$*g7ABXGJ z>qYH7H>+Kb`)}GL;Qw=DNsi~6pYxJ_{rIH1-~5T5VmP&>R!q6q{m%Toi{c8H+**1#|6BiXYx`x(-kfJy zVE%Cr)1+Qa>pRO>#oo8o=5s{sc^fODx@V`)%Bbr~Qq1jhWi-7y`vUcHOS=Aj-#oMFu^KyAa{HZ&(E7aAl&-s0=u~|p|$Sa1RZy8Ug zyqKlZ^Wv0VrG13vaj7e@r=DFq;hCDZ15%djnCv>b%SQS4UaLK4?#@+zdPXCh`A3-qACITk z^8l9{Csf5QHCDan{?l+YujO=`ed=9>h=tj!UkBV2DK|*n^HN~Z<+O{tcdvNnr1R(R z@xrHk5`14uZBi@+#eGW{E^_xZFFe{x!2_$Yv*l-np7esiA5{zD3EhdkN- z%gy=b{I;Z0=gPNQe~whfBll$-<_N!dmLcI^y8A*XuY`#lk`C*6jj6**RINo|CeK}h-Q}NZ4NrFdbGtE?dcyz1O&JrOhqqnDAO+yYk zzY5O}vcDd(^9xtc)njW9`rTDX`(S_HC!=uI`FAZJU2m;+x$IcsDb&7`W$F&MX{(}C zjF-BsY1~%dFOpv9{lg>PP;q)QV`Xhs)!&hmQ1(jWNcY-nAA_pu_B$3mSA2eE-O6nDl+}ge3Z~pM z9y?`h+i0ex(=p+0&^pUfRX?S@{!6^x2-eOOiah&ehV;$`pGL-gRl$K5S0$C#|C(!k z;|9ZBrIZDywf{fcW16D(tuMfQj?SYa41To%KboyF>{Gw(HO=22oyEA}>M60{gMsoP z&K}wEUgx`#t3A`I7ko2hZPr>g$>Q6ojK8W=vZt~Ae6Oi$*(JXBm&>!9h1cJ{3Yd`@ zXS!~G$An}>@f%Y2Efq~CU9P{$+_!k;;)ug#z4foMChp&(-gdE#yM1=~gFk`WB^GEc zNpt($st|U{O6pL|=TL*wm9z90Z%%zVf!A$vb^a&sItGOtEp@49QbB8tES_BX^dOk| zO?7chl=1)6`Mss#TMybA+;iI>b$oWlGp$u&Zc9#wE8EGh5;I>jTYd4?eWrh&T3ep; zdtbtIN3$UOe(754qW{hNPjOr4E(_gse8I7OdcmD$yIdaL?b35pKO5tI@V@gwi7oj} z&;Hcpdet1-;amRM;?UX62l~~`?=%11$*goz=kv<`d9(MgzvcDNzbnUkqt+a|<9bim zTKe@zKl5A4eB)Wi!`F8Ljth&FyME$OmCxU?#NRG)4@0@5Py#ncXN#`j0$Kl+f({n9 z3NzEzCt^EQJVbwt;$m}&t>r)l@1s4<u=vE z*WYC5~h31LRhyR^?U0rzIF~vvj!-E_9IRgWC>gvo6nJ>Kh(l5v3x+=Z@+grVq zawkr&+)=s9|JW~oEx9P2f~~8x^iS%@{^FPtT+#nUeXCBLfNJSf-am~(4I;cVJ62Yt zm`rtYp19!PJ?ST%3$8AeX5E~B%k{#~i|2UKyPDmViZ9zS-IeFe=j<^ln<{lJF=Z-$ z)a$M*SFY!uiFj;z_qdzHDTOO*^%V}=?LM6PVBO&q%_~>+w%kq$=VDR2ac}CgZ~liO zH<;$BS>;~-lhcx)@bSdk2;S{cT+^GEmNy+uwkn-pC$j8tz&+Vcy(m4ys33hAv1yqn z^uC3!_e+pgbY8wd)6Kge^~^pl=V#$7luWjq{dlHw%h|B0%Bu{S-F@U`4<9hU^I`g= zK7lO}zd|GwR;$nFY+^DxvHj#J{wpo9K{6N~Rl)`xBAx8GTJ?Pl$P*HvM9McY12U6fJsJFV!+ z!qb<&G5xf7^*xP+RrZM8LNl%=A#JuP;vs)ti0YmFWni$|eEJH8Z`q%x?rD-=`0CNZ zqFw@?}wZ}JkT-J|#A;4yNNk#a31cQ;jrE>bR?25kNu&gVae!K|m zIPKE#D5Ua$vj>mp>ePuw68H5J=YLqX=aHxLXNhg!ByT6rt>r&{xKv_Wb|>@2Ng6(< zT6>?q(2+5=GWo1N-OcLuQW1e~@8V0CO)h1)J*%lrn|ISnPWXAvjd^orr&;vsycd{L zu%X7&~c3xTJXJ(zy@B${kAHwt}F@LOzI>9?BY%?my%gdU%)5OnCzTv^|{Tm9y8 zT>f6kRHdlz;sQ2Yfm+HO5RF2q>+29KQ`ym#y}%)^ADQw7=}=H(obetHX8bTkn5jla_fttIsspbpGv>HH**e z+jYb-J~918WAOV`t8c#x-M(mQl8MBHx_5aQ4bK8<4!CSEy75)=tk=%PU+?bx_Tt2$ z>&El{X2j1m;F9Hett;Q;8Mpi2;_0hZS15M8-d)8VCA`OJb-AqmLX)+B+MZX(8qCql zQ|VYS?dqq^H-*1mI%=pPf06G2)0a(}+`gigGlCqI6>Szp-kKZII`{pK3x`ih7lp@f zZguEU)7rh5<)bst_KR;?kL(Um*T1v=S=3h-d#5(WiBlO4e#$P~yDOw|-_nn(CM72) z&ARjV+VQO|k9Ka^tH1mP-}XI|`t{Czd+%TJZX$nw(Xly)cip-jp22-?^J$CHrwi_0 z&WxKS7G`oyi+|Sabv9pLIM#%|w0)6wv2)d-{lR^8F7Gd`S>KbiI>ftQ!8mvOq8U9O zYz`!uhMur5*yX(NWn^ye-Iz+%-iu34Et;JxV={Mr{*0rZGww#b5xc7r)+3aW-1&_q z*2U7`=muTMYWoTAqqg+j-PC^A=wzsc*%zC2oR%N|toU(+t5Y~uRP^os+jC#9dc45m zZ*1@?-;U4=@)xSRzi+tou{rTxXt2x2?f0G2cD{KzxBmXM)i<@TZ=QDKnwQO&B-IIf zVp#3I-i-@zO#1!kQujp0jd2Q->cc{6ofa%ma;llP?$##*H&5#nw}ThsZT@F>Tk=YD zS()b9NT=iDkg(JLnyPMK>3$;}uh3W>I^WCLVqqF5h0~e`T6dq9DxmC*IMjPwzRDB&CZ$PCK0ye;kuInAx~4+ySmSK=lN&#yMsKo5_`V{_e|(?bJ!up zcz3t$-_~`j{np6INB2z3zqn ze|d)X0;OixLbof*A1Cd7)G}e-l00*prr@3a`To~gm4BV=IU}9T=kiA|#G!lUkrz4B zPHHc9*fVW);i7kwTBJAq?8$MGo`b(#CIQwhAbfzm2kcb;d>>tsuXQDW z;mHL>yVWc=s$OZZ%~XH&?^Viq%MWJn+q?elJS$b{9VB>l+g_;~#*;;Yi|VU(zn%2t zhVey@i`N%8ImKwNy&fi7zi`hvsV(n*+~O*KJb7wIX#0Ze7K^4VR||cr&%0yNvJV@U z-Im*OB|W4{d4>ItZkD_K>)+X^Uy@vB`KmH>exB>^F89lVrgJ*JwD@*hH&A(fu!w>E zPk(Qp?Wd=Eua|5OTd3?Lm%7_pcFn9MmX}{!T8RG+tlwZgZ@S0r!opjpPA-iy|8|kZ zxbW#T?Nf0XZudJ5Zk!*T{rBnFqqkSC?k*QUw>zj&Yr>DO&nN#qpWl4*(w#Fmq%_12 zImRWOy0P72N43v|4}yEv_)J~7W%KMmlR7dz7cXbt+j!ve({m45x<4j3)EBoVYuRL; zh}Zve=G-QO*DSN*Y8M$sZ~FPu>b2$vwO~=Tw7q+>E(-ddVi)@}XYqvCIqGg*w&y+y z*Yv0eoH}z@#z&cZMb5$V)1E!Q@n7b!X+cf-##?Jzcb@2a6dnJ$r(Q)uxL1~|!|VRm zeRXl>K~Hr}`h)3>W^s_gZ?6@>lO2x8amU}sL@jXdYYZ&nQa!zFE@JZbz_fVn5f-uCUoq-U*nv;z13`Ma-AF4 zLuB%uujOeC4})iDv*~zEM=&;p@c*Z9AAd z)@(ZXXKsJxoX>$pm&EN>z7_RjYFq!RLH7dFraikqhB9uSu-$v}yYlK8PjAg@4=hb_ z<^Fp`vNKHURKEJTtSCL-IR^fn2hFTX1LCp%`oxWU*?{S{W@DUy>?s*a$S+k z|F=Psfz?XJ@XV6)yB_C=aTs4Yv%(;$R6g=ieN?Xb6nC*3ciOM01~6TWEAn{M>{lPY z)@M1t;G~Bx71K`Gu=FqCn`3#RYW-4U8D)OS(zSjUwhHNeUiI#!)U<+43Gy*U?@sY= zy7^*?tkjYpjq9v$7qa*%P3(SQ@PpBVcjxK_C;gm^=jHGQr{+k@AG@5;p4edX^KX<-4owjV{%LyU%Y|P zHQl7Se9rglxn6JI%eEb|%u|tk)zSNU#o>P^?(d8+pDNn=ywg6l^R4*#@5~dr)bt$G zzU0s05f`rg=*G3cq2%_|)&Kk*=DcNl(Qotmc-sDO=HegI8{Y?TAL!=wZFv0ic(3i$ zI#=zxbCWO6I`#VX^9fUVreKNDM$`c)V zyuDroBscuss(rOwU{0a(23^yTDX$-0zHEDW=^Oy?&C1+O=qCnV629lT+ylxm1_!Wvco^5wr4 zte&^&Z6k;G&49a0(rgY)c^LL(Ucufnm%qXe78^oBm3zw%e*CdvO+q`TyY{Xnb+)C^ zPfo7NXIu2SXzsnwA~Qc2-+wNmQ6g~2++0!Y(xS|`<3;U$``#bEHYq+T(r#{k*wXf& zyJvq@u(R7(rp#J&wPz0#^VvMFU%Q@5-Y_>4{l_|UV^HYtB?hlLtX@vw*L-3;=SD-= z!{3j#C8=FnJ5SFsLDSYWdzbs8%C-AmHip29CmKms%Dm9evGh_FYlu&|Aq3H)kz5vg66~TdRs* zT=DRAiCMBP`n>fK!&}zfuFDdeVi!#)ciC65yvojFx_;7urz$UOKCDlZ7Gk!W{%&c= z&u_+C-?XI3ta+kxG(gKIw7Sw*+0gGb|D(M#jJ?|D{7h#vn$7f`*SCCYvX1S}gFY!5 zEOy`HxlX^fYqSi|J9pXh1pC*&nwuxKdMn0`?T#UoR$ zFjc44J=(_mP=AZY_9cPZ_8wn0um6xId$;QD>~oIdPk5|^3q>bvP}{!v$&Y~E8QLAW zobHdZYrZ&qzaA63P|Cl<&HuR21>RtWNU?8?eJk{C96hKrb#937%ZdADAKhMjL|P@+}!0Xo&e)Y67EAH8D+}qgl!m;k!hTfX?=6BjkuG7L6D((2@)t!4sM)6LVz&l?3 z)_`k279X@wR}?R*)tD@&z4^D<%ZQ@oAKe?$MRW2mM<4s#FLc!D?V4SGStJiGXD_(< zqci&C)#$}hTikW$o8H;o+*F<^_$hhEJ<AExb# zi8?kbAV2Now@U}#t+VT%n3DcvVui=CGfjRQg11~2_5Imn@Fu&vll38^lHO{wE7KO8 z3iy}3`R=qxS9ZY-Kc9U4w@67T^nu-zLps$Z8+O_xO}EK9ccQ`b(EGB92iSfj^UTs~ zeWh;pxL$W^=kv1s4D?~ZRb-}2lmB6a4!nD?|P^X0qhKa?%pv~JS0yWNWopGKdU zy!Y$6nLnq`iukO{RT{*#^O8{FsTW!-idz+@n;*Gs)v!EI?cc+VN?g9PZhf%JQmidn z#1pY}!fq9=$E}M+fBC;VqqX*d*viQ!i8sC+<=&$lSBS;#<}jV?mV|l$%ymv zxauag>*h&Yo`~4Ledc=!@wzVFOGUpx# zlpVLu_g>;~X+u^n({m?LIjaPj*WsV%xE60#4rEuqTpzaNta79AJ++H!_Rm(@nIAM( z&z{md@voP(O!a~920^SsW?G;2cS`?szpU}{bS&?Ct38^mORjVFh27P$E?;8IwbQ2b za;1fh`0nXK(Y3GE?pb|1E#lnayUJU(eu&aIy6WemH^uzLMuuOXh#sp<4iL7fWoVAj zRW^C;er?6u?OnHwzPWR*xFGnpK{Aa&c2m*&)~!D**yb?A9zEHsCb^YM)A+sO2lXEx zlNszcnYG&LwYGf8&3qK&JcWYgz40){_u0w)eKws@3F43 zE>ZgHG-HC`zS*L0&Cg6baBotV&c7dy+uk}AaSKge{WqZ5E8}O`lScJ;ofa;9-qt;dVYYl_*qnqt>PKm&6amPTB_}r zEX>&XV@t>XwAus5pB9MhVVE#|&;ISHFFxd+4|)B+`}mcmO)UQdoi1oHbBZ2wT(VK1 z#pvfh-HkyE4i9G}&-rkZt9Wg{_DLrH{QtGyi`mSR%X!{DnJg~%CiP`C_wM#1l4T3e z%=`2!$U5Eq@}tr%V_+6Q8N}_u11b=BwVGeIPcQ>w6Z1XWm1X5cPmeCWjBI z=J#VO3^sk#Nq24UI{zd}Y~n&^buZ36{nvFB8SUPGe&y%zP3OMgmh^*#x--`M9M-8? z$=GhN>ihEkX~B`{;>#{CO55wk(ERk8$o%Uod0t4(e3h8Jd|#mY^O_3N(Ai~Nkp;$4 zDHWglSx$DJlWdyCxtP`Eo@WNX_V)Qn>ps0vxpBFtS)feiZj(71r*uX1oQzsk{R5?L zU!-SP+3$N2b!czeVy;i;I?qea`SALU(&=MSRW={zzv%N^9G`tgq~=hAT9EVBm<_6S zj3<~MSnS;VW6jg>$PN2$_M1yid%M)QZ-!#KU%~zTLFzY(_~lm2_`j(_NZTWPO8D1z zd~-wvK7Od&&)=hRa>FX48=Kb2&CtIaU3%WeAc}WS_~q}LOW7A6FzpWMI}&$sul^02 z$Sk2`D+e35s-o`5T{&BCyZ+pDOm*U!1E(&mI;)yKW5a`kmeJV@PHR7kO}P-MF4fr` zdHr6)*8Et0oh=8a&N7=Uy0p6E(9Tusd>OkZ7#@??b-Vd)#sA9&h8D_gf=}c&9?*Tq zEgm&fDk5@D0GGIn+&|rW)mc+F-?R7HCHu_Jrt_g}!8K=wte^ibHp{&Uf46AwAwlgm zD$fJi1lBkF`u=@~=-#**t^3^~T8F+Htb5tILzJacY*X&;l5IYByw!FyE#GSOwyv=; zk)L(KLB+T!+UtZh_p+ojTYjEr^H+I~{%SV3V?>*(5@f()JRu#D{T5Vd%_+|N% zz3cDJeN-7#uJB_jyZg!_{zaM!$?>mq8T~HD%5zVB;U-jC2+%5EdR{ErTZpV`NmwzNp#=(cIeV}%O)d!-o&X*m%mNX zEjqREYVO+`{>FlFjt9rTO_k4{~x!!j-ohADq1SUG-z#l0ylv!wvWGEInQ-7W{UO zV&A-X{`LxbCq7+wV|c&$@M<=u`_`Wq^=gC33mrBpX9$xP^;|I$?D@z++%m$77^aEU1UjR@xH|kVI8e&_OrczBUkLM zpy6#1XmW{XadFl`lP+0L-y0=Q>SrG1mJ807yQsHCZL$2087&V}vQN%lUcBG?lv?Ku z&ktGejxBwi`HwkaMc}3|@4Obaopo+XGJ>nF{#n{=`0Ck5^?+@M=d@&t=GcViKQ`m( z_>*v<@B@3&+nbJ8vle=6?!Ic@(GdNvds4YmKlfq2*%>SD_-2Uh)>hsk^-_D2J=4$s zFTbYKjvqehU7!LG=Zse-m#=G29g6rZ^fqSd=F5b1USN_7}jRpZ< zr|UZgFO)PQ3`13oz8@ zP-fo1`Fy(Jv4H-0dFwm{AIYwsGFc%->dQs$THQpw_tw$hVlT^oYT#|yxJ&>0xhEzo z3|6Rg|6F^Q`M!|c9VUyb{AXUruaztRo3NtFFznH`J7Q}3)@QaaJIbeMQuv4M+3J+_ zjC*!;bvylNj9$23kKsj3Cr)QTdRvRUVWq; zJRxtr%j{iu+@d3e^3^}SPSbN>TvE!yHP_{4h5e2$;geH3K4zpdszvQLzHGkIKfgbw ze$t62j0?VI(o z8-91gR=Y%Bp7}F5uFm|sJ+G)aBkJ@0gK>YPVz)Hhj<&5jTlQJ2(JnJ{*PbJ13re;d zy|v7qTNse^|I0=8M^SH1U06P0^TMJe+b@Tc3}1<-@69gntejx9>g_YR{aL}Evl!2B zmQ3DrFMi7^|2c(SI?4auT@7;F(!OothrD3E?LyM-_nv>7t)6ttjqy?t)4}pTy7ktM zVJ#--Th=Hk=9VsMSRB4AUtsCq0^Y+v4mV%Bufu(Ft76W^v%l=$e6(qeO1IVx5T9?s zZ&to;%bv4SxwSi+MQ%j(CMW*gD)vy5f88@d_v!zR#Jn*5GHHgm*EU8GMcv3(rt@|k z>wOz_RR2cBhosppt12)5*4SB}IWeu_D)~{@+(R;7TwT@d=(CJlb7Lm& zdV&83mTi|Wk6I%2JajTnORaGmZ1YhI*g;yqO2uL<(m}-|XFe zF{qvE-kfiXPHnisecs{N;#UIoFPwEE=1zY8Cx-Rif<+80&u83=JHAb*e60fSvctxn zN9R|D@o~&u^!A|P8|8bqIF2~iy)U11cr%Mf@4D29D|g2>R4w#+W#@jtD89B^>A$#( zn)d&%-bN2~558qRa6sq67K2AeWed029#@(r(|+Pd{Bmvkf^dst|N5t1ydb7hDt5)a z@bPxPohc9hF5EIL>H7L)|H|VJwnzl|9+pr)GAFT8+(st##@R?=>o1xXeCa(CGP3ed z<(990>a_9IJ{d3Rv-&CFYp*9IPAbf5xHmytsjO@DrUa8fmkoaYhgsvVeztpd*tK-$ zyuc*>&ECDiE9UmiQD_t~bxE+TjaS)IXmU}|?~uyEf`#h0E51Lx%eTG$gYMzUi-l%q zu2=ZNpI6O3Ih8kZjhyhc(ueA7yDTqwH{B76i?z5pVZqwNWw+7-5cN<$-+y_W(~Emld6Z37-`Oq6RB4H?WKNfK zpVU&%WUJnPj)7rYE;X5l89iO{^n~xMD<0y3qCu(8W$bpFJp6n~@JLZX{<)o6Nx2d> ze`4+KS|T54?E6$)P`-^Lr()sfHBEc!VszHXob+|q{QPjk0q+vb()7X|5 z5w;}w<^7dMeJ;H>ntE0;?OV_(>xSHkoZ0jCMy|YS?tbfm$MQK1?^tJFU#^>SQCet@ zuFm40tC$*UgI#Yu4SDvWZNZyZWf&w)Po2zx?2CX1*bJ zhRO4YN9f8NHqAd`-Ir&77uE6IKYOxTrMdsjg{zN0kBs^GdHU6i{VZ=T%-Qo^^P0#F zhc8(NKAn3T*YRk1+~Ym+_Gh15-Z}Z6MY#5q3hni>FGG)dzMT-!q^1^Q-(RqL?Uxk~ z_icN-p{;V?!weVa?6tY)=Xh8i(z^Sw{ma!v-riHCEkSxcDz%=EUw%jn`>^C(RFw)+hko93+kgK(Ax!yg!NyKLWLIIEd&r*3VN@l^KDPbBUvvgxy~i(M8yGj3xxpQYmE zU6J0snw91YedChy{sxMkaSRgOc`z>7u;%T~yX}|s*8W@M-OF9iU{`-%%ks#a1?!8J zrf=6Pe36%_qW|BQ;jc@|_cAfZCC}4$o(#%#eic0V__`*h+Y@ei=0Ck_Iq^g8Lhk^s z3qRE=m;atGV6H6|wq)^*|J9fG_KI-!Z<_k$bJYr$cO4q;*%Q>RFTe4jnnR^H;MA4L z@6!IC`cT8e{p%Y~t}b&=_>SMtS2x|%`?Jt+ibDII6EkWz@BUqsw)g1?okQz?%&Y32 z^?h&Y4}Njo&ldapICgxU{luVRipb_pfoDsct+EcB4PLUH#b?{Ii2YAOW8(cUw$;24 zoKd;ZZPWelX1*y>udSvQaZY)^px?Ls zyq(3{ucD8PXPB|eeDj~;(vxNv!oMJrd#>rN1^@F8Fo>R==dGIv2g$Qo4V%`s1ijpK<+V?V?(2Ynk_*2k&R5zK z$)BZsCwZ5n`?M8r&edPBJ$BfY+eWAJ{Fx(nce&U&g`cc1Vg;jD6g+FQZV^fDs( z%Ea#$R=hv!4PW-9uV}P9^XR}dy%yeMOA`V%-Ydk_)$FYLgz)p=B3`hg-_gG)0%j|DoZSH-O<`L z>5FR}ZoIMIYmsaI=tKD<@3ape*I-EP(Z!q`lgLNjG)@QkD`5U(!NRD5;Nc-OA z#w%vsNrI(9MJpz#dK&4=JDgOcm$fw3ozvZ^OVz*o`J$FMbx_33}yW3Mk?$^3r z@D@(KmeT#PW%By^6I+{C{kmxU!B?uny1Dtv924oL6?)%}@OMo3(z5>g7MUk|Z?=BC zEtuN%*6d_p|0>s&`JFm{ryDNZJm)TtmNnCiDfhy=g!^_s(3#fnD|Gg7Ay;01>lF8! zXWkbq&Ho&u%D9)$C+Tdy`px%g$@8V7vNDb?XPRIu7~3E>ankW41t!cN64hVa=C-wa z@@P{9cXo(Z+TP_Zk>A~Fvg8HVD0~VYRC*SMWoLyXajthG#C@6Ow)u6q;>$dOG>Sle?GB23Rp_9=I3HTCOhHWifZo zrXOf32h3l9PRR9I!RrdtUQefWyjj+7ITR`nEu-$Vsj2x}(ya z*!wb_v-b$JZguW|e{7ATw(Bm|{aXv9)uVT{h7=#wdbPY#aZ{k|?&s&G1n=IF@65(( zYgr(=I;5xhc#_?%d*)v>?w-ruIbCwG;02vc>$C2w_8Xr*?x?FK%lXXXo7rerJ+@?)umdRn+oWA~v-wy2DwB(PC zl^t7V!JCvbb3!GZbgNcIH+6sx%={H?JJ!v4dU3K*ij|~z zx8FxWHz|h37 zxRe@e%-XCYm+|a;zw=aUfgpVi8d z`!7w1*mwEJdHrQBMo%sYc|Wl=7mqHHb2S!o;}Yd^PmP_%TT<8kY>NM)Uod<+tVThMI$$^u%tf z^1k4|BKF!#PNQTw&5otzikPi~xb&hGkc8`c>i?3a(6o%+Jc zS?h>WA>Rq{LsIv5_HyTBGbvX2+W| z_>$ID$(;9;GhJ!&ICjIIuDRK9?eXW*n%aII&=I)$;HOH`GuHZbpX;pk7YKj;WV!x` zcJ)LTX0G35pHtT6Gl+Uc-ZD>X)9jEtw>>}XMf2MwCaYo$SF@%6PVU=geQEY(Z(ZNn z3rwa2w(pM@2w1juMs!%uZ-4!eQPug9>2N72Y+qX;*B>`$KA)rD)CIvI#<8u_vr-%XPk(2) zNYzOFz*2!7ei_Suo%?rm-|}5YUR_)}`GMHBw;Bg?KQjFDI(l>c?aMnq%H3z_627N< z@bsT)#h$bBd;+hQuQa{RXs^=rsYFd_$L#!PQv?`fnO@2MKbYpfrz?Q@X2{vr%{RK% ztvop8&R0#2mHTC{NuN8o@nvLkvdpt)SivL!&8Dx+KYCIJzi;gr&?~iTh`7C3QHSgBR8&QYfq$R)6WXY`TNF9sN^jcDKWR}}|*Rz`s&iJ=US89@C?wupIa)KTG9yi48Jm4;H zCW0^Qa%J{s)kPR>&Birg(9<`l}y;Mcu$yqaqox4RyWLF&HTH;%q`WnokQhO%G!A^ z{cTdc;#D`sufF^}cx#={{zIQPRY@NdJ9JF@8jnE|n~Yz|f%yE-q1KIi@=sim`kAy@ z;{Pm;eP(-ae7nEUZWdR?=6`Ph-U3fU6MMZCrthn9<+TEAj?A>-R8b2Y^G zr&ul8{MJNdpRm@9B{N?ou8rB%CfjYkqOVEvwZ_zCYHAB6d#J965ZhJcWU`}cLz+C- z{ORf)+a7Xjyp&nAv{?PIt3#4TPVu#vDP_7UU6p}LX3AK!#!9aHVE)NbM=|7mZQ-P& ztIOk#8?>bI@teOn`25i}akGPRl@}&n{J%Np@1~uxD>t0lwes*sNA7tVMg~hR%s(&D zesABh6sJAnH`ZRRpSNb_v>V@7?mFYB@wqKxy<+-}j%***cc$XJDk8#;3AuOOuNRyT zUcKyuILABAuEP)JJ?eI_cF$fYuGrzzr!0G()os(7Mn=J!bZ-ADkN-yN)|}WLsp!-8 zd*`-^os$wLP5ht2zNpsRDo^jEPEuA+)dJJi8s;`S*IFk$mNhwKFMMOk?xerrw%?B2 ze(<9!lP^XtaoZ!qPRpHhS6PPodT!tMeFyJ9u0-9{?^3Gtk1FmsYN?t1*6Fx$)*_{J zXW<1li`tIwT;jOhcgvh7%}iJOnUy+OM}bb^uckF?5nXZmWD_Zb{rt{Jq$Xp>?D|K!kr zD>8X3CJNk7k=w|@J%iiEQRx(umvn2<{Oxk7><`V`?RZo&82giV+7}%PFZ3ujKKR2& zd0qL$o7PH2mkvp-w_46p+-q&qtnX5B>FUD1qkeoXN+(B`5||5$K0b=7}(#|zp!x(uH8BNeDB)%SCtQX`4_U~FS?Ws+vX5kT5-Oc|e{y%OfSQ!^+!gBQS@xqXK z_nt97`TZ~=^yKs9AI>sWt>yf`|3mqN2N5^lOf--Dy*NL&vbxJOS2Xx|<;y=OEZpVe zl5Rd<5uGol-kyE3pkV6+o{7CDj!wB`%(}|xeWc#0CI8fwPl)&@63gWK`-D;+NG z_McSt?~+*Lhr{7*0@ZctmsVLwuV%NN(egl4Dm3h2Zp*J#&(hi7Z%pd3E%Z?M*s=5= zyI&jga(f-O-F0uBn?I~>XZV!GS-5J-lK1;8bsmZa-4m-RF`3tD79Dicn(51$V5Pf4 zBIU7daw=E~DPQDazRnU1&lK!%Sr&^n1C*9E8apB{t zw4)81Y!^$_CP{y`_~0&QE-Td$Wps>k$)Co#10;pyLpchp)+F#8|KS{rkD z&*dL&u7%+u*(s{k7Urt&Dp-w*O#R<45sN5p{NTAr=0{h^;q~d3c|4mv%cH)z^k zXH9pNuKl+nF@)c$;Htd%^t5~>t&1Lty$Y9Gz4xibD#-~SS4)?S>?&V=<1v>+;@W?u zFU`KZxBGwOaEizU=OsE#51yriw}P-3x41RqlTz%=fxv;muRA=O)fI zo>9kLoO|R%MMs%-i%n}hexe)YnredGCcE3+n>zLDvkxPRZ_*~j$- z*3T^9IADGKp1!i3l-;{l_bBcf!B*by+nE-xPPa9Gxbxe76S>!>D&DqCNh*tZue$nn zuyFqkxG$5~BgJu2Olgbf#`Rq9)0h8ZTi(U-hT3p0s;r%o>}YXt~}pFwvBywNz%s$LH>o*UsFM zVzKP~)Rn8tvvm@^Rwb{U5@!6Bi#t?|J=Oo?$;cV*XYX{K$V(Al)!O_!=pw`0iz3G7 zCRxb8^jI?E%g6I!7o#*ce_CC-L+^d>o4HHQ*jCI@JN;97>$f;jp39y0OY0s!`k?dY z#;ZnU_0+F1%z`H8lsRv%bv#c3G{pQ|O5zYEl<#1|V(CxP@ZK64! zdD{EZE5kM`Jqy00f8phQP9uX!_fq_4Pq9j5FtHJ6Sy?ylSbp}mV=Lw@eOsfa-Ck@E zTN|gXJg??J%H?N=`MmX}_Q&WbOZAz8o;B3{FT^kN%$lMZEsTb7}I%QzIaL;C!14h;2>y|m( zWGxo_Au})E#SGCGK?E@_iuaP$^(58Eo%ktEzvy9eZ}an$L5#?BCef^2enPAc9e?DJGIWi#VzHLnB}QU z9))u^Id&d=eB$o=|L-S$wi07zxO92je|ev;`}3F;boCegTF%A$ba|pl?W}|d$H4UD zGuKy7Yx<${t&#t}n_$7DnX|mFaxQ6`GAng$LEMhZZ{=Q{`K(7OuZO$?&T$a-CL)=P<8)t zXN#S><7wAC=TFZU9?kU2^K5z_C$jur#1~0dmxG_RA1S@LbZNniiYDL9rTbh}?q05a z=C|_7Yq1#?XEKC-v0tdJSv0Hdqr&FH*O%#~t)95~<8R}8`@0p));@n7dZhQ{N^J{O z|NA?ms}-3d=BhrKzUZgchh)oz>PHJ!mQ32wIxpj(rW zM9h<+ajNZN&fjazv^0-DS$fxgGuOX;mO95?h|k|Ac5rUM7uIX33}&B8IX+81zEyOi z=jwqaL17LbP2WD9>UF1Lw}sWwMm00hFqSPl=ehX=F$L^d`}lC<)&2f@o_n_#GefMI`H5XZ3%n@>!A^79=+jbGHhA8Jpi=+6~b!tasPG7z#bf#QPe%RMnzh_yf z&HcB_qj=looo^;YWPjOsC_X7}YCwT$*V8bWMGN>Hy*D(5FFz)izwS+OpmeLL;-nA7 zi$Xka$~;v0xRHCZ>sM)wt&3!Tlyf+iUgK0c!ScJ|6pOXX!*`~CiarWt9epI3U>(r> zEt2K?<4JD<42yHK70UCoV!REnHh=G2dayV$Qkg9z@x{|6XD7>6RQ1|AIIu61lX>=U z`fvW?$o>50_nG52pJe72Q8nV8a$)uNkNFel9rV7@Avhe{ig8krlrkF2g-$+E>cMojjU6@SHR&x=)@Q3mH_ zj)rCA#=lv3d9!*QlZocsDX*Tdb3XBUhDPwIy?PV<;%91FeHN<7_RqFDoh)tf`k~41 z%Qnj`LS`{~Nl)~?IXy+!UM^1cOnbqJ{@uOTG}w0ZToyRBbq+(9fZ|Sr;N&mOzFY}{ z`>w6tz;-a;Z%@n;@xn&i_v}(xtmbDf7ad*@()L_MUN`&Cq5}ty^m03M-V z&Wc%Lza+Jvi+$p7aTJ(ev-))ZQ?7$|z8^2T_w$NKL{{$d5Bs+qBJe8))66*Rpvu1>bB^^1sp*M4Z;Jex0#jeM>uJoMapZdH^O84u*mzR z$)j5y@x)AFa%4-={KqeIf6j~KmduoRxAW;vj;alr?@kpp|d9n4yR5o90 zp*}ms=6lC>OxEJ6J{xjrjsmy7q}GWYrG?9d3xT={vCO8n`JNSuHeFgX)pKptrPosEzaBSS^0_ICMz;6 z?F~Y8jy-;v=*C^yXMT1~%ogr~8XnUJ9$J?jd<8h953+dQNM6OPc=xKVq0XKQy49lP z1sDIa2X{@^?Jx1@;r}KYlDKW}q0FnF7w%K)iO&BYlcjKy#~Hi-ZaONX-*0*@ z%l`E1`yWGugAT9S)$`|z^;L;YyKVdSFRG}HGoBVMTe-bcHRESUpx-n z{X^fZJyF&oj1$s~uKDost>4?L^;&3e@Z;7k`R89>oz?XGmwNlMuzv{?>Kny!uN?Wf zHAwwYm}f=(CEZC&wXLRx?a6qy(?+^F*E2bBd%xJT73+%pwkvX-u@Dvf`0$W^g}~_m zof*H5ESqKiZ8d9k(@Y^@{o@;deAQbpb)|W@iRruB%L4w&9hxm8xL^39iHP&$`v33L z3PrvtUwLSD@A8KBOaH{roNf#V{mApW(cR^#^`fgY7VfyVclzgudX;Bge;*31U!b%6 z+S{5r^ZBFBblm=P=c>b^y&vW^7zEs9UKBrlL61zL7%Q{Ba3*){Ixp7h{eC6O+bc^i zGWdy=McHdDIM|!UGFf9q|ITg;>Ap~9eeZKqnd6pp5Sba7f0WAsg)I99pvA5jr+orEv0)AV0>L^7*8 zx2@wrSbgBxT`_rw6`bZRF+DFP#XVWzs9pWa#j6b%oR4vB4Z5=a&E);FW4}L>&AIOp zd$C;hto$zihf5v`ESe{BcQIGr{j^vkZvF1|Ns`Tp_hJ^ZeweW3v6!U$zKrtoS68x6 z;Mph5SJ?E(-}e&lKHXziSB3^K3SIuja$EYpPQf?-bGy!-7J3&__F}!+_vVX1S`D#W zySO*s+d2J5(O;(xPh)BrWRJ}+E?(c$K80&Sb!&yhl8Y;@J>QTh7;v~D!QjfLDHHx3 z5omuuZM)xZ4yn5{)FtoqR$W-R{K{s{e;RIw>^J;-;PQO=%>*^ad9!;i@?Oh($#8b* zr6u)M5AI&7S$f_Jt(!G2wtSQz?at%}T?NvgjT91A*$((=YjPr->{O3;Ix$Yuly*FvXOCv^& zBfn#3-=8#JLE-l`sgIGX9xZ9#x~^lvnzs0oK!c+vJym9%HJ;J(t~zIBScJ@qQYDXv z0Zz4hzH2A3UNw7uQt-dRoZuJxAFo;+YW#m{h572UkGDuGPM5zkyCVA869>)I@U?S9 zeRb^?99z1xBCBLiioNEoyi2L`8BC)QM)T)#(P zpV7uo?|YR0UCzD4!2Dpw&%>+kx_K@6x+a^8U67C8Wdkqw%_|Ef8%0!Fx*jYN|D*8f zL&iq^%4wgkp6%WKNo?ck|K+|XZ^voPDSgv7pFJY2(V_0~83v|1ds!l)JLZLkMb!B= ztElo8$X@zvs%P~ign{97Q4{m|)@f$jFWCK%J$~@%Dg8H#7;{ViJ0_dlubsZ{X#_|7 z6uY0F6m3r3yRxOK@a?X|tqvCt--x_BZ8d9A@uzLu3a(CRG~$+Ebu3srF+tEm%Sooo zD^fG@$@U-dK9|n>zVP~xp>ed`@>*%I-p;waE85@uU7`7dY3H&MIoX$;r?2WN`Yzw# zFnj)qbM1?t9r`+S*JfVocbu?e zuR*|(WqrTfT6unnvH$MZ?dIr{-y)Rne5U$9`>9f;1s@iyp5S!NSb6<7zxhR#hCMwM z{)R4P2iN=h74jGg@e0gk{9>Me@|2+3P5Ym&`%1L-)=oKp+imlivTVt|Q-W6)9C@e5 zI!F3WuEKYR)|q+n|K*$oC#v)txXgcJ{_#)Qf&`$5-^{nmM=Q7nN_HQ~* z|7O1PF!|ApISx6j?6#)A-=WdoO(NM($8 z_4-}BIqasWn)0OQ$yXTl&U-#?|9+SKSF3yXjhmNxTAP6itm?SyuLZn zZm%w%^S<=$w<5%2c}%+Pq74doSH0nCaXDPEc_U}c>y7QF8&*nkX-7%NGr6)8vz2Et%P^n2s@Q3`CyK7U5cXm`ouNPUh*01-|riVWS#ZUUgZr$Nq)0`N) zjbqJU{qVo;59%*RJHFQV>vQS1+$@Hm(C_XQJ^Q{D|7KazlVoALG;+(E6ZW^m_=Wf+ zRIc1nc3K_uz*t56`_d09%YF6iwHfYWn7L`!i{ur2zn;m@i??R>|N5V|9ps0z8*8ZEbXzqxb6ATc?;{#{M_R2KfV2<-4L{qcDAnM?xKGwT@F z|77_!C12*@N8P+r>{fQ`SNz&ClY4SROs^q}M@Plg>reA{SI3^yx0eOoW3*ow=6{nRMX6ACn~_iFmA6X+ zMEy)=&v;YzlkHTw$b>z6cjk1niL783FDUB!Dt12jQclc=sn-^Th)mag=VPxrEA5{= z$IGx|;^NiQ%i0Phta@$Uo?dpx>CDEi2LYF?Ugb>TkXW8EJtDrFd-r*TXD_|N;wBuE z?btl&#icJ>Hf2Y~Ts-3S;f~OS1s2?O@0GOHh1G8CmlFuS9HaHO^hEkf!QbVgTdOmK zYQx06)k0R?+PmSw!iQ^~_UQz0?d*)(x8UM|Mdt!!^1iP8#GE0|wx}q;ZeFNYd-a~E zS9+PxpWV5@@aL@aRNhdfN#`1Z93L`%mj0u^jtyz0@4W7>l6 z>JHoFZ8XY!VQf7AyspPh8Dou-ixp)m6|YZme)kLA7G!Mh-Q9TdXx4f2`)skFcf0xi zj&@liRu!SQW|C0gtR=6LAFexXR^|GN%~)AJeS`2atGUnh7YMk9bZH9zos<$hSv5wS zsgPxXv*{yt>pOo;-iJ+^dNVjrKfPi7r%K%{$r^V1=$3c$i~bzF7q&V6!S~m{k3Z6{ z^_+4k;09O4@tAX~HtoK3O=>&;^fUQ^?(a8!pR;gL#ln)XkM>)f_>H`8ckV9QEq00Z z@b?X2Ax;~#P9^-@|IRsk@d`t~l&#;hyfAxv+xHjscSU6{z35gb zv*xf}t#XzlP+qTOZQCM)We>P*k6rpuE1I)-Yh3tS#TT=Vb}uSYVQik)a*ZeH$WE8@ zv72~L9y}KQu0;HY=2LC){AIn1nS=h!YwKC0Y1eh=L{)3^-fdx*e%JYES}*WAyKnu4 zH*XFIRIFO981el_)LduXlt>Z&JtE6%%WS!A!g8Y7z9|{l2e$`lJr}wexp(Cx-@{9H z{?cqd^Vjv~T}_KgdGADJ*3_mXZ$8m%bC&}J;chSyz z#(T%^8tZTVv~s@dUcSj49*6fBWqmt-iECBpjE5^~Z zq0jl%pFX|Xdv=3mQtiy!^^H;zm2bD)FYdN{_}*Vo#^&CUE?Yz2H&Xm5jA~Jm6~88a zt_pDRI=82V`)cP~t^ZRbZ{M9Xv9q|lKOT$a5h)}=aaktsaj|*c+LAy`RQtrus>khe+hKBFsD0X+ zW8WO^dh?qyCnY|-6W_Y??8|#c*r)yLzo7Hb|I}`uP1Z+GbT3f3emTv1+Z^7Ezxr%* zMc2N`pTv^=COhuG)vi40C)FAu*M44@zzOZ(rc(v}@Da&+t|53C2g@>A-O<%?T+&VYea_X|(|D3!``eweq`u5(; zzookGH|X85GHf(4`)t_6tja$+LW6o3w)yQ1A zdxlf>e2be@AYY1sp1^@(i#ejNwi$jjI4CpqYDwaXG8xx}cdiM?A32hu*Yj=4tsb{I zm%R(rykfc^+!Nd-ymiZMOGlBq2fy^cN8Ku~k$$)FK*Zd-MU^XMOrtiRj2GX-epSZl zw0WUO9@pG;*Cy3pnZtcpG2L^AclVT--AQX)-tIWsdE{5dsv;lmk~*UkKC@LM%N10% zE`FYR{LJm^UFka-4YdE3H~l;@{Z020hiB)u3q<_-fA34WN<;9|lP}k6@1Jx~Vi*5h z-@hPmCLyK6%BoH`e) zwt@Y_TfYxYKfm0Yu63}>zH!w``Mp9>%a>`r{@ndw3w!g?mO0Ev!sgKdPNF zGd51={)D8B``=bMg+FZl?tW@NL#jo(jL)Pv^#$9scbEGuGUsz+-XGEsA}^&PJZ;+p z`*@}AHxw0;^#7k*P*5qt6-IZwrL|C zrUf_JJo~P4J|(6vX-0X-KE{bIftSv5**ZNlFDy>JbFXiXB;)IK%eymIep+(VYt9st z3F2G<-TN6p^@HN+f|y+uFSsXB>zJ7%qidGPi0AarxgG1i%hJ$ z&9SiJ*sLRhkK*osQ86m}cd~Ss%EyS=D;e)>wB)SlmNeGn`0%qgF?jm0gmQ@m;PL-@}(@#YWg2d&pIms(td!`}O~J{HR&;Z;#7n=7UR`o~gyI z-(5Gq@8x*(GH0#DF zD!RSeB2ksjHPM%AzFE=j83zw5ADuDr#qmWG9^Vr0<$8WD-+OcOFKgj0AKi-A*VaA1 z<#C-;%46m0-@z;ACw{v3qrbp;w+J)$gyg=N-`wtP32NdCX+V?r4@mnXIE{xKS?(K`c zlp6E@oO{Hlg+C40waarBu!nRuhV4~9!o#7P^Th12=g&L-W%fmf*IwDSRH0&i4W4v zhj=q@X*Gyk__CFyGo5GUSC2QE)t@ikeDBZjZZ^j{)tJMxco*=C_xuc;A@FAA*URsG z#9y&|vs)f{t~!D1b7%GZ%4M(Z7VmXG*|(;$WQ(25iJGDxoTZohSANz`sLL-BX^?%f z4Lo(VOv+Rx2)fs^zOoA zEfd?@2QC-z$&~Q!kWX9IxcAuX|GP7MPHj(m8|p9Cdg@Mxio~qly)Uga_r%K7^|e>F zYYM$dC~B`h7QE)g+YL*NF0Rl2b=B3^`PsiGkAEDS%kt2z`mTsoMUlYrt5d6&EPJ!cI{dJa@Az>;8*36Y?k^BFIit? zI%{qY3z#%z&cna&FBkpYd^A@n@@nYwnEGt{Y=t{Xg5LeCc1d^s^I062>ijPF^ZVE* z^In)a>mB>ca>n<;Bx>TZXW!C_+1%^?)V>c-EnU7{>7+`DWOM_w zl*%86bUnL|Gq+2av~@!zv>Vb{+`;%Ql?`@~cvOs2h??LWb?HPrm`i%mxv8}oh2zqrh4 zw|=z7$TZ@$!MuB?>wRP-Lf;3jY5M(0G9&g~`LSi0bB-$?;a)-8oX{%iv(`7W3L-=|&TTT`I-C-B0e>35K z&fIQIcI)m{TFV>y_WzoybmFFXVf6L>+uVw)CoVSh-}~acQ~uo7wcLwVIQMV`{^Q*~ zFZf1yO>mpn{;2n>t>TU5?&a1|c_3C>XxpqV6>Oa(DqZp1#rf9k?{l-OR;?;+*~nn# zc%eqs=i=sfx1KSU9mmMmVmsB%2#*0VB-%ZVmFFxnHGgl_rD{vas{8& z+SpFdfEg=U=LA2xeml#yC~Jz*{3DVf7p!L-d{cb5d#c0bMa|2#til%mT=Bz1Rj-w&V>f)Yl*Ua9Yp1z#sCV3Zw3wuTWPjdaK{W4eY-p}0W!99+5KOWlf z?)>iR#hV%T6|I{v`J>OOf?`AM6sa3?SR5U+zPfFwdh?0n%50gY(;A0n{kL7}EM%8; z`@l?r=H2U0=G}~R?|tcexbjt?qh;IiDAfyo?G0(?glpAagh-#f`#kD|<-s+~G8GK= z)48Vv>z423Je2Y&{HWS1-kA{={JjlDVoUWLTtDCI6!P2=ByyyW{atF?tD+?*E&Fmh z=5zi#@{(1?OO*AOm51A(TWV)n*+R9~ZQjCVFJl?TYa^Z>RGXe_TkxvHA+9atKAXtI z(j$kAmriq-HnV!m)SBrfzZUNE>(y=4(a`#m&}#MhL_@)z3$oKE^SCSOv4+b3au4N* z@xA<_qe9@@sIf$xhb`Qs7u5d4HA5-dc@^zr^lviE7^VG5GP{q44V! z&wop7pS{hhoNz90MYF(uCN8_WH%2q=y5HzE>-@_c=GXt_-8vgNQ@zOJ&la3dJK@$MII{#&cfYZZ_o&hXWr)nQ0_w zEz#?W$h4fKxx@6`m$t|6dw$5SDF5v~D`wx_td$8fRbO!=2{*s`CUExC48}>D{xdtD zG*sT{TKR-ISC^e*k6>x4SjP;BweH{S4;=cxX;ShE)r!!AM<%xD7j^U1wlkIWPr9T2 zM9TL9i}*b5%HpR60)}%713Fh8aZ>ASWi(-rarihjiDT{OjF3Gp(Mc}b0aPo8Cq*(wkqg&@EfM2 zO|@NPZgi_x`C@|e93DGl}56xYn+g_aSd(#+@cxB1|!h?tJoxX4-$F|vU$3M^9 zD~g3%{}^0+va>|!Yd5=x|MZ)!*7Fa)?0$OQXsL!-TdIJUZJOXdal2cd>z;eJ9GNTm zVI|8%hvn^8GEQdC&bhz%!7hu}57mx}aje>UZOIFVei7|I?>zF(ocq3U<(z5SET4Hl z|69lT{B6laf&K|bul`0@I`A*i3r%Tcm0n`M-g(hKP2My^UX?5D3-e#kJ1X8066$`O zyLZaVV(arW{7&*(OixcydT{QM@vgTskHl|lnf!+HvGI*R9mk^N?4t~#Jv=rg<`t~>d9@hUw{6h zm_0c@<3oArMnO)#7WSPh-h^&gma%e4cekbb(L2B0W$RNbo+qr8U#3>IB$I1@{jW1$ zCv5)n?Z)jom8MyH=0C1^q;zn_JNZTbR?c2IZKcb>&9PP?m;a|pxJ{k%ppwZ<^G8Sf z`orHszV3g1?=*LmIDhTYled3t47|eVo62_~K}}pRF;$iCqUImdS)X1Pg#-&t_3#ip zJu%R7_1u&RA+yx#c%(0$xo=l!Nj`^)|*4emIs*_AFXA*^n>CTwp^ zREWvyY$oksy}vsn?4qtj>Z=@`99es3*^?IwuD@gXwN?Fo0;9u@=p1qF;9?__WqnB% zwnq;f{QdUZ>d5@&ITyLPJXIC`e|xwmuB7J4QPJm&iwzG?aQXJ=HL}+x!0t>CqLpNtE&|bjH&M~!awzEV`sM7jn%vat`h%8_(kiBX= z>r?a(ruQezT5me+Qn6+F{dM8%c&*2*yX1~d4qL4MXVP^Uz@#d?#yJp$yb?3kxnxFj{+a`%qXg43q{#x~DoUa7t?Pi9R!E4PHF@JX@Bb(`0cyVic%<T>0=&Rd7jqdf}yFHE1XOm|X#u-j*Wx3ZoWcyC>qlKAb^#JTsyCm+4BI(G8v&tadI zna#PsEu=d!Ga$rvil)r67w2uGkC+sx%6kSV8omFs<<0xwKX~Jgxkf51KV@coB3xTuPQRJp&;Nh&vCdQG$=v=kI{MF??*DjO?(eh%JGH7yb~kQ)!?oqDlBvtS)Rwc(*1sQhet$7rLAqJSMS?3r>~{Hxni>3Np_9>p*3;NtN(G| z$(tpRbuht6X4?F{oXaaUZa;0?WWrmKzD&oLr@t!jUy;~~BVY7$7R>!K>#Nmo!;}4!Rxtw_M+)U=KsC#p=8HcPA(QNjZDCYk}J= z?~UJn)Zbek-_U-S`*6~#=Er}f-#^n_{-=M2we-d?WmT_9ETOl;oT^uIM*e!h(j0dA zi;G-j;<>c2Bn^3u?2R3N?`{k z*1utDAYPPCUoX_?Ml=aEc~~CrT*$q!E@f+Ht}m%#8({s z_pqB~UZm2B6su?1chlE|FWM%z@AJRr%RV>tDtDh&RO@GU%3z3)`B^@pg71*{P2p6d zmln|<{{4Kg&F$p`3B|Vpk6IL$ByU@p{bZVmNP1gYc$JjOzNn<*URfrIopYI1{t$SV zb7tDS%YU+$g|a8DI~}7MXy=N(Q`pO3HPNZc;n?%H&#k1OWewbdV%&JaDl zPwIqk&5nC#V}&^9^XMFAkDumrU&-w>E8TzKYYeH6)#a0@d;D(6y`+VIS}gFwIcnR z_SuEoB-qbAj#}Nj(J5G=bBAH9lT&Knoa21`XTGhgOuYPfR$_ow^Gyyx&wqx0=R6jF z`&yMX#WT@6b>Wo%b&HIzwe-1vV3%xBbl4I$O|JJu)t(#8#tmN^=2~ApuBs+=>NdZ& zV`bO2xL5VgcdoN6jLhIx+~p~!!J{;f`>p6pPJz|)1uRY6GK!fQKdh9#VmZawO?yf{ z)B5%+7nLVIO%&a(IK}g5=+^Ghw8kKKGa!W{Hx>qsYi}4-V}>XeI2n^ys|yy!u}`ceW&@iT)+C^ zDCZhHPWaB)wvX{X!tC!Qm^z0_b zHEW`F+uTqp4m8`xV5ENH|D3-q_0w;PCSEJudgX+Cr^ULaf`iwdXFmzrF<;}{=go{A zWqb7=nmep&TR&m=s1?ahtXX71oImz-xl*-55TQY_>sUz@M_ z?;roKrCUw9bIh@4%ggFUXRECOQ*5?c%iXbgU$r@EzMr#X+%qoe^}eZ2?zJ{)Sz0M8 z69mQnJYacteNnYW`oh^u{x_CpbHD5pC@EU|hgtgKChx7y1uLEwRqWz&$eC^OeSSp7 z{|8Eo`V?nYYxV9;)~S| zf|OdprO9g5FM6lGZ}xqjGR4WrH*N9nhjZdCaV?*(RFd6zE>&#a1L>bC%jdrSvTl#v z?hOBBX1}|pe+{|xworF*{v9>NANN@$BLu(a@XK+jq(70GY^3|UKXJv@@X7fbj(qW0 z^?zNgS4)kWdP4aAwlxywKC$oIB7Gyc1)QvOckZs;+`*(TQ+z8W{_@+U4I$j!_jRI< zH1%!bvc5RYxPxbL;acSmf9I^LwQY?$t61XQ&z_zlKfyTt!m7>HM<=j(o^cFg%CS|+ zV4dEcRQHi-xp0$I>dS2(=DTiPE&YCizO`OfHn%>@?a=8yufi3}m{e}u%jj>gyyEqB z>A|(%Go|?c-&vfnc4uhvmnn|MTyG;I@+bWbxYBaw%RzA)oxQPpCA`X}O?o#sDm~yw z1Alf(PR6h2PkJV8>l0m7vuOI4DN27k;xgJoZhq#R~NzOJ4Td zx4}f^b_ACSf3De`od>UmF+A}Nv1^_!)o?0pFOSTwRV*{zKYY4d{CkGjT8Ev+OlR*Nysh>+Yu77^=j1=qyved0vH;`_|c_ z6Cd|1P1JudaheXoq9#Jv2!D=#TiW7Z!lESsU5_<%mSk^6H_EhbA--3sS zR_}I=($>m)sMyQ1zW&}Z=F3TIwhQtz#&u3wTXaJ~w710VJIku+4Q$6gM!#iw$Wr$D z-UBvM*R%6Gat))G9g|G|$&>U%(M)M(RA5TB^5RW!N{{mia<9L);z_2LI~Zm9HiG4D_$?F58lNq;t2)J)O%+ z$7HKy&t5twz5eCJ<@t9P)Sg@!IgM@V!`ELr)Vc*Xd^D<#=QL9+kG#b+llAVL2Mn!N zyC(cMycqpXVET+SJBDHtPP;=n4>JF5e_!XkX~CQ7%~CgokNtGlFgl(sv~F$2%$0Ex zhnIBkU%G@x!|vO@H;OtM4}vDkr%h3qDEZ_-a-xpKnS2g^;2`61d}Dr}(>P{-4Bh#hx2&!Hv_16q<3H3XbgH^vI-KoM`?W(|wtWS>^7_3m9B+6ZyMDybc0T7>W$%N1 zZ4d6Qm-&3+#!`jTlQsB_c4i+i_w!M6)JU4#dQ0Z6S~hF{uD7zgfAYEpeOoOtX~mDC zfYahaR|K{n+&1A)bIu|Gi?F}XAFywWdr;Uc&hT#bG2d6S7B96_7jkx;8Zck<>!!aB zt3L`aPTzC-?W3kGx=-%jU4L3i$JOY2tYYKd!--ShDmYv+Q;Fi{+Z}m7gt2j{LTIdE z1cyTAvb6o2cMWSi?Ld07t)zOr7p@82VFJw0RD3IB7; z|DHI_`C@-pd-fvx=CykBV*Xq9v@r<8nDyI8-@IjZr}Bbd3(pEy<>Y`3gbb$*;5_G_(_X)S{7~UMe=}y8!!)(m zAKuNM(z8*<;Y!`7X$vN*eEa#_!qg(C&Skfy$H{&5F=+pbx+e=}{A3E5Kk61^=g*B&c9L;HZzsKAl zDNVfT*Y5PY+a^Sa-DVFzyzA2(rxR?EEUATZTjnS}ZkRRqaKpp9(to%ZORS!q{qZbm zkDAR5rE@vzo_R)_cSTiQ%8pyfZu9Ky`&8Mw<(1V%CA;c!c@DRE&eL==xg%Na`BC@c zy8QG1JAZ6LxXim_V$($V zy7-QHs`&a(ag4T=^tUzoQ^RQggg2il{CIxi?I;CRaT`{)gsjS)JS{H+cDpIRet9IQ z=-N*+hU&`iM#?qUFMeTq+w-=g`{l)t@>WYm}e2 zyq@=}_&1Z8{`!0FN7uiTve+I|`7!jqgw5X2_*VH)?)qJ==H4Fs&lHuf@z<*6KK=7@ z#e})Mg2-bntpb$bUiPRwN;xP`z$o{Im=UF zZ`C;#%lDLNckYakc(w6?8MFI2@jt80Kb=UvXM|sB>hB+ZS8c%3+tmz~SL6zEjpb z>Gnyc;5poh51O4Uxc+q1hDX%v-qFpocw&32?LXHcqbZN|7I@dNmN2ti+s^$tCGc#Z zcW5H_QL%YnqW;)vw3o@r#73>XcDg|6V$V(K3GWi;{MhhDyKcs`;whmH4^p{|w|6g= zJhtC-!O96APPobL@6L=~f9#XKcjv+vYkF3uuehu7^4Pj}j)k`#tvckPpu#qjsppho zkjAM+@zY*yP(NvXLuSVHLmR(&U%7S9W@e?To<+1Kf4{j@-<8a1_3xgQzSsMrb(tyl z>B+s<=Ken7*Twc`M^x;m?-%xq$^1zCR}uX7$B)hZ7v@*4Y0-ZE!dC4n-=U<^nrp$T zZKk*WPwi!s`|*<7DJ;r<#-gnKA}KSbeEKN7GhWxSvAg@XYUksx9mzX_{`tSN+@i8o z^|5GWpKF5S(aqe4tXJ`Hth9(f@o&FC%4$yCq=vM}^(QrUMBVjx$FsPzc&;QE54)On48Sa|fKc|EzE{*$^@9kb+ zk>n}79?zbq2D;yLT3_}k+r|K%+_jOr^1->xQ>I=+van-LfR>qc} zK{mnjmyvY5a>W~^CDT{0Sjh44eaI!(a?vo&PZC+L4}973W|munZpfF*l68eKaU3qn z@}=)r@y%P#G)-KMSxiyp!Pz>Y(^j3%@r%B>;MCdNZx-)kUhHpP} zJaO)HUys|Z52mwyTa+qoSiE?trVv|P)0|63Urt=X8^7#q_TPhARSpjmKJo4FUnQ_a zPx?>);@1^se>bf^urf^jg{`PQtKy*o&3FD&_pG?Fck<5Xjk!zz-Z-lI=H8TDALJfC zWj!LL_-B==?!hm|92<-Sv>vLvUjE#mw6$TMuJlTy_*BKOlM5IBTbn$WbKK$Leb(II)ye+LhdjJi zn{PV!>t)!xgu8c-y;Sxk~2Q6ck=NH(pdJ%?nj6D?uTqEug$n}%u9Z9Rk!Y*Z8w`A zF3&sr_POa2sabVSbI#Q}X|<~#;eYb_{#mKebtl8?i8cUN=E%ByOL%@zGmdVDu+I-ec7bNT&=SDBaZ$YPu_eG|jgPazuV4+|L^9g(sssQ1eF0B9ip6(ypi)`78osE91lZ+5F;|%CaySr*T!^RTrAm8j=lWX}oyOb1# z=5!powEk`I1HrkcuD0yBX&rmzsYui1bw6)w3h#XN^yQt08c*)FNS`r!vwxP^ZUbiJ zQsL)dOyO=Oz{2C|YLKA)t}}_cS}_zp&OhS9ZDu9$IvPujz~w zzgQmg&Z|ie_V;g#n|35g^XKG$O?!hHV*^v_n6_K{6*+FzHxIJa2`YFaTyiG%?@rYd zTuV#!GvRs8*Ygi_|LDo9_rIoje9|pWpR$j<#|>Bo<->0L8VtUVpu`oMVm7T>Z!v(kNqDPHH#pL&t$vcT!0 z>4LS<9G8}H9Cf&t6?LWcr{M9U*VZyzdh|J0v7k*rZK5F5mED!27Scm+~pD^#^ zEPja#54MF!KS+Fk+9;jr!h5MopDof=bFYhEeQeHMSu^MON7qnxSeT&pHRgKMyXesKc-#Q*7*I5*qVI)3416zM~!ZB#yn~{0Z-+driM?3Qfsdo%ua&%Hd5**lyI6eq_kK)Mh$SCqd%% z@yGw=Q)WN#s&|W9Ftt1P@UL}~l6&Sn`f;P+K-+_aUz6WY)HM~KwchOa-lth#q8hKY z9``kk+sOU1oiSxu%F>mevbV_vzdh09uA?BV75=g9m)iIJvRC`dOm*CRbf2xd^Ubs5 z;>)6=pPi>(p7uhqZReLgA12%F*tg$gX)IIf5|vBa=PQ_M=uKO=D|z>Bt6f^nt&-;Y zKTj)9x_phN$N%fo_LsR<&(t@b|9yk!y3pFqnw-1e>})P7Fuu9=4(s~PBYi6m3wAc@ z@7H|ss-sIn_NmbaK5KWszA)w;>V1v-!?M_mJ)4a6ul+VUw^uJ!WBysqmvgRZc2Cg! zp7C?OYRJ9vHw%9sS~!cbp(!$C(%G7@tRATbi|Au%&EEp2ny2|~D2zLMrn*c`GkMvv ztu1Py*VK-cNBa93W~Ui!NOGOLY4+M*dU-0-8>^;=_21|A`@H*H$Dw@j0~hpqa?d`l zo?i5+N+9k+wU$+6S$#ms?8;1uzEhB_D)8U3%?67~>P+Y0LFXZ?wL9UnWvk`(63>RO5gf`(8RGT&?=?i*;tL=FO<^ zO`m7I*vZXZ6ecO-?afuP#^0L%uT*bsK>wSj1%it{o>{i&T*h+)uV2-Dc4ji_k@&HYBC0L>fI7czQ=Rx-QRy+ zRXg}iuf0*;r?!GcT0B>%N4Y z4E6Faw3!{c)17U`L9;na1(w*cA9tEO;jq;rxumTpZujf#bv3YEaO=L^iTW4Uv)k^d z_es8G6$~_y{$%z+@r!7j+@@>pe~x>ck4RSZbyH_Jyz>#;L!&uwxOT*e?r&&`@=sbS zcKh9anS8bV@Bgw0wQ5OcMswZ2skT!jYhmz%mqNRPldLq~OE@z8eZ6Y+R)x?8`9P1# z{qLVISo-wWt&RSBZUpSVa^+N=M90EiGasgD81D!!`+Y}jeeJ`_WufzYdG}d;o$>IW z?#l-$2UhyTPF4CM|7PjY2Tp$_c2_(K;Ixr=GxeVQo~M7lZ(!JeYr-amu>9lP;iuTj zzf4m5QQjNy!)G7st`eX7GnQ%{(%3d_-`T^e?=qbl8U641OBOzuvnQ>5_F5*{yD~mE z+O9s~Ja=a5;yb&ZvaN_WGv0jemWJ@vplc_CSSKG@U3EmE{^PXDe?sB2e;eMdf8514 zjX_;9Q6$CsSnJtmSK?+T1U?HAOjDE9nZdT@OnDu5PQjZq7Uytm8ag6Vf}%TG?^ z3VpOR`@2H0me{7oFH7EaJj)16FZH>-sO`kdn{5+W_WWAE*z3N|(gQCZ34HK>Q(t>p zQaddDN~+$kw3U5%6XvGdoYqM8b^0-@;)2V!y-yha76&tMW-v7D{C4={t}Dtq?S8L!(TQ*Co0s!993=1-O8`b&l4Clab> z)TICHI9;7}Z@1^Ea8}EZiB-O@HhJm&Q1?=u^EB?W#))GJmZ3`~Jo)$`Iv-S)k_cx6qlvDl3de2MNEUl+XnA~4lD!1L)fX&>e} z>W^!8v)_Jda_7x8k>znwIUai%N_FO5@!=P6a=ut3CHDK@Rt7x>qs9j(tyavx({fEs z`fwTd*?WeOS}d<7&pmlVp!kq{S%BI8)rU@OkEu6s)tl4_-$-7hK4->l^=jS)R8)%`e+sQk!JqKjVCvO!J;40qy&zUXL~? z7B#nz*=??5V_f`5eSd`G_P;vkB{aBJ-C{hszeaxJ>AA9nFB_cq8FoIrsF}pfToQVF z+T7z(nj7zZwK^QVIoYJR+3)Y}vtLX*pC>b~xZR+s$M~^+|4r|Who(Qd_21+72E8`M zk~jnBcay>d_$}qCj4WkzUqyzV5MyOsTVnEuxn;WO4cE)XCr(7HYmZ;Y@_6gIqBPYk&3kXOm=SrSeJNUv`<-;K!}1kC}YE=R#+5y)mXGD!o~@O7%5oeR$HVJL@hr&hPuWjg{G`LCjaDj;SzK z*I~QVlWP~Wbks|3C&YGHu&%XxK55q@;S>%x&&?if$0MfycPsw2&q$?m@!4(@>%^DU zFLzAOTfJ@$OY=PQg;#d0e8(?P9Oe zmEAs%V_NYKwMTR8r(JvypA>Ri*67G>Zv6wy35|uz_bd~x-NhkVF1C#Sz~il2R|@aC z?AiQzwsCR9N>Z}HMQpWk=dz45U6TBz{faQfvt zzgx=Rx4trbpL)(|ABR^mw~oCw3(M0jcXa$>*K|rf{%HG3_uB%|HA=hZ1#NJ%k^QAH zgV9Q1C7-;2)&1NLJEb-y|Iz2nFj@F!*ZY=<$5=e)tnIVX`B!CAxu#m}^o4B4*p)lJ zy4=fpoqhJrgn1wL#j)IcUwdQ)tNd}vO*u@d8$@2J?fm*2iCUYce#*|Pu(uzynX`85!jt9ZQyf?}Ox!kQ^H)Q~xedP8K5ulp*=6oxXT6H?y>akAtLH0@ z3(a8+T4cl%Im1z=g5}>wwk(~HF1<-P@r*kz$vJkUX<%U_#_w~}5alQ6qJiM@F@x1dFWi}twICWydM%&=0?R!sdef9qNtmY5ZE2Dz9tWuu+ zf^s)?6b0ZWfdKj^9!D?)*;d{I7N4ipf{yoo*tR_*DArdoQIIEKu-i zOFil=AamAG$1uLYT3+{oK#Odz*Zq9|CZiLV^bJ?;oy+$4$|cvXwY@qMbnZqh4Jwa~ z_fg6DBJ(ppLMLjUZfmsnd8SSFPo9+U8?R;Er&aw&dQo)e!xc)0Q&TKY*d%R#E%|=W z_wL=lYEDGwu^+s!w(W%Ml0PSf(@ ziK)HjJy+T;{C)7r-7xwa=m;`MdEH zri%A}YNNc_iZv~BfDnb>*FfbZ}^&@&X121OyLhRa@xH>_fnKHWA2LNqP4}_C$GJ%_3GWr zn&O}(2jg#OuU}!7b950y^-W#*2Xl|BZR$SBoSSv_7cbt1ZyOl2F z-8uE+%y?z?$4q`=Vp=)Sx2f$dvCY8izhAAE}#k?v#Og=2@n@o!Y<8 z%#`!oSJn45#J;UpsmgwLrfO$leZ~dzjTu`m^?aD{Y~ifOi~r5o)q3f@f_&d5zms8G zRWoJD%GJGd&UY%xvMZn`ePbKwofXoL{5LV@o&-Dl07u3z#Q_GWMUa*EYv0Hr4!;(8o=Wd#9YR2&) z!PLuo!$WQHEmzjQXZ?HpM#uY%nYV9seu&|k_4c0EJL7QGSDi^=rmWA`w>`_#s=30j z$>dgGPQS1DR_>Da(~HX=>{o5w$@_d(=kos4i!=U&`AyHe-FNT%!CMJ7PVKyRm5wXS zSjX-!an|JB$~&4z+axzz<+?q3wM^3S)JnnYOWw`MnDwCIv25;!Yk{fDFTS%1@-Gie z+jY3iM|su3OB=6AsqZP@Fg^eO)~_1D#qXq9*U7icoM#*wcb<3BVNVqF7F-ir>>YPa z;l;U%jl7Tcta*O@%-UlnPKkdW*Hdi9Tu%|^v_FndiSMynF zzhs$Li7x&3ec{O~fq!02J@CvsTt`H6nc$sQ&C|@&-W!JQnK>)hR{qFuhS_PY%5@d? z(Y4ZZzVL>Aovbp?`^Kg}8zX=I7dg7fsr!kBWUtlg4ICFmU&99%SSv+&EZ&~buw#|3qOiDYhm;F()ndG5<)6nbs9@A|b4_sJ& z=Zo*jNdm{4433=(D|o1-U2n~(a$B={3q$OMcv07PuIee1G&~MkMV_8{Q#>iXWCO>J zKhf(M{5StHyVsd|fiZZqePX_-cu~Ad`hn$7E-RS7^D+B&;n~;ue`n`bmd~raapl80 z{oAQN+Ed~m%8J?F>$=?aDKX`5(gNMpEAE|XTbsG&!atQWns=K%JeT?M`fqc^h8?fe zcW*u%y7@pr+2PHGNo&QW<{Gc#z3qPMWsvKWid(gx4}a<2#j_~oPkqEz{+4+YL!Fda zHcd4;9$pZ3G0fq0h~x`an+dGxA^D7-TK8oxO*`*$s;42BY1#%gdppfjk9SOM-IcJg zYIWqKgZ%u}R(uzw6QAWe`!MFc4f2A+wU4^(mpF|lZP)9Jci*vcY5ufv zN?zo@D`%(wJ@viCN>2Dj+|Mn|e)5kmu6o|OxN7z42i7)AEI<9)!}h@@T>bD{X4^-N z&Z}NO`*TXLcB9#cy>G-)Op;c;7S{Y=YIi=&%{Pl}dz&Yd{f^nYPP-p`^OAe(*M%9X z9#=%t8GQ@|4`i*WU3#vko}KN{zAG~;jPjm5=+?Y<_Qa%HQ*y3|JY`xvJM?tkm1hBG zC(7r|3u@LlQMg_4QkKiPgBf2HI2d2^uVI$IZ!XT3vF~F1p=_1ziSO+hKC`HCH|=(^ z$+?i3%vdCGDCS zN}iIeZ!yoWe43DYF0lEflcll4r@iYxNG)6Wiy+9AHj=GJl7 zm8q4>dY@kq?`(BTt)G^c>?0*8r?vlU;+0g@-5dPo{VCg{*HN@@o%PwjZf^f|^y1UI z*bn)ZFPnd8-iuwv!p(1L@?X4A^W+uMUB71j%QIH}6)f+LDcKt_b^82j65V&ZHD~&I zPKN`(8ZA==+~!`|GjGP3y{v0KHvRkCxXD2*P19MOZ=%7*!{R;_MK;2h?oIplexkUX z*oOoTwlLTI_g}Ea>}&Hn`pNZ|wPjoKmSejOzwh31>(~PeN6XnWes8p0Dzsv=tH#{S zi%Y~Fq!pSxDgEe}c3+!&$xZib6%s8*3uc?9{g`*2yDjc&_~T=@r*vG+XpUYMRh{Mh zVY1b4VfE_eACf-`ok+ZNI6(jDw~NeTZC9)8`7@VyZf%)Wa%Xbs`nu+qAun?LQkJ_t zU9H0M^OBeNvNgw!iKo8xD9mO#FY-gfcaiNgmSCGG=CgklcM9{qam=oD_FumD<)){J zRou(oZHiF&X!5@(^y$-(Lf_*XRHNjs)_jlPU6|3jYjy+cWQI!%$|Jh(uxxK+8=5yGgH zEft&#>+8M5Cf!Qqe>$OA-{_@K=T7hH)At0szwS8MEd8b+-0L^f^H{xYa*}m%j+0F8K`*`oIxNfh(A0(0OIa~M6)w>UVJLEif zpUQlEdv{C8z7L*3J~!-AL1Wt2I-?a4456hp4TPMHw5Srbm|5B~pZ*^&%$lqqE%EqNfzr5Qha^U@@S@Zn= z`@LA^{aT>^?<^IyJ@H$LJ6u^W8npG-` zZ2vU*6wOZD=1^a^YOlRgvFe{wS=B$@FSy8Q*I*)~`Jt zR(@Z3=~>YjrM9cQsz#Tu&p0LC8sFlk;dJlGTBaG7+ibrE3V+x-P5dOY_q18ze^d*2 zLv|@oQz?jk9kE37WF?#In&8HL4lisETZZqN`tqmllIKN#wtTOf?C^F4qiaXC@}ymt z|2)sqc3a8w^fKeJ==D4HxUppCeu}Y>cC?TQ%zkcayH-Sq$AD?dzB9~WEZ0_)N*wx^ z`uJ-MQ{TSjk#5JP8NabE-Bh_g+2m(p$7OB)lfN5cgb$s}i0S3O`FFA7)#J5#eoXO&^Az{;;b@#qo#onI0<6^ z5>IiLvsm%;(APC$>UY0Pxo~-nOa8&dC+`@ah|Kky&*(ODHs>L0lcHyNC9kE!B|Vh3 zeDJ8X|IZL{X|6%V>Isbx!jHeH+*tPhPOrp@`mV2{mEsKxb7O1pu7wbeFIkSorBIZn6dF0sci23Z-$^2>@FLJmxt1h<;5{jNX;X;vU>-1;ED!!9#7^0Ns+?jukOFQdJ{JB4c_L{d}UzL(|zpS2d z^Zu8@$90Y3j~=n@lCtGX-T&T0f-B*Ypy28Iw%wbrE5Ey`_4vt@9HqziUes&7)hjrE zZ;8OFlh@K0YQJrdQ~%v|d)iQ++Kyw)yVh=)vix@6 z1^tzBSL(Cp&y=ltFEv?V=U%sqpXcRs>_}gFv?qaal6%GP^rN+BK7YONyGyV_hV94k zIRC~q=Nb&w-LTmG@TBJ4#-)52KCdoxHJq8Q>if;{#@49HpA5n}SKB3v<$DD=1s6Q! zxF;v}=W654AN#&c+S(`YpX%*cq1pN3^PbZ-#)0Z@f7jo-Bw|wf|BhJ3>7OgmHM{cQ%0oLmZZUMuHNEs#PwWqS=1zk}2VOlpm04u%?<{bp z<7w(DZz+o)(Y&VnZc~_ zD(zRq4)4#mt>zRhW473A+P!3@=O$(Uh3>~KxnGa^j$9}73nepyp zpo-h^3*r^28~U1_rO#_QyPy5(n!@0LxI zk*v(d_S&wqI>hYez4)a2rZMFE26gim`M?)B&+olGR==8dH6D*T`mpEQQ4!x2`?=mZS>zmloNRRNRftq8UE$|^m7^H+~91ilx&*QIEE?1Y1yT@LHK=ye8tGG+I!U(}kiqf2L&i*x2__M(Pa z`_IpO9w)}hZ8LxI@$L3@=P%r44ZiFqUYQ}`%=`V?d(m|JGUi#!B#1v%7+Bonr2ogZ06C9^L_0Ken!R|H^UY@X2$^Qw zc%A2D@%9FM86Q4al31?=C)~2366>T@wWV_9}9ouKG z3%Sjy_F(UlI1gogO)c3Ay|2%mKHBo?W!pcl{uO6?o>>bYXJ?8^$Zg6?e(t8Yl&RKsw z{A!*VWAU1Nw%|GZNjHtcTMxf-*wD58f1w1=gd?Z=BR+;U?h06)-KO?GQy|?_^ZH{J z^^;#JbJ!ez7A9Y=i;WH8kvG;`ovZ@l)2A3wAjz)!kQ^A%vbL_U%7i_()u^Q zggTiNZdJG!_;7AMX7_H@yH$>g2j#L;OE(GLv(s-EuSlID!SeJ^`u#P}8Cjd!e{WyD zr#7y1!7}d^9qymvxU#EiVzoH}WvkA$OTP)6I%DJAIqB;{ME7L#D}GS?@g+_=Bi8AE zz$NB|U%pvO7AtQkEofh`w88G0 zzeNOk7)u|{SYlFhU46xcMU&5MuUNFb?_qPt+g$;M+fHx0|8=HszIX{wTb4)5yc$0X z5s$4!Q5sPnS1%X+B__V6eM=zgiJ+58kv$tbW%sW%v{a6GW7st1>{_J*VK?Q{=eUWj zp834EH~ew?(PFz4-Kg+A40f~6wC8{N@l|(2Xyyj%+XfrOmR;@KsKI}EPQ?D^Pv7FV z6@E)U^~_|3o>ggt%CShcRdYH2bu%crpWYY#{L?WL=ewsDyplgKbw{RGvYvBKM+8q5 z@7?!tPh}L_HqYqc<}(Y?$#~|zP3ZdRGmqXWD=GD}TNzLO(6p=Gb?&L}!CzZhEY!Tu z)F{nme0z~StaM$nZ`#dTw~f>Hik!Lsb+uPwQ1tUt3l7%rk^BDD<=5r4mk(wz?4P|Q zLeEjMYEi_;_q$FC-G5cHCjQ8u617D=3_{!UW^eddv;O+wV{AOzG&(CQ)vTjF&v&*#wQ}O zereYT%(k8X&Cfk)numP!*#M*1+o@CS1*XnbUG;m-a+OcYF=rOv*&CF;Yvt>d`{&j6 zsg#FmPF}TQa_=Wb*_pNXp01d`q;i4v!`rL!ciovS;i2~axNTYKza{s50$f+Riz=Q8 z$TzSG-SObZp8PqFzluqj2gcrf>My9WMQifz+!seh)dDPLa&>hq)%$d;F|N3&*^Zeg_8M>*Q~tW^v#vF=roFz`06Oadd%0T=pZNm8ObMqK7Q@^I62n&WT?_kWAFi1)OUg#Z{pZ@8LqV7S7s(y|_igujwl!w+c06zS z`h4bHgOhJu-|UZU=YIZjd*J7@%dVTarSjN(nQ2=JNDcEDExB%qE!9Lv;C#c(+{PrVGoiyVWrzOr=|D8(Y{6fKRLrK z61#-i`?80t51HPi&*%!N()q0G>7!d)x-C$Ft99K6+fWmODVJ^iGxII$qFp7GzWnkAmamG#m#?=NK;k7XAXOlaQ|{a#(A&05^x z!XKXl2mYDOzAd|gdDV*7cei>it=ev?!!!SciDXyV#Ghd`zCTWr$>GUSaq>kGkwsZcxU$W0no3U(% zl1&l!HD1<~=}+$KC0g!}o3QlK(N?cHq7&!38&5VmwXo}slB%C@mCt8~UrY`QKJ|7y z(z?DfpXJKQn`xSwXUv1Ir})3r*txW~z)W}h4fTr~uPvX$_}XHrYiL#+-_!P{3Hu+s zxX(G~{I17G($(f{sor%fLM8HUD$69L4N3?9ezx2;$L#G)(fp=g0Z)bg6^Ci_Ycw@V z@HQ@!UH+%^!@n8)d&@4JvsYN~Qe0Bx|CW1SrA<$KJ+&ye)3JAQ$(4koI;{t^tz?RB zUu*dlv$JvU%RaAZ($c4F*))A79(uHVj+wA@_iynTb3&Z-g`yE ztF_}wc4>K%&DZ@~6kFcEe$m3>nO(KES-J0PSe2`8UBad9VYTgn!RrN$8h7lfOH7rv>PI_w zh<{kO;(mQmvhkZY|6*NZ3X}r;tFLr3%(=i?`6mB=;%i&wy8;Huy-uf}FJpeXP>sFo zYy2g@PfnBiBMd$oi9Zhxk~i>k{`9|SR!GRLiIEoHMSd)lws6Y+ym{Fh){L6h@!plY zc_P@uKL;Lr`gHE$=J{n|2X0rW+An_n?rZC3F8u?MFQ&UCRPN-wczklfjVCpe)27Z{ z(z`?R(S%l$bOST#1#eTfrJRyKE&KX_D_5YL{mGpwN3H+8l2TEaYh5XP{es(~)9GnJ zCJl{2NvC^u?>wp?&^zI(Jk&$s-$;HuqdWGU5 z@i&tmt6k@lt8@@NJnzM$_4+=}@)J%@yusL9P~_P?!@&D?{rRZ^CV5Xw?Q9Jf)cReO zDOuT5w#_tLeR*49wA#h{TX>kw53R|VyjDluo^Y6oyiIc3(J&{B`ABuv zIoo5}v;6&6U)x@LXn~&u@4mZwQ$1evJ6TT)oN>W>kHb%M+aI~Qc^ctQ&dxb;Bes8op z|9+p;*60K0g-(b~ciNIUAzEtg8Z&OYe-abUOk*{k|9*W$#i3U$tMgqZN}uJaOTAUF zbLoeB`AIvkSS+GY5 z<%wJ`cJy(y<@BdF*9Oes`D{Atf=u9@8)qK|t!iI=)%>&;#Wzg0ttO_ltH(R5$b^Ra5dy_qq zzj$uE>0)$r{%P&UZatYNxi?*ntzUZ6`f3*6mYwE@PHq07b%0m6X7B9$R$+OG(4YC2 zMd!J&I=wHvcq_tf;-wa4%}2M^FSK6$;>Pmn`$ZZKS!Ico?fyBL(W>H@;um>_ryY5Z zzO4+3n&y3Um)er!i{p0p{W+TU>zr3(&FQ}zo_9}iSWw_meQ(9Pe^%G~FW;#5;{KJU z#e8JJ3Y&yC(q|iO-?95G{i|{PUBb*1$CtO4T+R_OOzhL!I{A~~&pz!B2?t!hG@4AD zxnhogyTPA)pB0R{f7OI$zY%e_Q*(8&-Ivm88L;q`Xz`gkscF`aT<*DNNhS8Yc-ne3 zyi56}*y~Mei*~;4O!UjWqtdXXSzoEg(#86F@uIT3!S_S|7F2)vkYkv&Y~x8$tK|P4 zi(c}-7O>Vk_)6QYt!5H;bX4Jrt&jSDbgXNQ-16;uh0IsuJfN zczJFFTR;=rrqJu_rL@fJ7dE`xy@}&gZn(h|A{(qB!am_WG?(4tf zY@WHVQk{LPzQW07j^?FPa!y`w|0lNEqjp|1(>BHPALOUcDcjIoksLX7 zReS}HYCF&KM1hXn%UTB``}tP4`)2(S%J%VjpZ%OeS18<8aKcX$3+dfo_XH|W7n`#{ zF0hHmd}CC<70dj@1!u20hRyvk|I|NK-N}b8E#8{)GRaN6)3c(!Md+T$cFE$jPepTP z9FI9&|7W_+s;J8TDWcc3?96v>@rvv|UC$rN@%YL&i5z9o3x~=zLbB}ad>81xy;sP$ zpE)x=STvOXsLo{`JNG@CGwitjZkfH+_ShAT&28Qs0>2i%iQF2ex5d|Cl1ni@I{(pO(!Zm)H%Fo^h+F3(Zb6>w=O>sIR~PC@st+jnUl;r;F& zeQdq0tL=*ow~U`xy#9OC=+iT|^Ssu7r@j~8wsCgeI>wojwkvW=g~W1~Uv{>fB@&9!NJ+~7MwcHIcI()bFc$CrByRVM^i8)#0 zx!{68;FBvkZ#s(YHZ~xfM)5Yb;OPi8rp`lMemI zbG3%^gTxKqDoYldnZK@>$uv2>mUUnADPC%$fpc<2e0NO8s8s%dr@hmEwoP;KIq|J_+T8sswz{1A zwddy#HMe){4;=rkm3urRqDw$wz)*m@txG16W6zyK2(ujCV6J6%hb)w7~OWhTAxty<+=HrEi=QL^V_`J znV0j~nP9)@!TyA z?g#a^{x7_)uWR)G=Jc{@QmiLxw3Lq=tvvOy#>rrE{+9>q>qV^ZM@?URRW;dhUEAW; zPq%(ss3@?%O;`UK_02crTyn`w4OWdEJZz$GHcI{a^_8W#XHtq6PyRj!;hoN0^GYXg z*wx&5zO8!uQWfDw)(PdGxe|+{D`G=_e7N>)-8{?U{?l7F{jfje&iYI;cePK%!+j4! zE+pJI`L^xF+sEMzK7KqCE$j@AoIl{W=;_BRJySiFTdaGxvggV28pV_fx+6 zCZB0>F^qZdK9f)ENNnO_3mqG;bdITSZ10FTvE;e!T%Z`NnwYsRm6?%c(J7udXUkGq z%YMbDGiMbmyqx&c*Wj@d_bvAQ_1h&C{zh}BzLpH#%=R?xiR969K^nbZ7$?5FSMqWH z$Nc(gyJw$@PH4N-=D4okX?t_SnJx#h_1+47w~tkC%P*8!DLTWXoSAvD`cV<#yw0J3B{vl4jZ$?bz@g>blYW7mDuWTW71hyAu39Wah($)d$&s%#1mB^oFWOoSWSh zjnX*{n!Jnk17G{HXO(0gU&sDs!Pd9t$p`paJ3Af-^Iz+1 z*PWYnE_bZ#U+HCR+A0M^8#P;t_xT zTkM48zizede(*VCLEygIM}yb4YH&1~LVUtE-shgW_s5d- zwWU0sJ6?rsJ14W;W-CvQ*3lHLG`RoiA1{J`vu+lT@)=Jo8d)v2mhM>|5b! z*4v{#{@(RIYK8h?rnB1}c%mn!=U%oeIP&O{t=amUUnBKD-@V(a?)^wOuZ7F@$M+|n zKDzORnz-J2*{yRRZG+DBw-Ikep7rfpE&jadu)FxLl#dMGBhJ6l2~M6To#m4p&e+?M z7L#DI@y>JRJC~%Mn}jXwUR12tbglTl_?NS@E!s_K9%2bNbgi!QYt}8sJ}19EpT6L)2lcP;F7KM|+@RVf^5y91 zJ>d_nI2T*-pR~PO-X9_1UD)+Ae22vfw@zpA^MCsCj+Xt|z4}IEEH6V?qxFU8^?K`e zdCuj1fBB@Z{pC_V#`C684)Hr@=kJt}-@m2$)Ak)lH+nr-@cSXNB4_Rw{Q}pD;IC(v z>|-dLyIifPPhwW(wov~)CiBvwUg9EG|S1pa*ONO=dYRgf`9SWkIm;!7;ifNHGZSZB&i>N#STxq&?+i) zmi4>ljeWrrMR<%I&->52c7pq@$lEl}u9O?8;&%Uy51lIbcqnk?oG*8oUX(Hiw zaaH$DI~{#5kl81AXHp>Rq*C_S$8k+!x30I$Q@EG*VP<*Y{@RO51?SIi-f8?peX_sw zgN-Y0XCJZE(b?Hw`AwoJwVr+ZHI*FY$~0dd)|fTM;gufp@;k46n^P|O`J;S+f9ke} zJ*P7NOc(fJcRFz2ns0k7lcW!*-L&-nQoa6AepkWv>s=ww?i^vcIs5R6pm!&8y|^?GkEMf&zVdZ`oY}pWCyCbckG6N(jH~ z)P62zNzcrwDq6Ryb}g9tyQQk*-EGBP2Dj_quqR(&ZIL)`9sBW6q|gQftM7r$JDbvU z!Y!nKMj6dqCA?~`#6{Pb6I18@uG##4DdWoH3If{9>g!n>8uWY{ z*wTIfEt6^&@4m;@lXI4f%-(*6-N&Fa^EBJyhYG@cD;L^LFnc>$V6*2J!OY6D56xa| z5xM>~QAFVcYj~4hP3!~LKqf}rC~vu+f9uqYLhHhJ2)C_OSlROEsnC7nXQH3>h;DND z!K72~ktA}eW&d~E6hTbMDi;HH7&wrQDepFaL-R;2AYx*Yx zTYhfc+2ifBYtk+Kti-(m+hU5Uf4MB{Shsv<->xO=4}X2(%23B9C4G8&&e{5&T{n*3 z_fJ#dx^=b7*!t6kH90xUC9;IK%sHcYt(&9b9M2BE1s(Uktqsw6y!OKF)Nt(=e)~4J zYV*78m0QjHeB-xg4F{WzUmf;NzBAz}qxrcBtCQoW8oj!|;IE*>%9<*U8X49%J&b`Y z#@-F)_KLStSa+BH)SNfCxiC1392)=zb|2t>9`1TbN z(fp2PnZ2_=U;I3OPm`}v*TtouSZ6wLr!AeD-e!Gyj{g6HN5p28w7q}AA8*Wd+a>j1 z^*Og=eT%m46xz2%_1>|o$Isr8E$7(%;OfL}4T-%qN2=N+1pO|U6jnB5I?i0MRe3L~ z@ck$2jn1k)HvQZ8z2?P=+#@HJ)T~(GH+}W*05#L8-;*C4jcfU!zk*NJ^~Sl(t#a)S zO?HU^hOcyFy5EYM{`Zt{&@K1AdvBKbQVmzd)xNj7{w(;odiwQ4sf(A0e%oD_%p^Kp zpXc!1iu$xy{k>}Ey;`d$hCREpW~+%=>?gfLyagP)g_VR`_nv5dnZdbyHp~8{3zqIr z_ifJf`562rOI@h&;`4N0-@NN{b``o6{+HI;vtHBIEhD;YN72k90-ItN>h>L(pS*tU zMV_qVx+Y?V3e0PwW(jkwNH}$R?y^Y{HS)Piw~cBd1RonM|KNOJ(fYJkVXs1*LUx~K z_j`9|(Yb>@%ir7&n9jcSpv9+jujda^dM)jDocY(j#)3`qb^1nI#^p-4u6_95|2*8) zT~7OPTlKlfV~0yKg1jEca4JM~?q^i~TGn|w(nkHt!6lv(CY$b&i?)e4#I(8dZb4n6 z2LHK0?}^u>c57*-N`;DZJX${gz|Lp&C))h~tr1$X=FOhHX4@=8L~YKNt+};R=1Ao& zna2<2L?>EVOj;_kEqB#AD=r2Pr45UDKGesAoR2)3X!-tmubN`-O`i>C4yY+6%S!z? z5gGfLL$pbVv1!?-b`GujAL_R@n{qw!IdR(A`KEk7OnK6@%X^p_{>t%8x z{-%OCDK$4%?>)#F6Yy#CjnvWr8P}Y%&T9$`^&QyzezzJgGOmo{PPuG#JSYCecUQ^$ zW%mmI$V+dRo$=?PyIeH$ce!G|cay|fcZ+1&n}3X3b4x4DlV6od&~xe|dCog5EXlR2 zZ**Q(I3SZT$vK)yZkqb;Py2EJ*0HfRimYPI~?S;x^2_#Jy2{tN&enmU%fRBnqDvTyT3Xz2$e!e^&3gm-ZX%m(sdX z;C5HE_vP%vChrckG@kNbHYKq6-mkE|K74`s^6|$l+@vS;_q2bT)%x1r)QEL{R`bU- z>&;hOetYBl@z)7w{XB24co*=7rO37WVb?t|mcI;V#R{)+>N`5_+8=q-@XsgbqOw`3 zyQ5-?AFPl#QT1W{_Cpi$p7*lfmT7)F_0Ti>?2D&OH<`|=-e1baqCLM(u4+L)SAv7e z=DPfs>qJ)?J&eD@^KeDyHFI0jc{8prDC*uWd7;qXBX{S`ri==Qpb~HWE8d%5r%pWR zZFBlk_mUSY87HVo@I6&|xAEQInX_(0<_0hGtH1cxCNkK&efkM+Rhy-uHjAZ;{_$LD zc_uSGQ0;-eX;ozwzyG|@J~v(!JrVEH#@m5R zg8yf<=gs>0YXT&1as=L*c{YJfqqF~SvcGKFiUmvNt!#O}ye=~SMn>0{!$Iu#4{e;f z@MPz2!M#iq&&9G{@wbo&u4*~HL9hRn#lP!5KTYpx{QA5?!>h6=&V9G_G_m>{?!4VO zjPG|I2y?oTDv-9aX?FFxY0GyoC_GTzQKB=2;ieKR>%Ie$LXXsywrDR%SX<@2%;whI zdHH9`k1r1@vN+9f+11NC{LbZ_PdvSo!(2sY+x5>A*%Wl{#@6kBqTW|&c|LS?bBW2| zjXGRYWSwQq5tyZB_UUiUq~M0DuS%y@#NDWP&OQ4=ocZ4LAi0W(f?+55W5OBMOg|c5 z%-5LG)A(_nuwkp6t{C_bMwNth)PogRHnk`lISe0q+=^ z&zfF3?fmCaSSJ&os9#A-=p|0Y_Wi$H=7y>B$FUUb>(D*^g~NM&Brz` zWyj;DQVl}CW?xD!%GuN~&GA^`FWeZHM+*Cm-iPw<9an;wD{y@?uF&MH|?mMHJhbki?~)F z<7t`LWh-8sE;ADIg@e|kHw>^xRy_CTVHPsy?ODLge{S`ja%EQTbpO*qDpR7C{dyB1#CC5rgL{>ItJzD1HwN z#L0zC)A_uN!>Fq?Ty4|AM&K(}t8E2KG8OZjYe#U;pZ|`9h{U2IiLZuDDyyibiF;V6zG%cEB%d~vT zw~$2->(`$vec%4bZU2JjzvnR8oNamAvv3z@o92wqPX#*-?z1<=cq|Q6C|a_6&8qW4 z)1JE3?>$`ivc~G|ZIdUG`LoUjvR`aJp|bAMnP=XQtXul7v1BA(6xn3*d~4uAuV9vP zy=&K(tq9-K7x>IE>Gn^bKlfADUDq#^;Lxbq@b$K}zS`}ccKb=}D)(bKTW{`YT{8bB z&%7H9lLAsEfB6+Q;cd?;_h4-v*T(|lFJ^y;X-bd%k$=2WCoWRFF?Gquc){A(84(J* zCI=*x^d4GJd}_u=Wy6js@2C4o{<@TE%8|0OpHufWd+_W+<;nZg+ZB(e(M+&uRaX?g_ey zu{Z?h+gHS$m{?)Dfa~xY=hQOu6AM2!;I9dc{Shn71`;FPZ#Y7k=t{8>6)cV4{xuTZymVa%3?Lkt7Cu8HyrN}?Q!4p+bQJm zAJIG8uNWKc`5VN3*lPJd(Wb+-*;0mnX`<=N%>*4IIemOkPvwaVkIySfXmzyQIr~0Sv1^)Cvg^$cYnkGwoj?2a-;$h$QjWaDr5|4I zjke;y8SC<+sTe?C72Cr-Tg?2bCK zc*>Sf3!htiiadKEJu>JzoW-|#^EM{+AIb+T7$UbNM}2eIsa-3pkn$vKvwrV4 z;VbWas`59do#r#n)ePC`!%&^}!kgPHQGWjJY4ao|`?#!;GMw_b@6a^f`G;Z;zu23R zUm3K1%97dhc_doz1pJ5-cx7FftMjwbN}VMz*W=uc!_1+D3$JYDkCU-k6`a5q+O^fv zD`)+L=y{2LO|PTB{BAasu9B-`E|ka#w)qlqI(WL&tRs#_6+1;gPTapM*TJ%H(u&qY z^5*MBu7vH3In>Qwq&NRW@auJ)K>{~-o!h=k#INs=F30T4QiAWyZf`Jq(~$9Kja=dG z-B~P*=Wh8-vog5U$LqCUA-(>6c8(HX+M`lkeY?2an)kV=Dq2R*Nso{LyxGF2zGI@6?GI7GQ` zulwoOuO@~~NN;<7EWb(h{_i@~rFYMiKffn5W!md`1)xK>I zk(=?xT8`0tyS~O}jr|)M*IDESzj@ysXUU}@q`Ya;uB<|h(mPk!|CPQgJy*H+)9Rwh zE;;jbf_oVsOUkVN-_~iM^;^JJz$*SvB*XtlzvK4nH%-{};>w);*W@L#iteRP4HZ5y z?TKFLC7aJL^yFAeqb{kXF|S!=vQvS1(Vs<2C(rsL5-)YeSngR=0T18B73DX7XqWC? za&-%HSkJeO$;`G}{Z=TMyz4bNvCLX(&87#u7ngCdeN7Ty)UrTj$~Q+9)ugu$?Pt%W zFZ?ORv-QWUxAH$kPhRml^FwTMiFtnepJ=_zl@BKE-MccWDZy*f2mkZd8gsA8U*4^I zs;;)_1W&N(3+tEKii*Gae=hxSDu~1Sl&;IlPV1-MzZC79R;ivA-Mhy0m&4&L$I{;O zu4t2ZyPf}_ocQg%y%%QR7TzTg&gR`D_ReCR+O(@v*S9NIzWrgl=#J?ZZI*S{VmT^x zw_6{I#h!bg#jpQwvf^TKkzcK1^J8zl%(}GxL*SBM zYZugPGMoL~_taO1wPwPmEqwd0=uH+6Pu(Mb^v(*uCe6b^@6ULi+}q_J@tG z&Rw-Td@R3{e=AMpSNhwj{1NL7v`+&x9MK|OIrA!iY;rd#Pr9z7MI@HQ2u6C z#|e{*TPm31Y#3*+F4W}w*T~AZbLBnNZ>}-d#jCuxzn^;l)U^9b>%SfE^<*q?o1nv; zym3bOkp=#lOj?uT9ba3qURz`Gz0S# z&l79z{o$FdF5>d~P!UVT@`S$TWt*le+HGDX@#I>-WuFNrTNe2i)^akpKL32Pq+!DL zBQMHMEG$wn)Nb6=e5HwR$GI~)$&4@aKQ|t=R(*bN^DHyLWnuwZU5k$0{*h|L!JPQv z_6@$^k_5#Y4QAau+mjNF6b>45oN7zGk{$H)DUZM=W!?FgD=Mb#yJGpN=EVQfPje^|mvM-n*?_`ljnyd%DP`*YOSuL+qtP z#A-iVKk$%=&@2D^Om_FP{JL%Y{(9V;)AnnL%#XWzy5rt!hU$$fB`IQUYAO2_KWiTE zetKrcwxf{(ySl#YR=9L+(nY?*A!+_XJZt)I9d5Bx)0^{+ZI)2xWc5TLZ^d~B|KDRx zT)gm=0Nd*(-|bs7kH0>@u5Y52s~q#q#3+3oP4kN)_r71MROZla)fVu(^m$Ehzi~wP($kd0Nypi?s&_|pzfECXrN+3RgX?QT;zSR}p1`Y% z+it0J9c(=7)Fb@;k>y;u9Zy&t=Tw|2=-PZU`RE5xo*IEY8Ve4uouhH+ar-L~rU=&G zyA2p?yf!9o&^K*ze^#gX_*B`<6r0@s)AuzF*u?9)ov5uAeQxR3w48lS$-zNTC9QM&hJn&G(!KX#fltUR3 zh09JniQe+aF+e4JflrQ%a+cA$%v~F|^Z8x3?8-gb9cxo7W0l4E!|VE_qN_KG zJrFy6!#3?*zC%uYy7rBAPv-|D-1n;YW%r7cQM~&j&){5h_lxvj$zl8)JMYC7v@csz z>0~;ol{-BzNM|ELuGlA#ZH?S zNpBvXsdfC#)$?dee~Ou;19x$bc9*yN?gyvc|7J|;kWbnZH|>>5*={DbC5k8K{AF%D zZSiRW&wh&|b@MJf*(f5oeS_YiD}JYVgD0vz$m^}`{4ZxXp;!Dx*Y(9MvY*d7yED}) zu6z4w>Wm*3nq-x|k3DEym%=__`_1zI>kQ>@Yqd@ePEktP)Bk^BiL2Wc$xj?@jjH;w zTV{%D8c4{8Sst8NGVR7u#xIqx`@cv$E9;Cfd^YFJh6NW^I&F|PdFc5{b(PHK%B}Ke z3^plAHJ)t>*U+nLcq6*y5Cniq*TjcHMhq;-bdNp`=?FYP9|1M+eo`7fE|> za)`z6s$cR$UFc(WVoC7EH?N)V1|NOH)G<@~P-0zEeq}mWep7+{eAN?Et&*7Zn8Q0_ zOT%*SAOCjC_jv960b(C-u3AT)0Jzt!IS0P#q%w>vzztn|1tjEGAhEyLoP4M@1MAU_1*o6 zx9U}op54>2JWcPkVik8;!u8sCxtmMUI2$&#*3LU0^~@~K#s0)sy{R+K&T)RP^7K&V zwx`wq9xsWtc&u=TC$;{vxJGcJA6r|Mf4P&miKh7e6|H;|eXCkjnQYr6Pcu3{d)TQ^ zFLr84@19qWSgNiaVe)acW?yxFx0H4Om(Q)>I}ITUj+GThzKgd@OLu;5wej41slG*Z z?aQ^YuZrI=h2B(&kh{RO=rGICl0Uu{JD*DDig}uK*M`llERbK}HlaPqY})e8M&Eod zyKgaITrzdtE&l^Yt{t5E=;nKU=UeKM^~_ymed;IoyxOb1s6fwqONRIxE-SGY52l2u zNOZJvJ}G2Py*=T#%K|6eXoXslcYzbX?AltIsu6tWaPL&^9##HL&Kpa&&75_8ombJn z{($!;5_T`-1%t{SF`r_4fA8D_6`Fh zm?^h@(x$9`;x*3SPBW>i%{a-`wdP0nRLf5@z6zT2=t%AF%U-+f%Au9#gOfsjY&Rx0h*L-tVE>^&-kcV7>7^5r3UG z|8-94X_npezNT_ECr*&PBcsL9Z()$6NAjPCdvkl-_P%|6OZ_wJ?dmrduJEj`SC-Xe z`>U;)GvA@YOGxPBvM2Stt(}S9j^Csra-PJty??>zqcY?2uFdV@@`rM^#Wk>IuGUHM zy;VQ$XvvP8`%&I53fFgk`KFPrdw8}X=W?yTZ3~!hF53N-v&6U8;qJk!6XM%_GF(?A zH)S8|T^KcW#fRZcBLh?w+6h0Y?5kl7HAZSzLwmE_10HjoK!!?wK?4{jjQHxJC~MM^}%l!T$Zide|+j0 zp|#0|WmeN<(tf#E+8Cq>x`>o*yK{zj-=P&v@$C(vTT6@o^qfo3yVO42t+r{U%bwq* z?|qpw&TLn%j^yT@Y1Q`a;LC|ub(D{eEIiA|px6%CKwQbFN6vfXrlR=4BYDZoGTG0Mb}UNI-fU|pka}bC z+1fabzpW)L7Xr0*n4L?v*)l63Ecb=p`~S}km2SP&P4d$^|Kopzc(%;4?S>7BnGx4> z9>CmYPY6F#xcOZT~6u}9^?2~GN$Y@+?! z#G{jQ(-qvAvp2E5Id%TGXy});Hs9rC&0&nU7C+>7cQ`D?Z5f`ZaFyxn8|VDie!F#d z+LzAVAH!^4`X}qdjp&5W@~(oM8Cxr!)*hbowI+U&vy1$qS?*Uog^sy?a4PO7_mYwc zH=X(||Li`u1*a449?$+KeD`}w<{cfCZ>JB*EdTji>GM0Wc8SQ_4W>zVTH1uB*c{(% zWX6BXU;VtmKkgS#^4`YkzMRq?!|ly?*X-!Md9rRvujWqPzq#Ueu9QLj7d7{Iw%;=^ zs2!Vf@U3`8Rj!=N#XG^-Zp^)(*9uMy7PJ(%+#Ax(Hoc^BSNM4yreuce);={NAH;i` zqI$|V2mF~O)_H1QYJ=m}?GoiLUTSdo+5K7Pdgh&%zsxG-9n*`Bs$405vAlEp!*yBr zuguX~btC#j+_9;?#nt-)wx#lCdf1zbU#nW^&KP*+4=c;1YkF^3U%xee&|mcG=hvvH zc~{nm|FU+onYQ+(?AN{Br+4pCS{vYtf%#Gg5?A^CaBGac;Y+q>-HTTh}E3yoB zr|+K8I>abz9(|*yxFPq<%pEy@XE%tf;_ce}#?#lnrQvg&|MVX@-USMG?F6Oop8Vpl z!AAZcN1xF7hH5T6bd3EpG*Y&F=F~ka= zf1UTvq~Pj#zJ)7HS@}2eM{2TVp6INb%{j|>&5dc-a(8c;)FmbTgi*RiYp&c5rqJ9E$SR=eiiUTjr*=>Xeplcp@Ssl*3~MY-i1#`4$x z8691E-um;T?5A!sHnCgISHETJV$q(tVWC5giL9t(y62${+3(f5BT`>5gjs!X>(!e6 z?fS-o|35?2d?(FlbTr`6nXy=nWm;BCr}eSw=qU#m#1t<-x_`^Lth>`9<~2^+x_wG@ z=%lG>k8>BdU&+!qQS|HFy5wK`)z_Tzx7>D2-SgO^g>OBUUa{}_p}_EX;vGZnnzwqN zwn+U=Zs-XYx%)?FHNWik?o{{np<>&vF=>^^ymJ2fPf5yKf{n%KN?(fA*RGkb-xl5Y zc4IZe$0t*dF|+7A55IElyWUNML_5Q;noBJn8Q5*$Qwmjh;54blXQeB1L)$#9J4uPR?=<5wNDQ#o?mLkvy@#iBkZ5%j&E zu$0a7SBNttZsFs4y7$)OEB|V4i!k!rcND3Gt3?IwdcoFe^2)BtJa59akLNg3{^!bf zEjjai-tArqjW6>1&ivV0>iG9_%!aK+i>GXK^8foLZbp@EhDg*p_UWp7&aYHdWV==P+%+x5j>*mJ74Y@Jlnbxyf2>}Y<;iSrj*-ppSiJ4fo%|E0RSd2Vv%#Jpd= zFXClaWsLH|mv5}*Jyid<;md~*iT`(U%w4i8Pb6-2k(AiJ@92!h`Fx$_Z{9Jp)H*g) zcyuf?x~{xIwxqnrZOf#)`U@DP#nRSs|FZqDq1?sDsYiNo=S1_I{?=E{3l}DB3R=6~ z;h}ek=vTiNiT|Y@wAhUGsj@n?*8}!a3Gc zXU+DJ-~WM^S@&D!S}SHQA5Y%>0t}35LDITc>-r8{niwC{QZ?=C7Uwz3j1CFj4YSus z$Vl3Mt!`#TLP#VhW2fKC$LZnoHg4Y`dn9YmYfahH2NHNwL_-g}>J}7ywW&ejUq#Ri z&6u=6Y4&YbrB^I{T@W@UtWd>HcA8x~m+^&N(oA(zvlXk)m+YPD`+}|N=jy}#7ShKJ z*0@J6nmZ-v(-g&fPbI&m__r~4L>5jF2#puGGHC^0+f4D-+3Q~0eOtEvP|5NQbHX!o zm`zXi94@f`zw+U{>b(K|YN^>@_I@OhgL-7bTkO>*+;mQvK24_P+E3?{G{;3AC-rQ^XFXkOxSc7)XTf*Z*$MK( zhaE((7cS4Ld-`=*`O0S#HA3X@Y;X{&-o5{yYD==k-alA*?8T> zK0EKbPJ16RE=XB<$^YTRgXbByE@TsP7V>?|SZ)&XiF_n#*DozLIMekEb~F`v-In{pFcyepE=n18tO+vrjL zIZc+h-A<}!IX=fd7C$2Tsxq2ub*jw6n~9U{&PL~~IqRb3cs|Nx@9qWnO6?2QbE$G{ zv{g!*x^7m&ma`?1J6#H@C0wV!sC;l+Sydpfdgm4WtR?w=mVaf`3vS$Li#sOnm%7n> z^XXXsO)pO}%-OK+QSqIJO$QG}-Z>WJwpQA$`{v;-y~(Ec9Wx)7D~E34*?Vel<9U-w zUrL+erH`xMebnIi|Exgaj(ax`RIr#-mXF}df+`L{C*mo*vQ z4rvpSnrrRyXtyp)f61>&hTFF9(!ZE;ind1M_UFE}}`e(MT=0OVnQ)D?C97-y4R^IeI5w_McKvH(| zNx|oP1ris1^S%G0Ft~aCgYW+3HxBWwSo=ZN^;lQ&pM28_&Er|0rtD^Oh*2z#^9YhX zFlX)TNvG{pmt?N7J*;Y>GR^h>xtS}L{OA&Oz2lzI-S#`3%R?f0$+j4`D~WC%2{Wdd z2C+^`Je&Sq+`@+A#ebbCpSLpf1$dm2>s-sfal+Ez*_FEXW=-$`G~$emMu=3nM<-#uAfx=C>9sfSjlq~^U%+}#_nCUMRe_Fw+5j`OxpPt2QW zxq{2T=g`aA)h_(KPT9@e_c~a1+&de}94)jkmp9w`L0PvH&*R%(`VwK%i+As5O)*!{ z(iP2Q5q!LVD);Y_8ikX`&Mo`=BP(`+pU&yz!cVjQCw~Yn&AZn*{eEN1?A*}o;DY^q z8bWLSimr7Px0_*W#`DBS#Bfp9O$LrK%YChq20fVV>AAAq$9sRntZO&e) z`n0Vz=9f>M(ptz6uUS<1ZjG0TsQNb=#~Q!E5r}=Yb<)ViOa=`VL^?q z6Qt*lY9Wf&fcX-oc|~{C`tt7b)y4 zJCb|v7*E;JuRRSs>Q|0k?cP|tu7ArOX6v3R9^*H=T=t7fvHYG`wrGyqhd5TJRjHn8 zXKt9duXldcQi(|0~w{pjI^<+b--9V#nGIyUEX+G#zD zj`qbmb1(JJo4LyJXkG-j<<#{(o<2Lb-)~pX?DV6Y|`A?nP>cNCPz7^qO&)CD)ZBumF*s}jeNwJ#q zqASlOx&9>Hzk5PsTg$>XOh*?#cv+wzptwll&=KZ*`}_mB7yVXiEB!n32Oi|_$VcZ`~l1 z?SJCbBOZ-gjXYh`>(li6*JaMU_CDQMKFj^L0_U^3|BQ=wwOcNJpu)%8HhIQ6UDY$M z4l|qIZTNff^38IO&d2-r*`3_A(uRrA>D;2lN5f=vf-J;aGZ$H3cQ&l*Q@o@-%~^HB zuk7_NbHh5fOZ3GpZ}?Pj;z`zkpPMeEfBDE;)AI=Woi_>aDwz)LkU?qV4n=mfAy$=1ZRQ$&cOi z<>uiD*FUSUIOR`t@ayqjT|7nT$%JF)o*6}kMU|g;r=tD+HILxlMU{eQGVGZ@U%SB} zZdd9(jb&rZ4ujA~yZPt5x#zXh>7(GVyBoJeZJx~f>_ZvTL(fVXr8&#W`5rv) zzhpYCn3Y-NteI`lKT(}qo*L3t{_#Jihqqpxo5W~xM)1;yeH^P+&TqMLcT452gFlbB zDyBIpK9DG`%UbTBe*gQQ#`rI{pZ>3^{`>Oux)sjzoD3w+NQfR@Sv9d>|A9;SXEqj2 z^=3YPSv+r>S?lTd@~`h7nqO*Ma;CmH>;88Z6VA_dpQX>#$^^UG{#mhN{rSHxyDpg~ zHQdQsUMlb>DC^iBuNNvDb9LK(+1aq$ubee&VRq8{t6R6#ln4}mn7+|MSNhfVFFMaQ zuRG^tF{zvJ*y@!6bC-VE!}v4(oXgptDSKoOTb~RUe=6m?;f74llf+uPx@{>-Yi0|5 zU%d5!@b69SGGBNt>;9?fF-Ltj_I`P)In1G0=c&ok%Tl22#I}8zr8D8QXzs&RQy;Y)*A;z|aeaZpXS?q{&+q=9-E=khdhCMl1rJ~Q?>Q6y zaL%lQY5c2SsNAedaW#^z|7q=**Swy&@cI4t7Qtfmn;H{cm3O@JF}|>9ap|JB^S9pn z;+AtLVoKQcd11zKo7?7^O#hd;NbMh2{)Eh6lbEo5Z=>FRbYGOe>)+KM^A>t=YYQ4{ zUC+yz>dRY@^em8}<%`O<$ufU#E)90m?QQR>yr5Dg<-Vg%DfwCEl9?y^zWMa*TYWa^ zQ;w7XyPOo?!HWx*>s^_#q(CI;!Hwy=cc!zZxiyd z`;_roJ0sT>2`YEuH*NFV8@J>|2eUS>n5XRaQn6_kO}#?g-=5mvGC#Il!i}@)BbU!EhIZ4*+cfLW$<{Gn@MIGIn3u6-$Nrhqa-vHU zem!)wy_%qy!Z_DCa?8e4rlm#>(MOf)HO1?1Z1;?vD)3H^&9VQ(oj2T*tr-hlat(Zq zPqf*2tvN3h&uumP`0Ai54m&Nr{Y(0`MOd@V-QI7*v`G$M+h0w+D%gKr^vMRzBfnRs zWV0unYTK%-B0JaX^M-C)r=@JqPrGq&p9}H+arEb#jn7{Or$vdd?K^plX>yFH-`a%& ziH5JV5;^S`Z+IKKV(l3z3I0USH-$T&ToXT0Gbh91p{IJ)Sq*W|ifx5!CTp*bQWt4j zl(xoww$ag3H9rrni0X`-=&kwS;GD|;Q%;>JJGlClZQs=gljawt>|1@LELdRQ49i_{ z$)BzFEWa$mRhf{q&Zp+bZI}B8FF(<_JE3uHhPsT5=;~Y*yK0TLWveCIqF=^^x|km@ z+ShE}Wa_ureP^zNnDe)X+b+&D5nOaAaof9OecQiR9Q^nW&JYoh;O!UKD(%y*EzH_E zSLD~U4zBfYvlV)M(iX3{{3Z67_G@vso_k7XMDKc;-tBbp*&ds*?1`C&+Sa$h5jPh6 z`SY9UZe~YTn%gG9hG3!RqEB|-E4nj5C+4sJme3^z`8t6b0%?!BdY{xkeHUZbSouZk zSN9Vkha)n9kBa_n2uk|u95O*7L#{O1Jv0AH;_38~N^#bNKZ-xByx&%NUVXlC+f32F zuNXrMn;%B$Ui!73yKP_c{>Q6)*ITuE?uu-waF&L4J;teFl4LvX8vo`RPda zN{L4|_Oh-oU!|KIo*2Y>HYog~+1FEXJw0k1eY>0LVuTic(qYSKUvmAoTGn(HBmZUQ z)7r##ObVYQ;n0|JLHUZAvG*S7S0?|b{#vDWDLM6$Ta(zFxF@^H7w(<>g?HkSMCI&? zV$~<^dn4Ibdh{GE^bFnccJky!;-8{7?fxFVWa`Gc?B!XWWEQUO}2Wn`;|?O*FKf2 zHuW2F)$a@N{r6pVGPx)1wNk+r@AwGOJDM?({7(FGkH625J|Vi_-rC^9+5Arjg+8S^ z>wHtZAhNaW-?A3QHL1>vt)8d+<~RD9dx0%uNsJI{@cppg0y$5<6q)UR9<+AipXtw5 zt5zSgD|cV4;3PgZ{TSo&tc**-B8NVSaAmU9UU+A_WXf@six#_;)Cz^Z*gt!?Z^_~L z{J9M0UU1J}QW9#q_178MC(r&Qv#p=}xvz;OOX*2dXo9PM(Ao*?`{KDy+Aofnuw%<> zd!C0ud&IdONyqpsxxk+>eVxyq&9z6~Ph!-zt=zLIDRL+0)+vrX^Cx~*bd#}64m>He zTgGwU+E&9GZ`5|W=`=(Y%scz__5t~MnySBMESq$DR{t*R&&M9^5zcw-G2z1L-@4krG)^|x9Uy^mcWHtN4u=1KCca=VtNgSP`u(j{9 zc-7l8{s%rxIXqYQ$#!?e$ou&nk$WRw=VV-X9?g54KQHaEn&|sW$4x$OnR83gCQ2dW zxcjrhqv0}Z*WNiH`Eae!lZO|Wa-AmZD&7ByacjB1aI5``wMXhh7vG3b+x@la;jCm4#XP}n6Zs$6aoD|Vb|{sDih3+(GHIrMH; z-+X2&)-eCrQt8u5W`|l2Ci=U~Zan8?_@qQJ=Xgc&`DeK`U31QF`}-nimc3Nm8-;4i z-v>9`@wl3La+Ybzap(G@lP1^l#vhXvTB?&SxF+_Y^i?KdMfTq9>(^(SI7_asZ?YHI z)UC13?a%j9*Q#rHm2f7d^zTI#AbfA6f#SKkIc$=dZnwW~Cj#ox$5t<8`zyDC88daA8^Q21Y2&G;pm zUTI%bLYHwYkMa+&oZNEezSm0LFM%(544O2B)r!{h9IZ1oEpxl`{;cVjhd@FW^Z_Nx6(1l*26Y2w*2SPFH047`Ye5PF!03Q zSZjWPs;#2eX6Nrd%l!XIq|n>wmfw7Q=gz*6?dJ1{Tx?`BHMBabSS#t}pIt_iwU$kv zwBIalNrKzHZ($Ao0qzS<3jHlDDtX`kXfBW5pR1cf^nLi5q~7ao{}JAF;SguithwfC z-?aThq)%)Xs+&E|A+Z-MM{= z?ER81&onhZnH{~SB3q6n?04z7D{4rt*+a=Ott1*c6fV=FXr;}x4O+M zOt=1#5YiW3Y#w#vfp_j|hKJm>hqXmTb=QCV8lSAV<81kt+L#hC?R6FryNr~Jq>lBz zef;>qnG@T(=h_5)o#>Z5%Tn>GyROfzV4D+6Hxe!h280AkzS{nHnpIi;$1Mz&@lTgJ zCRMaN=3gs2=j)2Z{`AY0uRYB;R(B-Trzs}i%`@ezJf?ia!>_(_LF9ooUG+D0^8fL+ zCq=A2@qOPdkNiJ85;yn{%wF}c^~f9toy?_dMVGE+>AQuQEB#yXyZ?M&n6`b6gNR~K?_+?uxDB+>QY z*?&g5Z=THy^jPG7(dJUSgpb}lyKRkPBGsO6<|JA1dfx4@_7gNl%uUJ}qOVTvmP`#VQIJ(=zm2uI(>;2hEodvq#mSyqlJ7+%N_<7;G ztG)4^H-|58nVzBi^!iibpp{>=g|hBkZg#yCB$9kvR(!$nJcj9?ukl4hi7(&wbdSjrq(uA80=duH>_&Wtm4f&e?Oz@9g+-seeXy>iHOI<&3 zo3DI?^0dRvZ91-xT-SUQFklS2WOV1M;Tq4j!)b{RJB8^ex-zLam7$Ro*iX0E#vuS{n{H<$aJS6a3P z*8Gn)tSLTlq2uLD?@O-}E5-NEmiqrr;eOzcy8&07H($J=aAoV~!~gQOF}Ug8e}8tb zueGlHg3>Cfhs^t?3theX;7pv%qWbA3w|c=7n1?o?>`Z&9p1qH|U^f z(GK&ZGtOVw%4Wu&-S=!0Q`f&OkEhQ3`sDu~))g)1z2?RkzBZaMCr9GcZZGR3Pdnq{ z??;tB^ytO#6xKDkFyCLV_uo!VU%W-R=#`P+Q@aDci$BTlyYJ=3=`6uhF6X&jaE^Vz z=Y;dg$6qcoFk)G~I-~8@SqqhkQ`$Es2$uc4_~+H$l--jVbw6vaP2Ir2r9J)fT-B<_ zkrDzqAr1k?(T^V9eMJhJDpn3=awzeP1}{G92``CNxij=S8j8Bk^Sb& z9lAkA9J-GVZDTo-R>g03=#$5PwXPkpJ^iH~FIqy4F4*|U7kt#uU<}ZIviG5`N9wo2 z#CPi5C7+Du@hI;XyTbeaQsLK(i7fhU%P&96=!(|s`KP#|+@U>9`RLpKi#KMbu8*JM z*0iYY*PpDh|EiP>le8~7b1t{- z-uiyV@q=4(nliWh+uZ#=Raym zZJ937XPI92ac8~P-HASbPTt*FF81g8?0+`lEw#JD?{D_Y(34j^{=ew+PH}_Iv=e_W zTBX~IUz%gmBzh;X9L+S2b)a+v3stpyEb~?84&D$AA9YV6j7G`SYS{ zF~9$9c)68B$v*MDxQeOPRxQbCDRx{>%A1&SW@z5J)coCKc}CJkg%h7`0(Y#)-gm35 z?9kq}#it7H7tLf8ZJ2si!_auc1AVrt`71qh*j4M77scP+^QioH!pzQeyV*icNAn+K z^t2w_JbS}L|7FG(Uu6fkrJOu|`p=isH6n^ZZ2N;K6K8gmOUC|imz~mQ zczMLPUJy&}{(2@@U*qGm`ySo}ZSZ%Ddz3M831G7HPFr9WP(zU;Zrc>Et5K$|>3!iI41!IDej&)!ZbV zSkIsterRgpyz7QrH#}SChr1-a8)8ow6wJyrRjBq}w-w&S*;Dx3d267Y}IKH9TU z)aS^8=H8RtXJ%MirfuhYl2duOZ7)wn*elP4#pY2ihW9UhDQEmL&!-`*QD#f@#cwvI z$6ltsINo>h`L2_b-pe)3F5*a7_}oy6k7>Wi>iA2mm(3S{Ft_>Cv+Xs`M+GImEj^4>rDjV06WMv=jMlw~L#M^B?tlNoP@s_efqHb-4X)Je<2sUF zN8Nmvto7dcUf`U?k7v7%-!8fG@(`<-YWQ~h?23I!!8JBHCO`hOxc%x<-M#xce0)1p55Q-F!_Bu-y`R5=LI&NW&8Jg3ddWPsi)bl`FZExSl(Ng zIli}aJ2W2a(enxV_5Y{Gwe+Z??uBw%^+N9KS$o%WX-eBp3^4eZ;t=xaE5GUupN(F2 z(;ZoK+2l9;vd$HrRu&jNIr&7R`T>u-R<2)9e~yznkhntS*YxD-#slx!FX>wGuS|QL z?wZ}<@`Xof(~$=nJ5N@MTyh9F|0yL`XQ$*-{_mZk(XR9NO52NxZ*?iy?#emeMJeAS zY~kuH3xD(Wafqy(_PEjH%nHF}O!s{3wyd_d3%Go$>6ycv+!sb08Q!kgowml~1|J{m zOYvDMiHldZuugr@p>;PvYyD<{2|ukXYwKPoKRuAt6RbA*{1(aA8Z)o5zPkP7?59<` z=Sg2r^eahZIl!N^;JXq(^WJUBcWeK!ML)F)6>Z)fRB?Zazl4|7rL8R|D!%6_-DOO> zFeffA{Ar3yj^p)tPj2~U2OoT}%A4ohW9?IXKkK*5TgScLV)GrX77r=8?A5dOF?1*i z84GSXwvp+`y8>xGQO{F3oF~t|jtIFt!?T00;9I4mX~Ah{&9^J;XP-aKe5z<}PH%Bm zPu_9o*JYbnG?Ikp1YYC&d{^#gQTK~n%|G!b$(noLXG{-2|9s&+)^$g3HoQ7-WNW>R zDRJKMZ^~Yk-j7}g-!W=#?VDFP`>EoY$kJn;sXzDsEag#K>3>BwMKnRpK9}Y8lLgJ< zr>(hfEHkh=zEr-<`k(g}E3dZh`zM7jXBZjW_DXcwz#F_}LZp)I57(PA-b{amIn=Tz zO43LaAxe0ZlA7hs6|iQh1j> z*_UjgY56N<=EkJFkN|PkDd%cLjGUhSz4YnA(+TnV@iW8r&zcmyXoZ9Y_nqD17e3`a zO1_vcSste)b35^-GJC?qe=ilzS}eKi5%Trkv>#mC{4dEDUTg?)W!KJJ?tMa3|GLSK zLY{dCSg$k-?X)i57CHBYK}e)g`bm$O@;}92Cc3Qfbk%fOy3(g;h2m}2Rqp~EOFGVn zYBflGPTrhVuTtAo=5X6+R`U}z^_rRp(b_;44#7`CMIYZJpZRzH+Sz;e?+HEkaQ=5K z=xiUW`3d*Fi=6$YY2C{zmdELuo_Qs-H$hBB|N2Bpqqs$a{h{7wUry~iC&+d$gLj9j z^@q+)dn4aXEZJzeYKif^b*IJuoocIQxYk(yPpH?Bb0f1r+m-H}ZE?!Z8+i_t9*BLj zg*ogN_d|^gd7i^|C&cajR#$elJ~_)De2H;QzsIBNr%bXdn4jo(-h0%wmT%v?&I7r& zmrn%z4q3|kyuMZMSVo{i=J$%J8{YZ$9Jg(rfBgU1!(Bbat2X!Z`-Jo^wN$j6aqGHf zd%~?R`CP5KQ-mg$W{B9O_r?~dzc?P#a%Fq7o;+YnOwZ-x8My69^w*L~j=uXavUmeuX@zm&kbd&GLwdF!RbigdlEu|szR3@`x$Wnl6^ksqx#GVYhQybApV=#Ye3jkI zrAcBF?nc~ePW<{`b6)=AH9yo&$z5LhRcZE@8`rOGiC?lJC%5AB7G2i(FLf_o1eBfI zms>T-p|d#r47aVFZ8T?HdBx=uC;WpA=0B`c+M%D!R^c6XPTQm-d*Rm=yHQWvr*+DM;|@9Of$2i;&++Ulxj1_zi-EVy-9xWt7F-lM${C_8D74ND7g!_n#7kzM>mJU@x~VU`#rY3&N~EeeUb>}p?bGA4XVV3? zSDNT7*>W}aUZb41)Si6Cq{TLT_hU7-KMdx5vfg^nnOPH)mS%eFdTws9&F<F zSNbSt&U#!elTyQXZ{pS+TX-YN%GxS!tWx)R;?+-*D31Y=&1M#mg2Q2!F$7E!)zz^Oo=S^))}brnQJm9yLk5 zA=qNqrq}1ZX%A2N%Q^C*ra6paxl5N@^e$f3_{aOQDA&cKozK3ul^D40&Sq^b6`d_Q zuhF6E4Ay#x5~EUGMSZT^kD3YPx?2cHW!#YUbH3D|lN> z7P3hf-&(3;f2Mr@q@!`OlI|`(nyRzd#%S-VPmHAsYXq0p$i$y(F3;Tdh}Cpj+qR~! z;U6>Fb#Dc%ygTV<-N!A`?x*4R4D?dT;;6 zaFu`3+21S@@|_!|9+5ebeAUzF%STBEMLREae|8b+*k7R zJ0=T15Y85hF(~-?oMFMjt+#$n@B8?7Vy~dd9Esz{7GF-1Ox<061GV&;f8-TigX+`ji^lt5iqrh&8!)780qnl|Q4P)gNbJ6F-{gl6Hw z$+PFK;N5bYWu-uZ`VSwqkRHL}Sj$fx24a!wMGVub#ikxycsy6!IyC85az)_V59^Mk zE__)betsG6kGNIqY_@I>%(>W=n|toCmwSHyGVhC@W~&SOE0^!!ncp#Q$~CIB1^KQRncLW`%D>*jTPJctWr1Xa*m!Idw*a}`0PR(!oVV9n1 z6ldu6MfcCv*6yugo3}W9*2xWRzPIAh?Fm;L>;0004_uWqFKBG3j9VmE8N{d_};d@`U~?qYWpQZW43WzWPy8?}Lrz z{&xGQwD$d#M>9)i+`KTUVT$K`{RuWd;@`Zwt-Mz&;QX|YGxL0`+p5pmglZ{n{JZd% zacwlin%VaY*D^l;wrX*SaQOno)8@PtSFE&7ZBtEAlV>Ydj!ud(Fm*gzb6<|1Q`Yln z@Ex%>D_@%p=|0J}tsA(OP22dDv2f>1g^E>CiCj%~Y2Nn?E?fzEd2sislY4gGU@|J* zs;2vpZ^`q{9$yX>W1;U~W~VLq(IWYGZ&93~4G)ieomkn&>^T)#$L4&UxOl;>s?%3C zl>A-jDU)jG)^KXY+5W##w`<~?C3oG(<8Vd&ZS+* zG-cW}N%7lBJ#W?d?#UeT-otDob&K3{hsG+&43=|RK2%>_)Q zWsCm?R>v;(oxl|NNBEf1=9}9pek>Ju;oiY;p?XSw=`?}Y3wij|Hb-r|pT_2*&LgzF zBIvBy0X?fWPEE_S*C|XbQ}*9_bGuP+U1ia=-7+x(R!=@@2TtjU+;+?4|6x8Y` zO#QrTZpMTY9VZwqFW26g6(YX2c>d>iTQxGT9bfLp@Md%6rttVbuH}n)H1co7uVVDu zB7LT5p6sGr`QWm{Ys6Mw@NV5Izxl$pkKQ52<%Etrv)Q%qr1^QKGuH!7S58Yz7Z!Yx zZ1<#(VP8w4X1(~61zm+T#@l-2JYR5zEuO2x?WC=_E1{}>*`z}fJ2^frDBscBaO4jA z_jB2iR~sBI1UbGsn3^0aEtCJgt;fmiPEu#_G>;aAi@AO;=8II_?0*yaVsAs)_Z4w# z81KZs^YPz!scXx`c1MlB!TE(dy&0kdEEob5XC*Rj?L9X8#PaDXMN>~5Hk(^9&qQ&5 zmjhX%dn&t66~F8qB{PKhCz@tknwD()7O%DavBJ>}%yKi~U%_U;)gW-SWm zZnrmV`>7?QmYncq(#q$lnrW8I*16D#t^vpKi<2TFitW+^f zFXL4Rymg)7TIif?`I&d$H23@dUM=KPkSieSy1duN%lqx|3!9dydBiBF_}~A$V0PQ& zyrnA|U-p@?`-R;Xow3OHzy3)P`48QyA(cOmFTSnsbmJFyiO{yS+-egQIX4PquVrSc zKX7Qfea8HsSI)oTmXmDw$J+K_$zT771ACqw$q0{8n{s#FuO#bLISb~RoR{wle4;zm z**bp4T&MThyEUHQ`Q&N4mN|=4I{e?qx4J#9SAM;kP5;_dqFXh?#c%7k-QNhnS1cf#KZUsMyR9~=c zqmX9pQ?B$Ys#maJQkT5ig0H?FgE=2c@F<}*A>;G+PP>}F zAC*HbHazfXG1}CmU3JFt^n=LOt2K;ywzsy1IHh-mFIw`_=$H3nO-;kw{o&EqZX3R> z59cX%O;S84y>hqCYP-sZ6FXBI3YL9$y>r9)H@CLP^*aj~B)^8}`SUN^!cx6hv1;Y* z-@zRU5BnV@o6kz$4eoh-^o2Exm`i93cXfiXZ1=~X#Rnw1YgwZ_q~*h8oz2&Xs=P=z zVVA|eJz=q-)s%`iYj1b0|MhjZ&h`Ssq=gU4=d6x(ZDXE0>8XgTSyYGgZuNCHAG|ke zdYLLXQCYzDdX?}u!36c#*wbl?J}2cQ?qu^3>Dwvv{fx26)Q6rW(<_d6-RE&}v+Y&5 zS*icxtcH-pxAT%5n?D#7{8)Et#^ux_JKi-l8!G)W=-K3~@9%c(|2eBI{En%cmI;+| zo+?X!<$bQkY>&{VFHf3}Tv4=%OF7)*W7g?9=iOpI)_BIyqzVSbYxy@n{Y%a~cfsqH z&Y$mmCgz=%6THl$LW^c~E?pV;@;8redt(5@zV#;-e9bYfUi0vL+0HvH-zp+gD^_Wr zeeosE?!|$x*Pgn4Qkh;U_V9DfZLN|79@!NF&Kn%MJ1#nUT)mR0u6j}I)LoA{k<~d- zx|4qIcyBd-x!Jj^=dFKkneJlo7B%obqfIy+_C;w@VyE}PP_Ze>aS&;Md|pJF#W zc&Z$-?@?sTr?P8%qV=rR3o9-7MGiF{ys~B1-Yq`m-BI_w0_*c{`-eTs`?&7H9LdWQ z{}!aJcwfEs^_8|K9rG_{+d5QtgbK^AvRxLz`0ve0#tD3_TNlQd+AK6Lcx_uXU!3`D z{qY~sfl0l_%`8M$=D*%poO8H zZDA5(x3Z>`OG%wO_`JbV@$1&QoCD9!On5xq$+AM2z3_v0#S7M-vK{;K?S81s&Uw4W z#klySbIZKq>B6TkSnp6|6;bz0UHjRN&Rj+j?a$wf z3sg$K_V61lDvI%D2q|sJsQI>kQ3j*&olTv=N9InoWVjs5oPFsfPX%AHuAjlF_9^|< zVczA-UgTUk^l8!kHpd+6h1V7BN^Ps9t{mp~eOGNW`CsLFfqPRWvfSloJ)8K&^|M+^ zT^ncWm+%EA&gPc=E;IeiJ>`+ytRF2m9t9l!qad8{aMIq6O%5yj^wL=+?%5o1@!qmH z_u)qSIX!%NSA_DcZu6ddd9pM5uyRgn%)710yz=c`Pa66IwRpD*EVNdsG!P8wdmNJZ zvGJ7Fc_*c*JJ}1wifUiHDf5`c`1r&$-ljTH)8D^8nA`Po36z|Du){~G<+auKg#Bp~ ztJaoxZSAX?rMAD~32%Z_xZ$*8b8^hLnysn+_gisA)VY_}7QJtZdvizR=?#^Xs~`Z%Q<~es>Gw;ty0rk;> zXYQy7wx00w`6wln=JERbx6}=eleHSAXq>(w?p*W6RmFBS>+>TOKkkR{?#=2bHuv7B z!RsyAz2&*Yq==LM)j!%hJ3oGC_hE^>U;tax-6>0c*9C|yyydpozFy0}{Z{5jUdG3F zPi;86d`HLIzpcybd>wCoU$R2vy|-6>-2ykMowHVDUR>fMuu<-A@=?l$HU zV*T9Qx3$YOBDe!%K5tVK(lm+lioE)8;?k%I`5zc(|GU3=d5!+33UA4y@MO=H|{^a0J=l0Bf;1ON*^W^$Nq9-zVB%}S76wWT5`hQxmRb}yq z+U!)tU9pp;_FX)>$bE&-UsH>{x&LQ(sQ>5ollUvRx9S^Ts!2+|*S56(#b?~B#9R;9 zz4z^QmU}7Ymes!dorde2ONzIbq)genp-WBQJKtTdI`L!4l#oby(f?QVesZ>09_h_@ zy8QW;WY5k?Vg}7OG*3=-l;e6(Sa7&PNaDGgsYcG53xD5a3kF^5u`!vUESx5rWjdov z|J|t_FHde-F8kz4&F#fsD;k`4$>dI8``2Q}^ZsS*G^zb}_xK&W#}mnTx2fGte6}nr zM>k)8`-ZGq=`a1B=0EggIVSb8Z)A$z@nu2Wx0AUQ9zP>(8^5N99JuVky!_R>AB_L+ z{aVX1{o1;~T``=$ySB{msou`bviwi7)8qFp#@@ZI(8d=abyZ>@oYat>sl?uEim2CZ8qK(sOPcyp)qD9AqwpLJ41L}UM!mkI~Y>ekjd$6d6j zt$#2p>cGx3Z7YxD-To7ld_jM4y{W1B(VN~=rMH~#F;$6QkhSH|q1P3qhR3AbMflaV z)g$Y-NqK0TPkC6;Fz?>J(@a7VZeDkOB*iO9YZV?)G-B!6bHVxa^OMIvsB<^?{|`{z zCUHj8I95NFZ~K$zkmf^gW=9GCh%QM^E7|%}QXt_-*mnJ&`PV{p?tUtM*s|Hyebv&Q z9d>*_D>ht~TD8=x`NOO$J5}Z8b+G*lYU`Kz7rIj}IaAF~=KY&^X8pInvD`5=)6G`TklvS-x>+hRjrR<5`OBjJf6MG!y@?`r$AZyae~H(e2MYQG-%;KbIWAp%9;Gd7z&Kd<8Cy{qzn ztgmfBoVYd(F`oIc4xj!!hK zlI=#HAnWZ;+3g!*{axOjp8Q48B0r~P^5LqIuZd#Y#Q%x0J+pKBu8_@k$K=?YExX=c zEW7hlRlVhS;{yIwF6rNUy}=Y;|{Z@Rc+nA=@(D2lJSGN zo%#<9v-;h-z;%! zb`i_wwxs2PV#VubFB1KrE>g|dacJ$alzUtD&6qZAq36r#%q-1!4i+>m>Cww}bI{g4 znxH=GQ`Llf8`@@R%;0}mAzH=dQu$+H=+23I%M4btyQCgj|MtPvaLZkSmdEmEaHR+Q zTYI)TcEcY@0g)>=*w#E`_V5d9`Ta;(^!28G>7xl}Pv5Oyf1BO9*S{b~j@M9mk@Nx9 zuQIH+Qw*m6y>?|s_|+j$Dxr%lQZ!>N>lRK|@uE)AXc`=7}C@3c$}YBI)2W*nZia4t z(iS&$a^NT5wElyle;2pMZF+WT;qM=8>pvM+d|FZ4@|e-}z{F!qx6Lx`=-_};sncRxY?6a`=QQiOfQLs2SznCne zURfB2NKc1a+S-zoi~|a%|Eezw&3S#Qr%Flm7RQ3G3}3~T{?0YOb+)=^_2e6>KTMQ# zYSzB*{k-;2ebqX*>M!rz_D7!&{T7loVLQuNrDnMuHNGK}3-&HMti7J&l;^RpO+EEe zPi{JQ-aBn4up}VrRo;|p)dzh~SM$Dq=XdK{rt(CS(?7QF{Mg`f?RR+o$NJX^V!Lei zFV|ic{M$r9Nq)bm+`|?%mM&Xg?!bl+@BbB+8t0up|w>kCs>%z zC_70^yHRO<;$IP0I=|3#^<84I9~72<-p5}0Q|pBHwAyct_-YH=!QWA}Hwud`-nUJjx8$*H z-j}-5e26Pl z*tjZT#)OY)Cte54&bP=B_;GywgqHAqA-A^8+I@!m#Pmrok5?T@VwnV~3mrF|;WmbQDW{~^t{TwqDp3Jv=NlgnTb+U@L?hJal?A8LKx;5+^=`X&2YPiC{ zm;Y7$)001yQS$GOoMx8f@?P2BDswpa5`$H=*TtgK-!~Rc;yZNl#EUsW(^g#;E(+B% z-k-|mZ_9GwncVvV`R=%BlU+oPC&kW>U3a5=yZb|X+n@E1E@%50>kclcmcKL4_0-DY`vxL|s{Pr$1z9e|+ zMN-eR_t$65KI1U&K~a5`CA-M|dAvcA%&DnKQ^Xf@_l;p`u2*Z;%K)piJi|Bbfz8& zRheP?beH?1`$BW)d(A4m!{fLz;^)C0lOOM#Rl-grJ^r%C>+#kDM!N$t6Wfk2V$T1X z7Bla)$itu$wOMn*R<1L@I?-jRJlD(TD(6|Jb%hjkJTcRJewr<5U)kTEzs*u2JMLfq z_3Wzqo%xd4+S_aP^-C4WHy7=get5aV9mh>|=Qb;>&pGJye9>(2S6lRJ{v4gjd-YHD z$pb#>f_InAo2GDIap#$7hGG|W{)TVnYuoTZ+Lo!Xot35J>E!#h8|L&e+RWsCe5sBn zT3aRM>-$duOnhAbmVUZFwPWAjpb9?=eycU?QIaevAxFdOCiW<;`lP`c7`e?wJATGh zDb9D^AM_>!n@o{etlgY1K09E`!F6R*B&NM=&$-3kJ=L=Ny-48?1wPwJ@3Yb-*_kiW zTfrR6UA7^(erxsS6F>g(ull(8gRjK2+u5Rf4J>XNiS}tJlq&7ZThj8)i0o+MwBTdWy#J zX~psX%U``o@VLH;N1d^PSuJ7vyQi}~*tx~blYfb(DXm$%&+7Q)7}1yJuWb*1t@V)A z$vhs|s{MKC)B8SwDef;%M*VyG{`n8b%kndC{c)YI*>mjM&)mdJsPHz&;*E*( z13z~yoGKxIX^#G-Z9H+;tUh{F70Mk@oPO%GZ1{c7Y`3FXKch>nRtkwpaJ+o-nVn;G z;H-1stki;o`F|f=ncv4VySa5ns~V%oy9jaXlsl7qs#RV{ZI3^+oj26~p5M-*E3P|o zTXy;i8s)ucIw6s{a^bBdOJw%En|)@vO5dLTy^B~hLgs!;Sa3^3xu9i^s-AN1+s~6b zCfP@~M>R59Nr_3Ff7)s(RxoLP(4XCndREsb?e5WNbDI3CdDQ{diE7?8p0AJW`o6hE zBZzgG_3!l)MMS5*n0;f-w$+(R?MY6$x zpOc=J2Msr9&M5B|NXVJ;Om_d=&aXC_0(KQQlDbYMS^t@QJ-*{%+KavKrAyh@$MnSo z?^LZ=6e-o47WuoGaeZgznVIva1?*`(5tF&_-6xgvA}UJ^pRHUjlyTDJf>eq^E6dGG zGE-J=Y~S)}icLYwPW?Sv9v@To$X)-+!OQ9M{Fm|h%U!mmmHYQuPoD5N^=H(VyeVh7 z$~m;wEWSDM$M*F;i>}{(q^?OD*`C2W%nzWZ7D`~01}GR5#{Li^e88ddJE zp8jIKwuL|H@sq$J=ECH6k}`LmT`1QzNS%>pKgZWSG+{-2-?g1r*e7cR%6RT7JaJ*I z;F-W%asPNk`aXtLW*n;XY4W<#_LRF??ee1#<4Up2OWGxB=1)UT@VvdhJ0Wj>S>*r2 zEGJe*zLEbVa_7hI);=EN^T98g|W$7Nb<9G99f4eR{ zqrban`<@l2KK~EVX7gEi?_>W%M#mYNhhH5ocV+V{XFadJ;Bi#F$i}c|?k0b8=NS6_ zPGF6H-4R>utjzPTzjs580o$8(JZefxdv88|@~O)StJ3l>5c6|}j;K8uXxk1*y?CzgUY>PwBVH8xw4JBEsmF=kv+DD$WmnJ12^65&ZG&`q}Ejwb~+U%Xa-)GUHGBkLt&E zs=q69Ua1z(I_Ju1hS)r1;wj&09Sd1|LEVB1)6HF9BUFpH!FX89V8kyUt{YmrTGh+WOzPk z{CC^&zUmBb)v*m?$)FiCo>ldFFCW8b@87{|0~a` z^LN`meI&(tW5<;@oK~tcRu?B)uc|m2snNKV?Ul#-AbZQE1K(`*dIPSmIB|AgSZeOR zv~R3}Uilx7c8TWm%&lXMl@+i^c zQq83wd78URKK_fW>z46hRuxN^m_Fx^y`jllXD(~=gI)`SZUt_f5-3)GUZgf7%5h~J z$3`VRt4?ccb^a2&X7+maGrPTooR|1aW1izAckkE-p6}CMs5_{9?=fV_;^IkDce`po z!KnM2`1<+pPOMT&$<4R!OkM9#`*)Yd=3>Q`JEb!$+%G;jb$+$M!gu~6N^*_4uP^Oy zDnI{OEZ^+*>3MZmtDaQ#eYWI3V)SGA`-|HQ1k#x4gcAt<#&2&LVEXK=-M#aY9G) z{@=TgT+{!#qvq0eEo4M=kcGm z&SM8ux_fu5FnRhSB=DC$-s`P z&ZHWy7NfWfv*73;3!${My&D_q7Qa)Kewg?p;@#x3B^jp+FYdT6@i#5D$mHkS4Gu9I zww(Uo`uD_~8NamiU#Q4(eC)re>-_NA^Yxj>C$D&6*t(R(&2$OxooAeHQy9Kn@SIij z>i48?`|Q31CaSKHiH-g-@9zqmMAtQ|4c~rKnZG4_g6g$@Ix8I{*U9xxtQNOSu{vu0 z``MDcA2goGbMwyMe0G)jQRcLmMezqKj!fP9h)=j6`a^88YWXylR|i}zIV;Q3rbr&H znd@lmeAn4@8_(3^H$@EAm@3RHDXGhA_EDO+%rYiI-tj@$3$Gs^_)hZ|S1p?O;^Gnk za~X$yC0d(ayLVly;yje{t#T7fyo-gfz?s9F47W~PDBPG6u6Ap__7Cd=3ECbRrF-LA znRou%a+1}uRLey!f}vl|G%`CfuCejQw^q>`7mT~l{Hs>?p3HiZhuqvwAwsQ@)i?vu%#hldXQ9%AAbsulGzfpFELk z*5{{}lJhkZ&WcP8u|6$cct0#*-J#i!R;;oqoWANY^QZC?CB{k~{JL>BId)8Sbvn`Z zb~&@#-G_f0PBrd6e(JX#`v#T;?%I|nJu7^w#3eIW*QRL*aG$K%w1Dsa{g7XCcm7RN zG%FLjzUXe?vo_1O#XE}lr)eJf$Iw4-Vz}c$3t6|nbLEv^FE0GbT)*PW>ebe-!Z;l6 z+qcL^ovQhE>DdY%w&@?{3x0J!YGFLN{{FS{O$)j&I!1-twO`O&{BDxr#>!n0(lwGR zw%DrP&&&_M;y zm_19UTd7x;9OQl{!BV6V zysWa3?+!kAwzI3S{K~mQZU4g@H}jbKZ8*#+bS=uCCBa>}sy%Xf?afd#i(gy{%v<~v zwu-Hiun6fg+5S}e^f!N3&%o#<^Fmy@6CI9s|1OhTIW=m{NmohD9|mtP+5Zr~;wwBg z^uNv_4ZF0%d|Es_OD38u-h8jsR9{K1V~(K5pOQmQ-K^#QRO}FbSLnQLeY49)iTmEm z6WK4{o$hk~wzI#W{Ehv-@3`K(|34Cy;eF`J#oCrWUYX}E%trkUtsYI- zw}0`93uZoxjii?E(>hgurR`lsXV>y;2NJd}5H#D(d?k)egQH9O6~iLENfKu+ug|NS zRliPl6PM@D*hCghS@AGe#lO-U6uugYswW6t(LNKk=%wzdS+mSq^NdP^la}T?UpVX| z_$BQ3LKAh4up++cxAQhSh7JAf$A+n#KMlBK67=3>PL(-Kt~2 zA@kJneN~Ol=HJ&M&P$r}U31>McKg-Ka`%3wH#TXe7B-6KPn;z5s@BNs#u*vLCdEr@ z+sYnoolxPDIpx-rFHT=4GbI+@oxiVL_r2`9^-(_~k0t-!YB;y`*GKEA>(AC$Tl90j zP)%C(FOfO$(1GUNK@(FBb(~t3<9;+^g}=R^+5fOs_T%e$DkNqx)SA?AZn@T0|7Z5| z)tQ^t8%^%{2G?eH?sY_Pe(^}R+b)rT^cg$;z|CsDyOn|f1kW&w6>@DdD#Yw z#Qe8g4jrG!6#Vw-YQ4qxrTCUttzDWbCLvwVouQrN-+N9d?3?nbnTD$kgqAnPwY!Z9WqJ?(U)iZJFY!sE zy6hnp|A4!;*`hz6S~IpqoOxoaIoCdY&@onx*9sMKS)-@_=vd69?fXTUe|oU&^giXdO832Zy2Kma zKzXIRp9?bYZ(j5vD`G#-(w0wi{@m+MTqJnTrOUhRI-lZ>Nsk5ZGnFmX+pEgqzg_2D zx~6h~&~n8$e>}2Rm;AcS_&YW$^dY-hx>WKa{$<b#B#umNH0kv--i-GGF4=QOV~)vFAfX z^$Yx1GE<7?aF+ftj!A7Sn)hhl*Z-0MJFQIJ8ISEz-*Z4({E4*H?l$!-VY$zXcKvy_ zykoyRlYZShw%kV+`&RqeJFnJq`OGlCTJ-4WwbvG1sbO08d;69dLT5Cj<>v-ORlP{| zTzO@8VDg~_jUVr`aBRP@@jnMO{QrnA>fO!l(y=DB_E?jqr;&r!2| z&i3ne{)s;tImh7DzrJca)7gh#A6~nN@mH|RN|)J-OMm;z-7CD&G_mh68*&yfsnU-@K1^sB|8zim=~)%Z@Eqy40r!~d{q?QaYF`Nk^66;&R~ zTW_5z-RQJ7OI%Mg&sW%{*Vyv9#ogYTtbej8kyeM<`#PsPT?*rUyzW@3PMf4`)ayG> z9=%Mh`&x2Gr(7rKg}&;`W)?=PrfZuXC2JfBytAXM>tKz#n9XjUWl5*Ck3OB*^5k@p zQe1`f`xT<{m138kFdq7-)^zsuw(Z5g=hSpb|HyQk$3Lfk|Iv=GyWgqir`6=mzj?*T zxOvOc9k+#j%Z`TCs>IbRD!Jd4i+!`$>u8PTwCqo6Zc})o@B8!}E%WQRUYV1&Bl3}p zZ|%#wl~W6SSml`;UEjajQ^3gFxF+i48r|E8E6dN;HI)hONKc6Snf83qCccLC)+N>- zq^gR8T)w+cN}a%N_H~*_#5?i3Zv;hE9~Qo|zqI!E@%N%e{y8`FzV42kw<*AQ9mBL~ zhj+e=h%Q{u!rx@kv7uts|1TT4QzcHEy2NP_`=dNn;`7qiozqx3nO47jmr|X)z#`*v z_{;mPk?LvXTl*sWA85~>B^-Y$lKtyewHL2zl+7Pr_b~1<(23BH{x>Z$LHDw#joaSJ zLch<~d9pQ*2E?y_a{lr0EbqvpUTcrPh-;sDbKmOOiE0NA>8KX|6+F4k=$~(E%wqv{ z*3~MFr!QVj4E-=?(v#l@RI*jR_7z;n-o347%9P!WM^6hsulw?G|F5mie)$L2uSl=` z_UPlfXq%;55>LCyZMYl$F=uv5w^Yg8&CB1l*Btlm5zpOVZTIBJKhFy?UMal_`=_}r zxboz-O%Z!q_k_%c4A1s|-6i^e!u>WYv;7WCufG)AeBb-%Vco**|2>{@`}BM|(s+6H z#Yue4i@F{?$k)6%OR?zio_mc-FE+e?R_(Xxys46O;`UFo1K2VW-h@eBsZZBA|7oG= zwCK<&KWBZvBo{aJ!zLA$y@8rHZd|&%`L3dmnAgRUf^DZ3@T&HNb7!SLxRUTAVV^HI zC-40W2R9r#TwJFj`*ZrQUxyyuyD2>1%5rU+vO|6S!`ee~6(w6QzR&5~d9*maQZvGE zt-ve!XEr)ZVz$lrn)}Lm=AIRm<%xU(YQID6j`2NG>QA3CebFhw-1?%0n=iHmEp)TI z)Vg|R)yu|@cQdYp6-|+R{5^gB2^GV;e;ltyMMqR7slRgHk{F(pp;o6AwZo+Ip6V*| z%{RF#r5+@hhBWA(@IT6TUuUx3x&N|GTgy%h#7Iir{8X;rb}Vm2_k&CAyBj+47B(L_ z`ik#jW#z8oi4$~AABfy8{;{c>kAIq#?dE2_2REH0yc2fZ>)c*usie-(9rLs9O4g=x z35HJ!-mF&5*m7T?Mk?j-guEir8C-cA`MSB^9T$|)>j{lG{52}q`*NimcVN=wh4#E@ zf)iSOI^^2E{M;gyRGc4Pe_|rDySmH?nQ!+)EgW7?6|kBaeCwAgA6H&bfx$jU_A<5= z?~5FF{rh}#J=eQwbz5|OV?%w^!_Tigf6+)q%Wq%O1OLO@^E;(@js6Eb52{-kw%~02 zFa4cgzukSY_L}j5y-OzT@Vg_)_iD>`jo|0wF%!i&fM&rZ<}J<9!N z-leOm@%D}CQsTz0E(+gTgneWfr@Y%Yd&6qsaEFP#Q5*L=x@r7-VeygaxaNHQbFSrr zOQy~?{C0G2_vy|r9*n0x7bJI2%zYoReX8X?3D>MI%WTWneL7rssG#F=>ef9+Ht|0* zZ|F6BtNu~rWsq{*r0hq$H?KB(dFZ#T&f?2FYBoFEkCE-hrdN5Te|{ctNL>0dS109+ zD#ycEk3}2jHcMt6W>`39p}KA2&uwp0B7NPZGh1fwUE2JqPUe^R{p{CUzZrVieS9#% zW8a-LUISlW=be^M#M>Tdge4q!US+IvH%K#nZt}Kyw`0yFtbJ>*nyPS~d2`|2))xnC zB*i98@SV6`Gx5at1MjCkfAs%*<7Cd_7O$@z?H(RGH8;PBnW)opyza2e(azPrIXZWj z|59{67c@tERgm6`?>G9*7IfIyZ#F%;FFu&(+UyM-CZ12H^Uax2|9t+eKId6FRfWEc zeuA7SuXh^Q8C($1TJtPauOMByc6;Q{84e-Y$D!y)jnCNxUI}SGw9pPN})16h_OLWxvcgc3bxJ znNQJb^X2!e70=I`zoO>ElrPVo7*@=kzVng2pU$s0(Px$$)XZPp`MKrEY->M}I~Mof z-gf5DZoWUE^x!nrrL`pryc6SM58nPIz2&Q!+r6v4bsl#G`F$^_cu(_OZyx!+a-!1& zvuMvl=dV1>o#Lmp$?o#`iBZMBCG9u851#x&_^wV-k$rxV=Brf!i=M8J3_JI8kK2_P zUgJw!&vI;Wp58Jc!A(7TM#hc3s*Upw<*qQ_&r`1MCY|3e*A;e3clp|?lcGPnUq{NT z8jAnoU7j~>=lb;$_b*2+6G$&x<=)P6gE{DOve<$zTb11$EA4pIvxClTdGTlG)_439 z>Kz^G!W-Yj9P#6{Iq2Q(`nC1P?2>cR8CsL43MN#$+eKB1@aB3 z+s@mnTrhEi?y2yff21lFO>Jl4shs*`-S0ckz6V9b*d+Q)`nKT0uNgv8f0>q_O?kgG zB0nYc={}3q@3Sr^NM|&yyIv#{c-`!XG$&ioAE7Dib{&1bfnJJtm+i24%<+`RFJf1b z$fnRGZx7CUHOoD_iN!y>DAj+$y`>UfZKd;5Z4)<0J@X3XSLF12yII(Jg8koZwMEnK zS?(}&>wZ`>*KhMHkmD--fkM+Z@b;=5hwq|cMPv00`KQrwb^8{y))|A5cr?*wA{JC;%vUp zAG!Bx^S##n^iIC%c#7(aU5;P>1SkgkXE}U`N-NSTsS2AG&S%PUc%iO-`Wf%6+TOrf z63jn*91~{P^RVhxe%T-u8(F{i=dOxO-NS}lyPdk`?C3l`_iE7R8_dQJX7=7vYbuQS z-S9D3inTCrmqwq9!IuaR$D5mtnP+dA;A`^caK~mxovI!0ckybhKK{YS;la9puZsjT zidKKpG7Pn|_3wBx`R|&@miZN7nn#0gaYpaHyr$mnr~D;>^)}5;x<{k(zcw6;d6aZa z+l_0R!TI0izPp7k`wBT8se6$4a{lk9j+YbUEP3X0uak55=prw?Ia+t-Kc$V$FB3$q zA`eKVM=qaglhMCl*8eHThM<-|%o2Mlo#H2K{n_(Wad+YOPUbb-(JoVj>U2GgJlY#w z3``dVPIVXG$m{C&Ji_f{wKVI6tzELFiaHX)smOE(wkFxb|8{d(Efw77dO>k}d-Hb<<(rYrx^DwLUf*l_ zK4&i5t|vcFuy9uUTO6ocEGy&ko!cVkL>+2GO(m8KZo*|9O7-QNW|x)4`@MLVqY%y_z{$w#vGE+R2}HrBwAf!VV`Nypa*U zX33s}gVPQ3HoRDWG|}&~AlsQ7>4pE#Zw_)*@AaK=C$>P7OX^1cQoe(8=j~ke#NDcC zo3P-C?*_U}OZ^Kkoq5jroRMjdx^wO+Pv6?ADF4c(J05Dw#Ls?(Rs zE&wMTRtuee@Wz?`}N_k<}1NbG&4yC|)}(SLI2_H|b4E|es#_~o%GvTN6Vhh49G z*0v-UTUormSlyAA^=Q)1)O6GSUu%A^;L1OJnCa+pzAo#_Go~M9I3J_Ca?ayLIi*59 zA>7Vx5?k#=RUYm69loVY?!cPgL8c{fpOp?jTxoNyt!8`D$^8910oiPG9Q%*T^c3E& z^U7MNQek~9+V{oQE4Sb5Hr7kc*EXwdjeTl+RkcoqeQ)N*57)0e;As20Rgig7XXvBA z|| zspqo$jz(^t$Gv@{@5*%RiAi!5em7lXZgl%jHM`Uy;hlLSrAsDWpvQ4ngvPJ8-1;*V zcK6*_8BwjJA5r<)#PfK$8_R`f*}Ins+6gAIK6_!t|NUU_<<$l8bDqBl3F2Pc#eGt4 zr&?apgpJpqy7mPJ1$*!b_)XKAd-&70#<$xS>ptOS%=&PJ`%0OtYg5A2OSRAXo(C-| z6u)a66ZXG`yS8SAg=;|0^NA*M(_gT)Ea14aI>AHj|K85WlE-5d*J+f#kbhmD*Qhuv zr%~#A;Pppmu3fx6N$U7FDZ%|>eCoHiDjYj$`KLNwNOYc!n<$(yj1=>%X%_X^M@BhSJ`>drp5^eGNUfn`@+K~yET+A z#>lP`ZWC2~R-#_EpX+UUSZeG+5j|nCLpKd;=kopdRxt0h(tLqSGneZhta5T?I@cR~ z&n3a6XvZ2sYrE<16Pv&bI51+r#^W!2Po8L0aHJr10b)0P{ zO9*>yK6Pey>v6pR$c5IePhwrc1FAYUjdP+Zr7%tlgMvw?S=9&Xj!5 z8yS+ETddQ04*7hQ-#1_IYQe^PZ!dJqF7I9GdHU?iCqMsP*^u+;dTOX&O56dN@T{4a zj0Ls0BsO-o#5CXTi)X)fBTV(#n*V*G#WNibzpl$vXgH`d)93p7!-);tW~u6zCJDb$ zELCvc?wy^$exdern@X%MpII=mi{-yp z&E&-_M<4Ea^zVgB)`Fn7(qYTgsl_+s0Y5 zZDqvD3xC^k9+f3I_#R!LQ+Gn_qr&-xH`fRl8tF>@(=1APlR9;A+VaQG-1gkaKa|TN zmSW4~nY?1NMwzJUKNm%S^V;13b&SEwc^98BD&Sv{QjCfSo8Bt zmSX)*QR`prMWxB>r?`DP`Qhr;TWzg-mlqdw9NT7l;5VzsYES;-){FJ}%8q}KV}DsZ zMRU7zIInrpuTu`y+jn^yEx9hKdGqZPZ^ldKId|P$qJ3>sLf3BztG7niioS)0%x3UZ zd?-;+CR6)-@tGMG?`DR4TDt$JxWdK{zb60gOW*suJ~H+5+}>WE2AP0kJ5Bk*6aFTv z?VpoqcAZyXc~pF(ePBTBLU&$Qg-olLS|w*#<}}sn@3g9Zd2QbLSQdBT*gIRM`APe= zZd)(K;&SE^--PbpJ=Qx8+&daIEmNr7*IR>g3SK5zxASbNnV%Q$lQvv4Wm1oU z?Rf(yUyfV#83B^cOFg}oYzca$pjr|)z2frj8T*>9pYeD%mHDCgoJyUQSAQqXk-2<7 zD5syj#qMIs=Q)`@x~1&tiF<^~4xL$^J)_XzgZ{Jl50*zGB5RBH{_t{(c~G6Tl<9Pw zul(MyD*@-3Y~MYPm-7e^-`BY0u^;E+z7_L*W-QYD+4k!OC;J~cGojVH4(wQXZC|o>c1&?O zV58h`RP>9BJB|IN+b8|ro2f;7jmq)sUka+3iS6c@U>taNa{Q&=zZOf?ss5F;KK*tM zhyM)GBk}*v9JAvIwNspaXF;>3e$S5|5pTS{s#?DJv~GQ_sDj;n!FgZiMjhaZ3!G&A zaHhBF5~WowQLW3h<=xoh=la%VhOe{;3fM7g!fgAj!$GCab0a?=&{VSXoVD_l=>yNE zef+k+_6y(VS)#f2&2hHsyzBF>*vtv~_*X0<&`n{zN5!(MMpa9?E2pX4ZLOO1g1IZG z;HTU3*dXH^(S=2?tZpo9KHd6z^SL934(xdn^!&rEW9Q$l`(3vAXA^_YteMJl(>K>B zcpWLTeB^EP?tyhn*5k@AtNTm))W7glyt83ST(o3Iaar1rrp|fOeCleRJT~68d?D-N z6+d?fEM9r|YV*r=PrDK)na^JSP%HWKTDHCI9Fr%A_%74_x&E5S43WlV3>A{%L0y+4 z3c~BvIBsU|$*}qFuxJU#0lu}f>kih=es@`J%7$ALZ<$Y;QYqk8yY=g?pI6k_xgIpE zm5_JK75BR;pZza8Q^SH$|4zI1LgV0yY6BHl--9+j*9AQ%>l|M>lVw%JyGr|vyq&iN z^zuG!@f0@R#GU`)JL`)7x_n{19H-58D@M9s4ZP+)rK+ojcY5tccj-#jlP>?yP0lc? z?4QN>s=ZKBh+9@rDSyL%rwtc3r5J8GU+Hyp(>t5LdF#y%)hb4~?MpLVWAA-xMd6v- zy^0U*CW*zlJ~Q#3_(`sP!_4gqBt*KdXZK$H_+;*$ntk&Zgvp-?m-Xym{yXEwM=qUz zm#@8lzN~Sp?MY*)31W=bP3N{YMM_L$YCPI{Vd;|GL!Qa24*dA9aC-Gr!}Ib^hp+#& zaw~OCuTQKkJNk*?%(BBtx~)rpyM5*~pC)KivE{|7=Be(yM{@V}-ISYFz{qtZ;o0Hm zzSHMw?8?sXSM6TbY1bWCxJ7gMm5a`QX6ovoxNXbTw?<5B zuX}uNeE*qs&AH>#x82m)s(RwSLfg(44~-N)`qs`j)ai`lj9pmqT}a3D(l@hmK^-Rd z9BIj(Jx@P_ z`T}Z=WL_+2UA{ci`8A{4Lq_i8F#GNAJk2yb?rbgGlYGohckO$Hs3-I0UG&p>xuRaQ z)nl^e8R^GgKKd%E7_cuppRuWI+uj^j7d@@OM>_KaHa*A+&Y9(wxF<6Ip3AMnTki4( z?fKOE`~|-<=kByM%t!veE4EyJHt@)U#~0O)uix0`;! zZV9~wFJ>$edUW83-;d<``crBgKK9N1vi2F%%P%to-|NdBKDG7FvP`GR+Q%NOUAp4h zz07-`ISj_`;l5$4<}N|0ccq z%ZbZcbuoS)-0%IHTcN1)q)R0Bg<1G=*^|ouyQ-@%`#)uTV0wAYugz05!_9;A>XcVs z(rLMN`eBsYAENS> zyk=Rj*H^qGgX7)elgr=9T}fmvHrC!nF-D*@oG7G6E_y zRgNBeRcmXy?YhtOya%&Xf9uR|zxqPLi}SLKeN5GwH17_6U-nNOYgeVLk$m>))UWUE zPOWo#3(~v}Mm(bQR8m&O9*nNJW4eWV-Kp2c*RywgJlg*1(6hrI ze`}wg@@A*`x!EG8uG`n=CQB_Sn0$ca$(n1sHM>@QsF!)km(_9mDetk3lCNL(t~&bg z{3KrOX-R9i+Lo5c|Bi61stv7JafMTft>TIQe=}Z9F8zlum|0&)znQa2+xS$qR|^S*m=NHv|p#Sz2q}`gQnQGPCw;vrh}1c_*&_xm3w=O3QM= zd3FW`zkiiF#5*on=C<-#le7}MF^|?^9^Fq#q6z1|P0gRTMoK$fdew7QbE9c-U+%K5 zz4S_do|v3_MGlLoiqealf7|VjZZfMrmN;+sMycih9^KBEZ@+HCMWF_kHKnEYOz9I_ zeXjbPeyDXe^2*vNkuPM`t#8W+glh&XaF)CN4v{TdwR>Z`(Eawq#<4FK1)X^lEH9sv zYp8Yfh_XB5?-vdY_k~`in-w&BnRFjmzOU^1M$_KwXImFkrJk?J4G8c0$~pC!LYDuZ zSHGOtU%hyd6uZ65>(u2H#_b9cLcjiB5$UML+Bn-;TTcPxu#y z!|5CSR!AB4vBuw-B+`Fq_55e53}HpO#sCm>-Vkp9BuS&KJso#agVc$g=)BZ)e%ws9vdx> z+usFNGUmShDs#G8$~o0RI4An_gd25opDx?kT)J~{sU(Y>Pn-O;l4yqRV}>hED$SUD zzJJG-dH-b7x}3Mh*_-Y;&R(tAVb-+zti@rK&3r3s|En08{c`L)qL-QIeCb=y9ECmY z22JM{{Gn3;$W2_su%#Cp4pB*7pBKlwEwunXtFL<0=?40(&Tw->|r=-X6MhOoWKDhiVS<4{p{xB_&=L~D(7a%LJtFL08`k@QbC%}&p~`{%w>i*WUgo66oByEQ;X`kS6 z=b}}lmiyAHjLIbmOwI>X!`VGr5C56X@IrH5p7$~3?Y+yt2|U#>f3kmK!oy_If+I7N z&!(QWu2)F!=24iwUOC!u{$n-vHLTB^=l@N-+H|=o@#!h{z3y|jXB|JVpd;?=J@fky zGj6Z^ZZI|R;(>Q_SU(Bv$aAw=@V@?k_nn8wQ@3kw-lylaw|zm^TJA%sEwW3*nx+(( zx_4V#6{=3?<>3FYyOLkN<C%0Ek1PxIRHUDcWQOhV#c(YWJ$cap?ac9yPRSi2}y zDZ9UqrR;vVLK?5#?|kQTQ=3$@+^;4+^bzL`bNl4He&1{jf4N_xiEoQ_Q`3cWnpS5N zmHzScJzH8_aFWOUh|A&mE9@D}H(dATT)F1Qq<38h=c?Vde|}Xda8~JT;jh+jrvw+f zPdzgKME8LsL9F|4<*mtj{z>70n5|Q;!b~-@f|^;6gQWhP&8juNYv?mi;}Q>hbFlm8 z%Sw~20(R=L-=BESF6(sD!^#QHYMq%s%xl8s*L}Gb8UIKpEVM^OWry&JTW9mGuHhG) zsN*#KafEUCo3%~}PL+}qeB}+JLH{V$A$U1rbo379`vpRKV>pLY+D01c6KI^(D z%k)q8UObL_wfpPL?+e*&CY-QdGyj9Zw;Q~tBL%juQ2O(hgJZM)lhxL~tAr+&zGn(| z>z?md)vB7sGhqj_&Yi^@A8&pgZhh!l2*;aSM<4lK*s3sdk9hjN5~gpwM9ev~&S ze#u<;$=T*-U)FJt@Wqp?9!-3(QFOrs(;wNw{BppclA?7vZi zU1i_pYq#bHyv*NdKV|()wpKoymos|bnF=1y|8x8vYjZot%lDrvHB7fMnUpR~p6Bu_ zyvOzED&vdgGv2KYVV8}T_@+B`Q&P}{Gn1wk@X9o=O75(P?=b%u=zo;4ckkClXIE%7 zKdHXtR4#F2ZcfG)rmUIb75nD1TMBX{M;*-XoBg4@@Kui3rOmm{O6P;7zyG;hj{El4 zSYOsjpSDbBlY6svn@UF2ldc^;8y%Jy^Tlvw(sUIh8H_|*9SY^eYq+wLTm}!%PT7zoj$iqwFrC0rYy|<@gX}je}fyp zdi6>BzQV-Bpkz<|{pa51#&oyX)m(jglkv#8KeP2x*2vd?vW+$Pe(^`!hbuSz3^v@p zbZ__jQz{1zg>^^;2#TpR=P+*KJG|@J^JjanvYk4(f#qy%ebH~@Ir?=WQXESoU((5mm(yfZW!v=<-Qo$>05Rj$AN zwA{z(`&_&0-fp|LpQ%jCE&9ntcROaz7a7;eWjn=1m?r+#cA6VGtFwE~L}vS!vuq}? zL`v?E4KnI>`mt-Fh$w?A=T2Sg9i=`2YrAKDS30ru$mK0@o85H+vS;nHS*&I!X_T_4 zr9`kN=kTnow?~h>{xd)D{kRz9uW?i)Jm!SX$4_8L}9E7&$k?NS!sXQ304k-9;jB02X< zl=r7?eRyXH?{@RM$2sOaeCDgh$h@s$>+$CQGv*~e)8a~L_;6HKcp2}_ZmXu&;|s%& zf8FuO)O_m9E3=ME8w(_z6O2_U{j6)aUoNsu`oLqK6cbxpvt;HRSB<1z(d-M+B@a8F zoLGPCcldJi2$MGE#}ljgr{0cUIbAaHDHTkUO;iQ=OxjK(i6jc&gvv?jatvVdVjz*g%vM+x*ZSwy~1E` zwQpkmicnd9qo}%b^S0WD&NHd!KfN)x;?N5>p|1zGJ-uMo{nSMyhn2VZ1N*d7#sXiD z9eZ){KupsL%Z`*!O7pmT{w=!BGwtJj&gvN}V^-)&oE5RmvD~%yLn*_Ytd@itw?9s1 z7j|olES`J*97FQrJG0reG{r@N7D&A~-e%A|&w1b0&9~cjp1vS_x@_9ry?0;N#whvx zu{C3h*S}t7XVw%EQ^mIHp^KYcy`#W8fnCeX9{i~MrFZwIV1Z_=-BB(U4d>A8?`*0+ zE9^Gk33CpxPyNov@F||td_tRk>96~7qTGG68BcCHcA|0pwKV(og9W*L|2KZ_3g&)p z{p_{x)J>*#uJy(j-&e;RU%0>S{{Of7Q#Y=@_^&9ici$bC)+g4pXH7Eg7h_tz|KE!; zYmWb~E*g3ZaDT}@Gs$x55(zc!NUBicRWvl%MioRFBUE|hfwbbgR+P>7EpPn%&^Q@?{{_|C@FL5=)$-R@b z9~3Ak%M0xi+3)yDK;gSac-8y{q2ul^S2sQMUyymR>Yn!&)jw7rr=`@FuQ=uBUXm(t z@+Nb3Xrf2ytkp3m_bq$2sAs9(cfpE7jW##bWRv{fzB!tEH2uZ5+m39{Oqi%($|7BQ#tmnEy+*p^LSI)yxjCk z`?^hsj@Ksc`aJWMv~i}{mtvl>wXrVGeM|dYZGZlGDYVq!wxQ1rzn*Ll$5L+HO;d{c zPNa1IIehM(fn~hKYth|v%{HsA^Hs4IP1{~jcI8LmHTPV}!0UDMgBR~Ll`rf$ysB9! zwmK{NBCp_wMKjMAyt-f_e{0w47ixLm7*Cz&KGiNdjW;s*T9Hr7tV634U9ZU79i6-R zz0UdEto>|qu9-fvn_{0{5)*9vFq!?a?^4}cwo~u*d==!|(cdpSrJBW8`P;|LSDn(m z!CV}94lLLBI^>+nJ~MLuOZs*zSij3MW0mW6Bjw+In-&yF-#OU2U%vM0xdi={K8x#< zb#eth%NHxn@Ty}dxtJgS{PKUBB$sDz!+Bl_Op{#xxa^q0Rz9~$c8A-#-!*fH1zkv8 zBBv-+S?Z9v>7AEq|Nl$eg$YNx*iEjr2OfV`a9_dX%`J1yimEy1yXQnI>b$?ka8A(C z(A)Cu>beUq|Cj!jRDQW8-F>%lr{NmL=OVhv?Dgi28%66Ft+y6C+<&}p%4E*jn&%ro zne3jcpQSzPrdaiKPPNLXipnCBtycU~UU>IJB_sPI$14}s-YDnWaI{8d?JBk<8uQGL z75-OzVQ!UQV4T8}d~rtBgHxTs4>Er}QZAp~vT<=;>*rv(m6I0z@|au@eO%^c*%#f9 z)$6jeJjFXS&b{2M`u$Yxtu=pL{WI!0v!jDIT(B?+yYl6F>t(IfhDx5WrN@HI<|UOa zwpB9yo+NpA_nHJYp%jawYrnsE$C0gj@H+n{*5zj;H0Pu%?N4*pFpMkIOsU*6$-HMGL1Z)`o8h&IybBzwYU0)m=;NrbU%MjuT?`Tay_SwzsWI zAbQ5M3ahj64&o+TtB8>lPfCpW0y@nisja`F*8y zw8)L?b0>Uw@TjYAmOZo3(x*&Qw>lqX(=|}eI#II1?%JA1tM^{BtLRVrm9@Mlu&n6m z^fJZmrrbPQ786R&+ig=IS58+>xfZhW6~nP7_cz;Wn9S5&Z&E%{_w*OD&uul{YVIP=4T*+|73;$;7f80q z9Wr&FTiL^%m9)~bc5|a%RAJL)f^QRS<7W1E}hbIzp_!_!&x zaC%C^^uOz-uAMKv=SoQO+4KBuyBs7>ntIQvN)8k>>=E9|*=ZkSTal~%Y^vY|l|yU4 ztLQzWMdX z1jl8^Iki>a%z0-)PR~g<76VT6snyNKywcs9rb-ka*R|j~ z-|y|J@nqgNO}qAcoV!om_{(EBzvF!Gw0D|U%RS^&@APo6S2(T+p5_u2vPkjK=Sxqu zWJRLwInt#XFR))uo)=TmbIs%ZX*MRkq>1iU3w4A}o^{$M%&5YAYQl0aMbkQq7ni!E zYS*p(BYEpykXVD!rtJy~v?|QGCc0W{F5VIE-cp;R`s{%4-p6@~_YbtII4_gCVVM*V zBx7D$xzu*|v|Ft+pQXH5^XX@UpSqs^V)KL5pQrJM9@)=yW|MaLSl5mF z`>!}!f4&{KY@fJ}+p%3D`_Ec-l=+99*eDR5ANp$Br{hnr-Hv3b_*&l=v3KTG7tyb* z>}(x%1#ka-nd0$x!R57LCnx>-k*;=CaN#2NKk+(s9&;r^HMoBnPs|Rv-u8d(;;^&z znF3EYYLZ?>7-he z{%`ux%**|B!7Te_FMdB3zW4X6xLs&2CyR&S`j34T>DFsy{@h!_C?i#DdGc}XwmrG` zf(zcNX8x+V7x9MieYmanges2%PKNmrJ2KlBHcsT>FR!(Hx-jkG{nr+qo9Euvvzp|^9P9#Vz1OpEO9?Q! z{6C)^|KY%_M@ly)^H22aUzNP@+u8p;soY$OVWtn1%CgEPZGUB#+M%FuD6Kkl^WWXV z9b48vloMkXxRJH^;n8KbDTjZyOY+&DKYB!pv%SpcO_yO=?T0+pOFxhP==<#U{g3=h zrDc=%ESlZ2`+76y;?!mGx3+1{zcb^4L{iPOqIo5MHGeNRvhz?lC%~(_=i-WAtCw=r zRGglrY9?2^|Fhw)lRK6tDL3)5B&^n8{382KnQzWcr48qfzhcyXeQC37 zw(N?zu3E>Zr>=8mGQA?M6qR57bmz1a=1=xW%$wR*u=I7Cpb#VR?oiQ&5-ID` zn^%U3h^?yn-*TSuGk@vc{b$eHUR`^zAXhE0=Tm#QZI=9skJocer|znKD9y8Z)4Hxp zRuitwvEu$E+V>)JrpIf zEb237GbkRuvUS;nAAcWenW`=7h?OglJU!#edO@d2%vb$c#rB_M4Lxvd$Q^$z_rd_xleE;FT0?h zd(uvVVcSoS&zqtoY}Tw3Ua`BpDn(W9)N;1$AMvIc4gQ6Uu`!QyCp+g(u+(H}nIHKq zHA+zB{htl~>n2~}Hw#~9)0XOo zU%ZpQ{nLN>e)_B<*Y9z+e^OPfoBn^zuIB2mAI!G!KRdB7=W&C}gP;q4?pd(4b{?oZ zJ#nEzef(E9(Y23w=G^>mbl?5#kEhA5{a-e1E?jC?_-3kP-?a$~=Jxm*XnuXP#=67* z$+zV;904g)K4!0}NMV}tXZDI!jkbYNVh0SLCN5aa$Fez9t>;~uzxr0rlTS?w1y`I( zJ{q=kx0WAU+)Cl~X?!O(NoGt}V4JzO>WOiP>3y|E=EW+lFLvKb_~1x z4b_`Gd#80Uai$)gVdK=!$mtTf_H_EGuK)_0GD<-`Tc5bXztv zN5TJ1(f*yf-+phNuUd9Or^@uI;Fk4!UwPe|=NojB$9i@TUzAX{v!t6|&(0$G+w8mL zPb`gFQ-8Ag|I@@dqUWx-e^F%E62r8w_c+s+V^c5RVaaij(sAVDI5%yB$?k@;6Pf~B zeHOm{9eKRf%tGry>ih35*H#_bBi$vlCnGyXvf_@t-UZd`CiOFnU-e50S6w*1K3B*~ zQEq`5x8l;KRPU!7imn*#+*5ribm5~{H#p^;ZZ^zrwB56{Lox1(zT1my7cV6HO-k+S z)8s#;y!+-?B{f&^FAMKqE`PpZ~EGbv<+Vc`n}suT|eq zKe9Z`@_p@IMsEc+rd<}#qL`0F-|eVd@8{!S5vnD7rFN_IGN#`~ZiW-n4{s7Zc<;{j zO5si&&J|0pOpc6Lxt-QNBflL z?-P7?ZJEaQe{Wr_-9%z+9v)onI4>^#+Sxkw%?uNNrWa4O{`^F7r<$WW-~0F(?$_7< z5}&$qWm@=5p6PqOnqAFyunB+QH2u-RsqL$bczkv>zi``L^lrcC4$HX<#FjU(+2rV5 z;fgr*_g~LL^CvqZjCi|C?>>GoYT_v3{ln`Zjx9y%lRs^*}@w`PYM(*pxt zEYnqttAsYQ{|}jR%GvmAa}odh?N=>tsC@_uTA1}|oBXLWzt=P$^2invo|d|J;%?!S zcW-fYpN*N`D-pTup;600*T{rRlII?^=B;`%zwYex`sN^~)cf5rlkCbDMD2*N`@1vq zb#rDn|2Cz97Zt4~v(>!Y-@RTjsefwaV#%mS0bh98!+mBmXddSfn_mzmD)VEd@9nP2 z)hl0Hep+c0EN{+XaD-Rs_xAJiuG)uxK3t<{5nfvF>pW#4!--V|9Pa;~9}m~*$n*9y zUH4@M-^zbS7ceHxe!n&9ed49U4M}-ko4u66SRI!i@k{?CXd!;g?wy~K(e#;z1(mps zHkBp(5V*ZdQaW?FAWOrVnHHxPOuT>T(%QHG7}D2*id@?C-Cg-nN`=aiQ($ z7*VNxdxLpJBNZ2NS*Py5xU?bv-|LlApV)-9y9mC`RqolGGh>;s!~d|!q95J5BnYeRo^R&l0@Ybw0s&OxBGeroL<@7rn-igP0Ok9 zWoX~iKG7}e8$ZcbEWRo#`pfZ1{ZoclCfVLkBrpHhkiXb+DWTN!bYb>t3kp`_|tR z=kf1t@)THmk1bVVLEz*nk6G%@;Su4-YRm40d7oBF5kLCJ=6lIH_te${NqR+3d_;Xu zeGe-7slaJ>a@lFw?T;U>y~^+MN~!4E)Yu}zG!;P zG?hgwo7~#A^eh&CRUkg&bXWA9$sAv0{_Vbh#n)|V!3iaU!@4idi%xvZ`S`ZV75Or? zlOLZOtcbJwmMOhd{N^+#J_R4Cr{Rkw?@v^?{Qaj4mzLYk*M^j>k7T`f|(xo@(( zK9P1iL|QxVS3Q&Ywp$|2x=J(SR`{oAM+BJuFgnirDtq6SW1@S~RZWif-#FR!(o&h5 z#X5Y&j-6~`lP;T2_;#zQ(e~@@lYTuV{F`HwX?|xq`|I2^MZROPu zA3J1P%C1hx@%3bCVMti^EiGraTdV8TA7QcFnb9Ur0vshc7oF%=wcIT4ST}(GO&2RhSc2cyf=(f`Wj^1kBc7tit z{O9o;IrPw8S#2I?tzGU~kBO`H9FTmy(J$yq5>LMFi|~ER^qw!`YD#2z=y2)EBL)s( zu2uisPFyk*dF4nx%sSQf7}~({_Q+0Jj>T|F4+7k#q4jFDet%NvnIPU z1nsx&5Xxe|kzX%iQlj6R;l|C@W5W9OPqV4!zMH0J7!Hb@Ih-$`$vU+pN;LaUqxx3P zKACl|QucPpMrW|EFG;$oE&Y>G*_gq8pRjlw&*y1^Zf^1d-{0^0=iv3u$o80rpyIKN ztuHI?E?e?9^?cAZiMquPj4gx}#J^RnWtZy|SRT>5>Ay?OT2sD;J$EiLXCCEgyKup! zLgljbr0u1y!9UlFxW0Y&X+uCsSw4$wk*H9yLr2TX^5{)HN(*=Q#=T#APvx2Dt(4~Z zp0CzkXcYZk|4yp8@zR+{cZEaVzF(bp81Xvnd2*fET2(8pvZHxc_I55t3C_nkJNkDp z{=Tu>L1qiD7gth#`sM_#o(G}3V{GpH%FI0`w(IHKO)DGpj``?bOjDS@d6A-TNBYul zCw1L?HLWl2Ze|QlS$`>Z~04GaYBUX87m$bFNEFv~;dv(*O4Q#k4%+lQe{;N7m;18Yb^jv-^d=ms6>#d+S(=6BdRK$hf+pnu_{Bz{M-kZ-=RE(xBJ8foPa{g4hnfAOLte0n3mUk7oTB zrxs7qJ8u^`$WM5wk=kp0{KFl+eZIv>mpG<+`|YkwQ~vbQQH{~w<9%e4Z95~gw&D(Z z4M+bg)|<1>>@)HV?pa!XiN&J-+PO2^>|46*6b*fY%IXbN44VFK{@%{n6jd~t&nwjS zbirNU-P10K&d_})bqmx{wwBdSH%Coaq z_mrrv@Zo2^m=W6%ysW7B1)Ik|!{U9L`O`AvKTL19Z^Y~U<4h=@{y}elW%qf%()P{V zu;rqJ)0w_sm1$=fulwA2t>BGDaD&bpv#HuuE0%KJGKmwM>eB3Q*my-HHT}F&T*!XGy=GCn z>TkT3eBm9tLCADs0B>^O{UvX12u}Hx;goPx|E9O4qvS=-89G`T-=1HUKe>KE+Noys z8~1mpi(75mE_!5-&E@ph2P_H#9v0}#EKt3??uztmpYM8a>Tb2!*_lu3Taf>y``+Fo zf@af2Di*9=z2C|FMP zVfamW$@zeLl2aT_gyzqEb?)cIo3hCqg^CZG?-pLMZBq%2+xUX-kHDX|YfmlQb$wQL ze8=U~+o~Pz)vLd&ywkTflKspZb++|~+nM-+Uw%iICv?wHm6ncZ7Tt1IzefJ;Zk-C5 z!sSn|Brm&^EYKt8y|a4Cu8D?ouiy5Y_~*`to!zeH-p_d0p6mWyA!R@BdSv6fLx1Zt z+88ArR;+z5l*GI{*WY2gapuP?ut4N|&>bvP@gYT$TB|ee( zKU-Ml_e2JEoBCHQ3lsQ%u-&SebfR?4&fv?7SZ@j`O=6mzW0g|%^_jviQBgmL9E2kJ{f9_OrD!bv7xFe_i zT+xrhhtj9iTV8HR3(nn|=9A&ICMY;8%pvWT?FO#ozm?o?)1tqBKPq@|R=G0k8i7C6 zU;eE;^zOzzn;qHFmCd2AH@Pg0?0#|S+>Qx%loPAPqI<-IU)_lcDt&4gT0c{fJxpBL zL+zybor8r|0TG}3&ZMk+Jl%J>*o!^0yB@u~wC-l`MbF;_^CX2Xi(R|p?bn&pleQ!? zSSvT<NgvmtjNw&QeD0I%C_O#F5 zrr3i|>o}*YpRqYN>43A)-c|e3(hF2=AJ~a)-tK4q>~X)DMNZ(i843aBCA*9GryQN< z!c?CSb#ocxTHo0x*uG6#7^gn{JmU$$&s|b!;VO^62U<(tnvoZ{n_Ya-|M2={$xmKZ zUzVAXlrH+}uRV`_pV{VR#$g9etxH+9!XO~w(}F3%2St*XwAX%FMtL z8{1A}Zwi_1yWxFc<>rq$GSuJf8Rc{{Asz|nvRcW_derfobs{YlS25xo%}Py;|k9wl7#O|dUz*1 zdmhKaK=5AB5PCH&%9_P3{(bU6L~XYP|X3E8mE7yXYdUQk;DFo?Zvn#s}{uzOFl^ zl`X@(Sn@{B?oF>F1+>_LHRr{=$nrW7elDfx!8N^G6W?WZS(xpZo$hhF@$*{NNgi^t zhCIG%s{7j+Qyr(?({kkVxpJX=8Mn-qsc$&AWgbNe`DUFh{H;;5*6}tsPiyj{WnZ?R zuI+m{$@Q1vDW};2%Ppp?;d^{^3Ad-&f#)C01D4;9 zy6a6JpZE7hsC1j_C|CD~r!#ZW zyD8Qy1Y%ck*+@=HD0klyH6f#5#%v)Ak0^cXNvm0B^C;F{Jt^~Pb9Z80-P~EB{=18P ziqA9Z_U!!d=+)7zkfgxa#55)LhMUZpeV5Mfc9LJcM^AQlRm;n3H)CoZ3Mzfb+~Oe2 ze7xw}#>dxcs^&24uSgbNXuImqK9zZmvr6V^_$%;F(dBP%9oub|aZ2x^^vAnLXPQz!Z4h!*blko{+WXCg>|;-OX4cJD;qi06z|>lJEp7_`z4qd8GJeNP;ku|pTPdrQrq85_Y%=z-@5EZ|N14iGVSMA ze|~KvK9|@0qtt=@4IUb=zY8z>{;X!vdd)}93vz!?lwDI^xFVvS?My+KNXnad+2;3e zTW^R@Q>v*--P*R>vhS^N(9RFfXZ{X|f0fU%l=}Z{5wcPFveqbz}+?>`QwN$u8Y`OTM-4iG2J6ww()0jvr{6ZnWC+a@v8m*Y`gx z__p%c#O+g7ozu@S;d>?8bVDVI{l&gxA))q1lvc;3CiQXhyx;LjYeL3RtK%1tz}R-=`3Tk-nCVt>)`Fq%r}SU zahMd}Z-4XO>+P1?o`F;ACUNfk+H?3+{Oz3cUxH1=1qH9MX5ACAS9v)vkI~U-(YcS8 zSE_}b)%yG0qDB8lSVhCKyTbKS4*O$OJm0rWoutS7CghjQ%1dmbycQQ~cjRArE@rwQ+u~9X<5$Y zeW$BnxzQOJW$70s%!yxj1vb81_;7b!E$c$|8TSiPa$E&hPR{(Auqy9h>+iGr_gW65 zW?L&?`&FEz;l#UXUSm}C`CZK|0j;xJ)-L|Kc$1fN@8*{x=?>L-mV2Yp%=lD__WMT1 zeZR$dam&9%4(1ijr)OuL6L4d7yOQ=_F;z&1yWmoS<+bL&HxngiYPY;tZK|4-^XGqk zLEI3fi*DR;md*439X1pMN^SWtkxy3RL#d~u7-}v_WlgoyG4{XubZ`YI(zHPf@ zuDH!%=dD!-0AH)AOf1P0VhaeD<<>wC>LJP3`J8 z)hGT95)G{5oXn`PqxyJz_xvAfds^~M`yAf5M9r^XaX%?ziikkXEYs-=k4xV2KHJu` zVfWR?T#?_q&KcfvveAjud348Bqs01J-_mQE-tU6j(&a+uv)Fu|^?dq%xk)N~@>jZ_ z?a1ob@NB!}1ef>i`J4wnq-wvj+<7ERqG&C%+PUdJmvC?Spr)g#xG_y3$5ywneBbTn ziWyVqEn3Q9kmPKy7#JULGFs=>^`Nh7|J8_G>Gnts$k!_fJ(Z(yD)YZ+JRupfec8X$%%jay!{Qy!NwD?E?dYpG#FC;u z{n3j3GEz$GpFdqItzUkQVfLd$#)6BlJXin!bJ4qUYq0cIjpbkc0@jt^R{vK0vf!DN zHvi@mYeMepxotf%&)v$rCZt((srSU`w)dXw{KB&M%$_7k<|*C*Rqos7zD)QV&?INf z@+9?)AM>Yju9b;Kp@(WWz3ttTes`sZc82k+PCMSX8+Z}*PMTZCtp6yy@GASEm_uC$guOEI&rFXH9;hRh^k$EC%$N}gQptXstL&Q{Q$!69}1 zmqz>NOZ-{pZi>G5tZP|#?&og!@7?)i(e$H>><+Iy zx%9@Bvo`uG7Csjf_VktvNq*h$)9KJO+kK<@@=uMbZboj$m+_j^#B1IA+I{;Cmuctg z^grF17q91T44x;QvXb-l^FQA+mb_KvWSlVj#xFaY()+9B7`4RXeo0;B={S3lVdGX- zjt__LetNkoEl7B_)5UjAtEcR;S-U-7XV<#WoL3(F>$^%-qnEhM+_%|kO0%*{>w==< z!2Zc8JC`Ng-NU=^64!37;%DwVFaFwAI6=Tcpgzk_)qKiD*@ zSYEiTW}epbD_v^?j!t7y&}Jx_K7UGXKwIhB^o!oc`~6aaeGfE-^C-@kdhbb|+=bTV zhi1xOFnPaq!}E)~WJ^-gk4`Dwa>~|~f0OGamc2)v^5-#jZeadt&FH?TEjH%c-rR_~ zFxw+jIFf}}gH$sQZJr$Zm3!B+OScc_ot*k!+F1O{!8@rF7d)Q9;$tVR);L4e`;C99 zT<7^&Mz<^4AE_=#&3WMPYk$>T0Y<;AGmBKG^EtN)b2i=ix-L33_m3vC%zv+`FT)(4 z?w`WL>cG&cXtn*v9>^N^T_-znNcUElRJ;`-SpZ|_kKI(p0tIO`mYJ>CrWR z-&qY49+YTLnmJFa{`pw}c41BKquQ%ZDgJh!b!M|!|H~rQzg}sH9Pg#779N&7==wBq zmG7h1r?0M@b?D@8J;rssk@ls1D|8L#EO~S49xFr1-@^HSFH8+$Yk6?@41?df?5^9N zy3K^$Zm9Qm@aKu|wAvxV6TC}TvGmE|Nl$W>gwp-*?@*MB!J=~TaC z^Sv`+N7S34go_%l@7DYPC1mU@^<9KPMcOWV8NtT0bjW%PjKb)KxyIqw9)9 zLu6O=v&`9h{GW0BpD(#$7pDnc+$#9ZM9!hYb&{FpgAI#4Yd%ZK2baI9d2_$=^CBD8 zSuZMl9;%D&`1OkCq?7jNnYLP&9(UZEBL9IkGx^eNUuA=6jt#EU*-jjNd);5&RH!?N z>EL&>(1QZikqVOk{(M+@WcJfnjn_Np2(jPxj(Ssg<5kGr}#aMy}pa%Z>7O%&HIAsH#V|f`J-|v zc6SNevWV>q!tV24(qIW#B&^QVzJ1=L-d=+ZI++gTZOm~QYob%`$xV4GafX#=+qBLO zQz`eKH%lizoWso3Ro2v|oBCw#$Jv70=ZJ@Lu1HjQ@oU@C!aYYKCS^Gbt(gA!UdgY5 z$6i(*`euK(&DfRlBGZ4b+QnRTfwt|X7wVb^rkzcBi9qux=!@%wvE%c@-5x0z3ah-AaFyrNvmKMZW&N)Xd24;l!>@+x;z#bcY(cN8 zmn9c2*Ou{FA`}|=_Lh~)f(aX*u}NJDSuZ*Bh{H+OTg@^tk~|qrhdMrQk`}sfUbneo z>A@{u&M40+`&m+dd%3Cpw1@U{z0df1&iVan+lv(OE&u$Z53!rd>ZGc+1nm4xdYKK6Sn0*2Svs>GdDACj4`s8UE~Q(CTfL zds0?N8Lp9cSX3wTQ*Ysq<%0J;lYM6_wkQa9T(kA)zuU!CyWU#P<(|Q0_?Pn%tHH;p z(@m#eP4RkV{p{0=^M9Y6P@4KD^4Px9GOw&uU!PHL_KRu@yC!kLEz)-J{Iv#)cB!=r zEwHTmnmpa?z(b$U5BGF3)J*&RcAx43<;&ADU%jZYi7;(#-W2%bf$ZHj!wVy{gh=^ zpH6q?-}4l;=P}p1VZ{D)M&Hp}`s|5!gFI8>Xbmz{k zDN3>Pk7O=SUmjVnJbz8tZkJBqOKnv7*_sUZ~<7eyDgaoF7#Z%Hwrh2(p zuzgfqdO}7t^!iQy$6~(~OD=CyUmvwSXl3c&)RIGv2|pk2W7)N$$S6#=a%X7h?WKzA zQ^lCJe80x?LUQZFf4-BRitYWDdN$zs_vlzv#rq%Sk`mjBA5|{+Aga`meEMgX`!#=A zfxA^IPmc2a^whTaa*ZcD(D(UVoay;%*UZSwqCIkoHqAN({8^LoA*7Qxk*l7NvAWX`qz1lpSy*f`&Y6=K0flQ z>E7>Cs)wq~;-*UWNN#!e;Ru(|e6HI{95$10U1)H#Ikjqk_qmc87vr;EJ7&kvD?f2~ zUz)Y`EzXIPq_Sjux<%)_YQM3hYx4YR#$MF}bARtPN&9j3$^MVQ-bYoYzpNH4>I_*b zx$?~Y|I+&<7Ac%LaQASH$TqE-x)&k~-vmBz)>*PT(|hX9euIW-Mfp=4${!TJ^=A0+ z`Ila^!{dO=?3Vp+Z*Ydrg27=GHEg8?hyJxpVrz zMg7qA(9?exS^s+BhB!ZKGr{h%H-}1kZaM7b-0X6E;x~B{f&I){v);sipWbyfvq3BR z&YMl*(@&q4RgRmp$Ew&%BG6#=^Ze!Ciy98<>_%X;j~R$vQ~=&%FDe z%kpCP|Cp`H&LDVy-M6$mb9TJ;Rgktd%T3|zpS4~7(ZRri-)CY1*b_dkkbJN|Hco!m zthD0~w<&Kte(?74Q?<&v0tug+fA05*f0TS@)4O#X-`8B*H07fbLsCzM%?6iKtln9? zajUa3Gp=YUe`6H4?G=qTDK(a#%yH!%qlndJ%?_@e^Y)!NVe&I!&R%_IzKgf4zwAzW z`jRJ6>LpwMzs^Uk_6zHgp)GEFD0J$})nsHNg|^t;-xC$$r2?+=h~pL%EQ)ybTf)IL^P z{#Sn1>UZ96mdN5x-ESM@6Q9n|)p2p2)_MHPWS*J9ouZB}^-nkPufL;f^?Le6=G|+r ziwf^(*JIQEutTKzyi4k8t~Dae@{xZeXB%d24%fV+@{aXcZT-F@kJryB;I-K~XIYbh z`}_BQ|FJTB)hR!6ex6_8?iIefy&{HXVfpThgtsRLvDB-VxmN@gN85tQASg z$#L#p8UerO2N=tVW#P`M01td~(pYk1b^rMLiEZ*#6yvK};g?Id^xaLA{-Qzs%kb zrdrEZOxXCvQ~1Q4*1ieRweFMVm_%*sOWW|`>2-@h)1=p#$x`dRoccb5eLlA%TPDWl zOkB-sJFkb~+1Fh%Bwoi~kutvb&T;j=t@pieWxT((Isakd`VOx3Q=VQ`6L6B8xzw-k zht-eZd6}!^avpjta?se7kh}KSo&2WU9sG5{2M?I5O_m4{%YFKeZRtP%UA{BE;?euZC0xM3U+;fCeEZH8*%QAic8iJRdG7Sw zSH9*oo7B}6jyOFep=hZr>5>RWVz~Nwd;43$;@0Pqgd^>?VaMc zH?Axx|HJchZRq@`(#sQs*T$Z%+P%VK+lt!9bA7&?`8(-gc-`ce*4GO6vKg{-_!u4i zntAyw=etF!tl~*$f60lh(RQ9AcaiI#%YNo-UM_E2)=nr_{85>j=Nx}*(h;RH{^^?j z789p1FIJ1^4P<<<($rv!!qhw3ej?xAny&cavh{TC?M1K3o_)^vQKEbyGr`Q8`|yFl zNeit4s(d*9uAf%OzWbcKVaaZ#D$P(0TlqYlM`>PPw=5P3_h}L_cC9|9_qbSel?c;> zsOX~3`QgtNAAcAw82)FQf`_1%%oTa>xyC(SMe9yHU4P}QL*3C+udY2d-=IFvOk&Rd zu%(BN{Fq*A;@EDv%5akH`kM1??y2dw>+;Kz7%qiRfAVK@MPqAk?&2*=^Gl|5$tY*@ z*o13ls?0jW`SjPEhc^X3K1zCYLTh2-qp09l>)uCPdy>0|IaHTNN=qY7J$-fI`q+$n z)t?R@E)aGyNC`aqxniz|1Kakd`CHlEsb{zpDF#0moLTqu=`Gh4u`9M)Ej7FNGv+>% zv*3!Y3lD9*C~Tejr_`{t^+M+KUc;rPIVKAkrkT~>QMX$C!Ts=(_3jJj=uS8N*uU@7 zvCBv9-~aY+4~x1*VfRl<+qCKO5iz^whH`-78X_C9&>Y}>lW8@6Vj^=XVtTa+K(_+-(#?+;cih8Ync;oT#0x1cjd4X#kVd={_>vmJadMq^1iLya}1kL zKYh2>qt6w^LaA}w^yMIxi8fx#FyG%&3ua{eKQBhdcsV_J3hn}ahvPcJc;xH(x&|G?x$nd{~rJT|-QAM2@{OJ)AsZ@yqEom6Ak zSoe3MxJj;i^U~+M$ND$kxRi9})q8G(#UEQ$4*m?BI8m{AYRK=2GBY-~m|Q>Vy6kx| zAKx6A6^Xl=wp6-gM$iBL+&pGw|6C@ai_3Y+yPom=d9iKPvyH6ZzHMVtT(s@D$S);V zt}?Tj1)`HY{p=i`?B2du^VIIXpOH;`E6O;R`aAz(J9GQtq&6l+W5L&#dY7oL2!63J z;r$-DaH zdu&hnAD$DkIcsa)7QX$f+{nSYQQl*w{mEYu250+RQ?uFcYcIPUYi{>n^0|Cw>zvfn z3pU?#)(})uXn4*SzrUy~bn5ZQQ;E5!SU3C3`?sEDe-)obktg@^%h!1&3)QB`Rjj`n z%wyo^;!xOg_29|nZX$hGL%Fgaa#cM0XFBKTzQ@YvvYltF^4?p+dB5j7XL@V9+Jh^M zzF!Mo+}|aAS-JM0pw7%mH(h)~d5vB+_b*O**;oC#|Csn=+rIYLb8bcrhptr}zo+;( z^n+>rqlL%povc>$&i@f(QZ(;xqt93P{EpNfH+sC_PiWL==@kb zaaDb(uWI(aw_8^jH+{OwCVn+?=6wzCjg_VOmfsei($U;-a$Dro(iZGA%6r1)Vta*Xmp1jKPGrUeE8$#5T)+kjxIwL@*XE`JpWSrk6d%0A~*wail2)pd>K)8I2gF|HT78MiuIx3+oO`(UnT zTSVHtvbU`4stZG(X1p;y%y>>o{d92qucvPDW*rKi77`lyoo|oL^2q!@ZR_P``K6Up z{Zm}E_El{+(T^9@m6k4AnZcyKKYj%#zj8PGGV!%lF?(XgA2!&xiKz#dWn9=l^Ma+x zWC4?h*W4E0v2?rRVEe>gBrquS`Qj<=702B~Ed8R)Q(CwgFEqK#Yrat*GKX8FFH}`X z>i@5gvU5MjroG+4Y+Lesg`eZoX^Ap9S&MmeCdPdf-JRmGQ8P^G%dMtr!xxVhZZ~Ig zR;r=qsLo&3fH{o`LTJC#`@OG!}j^PvmLBE9g9+5U3(C8v5@kU!w@amrF~(JzQ?}geh{lgzk+ib#sdLueZGH##gdp=SD@lmEBGJC6mv4 zn@3nH&n~OH7_P-E&z>do?ejXvd<<>zP}e74*43>`&*?$e2{Iaz%;mIU%9nvwrCP zXGNo&WZ^dWD9|6bok8&DoYK9$JYa_hiwd?AZHAkjB`;(lpe`lk0jgMmV z3W@G1y;pB_N<>a#k&U#GTGH^Ve(t6nL9x9Sf+FEYDVA5YrKc&!?k!%s`SP;#ZMPQM zU%$S2^Vgu%KCZi3Y&<2(j68Q7BK}1#QL$@d%!z+}Z=zO`{Na%EkWo7XJiS6;x&Oyk8;pPcmek%W zYOX9ImH70uKAV`|Hkk+2vv`(*g(H|&{kX8l`}>opo?^ADeVmDQ%bVyEkD$KWHEXHGh}$=W$; z$Fx)FbNZi_wTMkPACmioD?Z`8oan2tgCF}IsvVp)B}h?mWt{P5lbL#X!8^6$ozwn7t*nZBOv9++gYROm#@Y_VJS zyeG9?DPVJ{Wc}sf6*(j7Oj)aZyKqe;HE6*o5=Td^}F)<%?o#T-o`v|a1?~EU(&we;pgOd zrXvDk9IuMRZn~ekuCn}y?yc#s7g}8FpMEMdapmM?u^*=A>e;D=O!{^H&oAK_3hWW; zSC3!b+Pxxs>VY^%eWtfET!ouL#H8+Ks=nm0xO!&QF2hjOIe%IjotKt=SN1O6_u+Gy z)WjH>QprgxLn{-a@{M=Y$)4^!@qe}=n_VsA%xeeD8GhSUrPQt0zIXV_>x`_xwC59! z?)>?F`60gb@&66y_R8F;>0QujB|Twc{C)PkVrOkF@o;gWBd=u~#B?eoXEFXjUM7Z692}U&Z8gaHZ0x1-wf` zcbR`a{%ft?*~;b1XU&)xpnyC(PDGKH(hj(^*Im$iMj z+g8o=&kF<7WsY2W^Dfe6`j0I_ud3G{XH5LNB1+jm;+XaNXycoI@9)3jYH%Pu^k?*c z9==1|XL(!Gd=Jk1z4z%IRrw_=wAelUssa4-x*gN0Gtul5in%|&! zEUWa*xhL;=&K|fj`&8Cfc4?E33ZXBi_}!V^zWrt-`{D)b7`h$qXfou^T^Cgz^X}=b z7qfg`&OY&==c9q^R4(_lKe|`>w_LjKA+q;e0pCC7->)8Dxw%8d=A@}w^J?RFrpdbc z!CZk%SI$;TOs!hWGYL1 zjW@3}Zt_GZd0C5mzw`KPlgElgc}scQmi3D)m)}YGC$!&7%0A!p#kWqQve-q3nHMu} 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%0DPm!_!m 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 W%g*CeplZw9bnyHC|EF*Ju>t^|Z|fic literal 0 HcmV?d00001 diff --git a/tests/lzma.cpp b/tests/lzma.cpp new file mode 100644 index 0000000..531e0ce --- /dev/null +++ b/tests/lzma.cpp @@ -0,0 +1,136 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2021 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include +#include + +#include + +#include "crc32.h" +#include "gtest/gtest.h" + +#define EXPECTED_CRC32 0x954bf76e + +static const uint8_t* buffer; + +class lzmaFixture : public ::testing::Test +{ + public: + lzmaFixture() + { + // initialization; + // can also be done in SetUp() + } + + protected: + void SetUp() + { + char path[PATH_MAX]; + char filename[PATH_MAX]; + + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/lzma.bin", path); + + FILE* file = fopen(filename, "rb"); + buffer = (const uint8_t*)malloc(1200275); + fread((void*)buffer, 1, 1200275, file); + fclose(file); + } + + void TearDown() { free((void*)buffer); } + + ~lzmaFixture() + { + // resources cleanup, no exceptions allowed + } + + // shared user data +}; + +TEST_F(lzmaFixture, lzma) +{ + uint8_t params[] = {0x5D, 0x00, 0x00, 0x00, 0x02}; + size_t destLen = 8388608; + size_t srcLen = 1200275; + auto* outBuf = (uint8_t*)malloc(8388608); + + auto err = aaruf_lzma_decode_buffer(outBuf, &destLen, buffer, &srcLen, params, 5); + + EXPECT_EQ(err, 0); + EXPECT_EQ(destLen, 8388608); + + auto crc = crc32_data(outBuf, 8388608); + + free(outBuf); + + EXPECT_EQ(crc, EXPECTED_CRC32); +} + +TEST_F(lzmaFixture, lzmaCompress) +{ + size_t original_len = 8388608; + size_t cmp_len = original_len; + size_t decmp_len = original_len; + char path[PATH_MAX]; + char filename[PATH_MAX * 2]; + FILE* file; + uint32_t original_crc, decmp_crc; + const uint8_t* original; + uint8_t* cmp_buffer; + uint8_t* decmp_buffer; + int err; + uint8_t props[5]; + size_t props_len = 5; + + // Allocate buffers + original = (const uint8_t*)malloc(original_len); + cmp_buffer = (uint8_t*)malloc(cmp_len); + decmp_buffer = (uint8_t*)malloc(decmp_len); + + // Read the file + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/data.bin", path); + + file = fopen(filename, "rb"); + fread((void*)original, 1, original_len, file); + fclose(file); + + // Calculate the CRC + original_crc = crc32_data(original, original_len); + + // Compress + err = aaruf_lzma_encode_buffer( + cmp_buffer, &cmp_len, original, original_len, props, &props_len, 9, 1048576, 3, 0, 2, 273, 2); + EXPECT_EQ(err, 0); + + // Decompress + err = aaruf_lzma_decode_buffer(decmp_buffer, &decmp_len, cmp_buffer, &cmp_len, props, props_len); + EXPECT_EQ(err, 0); + + EXPECT_EQ(decmp_len, original_len); + + decmp_crc = crc32_data(decmp_buffer, decmp_len); + + // Free buffers + free((void*)original); + free(cmp_buffer); + free(decmp_buffer); + + EXPECT_EQ(decmp_crc, original_crc); +}

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 z z(?9KP`rCD4=B2$$m)?0b{qE!1+UN2Mzezsy{I$>Y9`Cn?L#$PE4cqe98VLKgMMkRX zZrL1jP_OQBRiNqDDQ=}-9+qo29}7Pcv(d&NBJkpcJz8e(m~Wq-6;Kv3r(WxJ%$K@_ zlEtCd-YlOXe8*aZ@|`QdH}m-UZr(?i5-eHb;ity~_L!8JdMvA|)1 zcCOU(MMCxSAF?ug#CBbh6R%0!cpyk`Yr-u4J?2|Af|#|ISFirVaa-em$eD(V0b&e4 z{~z7n@h!N$%C=)IxBA;cNmi#MarM4;Weof?vM;|5K6~oH*(Wus)8_hg9lNMq#F}=M ztvk)BZqH_slZU&*Y9;obUBdOE;@IYi{=$vlFDWiu@=9;oQBl{Y|6PMy);&?kekyu# zZ@)#@bRTQWDs_8fwd|FBS(CyR9S~5trN+5dMrX1Sc_fCOzPWRb=FYen z-dAh~ce#GxQrMVuUN8D&zsiIy$IF=J>g71`B;54wuatGV+{mIBTmN~9agRvM_nd^{ z15e*a=6pAr{aERMW`JaZ_VOw1jXBwA$__u+zXrcvk=i@|+mrq!{d|X=K3SdEG~;dS z(fU%4_@1A-_h0P#%-_G|&Su$|^TxItwtap1WzQ?-*%mry{R+ZV7YV$7&g*kcE+XAM zIAM9-%pa!FaYyU6D#$5!JU;k8VP{1#``S$lbW^jB303qO+cbWW$gAaUo)Chwivt}$Ht3ZL)(v3gr5)K$Ft z&)$QtF0FX<&EdSC$b89s{S)Vd;~3iN7}U(XY@JR=2C}sEMBRUuwJRI8pm<<%=g=R{dnP}aydn*ix*#ME^B;~%&oh}Nu!Ai{y(8Ce%NZPWZMesK)ou`L|DQwez$4Pv|PG zO{)l(<+<~wN_fgy zol1vfr=R|~{?)@(yL6WHxGdES)cW%BcJkT6%NBgIkGteUmoi z$oXBq5?BA^>*xN{#$7XSKTS>9bL{ZvA9GIx?3k{xZIZwV6`#WoHRa9qrpC?8Y3FcJ z=5kNiy8X=Vd%La*NOu`TYdH1jX$D?*Q zzl&3OEy-PWwcET}?(gp3fnTH#r2D2m`K3B}pJwe|Kg-D>3Om+MZ(PyG7b27v)BNj6 z`KLpUb-Ok!njxAH{?4nA96^*-)Mhy2XX{C#uPV)fJ-ymF;qZnk+T z`dWFjRQe2Fk%>Z|7yGwfzZwSWJQss$nF(0QCZVvT+lk1su zDejy2lCb3LwL#2UEE)f9h>86+@JYTc)ycxm_gwKI!_JGxUkhu#dXy|PrE<=kh_p2y zGj7%QyvgVnPn)3jqSQ2obLZ*>c|XOU-r6UTe+lGcaIxw!W*SpS@87IiJ-!W;jRx&LZ{+*GY!>bbaH8P3#HzwY1}(S6m~KYj zy~db&k-MNshCw)ZhPC~{{ZkrDLuEQwPR@RmTw8YJ&v~cqYbT2YJY+sQ&+wpPvyU;? zI!%)gp0{hmCYZkZ&VAf>_g=mmIZNW7cyKkEMrE(|wRx^~?Ubp;!OR^ur*C#@N<5vu zn(u~yW}DkJjg<}_%RQ(4Jrga~>c*e8?8DQxJtg~#b^1M$g&P)_{hYej;?d;^Uys~r ze%ZT9jNz|iK(qPT1v6^zJ4D?`-)O1xFGWMVZN9?y(=~=GtpBF)?&6%m#=&4^6aQ*o zO6PG#vD5>fwJaX9&UCtV{ln@6M)mg})t<^;uar|35nZ8ua7L!nm32pY9OT2A&25un>x89YGd<5W@z<`n9;EUh-{wQa?1Kk=wDKOi^Xq1cH%7>xEib;P z@OiEuQ=i#W)@S!#-SWH^UU21^QHP(G+>)rq<*FB=4)33P&`KisM9Y19IkA=f8;Tcv zc+bwUz(gW^@-CrIe^ZtjYCdh8+_L*m;zWivlj>mg_gi#tKfGs=&Tk^P&5HT&myJ2K zlebtLIQ?2ClXIu8K8i{_JKTFuYavWD+vEBI@C z^Q2C_cHGwos?Xg0CO2$yy?p(3ZG&M7uZUfQzVsib-wU^?s9rrD=DsU`g}Dl+uRn7H zbKRm$(N~)px)QGKy!=tlq{iTnn7!77(#@TRrHaFE98bPgyKPbRf48sFrY(YJE(gAQ zdC~oX_y6Uc|C6p=zw*}lt@lLX$uIjvKZT{-^ISWlZB^FNMY$_xp4OS6$INKhH?8g5 zohbXC1^VeZw{%1~LzIrmK3^lpAJ-pt#qXv=e_GhLI8*LTlb*F*-Ti=NQK(Vc4D0-r z)r)@CM;Q7W)n}y~_DXuZ-q(+LLGV*c$pkmEje9vW=1SkXyTbFo-8|7%*PkE$+~u-* z!#)2E)3x_rn?B>H(m2U)2dluak&i`@! zM$8iKlP@awO36AeESvXX;cZ)$4+i1|?M(d2tqTfP8{f>#RrvMb-SdqN%OXU(6uw@m zR(!azoO{+2v%}v)cG?@f_~Pl&_@KweVu$&T-*ZKIBWBo`#YAz(vLsCU&Z>P~*OxnP zTXjRF?7_wwrJ7rN*Zeo%Jmuf3Gg=-`BQVl^p9gdI!ZhcyfePHf;W2@yfpb;q)m1Q_>jtVnqn<&| zjA4EM-iVaxhZv@rzmm7F*}pC)VOxG*flq?+d;72ytGpDOwx*6552|@YRMYq$MOl4Y zU3p=0kGA~d-i6IClFFDEyZirer}=isa-AySU_6&{WLxUxwIB4@Q_l>EoXz6JnO>Mrwq5_bhVjaIw?e-TP&o$>iRPrkBr@Yx76W zsr<$HIe&p{UW7M`T-wUVdD>KJFSFxj-YFK7q!xQS@B4IN-Mqb5HEm{|XFgnTUL~LL<~_pZ3(+xpt~!0Tt_M}mKKd2fuZ_;CNX$*H29&kLq^yp_5$ZE5wv zqgn6PEN-1G#>Z$aXOdqs&r43SFoDPKrwPJvif~P)OE-{!eeJ59gY_U)w$P{PV-AMosg7DWqOyRJbfRbGjd^ z|3==JKQ~isfAVg-k{Gf$%5Am1_QHn##JY zSvX(3I+fz|_|9}k#wV*J;>CNEe2ZnWXCIW_DE;e<*v|zrvzJWkQr0}I=Ket7oTrPC z@foRYq3sW@$On7(|H`&rm3Qf_$;~^J)i!NkuRA?`_UV+%yua$Ff9>bA)+s;H$o2Vr z-CfIhTt3b*^5$iWPBw-mb)T8S=M=zhJF#P{fzvil<+2HZ5Gr6}V~9gxFTA46?=*VC<;3o& zs>V5&QSbLRSB3Ykv+wM!{_q`We3p>k9`S0tze})@POgMIbg6_r@XOmy}ZT!k+XRj`^ z*6RNCSta2S!ulHzevyk5;O4P3IJHn%^Yfm~%%Q9zPiK6X_T{q#d&=)!eOGQAW|$Hl zE1Kza)iG-k$Mv6)rhI|-l~*5f_PzDuU|;TSA@Rozb$fpZ>#+abG)1h>Vbue+r=8AA zJof+Mzj~6N<(mAO?K2)*U64?EZoDc&_@lpDl0Wav^@Y#Nj-JYtT;ugG<6^Sk!&6=w z+JRB~rz$Y4zu+&^u5|poyU5j>?8WD{zl>8}y7p%;bKlzy)4o=(DYocadVR;KM)3w&WdlPjnI7I@zrq6tMyt~V0VW{AXy?RXtAMhLvzOsoYV{P-kdCUC#E6V46 zdup^*ocH16m)*7PyJL5>D_t;i`WuqU`Cado#I1YQuab9PDDx>Tw>|W(zdpn-UasNN zkJdS*$qRK&=lqT+lZu5=hiL#jU{vL z{5@kQnzBPISZ38^DfX@!x#fBR+dl6NUdORyx9Ew^88c68uY4+VrNu&F*IXs{^z!DI z^SbiSohtXIdxuZsn{uR>@6)t@+dUslt+X_+{Bt^7eXde|=hjZQ_xHbd%%6FcE1IQ# zrtqishV$wR4eE9zr=O8~b9vRF1?Ll`=douuHS5hiu6BFk!plE7GE<8*A56GxK5^4+ zN9zk!*;+#Lu1t3E?fo3`cxiL>`R0p{!u~b5E$r`LN?mZC>9xy3BhO}&nAPnin4^+L5f$M^$guT(=0E+rppk;x=n%jo1d4>7|Lwd)A(JVxRYS(G&LC z%c2s^vh6%g(!uwht}4;``QK`j5a;KNkMos^>ZkFjpE_K)S zz8P4c9lkIif2nYH=hE1xQR|=gy*K&b@kN7^{}FR??FOF1{E3%Ou)dPJpP9QhHsZu7 zuW!ay`bJLn)e)a2*h?K3a5d&%r#o4P``a6~x~WGKIBvVTX}ZaoMx4`>;gmfn$GG|P zwBFpL71RG|UZ`hZJ?GJ6pWwrZ$NZ;i^=yx1)4VY2h|s&Mr)!F3bN;oxi(Seq|3UZZ zn(FT+)^aP-J{`2>WIm@JYj=U+{*!iAH-)d~KY0C)UvXR0>66jAY({R0BmJD)HuKzS zs;;R!Yi$4L@52sm>5bKSo~WX2iX zNjnQVGTCN4=~as2dKz+sgZ2BAOY2lp{jML|?fZb&*W=dRsmlCmlX=W%+`J?$R<5)7 z_ryA1#rMW0wa%AaH!dmUyt>2joAi9K1J2z4CYNP0*v#r(akgSYiR=2=8&4eDQduCi zd0UI`y`KfOI~}E+&lFq?TXUo^ko~;Ivu)RWm)JxudcBl!;U)h%pI5pEFTGb#ewMD) zSIL&1m~N+hVdnq6U+2ku*=P|^uBATRM)!-|9tDvP1yfG#l)n1lv07sEE{BINKPmo~ zG7Z<8>AWpt|Bh)gR+>|Go1b(H)?fX|EyHKJqsd8ya&NZwWgFI46sBoi3iz;6(nF{B z;p3pLxwmE=ygTj07Ck;+&e!&}ORko^OA*#DN>J~ZDSf@CSlsF3B_#o~F5~ahwRz6& zyy@X}9mSUcYTX(K<#n8RRA;@nshYj*r~8?N>RG2;bQ)cL)!r~RoGQAWL-^Dl zUh`9@uKbwlCw?~azTZa{7yDv=cM-KZM(N28>NWlsbyfA;j&4EB>dQF-dh%T{m%x_%!*; zWv7?LbPAuIxb|gH)!Lx#j?+)`ELCTd&7OI&Ev7TEMt9T7FP_H^DKa>-G#Ih$xRlSF zT@h1PTYX(jYtI_q^wMvAArt3ayTq70#dB`x{OQGZ+xhca3$)#n&Ifh1S3X{u66B^~ zP`@)c^!R!u3)KRp{I8n#^P3k3R43XPzX^_ia8krm&yn}a7fqed86C&-XFZvB|CQG4 zwN`hhtbAGa=|x!Tkpq>sJMQObeOOkuttVDrTfb^!&YH;|3!Co>?$S&0IhSC#_DYUJ z&c;n|ih?6vg(|3SyYu+f$(wpxI-3qAvmE$-#@B^yuG5s=vBs@aRkwaTW3|h=Us(L> ze)&x|W}58TIcch+lyk-1i&ard+#N^0`Yjh?(wSMhPSE9{gX%-qZ-0%}t8CtLv99dY zgdgRJ7R-85{ZAQ%&tBQZaM?oRGIwXr(tt?EbCvm4xeb*EZ7#(8Z0D0!biVd>ZIb)F zP0C%~_hn5^_SnZcM#|L5{3!@NZ+w&wNLFU{U@`B;3j%)He{N|jD;NZfiwcwM<}YtOD5zyn*LSA* z$&Zf-r(>$W_*yY5?$mBocy8+7^v6Z-^sdGQ;Vz$|zfV2+=jid(2HW;OxBKr=)yB4g zQ(66YSINA;q%igIjJ~c6U3%TNTiJz$j|%SI#%>L9*x1aB4e^EuWB?uy;tzhME#?td0%EsU;h>i**tZ|!o# zDa__zRrr0u7v-7O;eURfwEO=vW)nwpGV|J1De8ZXy)ztUDFj5?_)A*<(9GgJVPIWd ze|tgd#_%QVn{9PAMZVyuSvGIcjOHgZdOv*Zw=6SU!#q*eVeONSWs&yH=j1jDaeFhS zdwAXR4cesttci7w^(3LQrw^o0`0pI}%)fAeZs;-%B9EW1EDNWVDwx62jTsKN!cnFT`s)AK(6zIMZ%*DJO*Jwa2*`jkV7 zKR5R){WZlO;_frn&#}K<@M_hwKDQfza?LhPteU#hZ0c8RcDll7z`CkB-B+{nhQlkK zE!>-Wr=MW|KlPjb*+WY;e$Rf{Zr{3hf%ANiOdU@C>-CqF4mu^TnclMacdqdg{Q$dS zZ^l>^t*jZT5r>L>-dX52mb(=%o07g?gMXDS)1`0z0c+U%Zm%?z==sre`Ho@9w8;DU z9W60`x#aeL%DL5Q-x`{zP;|fS%;TBbrR&z5lVnQcU+-PCzb<5lhC!|UJ=%A8&*kVj z>wuqy(;j#99sE8!AVjlr#-*9bM@;Ty&T#oTGjGw`C`sc+VQZbgpMtH`($u(CE?nek zD64aG*`_PZH}6jRQ1~M8FX}^O_WpUlH?p?AzqwQ5+2@;%*M+UBrZOjQ zXcUt8u{lpB`~I4_YTf+`5}&!8l=q15Vx2pa@2xNUz4qsm7^nY9Gx=iDnD{&D`^o$Q zx3Wn)eNMJ5Jezy--5C{zM~j~aNw1sB@O4kg`g2m@?9(3fT-VEC(#<*TV=Q~|@3J(} z!ux(FgSfmm9I5dWTiyCp@695oUCN&}DKq%3xWVt+{oUqC^|!~XTQ02(c(B#c)$;TF zQ;mz?cCydbQngKbk!@Tgrq$wS3Hw~hr%ZY!OtWA#yv+u1gKn{9@{dC!k` zP6=`}`!VkE+kL$&%Du@%@lgYF&@%3WPl|h*je;b-&(su^79RQVb$;8fI98>S#eeud zMQ-7Bzcb+yTVh`REUz1jXE%Lr`0w4iU!c7Em(10d>pto5s81GQS|7Tk@zT>JYv0%8 z2_LCle=XVS-1)Trm68P?UvK7BcR0qbyLR?o;e6Xu7k9)9yjreYwVA2RZqt>&@lqOF zC+2*~kzeK`Y`bttyw>{Ywak9s+CQH6TeiMCTVVH(5ZAe{1Eo|7_qd+;ex{%*b(Wex z|30SUD*Ly1nqR9_s@UH9(oW{f_19O}7t~fi+#4-6y+Cimnmx0UJhrJ_J@&#SuOQ6f zYh}Mu$&4=>T;lV^&(|n$u^-Y}(08rr7+3MeCQF9Pae{B|66kP-az^g{gqlHQiH6K@ZCHN)lAVe0L_D{b6+FL-9f9*iV;vj@-SjwRfp$QAJ+p z%*V}+ij4(3JmOr1?z&CXueyEcz3#95-fGfKeUC0OA96KWeCv6EUhIR6>dZsSzur?^ zbnw00_y6->Eah-*RhcewLfncc*vO)La?V}bUpE%ccmM7--`Ju&$mji+<=v&cOG|4* zq}xB|WGCqx@<+RJF#G(w|1DH1)=fml@7Pg4*7&B(*E?7JR%DA>xlW4f=ykq(Iz{C> zzu)ZHwtKqL+O_^df`ZMiygFZgP488_6F;w`Ht1N*Lg_^^MoE6x9(G`=-~|x+j?T3**h$01+XpC5O!K@IO3pSayBrE6sY1 zOEL;3`h7by*(;_0oY|?^x<16`%sc12w^;!yYZhzg$*oy5lU-8jv}W-uMayl+ni@~M zTvlfy?jly()4#dviNdvKyjPx>HcpQYo-suzi=)2w+ncVb0bis}-90tA^-H$UgISM6 zj_7ob$8qbjY-6b$+v%T-U$c!7*c7!1{lJ=fxy%FIE@M&F{>XiV5iH zyKQeKCVwVnO73LY*`?8jEMjXG@$X(M?$609mAC#;^RG=#{NK;5*fY;P>*6P`9nvR1 zt#SOauKago=*IE|*{kxBb{zX0lO8a8%2~JQ)*CWvv70CShu`u$<{=gGS**1u3# zu^{s0x$DdG^;C{{zYT5)Nt_tawXJo5TPfF-EjEXR>m41xt=_$iS;F3~(t}5`Lnf`$n@<#r14&T)vFZ~r7Qns zeky*iP&wtX+=U6!7hI>kK5fCuXnpdpt5;@{jcb2JVxq1A+vD#ho(qA? z!=~-kMKi7&^C~XQVyb@j>DhyC$?3O^QmpSJ-cnmW|J%+ojnyy19vfV>U|*EACT){g zYXr;JECt@ZCqfb{OkeG|YLm#P8~a&&zs8q)Iq!B)kJa6*m63Gr1Yc?6{f%NPs>62t zziOi4ZhYauY0Kz`9+EFk@maoEsUohH6rujNOi9{bLt5m(tq;yOOIL6&da|PDVf+js zpd8Xxpkg)G; zXTLD=f3TJheYpD3?L(YDrVIL2e><7cyn4(1@`hO-q|a!6OA6R}w>^2$Mtf#~uKVIo z{sxuqInjCWdVMIvsW<7n4}Fe!bhp#x#^gV`EnjZ6YQd9b)E`wKTJq85BQb$^-)tl ztF8Iu-Ft4GvPn38O?+Ki)oG`LM}D6^!QLTc&!H`UNHulR_e_H~7piN{o26X({?{er z#DSl>EZpA18QZ4Vs7zJc!@lZP7jD;x z)|!Rft68IcysFDBGw^J@mEN!Ti7%>8q}Lj=-LDE2$~%y}67R~^&ztlM{Kbxb@Vgyfaq>~K!7bkXEA%(Ge@{u) z`mLYW>bUZcTEZDGE4O98`S)GXQ*@>0TM-P1Mf zv;Su7S135OdYQ;BokiiI^$Eoyz1tVg+2T|F>|Wrt*>avTe_y^>-1L~|#cr<2am)Ap zJUQupHp`{(>RIN;7MdNEjM?91q~o?H+;`r7R>Q;Hp{zwb#_!KIA5qw4BlrCpf8K(k zVCi{r2`6g<(w-hS%{BG%Q(&V_kbeD;rv{}awEfAsM3Z0}pg%Opj!!|$$FpWWN$ zK4bkFSIwn=o%wsSc9f>*RczWY0&%xxoJ9lMlH!-s_ z;(x0XmAoxxb>rpD&r>(;VG~-ya%snf3H%RcT)NS`<{g{Lo#>^O0pf*c7s|;sA7vE( zGw0|zo)=G?xii%}E(RaS){TCAh5h0tHvywZ7q*E7{pw#Q)taofZAO6J(xOyDv19)C zwr{Y#&wBmfACvgf`g2 z5Esm(+SbZxpZo37=~bqjV(b?TMh__U(FbK^bZrMDOybUakm1*hh0v%B%#B7aGo zs>$jo+35@B%FFy%IrmdsvzwP!qibs0!(EEExVZ1SRqtgqIaMHSeeGm=l3@pvqH%7u z{Na7;gf=fLG@0FMx9PEeni40YIDAKyQP1)YHop^N9a%eXNDV-%VNZ}IlcW` z*UKtO9(okUU-A0T8K-x9=A{*^jQe}}-9`4L9$F=PF3c0Q=V%L=zbMZ^y znW1e-Z`JBrCT-uk^U!OcAlt-D`j2ZXrXzjA+k|4QuSOLy{)Pgl}r)^1C&s zuySj}>blUn>CtW{XFOZ-(Z4%WAu;E8d65ZB{+XA5pG3IVPHWuio=B$M3L7FbBMfuF*+p2~Jq7`T459 zOzEC_POf^mJz&6{xPbreK2QE%;*(G-I!nzu>vm02LcYWnwy5)0c zZ>LR|W1rxY=YMz`G_#9iE={^~Z~K3aIqUK*_U}(@u?V=R*Y1|q`_FT2#6^zWgZs8V zOS$hUV_5llG1s>3rAJPe=T8%w>YBv=LrhG}etl$V&b8CYvudrU+^l*nEOk?Q%B-ac zVrwVf`S<49b(@FP8=2CrPng~7xVh+wdC}(t_PQGl9m>BJHZGcaMqp09sno(b3IgZn z9X39+>DSco=xvW5dYM}kJeaa%i{(8t&-?Wj`X@ZR;?nk>+tKjGMTqeuM^CE)>j`1? zIfqYdI8kS6TNSBmdp~KVjqcdne@> zFP$oPw$!`k@3!~CRPL2-It=YSXBE1$Hm#}==#4&+u20TBAETlJ;aJKYZ9%sk^6p>m?P- ze;fa=x$#nEHMjA*_jQ>&W%N?j3uTVqIZ^oN2m7+NSXIV#NqbE1vwOC?yqe)G=;e`} z{%LK_$=JW2($@aaD2H|{d(-r zH7RxP>$8V{nJPP;sEz*1B_Xxb=V)&Pjp4lQGmT!o^-T6z^*-v)ghyG2Smu0?QaNlFSZ;{GJC5@Vm zYDafAF9$d8Pk6*BOg%-!2Wrum2WjDC2V@!^J5S!?@x^mA;Ypv>OX8Z1Sg}hAf zIHe`1^}v0_jmO;b%NBXRv3}F_>()nZtM)`;JD-_X_HyrE>}|H;=uBzrk8iwt7Tj;m z>P~v^@;9{Mw!8n0t=nYzAH{z6^O0L4W+d;>E^_SbyT|@sWx_ig9-001@XhJJIw|vL zbHus*VjJqVF5IYV!{wg6Q!QC#$EGD0b~@f)68mwZ-fdPT(Vv~A%~vL69+@k%uU++e z{c3+zhdt*`waQLbI+~{W{D}0zik&M}Yr+_^wbmxPU7pc@$$9A}o5P%kZg;%$d3;^O zQ7=?(cBE~Wgz4Pq)D;h(3N5O$`6s+vzb08>?THuv{xaQdbGf0SAFZ@&s&|NMrHv`W zlJwIaG;zR#5^7{9( z28cBEKYxBw`wLUO)^4_vNH-Ps_QLQ65#XUc5)eD}4-CoYABQ}}YYz1^?9e|Xuv;qdpg{-Wu2d+y6moZ1{0&9Qevy0g z9bN|goK>YfNzhC;aLuW^!c_{#XI6ffH*ZOvmH zk970Z-&Yl`tTdh56z+ab$9C4CTim^8BA>5Qb$k5aflSPcpr*Bl884`8_&(uq&(ylf z;U=4}EPi`=L)R+nz%91beN*2}YQM6%!ffFpH^J!rU0*h6uvbm^cG598i|NG^k-59J zNdLclNWR>&LVLRA`B!}(qZXbPky*CLgfHH2){Erp{-0PRTKj)S{vze$ z%5Q|0UzyV1?flIzqhn_Ey_b@YuNZA!Jn7Iiv%db>_dM=y`~B^05{FvKVvD?{tj3+U z0@m10op;*z+-sZ3g$89Su1=mi<;C7_aUGNA+F!hTA?2p!!{7}c6r5B7c26>&CB1O5 z)FM->$iDCZhg0(zs(SX^>6X2>d{%EsRZV-&=~I>Wmd$8d<-p<{^K0_e(8iW^MKj(v zFgY&kPHnwCo9xeQB z9&|BvSHQwM?o)kkoax_x_S#H_(_eGuJjmK~$64{?wL|RJUbS)@s5mEdumkQ zUdD>0shCviKB>DeJmYxFab=-)X73Eo(DVf?Pi`!;agscIW!jmq>;K$ijZoN|WO0!988S}pmHp{re z6YHYNYA#RzbZ3FxDqX8q{>sKb)khUW_)|Mr|Gd&qDR^{u(ypwJ(+)FlU1I&hGwJx@ z6<0Tx{-4C2u=ia2Mpr{zL$xkI$80Bka z)y*+TU6%PM?>0YoSK|R!p^vgD*{ei&L}n$QGW{zgm3a8>_kJfm@0BJ;))jTf{|=Im zju$@bG*8~--sYDZj+I5+saWCFm^k-+hpzM-%{hi~U(!#oxNZ8cHAh+bQ~HJys%U!(KuKm@jy%&D$OvlruD`$!6@(6M>q)fUZ^nHuJudvOFf&%Lq zkB?56y!P+eiJgKr-G6&BrYuaeQWi7|Jh*!OwWhlVFI5`VUrF4!fXAF=(!{>xehxO* z3o&A+1k=?uH%kleow{g){e<&d|MsdVZ&BS}({wF*qp5j+PEu06MN!2h{;+J$ztzkl z3Jv=2;^YHbOkd9KXv{P_{Z@9x#8t^*5}LBtp3OI#!Nzp^$zR54<)w=ZCdI1R+g@CD zr1_)ZsXft8?BmbIYu}6Cz}u<4u(Wu4k>M}Ksyp`8?2Omsr?PLeP54*JQ4pAS&`tY- zRG!@0NtOcg)w{Q7&u|niHNIu(Wu}&M-{>_2g8Pw;T&}OL5RtdaVZ1Clv7>{8# zQ%>*e^9d_r?&>^Yl$(|@OSjv}-6u?~>_X3OGb6*bUl*>Pks!VHvwMqykwMWLrnRRx z{K{UndiKNe;;Yv-wEfl9TX^M#^t~tT$3l8)Bu*b?T~lB(t^NJAR0Y+#Ql`mi9OCBE zDT0OaKjm3mZ4?~0@3LQPtFC+W2IJ#3s$ai)7?@nL-Y!x3CeN+l{6XF&KUR7FTv~Lc z+$Ns+T-Z8;bE8)?7Rw%-wC%T9#GD-t6Lr?<+BE65 z>2!MU{j2u!i|zdKEql(fe!6DyV@8X}fsz&b`9f}XJwCotU~1ZX2A9SUi=F=Ey**>X zQ|WkzL8|w;bm}DzGd^jKc$cgF0s3F%ybk~MJE_=}ASQ7%k*VTgUe}BXrSEy(uUse~ zofs6_TK_anM&y;$k>jDa&;0J_oN)4*s;|9G8_p=NS{qUQyJS?I2XAk2Cy6^St%XOAx#LHQ~`foioGC%e{<>l3UKZ(VATPISKnK?%zNTOgXo-lXO4V|m=;!`bS0O|I5}yfXuPY{2}Vb=P=4Ku8GgNv z%|Tlau626$%=T~pKZo0rbN!aOE&mwF@b<}Wt^(Vqn)(K}#Q(y3Kr(Y`X%K9&>w`#3>Z<+OvTkTQt zw4bF>^O>rr?>9amvF@yayJGRgu)9vu+8^{PpH2Am<)lzvA7|+@{q=h7HPdfh^=*tc z*s$Aajikv;%VO4;wMtf+j!vxZMgg7=^dzrD{nap&eI0+9(f`c)ZPOP#-Q}Hi^39W& zq{Xo(Yuh?k?rx2)x@Yi2>BMhg9)Yy25|uZv9ltD-^+~}%?B257f$FPof4P2V^Z7-c z*W9$(KD0X?J?&6b7qZ{r!bg(^-fL^UAMULa=aJav7Ge3!gE)RY z;4AYrxL#Ow_0rb!W&K|rJ_$1YZ$AC{L=0Om>(k(ZLl<*hHgq-K>sWnl^S@;iPJOF6 zmAXXE<=n|1Z@kq!&pEuAJi%{rbv*B@{nt(YT5{SNp8jKfZHBKobg<{ zsgu$6r1*<3Aya>Twp}H|vgC|%*@h>{6}rc!X z&3Ss#&g6KQn3wmmFwsx${?mV!wD8@Gp7CPAgOutCOcx@Bu_vw^|95@ zxBR(R@k!E7+Va)>d->m`UB$akKVCh_^v9aT7lo?A`@)WBI*QJYyEpC4#Jg67O^rPt z{40EBT{-_PPQpcd(=XKm?Nxmo+ds8L|LBRT*;Hg;ve#|h9?kbp*BxB{DQbJn))T)a zmu_R7vg~2NyWCGo#dBXyc>ajb<@d4hSF5@vxG+3eV)*WR&)p9Pjz03rGLKuPyt8lb zbFrKx=YxB%+q0a%v)SN>-t#YRpB9xo^1QX$-Se{dmEgvuB_@myzdlq6Iw0VF3#8{FPIp)GnW7ua@0%K%q;F&#?UN<{OhW#2PNI zWmW#sG+Sqvmc4RPeB#=oU%u6^#9n{xmuvm;kITMNa3R;}i7M}3)}3bi%MvcC&SK<$ zqHm|ayq~G)-@4GFuXj3q$a@(sG}l?qwegT?#?Q*B#lb8g>bvdcoUX9)$%uT$&S>^S zuJU5XhJW{ey}K`*J8|}AQ~Mo<4L{aAcTs7M{nLEP_0EaofAdv^EOT$}o08o8R7l}x zoBVV~nWZzr&N{#B{89bO*zw7RD+OmcTrd8vdcS?M{jRMdIt*4e!SyzN`su}f-+o6& zMthVmSTXJO1!?Qsi%lbxCuCP%IksAq^S}xQS=C&A!3T4_=H&$3`1GxR*L8o1@B8DV zFMZ*iF74NnW;o41`T>(t%r>@mkAMwEQg&YcRcF+vPjc9|iQ&%oK+l6la!t1K5rUR83Ur;@pcRD5c@{c6@)55;-?-8HLNIX`Ir zzxbncWnyE>>}+?zSAOD|(lV<;ReV;9UHrkgGwx$s^0lHL(>}agcYF%d#z(PYJHNLV ziE&KX)%R@D776mnLnzdOI_z01^mzxL4L%}R+&f7+c_ zPM&Z#rbhf*>jG!1?H;__XI^gjb>@V-TIofm0+HZc<)n_l{|EBllmZO>;BK!0I z>F)Hg$g{anJ}W{wYGS+W{w8^wy$2GTXDF_9d$&qv)nmTqn`%YAK~aqltB#&)2+?2c zxb&!l+*0McGXFL`$p8E8y5aP*y0_c~a_Gzw#6fx%tPY$fl@fwnxu-Ycb{BhY4B7e)v3< zYS9utre`8xELL*e_W05%RiAkMi`}9V9;@`Ml__c#YAstYsb5e3(|GETdv1YCtR2>6S1eV&2(}hdvEr#%kG&A*DSv4b;s%ZjmBGh zbq+82RmgH$xsR7s&b8^$=jJUwd2T*ITYe<$%j{3&;e8OeN}R1%&c!=7^FzS>voHB+V@>@|JalfJJdHSKfouU#K*hFp?4 zR+|6xR*Z4YIcB-vr%c?IKK_xs=#1q#%Z%yI{FeA8=PEq=yG|uL$&@MZVfVVsJ?n3! zXH@KdA@Wi9xXMMZGm4W>zxYrjTqZ8zey!yB{*_-1!Y;PwSzUOdI9uzN^B#A7-G?`- zUN_opm5g0(aE)`~wZca+1~Q+{mfQ7qEm|hHyXp-KV`6d0nyrVr9&9Y@SaDF$GdEIy zl7jmhgKKqChdbwJRwbE#`Q8|-@c2S3n??IJQM1|0CS3N=OA1h0$kl%5>-o5x?HWgf z>o?53mf3t<>c;WNoey>|$ZNRMel1b*(Zye!hud#7yxzrGt0GnQNJ(?H=E3|YRva%C zH2lH^Cn-F17j2Th|KZ4t_Lz&6_Da0U+RPr-|FjOg30};9-l22)F1G4W2ifLD9Dme3 z4p*7X`1yH*6*{%sYEVo*-Ugb31A+^6P zDCV?v?3bB$JYOm1oH;(}L(KJS+yYl$FOG^Vs95`c`Ax|jtMvv4r_|oRvh4a%J4HFE zpLtgfeO|lVUNB|nXIqiy?=M_%`&KuR-RNKUi(8kQ-A_IAc9cwe{rL1o2j#QDPlGPW zF3vx#wwWd6E7PWw+Q&y!tq;_fR2|G_S~KB$C)1y8AIiKxIX}%mm(TbhLO=eUQJzMm zD#w#A?`0nzb8WaRI^mG0)Q=-uuN403*>ljlZSxe(neEk2t5+q=`q;eLeYJVZk9F+T zE5!HN?^(cocJBV;uiV;G&Q}RCOpJV+yK`~Tk@{mFR!)?%I&S6L(iwl$31zV^yrB9UhSXje?4Q)T`C_U z_LQx3$Arv$dsFf5UB&l8Ut2wH+33{LzwBRbyME=F!1*<4bFM1pxRh;6VtaD+)T=dT z4~Z$hb9P-n;mTyO=sQn%PJFkw$X{W4*5u=ybc@FQ%f2_A>wm6LA@;v)iks}Ow;IcI zHB2id*GcJ>{pqfs#ryxtrimkdeUphwJ={Z5+EE2X5s{3v@qsqMFS&PGVt(Ow(+>gz3K-kDWihi>J=;p_fQ> z)4P(xi)MC52?)6xUHsl5p|a-g-llAqBO%9c<`wQ~-E9;6EA->x1B>Ls9@eHcJNz!;|yQLG8cZ8dyn)+Y1E3GYO-xysUc~*%`WN6&IY{R^@ zYCo>>P40Pcqd+T1LdIuvp4)eA{gv|i(Gfda!osdr9x?XbKB-)AZuP0!u3E|OlUFz; z@7Q&!Y^R##jUBI-wVG}$xmj3sQAK}Cpo5Lt{Pqyu6B`6ps54LYF%H}F!^UVu;~Cee z()cJV>-y%Y?-toC`Ns5a6VIyh+M8R}E_+#iVv73zSOwdJzrXFK1p8Hf+0^3s=fN_W zU3DujtPpjd`8~AY>aL9%zg{K9P2j!i@U3pamdjSAZXe@9t=?RZ=4T6V%30nv`InWQ z)W(I!e08*SLVnrX7S($!{Vwvm_p0B$_cLc)NSM<1CtO`FJZ+rtDaCstvw~Tj{e;YwUxZJ+33{sBsx7*i z<#NkSKC||F2_GW%iX?3U|DpKe|}n zBlU6Ve~T#xz6xtHz4+_PU2#r9x9>>*5?T3QlU^IU285oinH0c((dOAs%g{|1Ryw6O zT-ov>BUeg7_s=l34xH!5y>6t&enaOGAu8?jGE z^_&(jEHAX7B970aq4mf3ax#>BWo* zVQ;UWv$2>sVfU4TN;d`i3QDBca&G!~cNOC<9q;0tpK6U4pCrtCv*6tZ7^%6>hbXUF4H(LY&Lb;X5k^*3M0AN04I-1%IpPu%3xBmNm#6SlK=oqZoH z`Qw+DuHigE2lfs774k}Y4*FGfsg`HYdA%X4mmz3T@{&Y8zo%t0*LH3+osbsPV0B2& zOMB<*&a>9OhWCGJeCrJ65P7+yYk`?}#z*b@SpE<<=iQ;xpsP+ong~QsdM*w>;`t^M&AS2|4*;9@2BRy<+S=GrK!GF zc-c*jM}pCH)>jTh_0IfUbvS0hYZ*(P@M6}>Va--=zn)i2w>K7P#{(NCKL;qaL!SLNH?%LMGdA!?DyNp+__D8Y3bounzD&>lX3Wglq z=US@2#C~Jo>-I0KI#>Jnm#AKv6f^IHqsK1kG5IqrOZ2_H+D}7C!;E?NsgDm_a>aPg zD0rPz_bPEY>EE{R&7VgRT}%=&wTsx6i>5E0W$|eH&!gSUrR$%c@Hbf0Wx%rQ^V!{< z(-aMj?<#22{r)5JvMJ2s_R;?EJ%PUQ|FG5Ue8k& znU${$C#p?8f993G`nsk%*{g+5y(9VWbpN`!=!^$@<#o&ddQW}7Py7{l_(7%ljs4T7 z->;c?(*9Yh_CC3|4Pw46?ZLaG%cRdK6{IjfUHIs|%IYkxttkqsm2a8L+#gF6_%LV* zARldp>Xo?%GN){DpgOyBz|;|QNb!ubw`?C2YB-<>Niemm)R$A9S? z;=b%EdXhp`to<^NTpSU-v0E#byQ``*~fBZ^4N#Zx38Fwy3%KVPW6u z=0wSQx7c3?8unC4a4Zp5cV+V1nKk2qd)~ZxlMladoc~!hzbfO{wxA>tXP@Z3vHu&A zotsKpPEIh_ND};%v&yOeNiHcru5S=_ z|LUPEhp+woH>WZ0?wv6CQ50)-gi}tZSkmsrITIw$@H?NG_;Z5%PwFdN|9N%~-@EgAjwha# z$)`V0-mpL~sJY=o^Rwh%%cHKWJ-2ja-|x4dEN8rSxOsRVe+j2|=F9v`eX~ETJ7c8s z@c{p8%~>K(ezaITRbG(is9D~`Gf6>YZg zR$=eneeYnE(N@+yHL3WZ#r@U{zWpbUtDexWPM%b;%`<%F_KC}7tq;X0pUk=C!DDm5 z{btxN(Weuf?~1E0x%qNZFvEt>qd})H8K=xz)pBuNeqi8iHI`Fq{Sh}cY}X0}H8^JF zK9pJHa<1yZ1xI_u>!neT*bhXwov)@)n&Fhp6ptnso-hBO zNtEB^S#Yd;!R^mNhxVIJ-JyAvOSRyEK~L=7{#{rB3jGw(5T*Y#P3>L(8EEqe60Y@gGia9bzyjCm$Tajvs2rQh6C z7Z*L_&AE-Pt&fgNy#IG`BXfn_flFT^^U4?wCA&!V#^%T_TR&-=&aM5^m+uWbY|F+W zF4b9oP^jtF)7?k^o>}A`diiDKnT17fCaEsF;Jl}J7F(29Wbpp1Eo^o2ey&Q2(?8US z#BUVxTW+_y-F||gPqomJd)`}SdWY5Biaqw4rD46;#%a%l{;A3`uyCcgJrv5@)qAO6 zb9+W$Z`6(h0`*m$h7;`8ueXZc!@5OXmG573?d3{FgWC0cf_LLeWK>s#Pr70CGM;UE zuATISw7aEd&)Cm4&Ffs$b?E1*+RP)h+-rXKCoVeny(7(LA?GG8wL@`rA&Vcsh_q;J zk&a^9e&4uiy7s%%Z@-57Oe))L!nx9W)fdAVPbV*H_&wK;^=$on_aiZBKhLaqSu!Wp zz;aT>9-%$Q_p4Ud+Id(!m8 z6s7OX4yn>n2ixwJOUQvUWD78hl<${@u#y%F~h70edXs&-K-+6t<4#7iPB9A}V93GpsqA2qHk~T}Rb0;Tp=Y2M~x%5l6 zb>Y6_k8h_ki0l=THF&aV<^k^J#2e+(Mbp_HMhfn6ko#6rV}IVsM(Nq23zgG)^qh*A z#e+ocZq*dBC{5~YU;V-6YWkEPi%zP?m%V@awR*{K<}0V)#|X|(Rxx+oTj(=UacS@E z!)F3xce%d)_xIn&wIS0ACQH|txHaY+X`OETI@Xp=h3S{ENtW*y%X@P>78TkABvy(} zD{Gt1V8Ql9)FUgvEiQ=p#Jr4Cj7fXB?K}5{I0~%Wb)u``R-dCO8?VN^WeWLb75=aE zGp66FXTQL*S#65iqV^G@%7RUpy+MS(+h=c; z734|3PTO35I_UG1;{~fGOk3Z!apV5|245SGo!b72|ALZUUXO0sRK@+7_x$(PZ0UT# zay&oBNu#_sm&!+NL64 zcE$5$YJS{-@gGcOHeBQIqZplcCbh(n!*ZB9+?%>=&Sb@Pj5DXs+pn(?!+z%Q zhQh96FE%iQdkgLVl%Zv}J$#bU4wGwP9wqM?RwpvgQ%$kfof9YVV&(5cto&zo&seie z_^kZ9Wh{+h%g@>Ujb1yeI#StDQTL`GXHx%yl@SG37gRi3tucvv<&Kv}EA93LCp)J` zIMv$g2xisCO`KTNeCdStVo%Q9C7#0ncFLB0N{?cTN6Svjl`Ytt|L#HDgje!sKdw1r7V^2Julv)^P3z}YD!uUR=9}F741uCao3BjDx0N_sI&W^tG2>fhcP+L4$TaS`BD?O2 z&EcvyJ^$FQX=%4*a4)@ja;{a&rKmTd7bYCq5cx%k$3k%5j17;<&mR1H^Lxq%=^Hm$ z6jt_pxmP2ew1M@h)XI9Hb!p$WF34V!-!hFUR6uA!UUHu9gR7g5%uY@;tPwU_rzKNW z$KkT#klwsms~(<{ihkH7yCAgtN~Qm8mV@v8#DrNGmzug&NLHCYcx|7IZtm)mkU zqFAMptkbn~5`Ho31g&!~JTbTGL-If7V(uCj?5zF;YHdbGm$fmiUqY4fs99`ZeO_4mYl580JFrGss6OFs{K9mFbV znY8Q6qYEz*jtj40H4+idxyKUxCt`+Ut+2&h#_f(b*b8rNb36QVr^925`;6;^eqN86 zbzy?W+wJrBChFd1&}+KQGQT<j_EILpY;;oGngSx}o@92%r77dB`qwK8H;OF0u>8-at#h7C{3~%%LGaF&wy?D&4qMl-RNRVBTm;FJ@yT0u;+iehGv^4Wx_8Z4H3htYEw_MkHF27ndPCVgUWBUDf zsjD}L=q!|0<$X6*xZ>rrxk8>R(wat(K zp_rYn86YGf{p9rXxWhTFVJwS|^gT4Jj22mVeTrT{Pt2U-p3B8Ispsx$TNk-_OUbQ2 zTg1QSawtsn=8d_2>XY;PH+NRo>|U8FdM|U%_9b=<@p2y9UY zyYa@jY$@LIaK{7%>*$Z4TfS;!m(60UQNFRI@!P7`ZH3%b&(=?RyIv@{W<$vHoM(-h z-db(7zG18vYI7Af2g=M!Z*x9Vp56H2R^H`Cl@KSDV_sXLtXD5weq~p^C5xp!PwDBj z;8(e)or50r8Z)gAX}RF{`LbQQ#FoFl_62vYy?lR0(`i@MtpoB}&!)S+)+}6Qo%~e# z=(-ykOn+8=TeEi8@t^H`gIS-S*s_f`AneG8rtkdbi~s#T;+fsVcD=0q#Ueh5qlH1; zuRC3S@f~}*-~Zn2-E+=N4tc!ct#Dx8>*oPy>!nt|yP2BgH@|5Ucjv_@uGFPs$_kH~ z&wO0_q(s$aHUCVTmbLdEl*<_JJZvo4|5%9iv|Je9p%b4avKU@m@Zl~p6Ir+9#G1Qn z?RYa4JBySrb$Rs!9lN_Rsi5ybxL~sVP3too<}9!O+wM6j>e0if+=(B>K5jJ6m~k!N z?7ij0H}elX`EX6JWAe+c<v*x^O~UI%oA3VG$E=wUQEYxIERbAPV^+t0F_wK?Pb?I9=b0+1s zdL4ZH>;8r4wf5|5)F=MG(O)ug(*+~X(oC5vSCU&+nHKI!o<5t!=tpq7(XD3-1X9x% zTD8qs!x$kdIM1hzp^z)0UE@g0@`y!IQ?I!MY)?9VY>tBBgU?I>)BY~7b*}0best>K zgg`;wO?y`e@c-OkLQA9JH|x@%n@y?FYhO$E{5zmpwk3B? zfy#4_%bC{iuH4+SB1XXRYk22>WsVmmg?kQs*r_#9?pF1mr+0H*x6g5k_$ee`)jlbi z-R@UF&F>C{Cq{C{9TO`EgElXu(oRz zxZYTMQ+dU&=>D%YA0|iJvNG$6pHr+~a$rk?%o@{l;oXZk6HUCf-%lye^;whE=^)tj z!&+j;j^(MD-(DD`f1SI*_6rM(alXmpQy1U(SG3B^<9kuYbt^3HO#wH<8o{nYrkvlm z!u2ZO2r;gH8tiPo_w}Sd`{F9{v=BiEU4TKOT5BWJe#DfnE-#xaA(SG&e&is9U)edX_W zcO`c<{Vo!<(OGFfN9kJ8EYVEQo9{kv)7j|Tx=U$^bc>GGovnAcrYx+U-{~Z|sQrvY ziTWx3uaS3F&$Ep15_4s#F8-`iZEs;!_;F3rqsBk#*(S-8zAsv!eV|COx>Pgkb4=B8 z7IW82RVU7VHvGLwVcVzm;@{l*nf{!1H`8EVJ?-&6sWOQQpOx9ACOM`3;`>d^H=TVw z_4VWWE1N{^oP~~myiwKucf;m0GMirh*ss}b@H+8hQH}nQWL?$=F-zZy#+3Y@dtz1Q z)2Ag0dEp1NzG;YjIM27Dp)}=-L8f2mqM2z?YVG_>x`bE%=;PVpl@!nMSrXeeS$EcjH?wi5r@{AGw!yZrj1w7UV0MX78pZ^q8w^H-qlZL!sX` zt8{NZwX5$~jBCT0-7(T4ot{Tt&bY{Ezu?H$h)WiJc6X~JI3F&5=69=RmZoXJD~6RX zX4ta$x*hm7@8@HagJCU#R)W4)85*T#RWjP!ZkhU|HaY%J`hTs+uAJYg1)SNr?zeAm znsLm_Q1@Z@fmqpn%i?EjD&T!DlzG&{ZK>%!i5FU3E8a;rI!t>nwK>ga+tYpjUcIb6 zUK{)?^uM;x7Uu9SuKfmE=H+Owy;1Mf96Y&ttLo+Vf=#PD?p)3|G(E6pWwv0(EotAY zFE*&(nQ%0r@qg6vX^L`dvc9mU_yyY@zL_GcZ})VUnM6{k#q)g@9oMEU3R*Pl<)6Io+$pM2)I%zix6a+3L?=vKYW@+$@AD@ClmA?JJKmHM0AM_CqjJW#q?bi}8WyH89$deszeV{PxeI**gzbjx$tl#a}gbpKY6C6=ag{_U|1(xFE; ze=M7qX1#Z1D=ZuI`N!(-ssU^vaE^DQ>%YFCB^851a(SwE0T&^z>5V5UqJ6{0X}d)d(fNskdk7JTZJd*WE9%c*iu=BR#vG&av{SGT=^{ zCe*}L_5aM(#xGyi?X}L@zcpOaP%py2ui?G4Zi~DbkAz68xK5~yvg|sCWe&5}PL$F= zz3tFc-pSn}z6nAX-zVN${%U$&c-7?Ga7X{1f0spr75AP^`ZewSwAEX8*-!rLB=heO zr=xnj*_$WK4r?FVKU8&k&mCwho4r)Nai`MeZTU)})2;lcd2d+FeXyKc$S2{@MziM! zovJw-_5G8?5BDEhSK07yrJlwlE9VlHhz_sUr)myoehIF8-@eCS_S4U zAB8dw`ILmOKFsh#|4LoiH;Gx{r3ZdaULY^4TDbkt0UTxphPO6WmD%rJFT}c5`zOP#S%I0}!DaSdij&mZ4S0^>&2y?s6edqL#n5Ukeo?D+t`F~saf+c#V z)5O~Sopu~dvsZKF`5t!b+sVSq<~~X2=iA8_Ps=erkofwh^l1D;*<-31-WrQatKyC4 zHW;fO^*fSpbVS@kB<{kWDfa3Wx41I*`Pm+is7}3~oK~dZ!%)(uBpabqx+^OBbzaY% zPw9~!7JOm8{X8>w`&30nP=Tr6 z*Z7);O%~;AiRcxP+Yr6ERJft#TF`OX8ICh`Z^*te`!sV-XVQkNysxg#{<%a!{kHc} zw}j(ruZ?HC`m`?Y#MH*k%lK+1oViuP5oq8WQ9o}_@0!JP&bJ-Dx~`1-z^BCtd8?XT z>_6=)QYk(>>*<>Sjpv55l&hyLVs!LclPflF$DX-~N0v(^1ss=seIez-to2+o7N%_% z7v%Wma<2KthE2=o`AnTQMI$(<<4nK9p?<+#Ya#-5l-|0k{&%S1KXR$DsV>rD zM(Aom(a)m!H?3pVI^W#z;$C$5{qNTdl9;cWoc4a%I`yvf@||@L3k#b*D0XfRKUihz zy*ONS^?bKeha30Y*i*TB&Lr9FXKfc^1^(vtJ@!89ZDk=TJpE1Xa?=}{v-zj`^IvDY z+B>CscjOP5@Kmp#72F2F2^S2e*V#Yvxw51y??JiH!Wy^QbC+%0x0=KkJ}lgC&F*XG zVtRr%HedOn)IaObvkcaFCq+Ct`Y%q{|1m4HcVW=Z*|N23b}3CS*tezY>e;(@oR!`N zEMLm{^s)bJg@}uPKfk#VCNFgOd!p$?qs8TZm8&%FOqhSs`Ev_@_lIwd0*9CR@;WZa zYxg-g_eNmhx|fj}Ucb!_7oO|%eeKhFO~HyuY`)5>!r~dXH|}`)QrcCz=7eWoZ2E@} zZ{*gPhXh>N-j%g#)zNyYPrg+oauzQXoA6{# zEoZkwhKTO^%LOqX-@QKdk8zF0YnM5Dr84>gc6WZ+cjnPo*TbsH*FX1VFDyG)ZM;sx zVsA~OmBLfo?GoY-pS8_#ymd{Z<>976lXptbwU75b4LsfPcgnem7q^}3I-4TZ|1YoZ z`2rF-`@DtN@}^3?l#reyg%*d|LR$M zV`-TP(?piW>{f;UTU1Y_v^Q=0G-dXzf}VNz4{e!ldpn=EBl*~ZjdpB8#}ZS653A&a zWc<2Xl_Rh>qWW`j_Uw-SboOZO8x60d>^GMOZJoW~*7~lu)|pSAiA$Im9<<8cf6^!L ziLm~1C3z_m9(Q-A)L*~*lq{kJ*xdh|6=IL`I->4Su>DckSD|$2-}P&zM1Gm`_Ig&* z)p=n_ao^Z^=1+7rPFbk4cJmfV=lT=j{zt6ZnOD2FubWWYr63W`uXlg5zJmB8@o78P zt^Ow-`ro4E;zPOApJo~ZoizIw<67QYsmqPE!n#sx*kQJaFXZ9wmaz22;ki#= z?Y7tX_*3Y&>%KWR?(P5KS69(Im7~f@PU=7F)`~?I{$5_Qetz}2J=;BIN_S|f-$TJK zAHGM=4a(4S-C*CeYU(_}&8{8V2bF$XF8fq4Iq3JNo(aWF`%h{7lbR3_(=v0$tUY-X zRvpNZNWPkQzd3Dd*Q$-5wYX+J>@RDItJc^!`|aZHJ$G`ZN_CugsUa5T9jaM>mo;2@ z*fZ)#8Csuxqxxgx!tSEc*^Z9wz!kaTczPl8_@Tca9)gFGXfHf=%OvjE2{?w9Z z5ph|`Xrw52Mf_k@&+&-G1%j{GE!X+3a$cG{`D@R#53|;Fm)nTRcpr5?)tt(?<5PcY zfvn9uy{|_sGVfb2IOBPZIe3TjwG-!_mYbXm*sK~gC8O>7w+~CTerdO_Fb|Ej+p*=! zsR~IEF1zyHXZMmf9nsX-T7L2FHU~l3eJ_Q!z7bsd=Jd9O;<8dRX1C0*ztbcwvw)>L zH0bK>gRZkO=i0tckJDo}+VrdM%}uG>3+T9>nxlvXnT3? zN9NSVaP6oMj~}ur&o_|ad7zrO)@G7#dQ7s$w0{Q;lzKYA`2OJNs#r&hgqORo z=bzXXuaSOf+8ySiK!@TC1(vpHWSLJx$LNI5eEna~_7hvYHkmcbutSsH^sv&f2J@ zI*ED8;^8$eLHFZa-$yUHb3n52wm|IVLjsqdaQ$TADc)f9EoZvk;ok~sI# zNdN8k&84zz%bza0_rAQ_W7CDssJnVU@33!Y%zvKO_kKUet#xaz?VH_m=T`OB{qdHI zdYRvFBnABbweO6Din80+#S&}1FP_L;nWJ)M{tb4UlfOoOv;L5(_iPXZ5#$=s!Mf-Y#3g@3Fd3klwv+`S4YMZ3fcNeZ%>$iFK4dY$gPIW(7 zEi${t=g^tHYg}toIPMiGfA>;Y&HDTNPXm@k)&H|h|H%t!$i3!PDTuhp!+!fOx4N7Q z%V{37vzt=x1XtwTzC82Q-oK0y_l@H2TQJ}5oV93K^);QxvxJ5EGIm9$=sr7kkbO>K z!P{wfqT<$Vonct{LcD*H@>ZsQH{ZnW*q>o5RPgPCc9;sEOx$A&y@Tmpd$l+n%?w>md{SJAqCGYyw~a#&Xra3(KY&~sj$we#j|NSk;y@a}%K?awQPa^F4s^j&}PiJfc9 z_Z@m@dZXuLNrq*v^S0F`e{VN2Sw=lol3bt6{3gCs`1Ksq{Zi*+Wur@k?4GG)D8;n? zj1-DG+O1MIBjXUCz@E2ZcfI)?Cuw;xr$=vcE)dUKo2Zbd!#88atsi;4Zv;Q;-UuvK zEwxSpTek9iK|gE5&Xi{>>pEu}ICxmaN=)4=pS$Mfq3w_5Pe~oAd{k|IL-ffpW^)Uf zoBPDx=a{G0x$6hISR7fKV!yn$_O<_e8^d6!XXdP~wR>0F9$dS2>v#9uwd*T;wv=4a z*>Qc}qUBqBIqocwZ~R*jGk><)Q*%i{_E1kH`Qt4R^CbvX-r!an3~E=i!M1USFLw%H4RcvI~4<(8+yvY3WXpRr>61 zHdomE9S?52rt*gCwqf55Zj+Bocl+OYVYb6W=78X{EykbjE8LZs>9TkAR?b87zb{~X zzU%05PpPRMR=mX?bJzbqFd=`n(BtY{g%b9Ibv!1WPtB?go?Tjymlu&f>r?eqwe7na zmR~9BUMICiY}G1uf%Zq=y+kX@G@fV3ZQFJ7wcUB1RW&S2_iOFuI8%GIU;OmC7oR38 zl{RgvI}ts-y8rhaVbvX9o}PO6!m%fOt;QXj4`TL5mtOO=re~|OxQR2%RhyH{oTOafNw{=29$Y<8X zifV;8b<+uZZmpYnXQuhXbE_9GGwq#qa@F;qHJ>cCgjA}&Zrk)HXF2ETOvk(L7Feqb zT&>DoyX`jX+&v4mw>6*3dB)_JoWQ*5C|A}~$JLjkg}mJxLT-o)Olof`?tUWlqV}DK zIBP}w>@!T~xAiszUCjQb##^ud$=3dJ#?hOP;tz-Kkw2fupYA?i>&t}e zwvD#3_Ya4aeCJmByXHXXpRW_HxNZJ&(33Im{Jxlb#vd(y_v$ykzI85(t?|)D*NSw; zJ16zFb}RPEl-%q|@H(s_ z3}=;FJSp*U#quRLa?Z*9%zZuS_~b<&mWAan;S4;Z`AIU{a{9v+E2K0U+f}Z9p1(!P z^=q=>gr%Rvrq0UvZ~JAtUYw@Tq4Jc^|BuSbe_z+OihDyr$0W=1nG&i#e2e{cFAAL6 z&ox(b$(F{N=Lb?>wtB8J`Og#M=UbL@{Ni*~olVyJ@8s%*m4Du)!aVPcZ2FJZ)%m4Ockcsw!CqBt7G&u?0=`F7srm5-Q0{@T717|*i1G4c%$cc zrcmT9g#)40nX{gJJpD;0I%Dsl_?<7M&3N1ccFOG6JY8IJQO5J--WN}~5?=l=^gewu z%ik%8pbukEUy%vi8o|tW`+N0R3jP1QMeR_+cL z<+VLmpHga$jZoZVz<+(u);(9|cInSwb$y%J%N_BmCf~12I#KcNUGubd&MW*g5)WN$ z{lZhZZt>)-_!%8jW%pzyKb7zQDW+IFRq@W0@Wj=%c1Kn&k*l3`c+1T{Cf3g70zV#9 z+`A!=x<9KttUt6KOMIIjT$5|m@@y%xZ>Tw@p2;3`&`i@+;J@dB8=|RyZgMdxZ8G@V(d<$Fb_>%p z39lDoJFkQ-@V^!^Gx6u#^d}hxN}P!sj@Xtx>6y!%b$W4A`2v<%g+aDuI;S-5ENrbh zc}D2Q(*J)f)VFdsPCho}$hWsAU!0wPcfRBl13|BASwX(*Ln~w_o;`W5N~TydI4W{_ zubi{M|LmPJm9jT*t=cMS@SFLc(xgbmieuIjG?#pv?7b&qVNHp=L!-E^Y37=J*G-S; z+|<8*bGPRvhi4xG{;irxWx^dX8zjqxv%Ec)~rPz)tB)2&vu`r z$bakShWAR=m-IH?(mcNUT>Q1l`!X4S-_G9VBAejY_;B4xcfVbw9Wq6~PqjHsTX$en zpi0)R_iwuYFaOT$VZD?i`T8wRhkNA|@{-y(eLcR%la)gAh>!NgAD{+B<>J15Ou zb$X8Co?LHsAK9e4lTFQYeJ69cG;Nq?7%C7dvDfQM(dqk8x%Ql4tY^q^#}gUsdo_aJR-L?LVUQHfe6rkbQR2gd z!}5IPV#jrA^gYigD?a^{Qt|s+zy~ z@C|>p_VTZMlfNtX9GK1^ZZSvQHc@=t+e-0^ZkoHevkjdCkG|e+m$K~l)%?kO&$n%s z{-bm;|98O?#r4lm_3gO&Vja_iZ|=Su8~C1AuW{6st0;awQ{?|ip_dL1e^<_uPh5R8 zPLcKOss)o%zMA>Iy7?i_K*e#d`SkXL{Te4_W|$cYO`Gs_gUZ97qPHy%Og-q?rv7zx z?DZKM2Ce(;doF+Ue*Am&ZBOSJ%kyr$Rfx~yspnqqm;L>V+e6N*OYdvkS8Wy3e5|6SFTW)6W(Mr+(-_s8qvMN4&MnC3?A7@kGDu<0CM<8$lT#DC0H21&=_|NZpQd2lIsl0KLGVZOP(#-;3~iyNh{ zuuqy=YHXRDldzvrR-APc8~ghw3ojb8_cw~O$&r7JU+oxQcM zd1sBI=@GkUO;HmpA3vXL|1se5s)&~FIdN-0MVvX)vF~)kT2HROSGrHsMz$m`&7Z@e zeZgAoMq%3vsSh$cm*?;BK0oh3x%0w}DnYxs8GfIAdUNCRB}?{{EQ^(XrMvdn_N8qW z3;zCoz^QTQCXdcqzqLC4%&&Uc=6%-gGYrf5^zGB{?^otKwzYmY4tVf(jiLXqJ3i7o zKQTXA^JIqeimcbB{NYA&y$`;KPyT5WuJEsIi}uSX z>sw2<^T=wd<}?Yp7<{?)^grW-nrAB=^3^!qEgd)RR&$tPwQ^@4-{0+A#-DSzg*2Vs zeM_=qx0PaZJ96UBY_kF`T?Xd%UE9NimaIC~@tAwti$_yhw(TfOa+VKH`moHPQ0dOR z7#B@vcBSmS_ST+v_z@Ll0-epG`ruljL&lXZKF);R>uf>$lwePdX#D{+~)-0dc5@q?XTCcEWs-N_; zqZ=MAFe-Q;?9#|9ns}=qJ3{qWs>OA?F3y>HAH`1G_b=htULzTwuD@8v0TS5@j}dwSJFWLhkgAoQ%@Vsr7&4KMExjP3g9Hu#5B1+}Lk#wwf)txxMpK zjs1nS$1XbQ`*7`=F4g~8EhTb_*r)QP?rhJi$}jZZ3!1g`>Ze~Xmv;2+&sf-|WqMM? zd9_DcP{*DHiY0oMJmDq0nzb&wyY-YAGTG&F#08Fu?>gW0{8Lq~fYIk7%`P!}pY9_8 zf?Rtih4j3?XXbs5VgHS+u4xzVIIB*rbnvk_{f0wI_|~>dH>0md}kJ0&FS6pZ=Q9&)+N3Vw&lN9)ClhFdAhbG zPQg7&&EU!l4TB5Y)8gt4JTeN*rT@-qRM-5n&G5B&=axxk{F$F*of;NNF0$~tEFAP! zyg<9Kf9FpByI~UkT$?Lg`yMb)nwNV)o!Kkv?Si#O-7lC59sfC<|5|UM3UAlfDb4aL zBsCHn-mBNeb}k5uk#39?>)O(l@w+tUN~N3m!H30)lg#R(wC{-|T-sL>6D%MpsJ~sD zf3iYy6Q9d#%WdZO4cE+B&blU3N&lwCq4;*5Q{OqiMYMaWS?Nq~YBn)0v5H||`MtG3 zamL;YmRo-xNab8G)qTpFti8`RpZp#1Zg0*F=?xpizP?W3{$ug|aOK4rH3d?-hl_j; zFIMDi6HWec`aEmit)3Z77W>=lE}Y-Cw))Glg-5P7hy_cq?p9orKd(A%t(@@X+{+U_ zf1cgfp)~1Hzd@EpYt1Hcodu?qm%1g5k87>>`saI&VGh$?p#*- z{-_ZD+597Vht9nCB+tLNI40Gp=G(=i@gagIb8Gq?TZ$e(IR2PTDzP{4Oik5Xb~%-G z>W3y3Wbp`=ow|N{)7w8^PWat#;hdz;dUN^oZKf|DYrH5_j#O3tU0kR1=cvYlJqsn; z7C9ZZeK~KYu$=O@S9jmP5UZM5kz27vjhFk#hZ}28748ZBDXcE#zx8Ug&HFzp9`BB@ ztexCE$>pio3EtZi0NH#{nb~CD=z1KKR&a^H)7(-{XD!I&rLPFZyoUI!o1E* z)BiiaEeoBOQ#vD)&1c5n#Y^6t{=Dmtllf}KSnYS+t%{1$Tk~c$PM9~h&iVL`9jOz} ziE$>KwebmWvzC(%x&Cg?WceBV4W@tkRyu`5-Q_O-eu&%J;YP+D=fH(`zGvzsd)>Zu z_X%(0WQ$vSg*`$>s|X0D!#ZmqvAafu}mS)nG0 z-;3jAZuC`$+;Iq-w|bHKRneb|zVQcN?B(D}IC)~>*;Sn0aaW99@0<6WBmM;YtV|!L z-3K)p*T!3|INIuQ@#E^6n5JX7|1G{av7dY3K6T!?T<^L=rHZ;`B~=FtlzjeOTl@S; zTM?ha-mb3#ALmJ~xxD5Y<4b>E6Rmlc9op|#9PSQU;PC$K*Tp~17VXbBeb661S77QL zp+|9-Yu~SzuFpMxGe&vqjzd?@ncd=?Hin`7^=tB% z=p`#Y_`Jwz!|h#@8utk*?p$>R15U+=J>0g44U+BV~paiIbPZ; z7;FDrUwW$LpsP^#97E=%EfYl37(Uc6Or7?HoAX?og6}kodD-WGg>6V|S*o*io@33P zK+m6_PTn|}ca*W(h_R%+?%jijyZN{H3+GF+s=xj|lV8iaU#@go*ub5KO$>-+5|z_~uUi{hQWLdAoJ>@|}Mm?``Buu$`hOccxaK#dc26++EtZ&FCp*8rEGQ~jX#b}%ti&Xg80=e7V&(uXM9lbQ+Cbz zSKt57X1XB$__Q;1KV8@qOV4aIa`?siYEN~K#FU5c!!EirT)D;m{4pD6Fx!TOH5Ps) z`h1TU`+f-7{(H;I$kpZ7LoWWm`9s2WW}c*n$V;gyNw=ilh<>ot__;I%a`BeWmoBfheLwYPR0;FU zS!u4`N7{@%g`IY`@0(z&-Imb1%e$&Jfz9LF&u5Exo~>Aa)g0rMr-HA&4LNyy+0x(34mE!~7{B*eUS3hzY@up@DY=eM z)mO~>Y=i&YIU1zEWICTcD0uFoMj^Ey8Fe!&AEdmWU1%WGP=BF$vi;jXx7nmCd6EOq zI{VMwcSZ7$>di|Uf8Ol-_-W~seLFb6Tu~|KyJeiTWHoQ|BF*3B6DHp`^%Qo|Wt{kA zH~;pV_UE2F*vP=ew@EuiLcg}_ebt6HnQ!-ha7tc~E_tW?KU1jos_^&r?i1U8=Egl; zpggm$GSS$*CAi6-$^XOEn`f_N{ghOd=&IVsoAXLFCN1nGSH`M_tD8Jk=cxEG$7Rgf zAhv$jCyj(4|L$z}tra)EO6D_5urON3zjx^r*z(n-yXC>EZLb76cQ=J?mAae}%UZ2) zar*zZ^Y3#GK5G9UyvN=l_cudST1JBbG3PBq6I9Zcr0U2i2)eto9%>#}%xL6uFuz6Wgc8NSwc)VVcywO(o7 zkX6plEgWnXalee`=!fUV&!1FfPHO7i1?}T<-89{ z`6oEs*QrJ6yR=++cWT)R>*ibR4$o^A8XTG5({A0<@4aPlUU25!kEJ$NNvdBq9C&nW zf|^ls-MWepo>-1+x2LIWl>MFjFC#*qRXOR=!;+0`q8#6UWGvU4^W)IM2K6Wf>%$9_ z4yB~KM7oJuEjuN&!J>)9G5y~1NjqGYRPS_EvO02rqrrTw;l|z5*6V-VUS?;LDqe z`6f%59e;4~h*qekhirXS@AB3#XwG*3Nn4-tO*p;#wo|2rJj16^GMA@|gbXU9j zsjct){5E>mZ_3W%-(Pg4^k!$J!GjIYp8KTjTX1f*?Ys%g^C}`r^^?sy)t_+Qo86MP ze{bQ{lE+hc?3LElvETUJweqXr{#IRKW(J8!`=j!eiuxkeC%;zR`m|kJFZj@k^+%_% zAL>}avxWJoKjS&CzSJ*WJu@?xpUUm%Z1{RSsQoeP2ED{>zO@~Rw?4Jqnv(q|hCO&q z>-mRCbxcyZ9=Y*j;?7rQ3F0jC9t&3J_W{-yJq~2|_na#KS zUuwPIl|x^@COiJwjE^%qZ8m?giI`Huurjmwugj_MiW^6EsmwoiJY!wST)rC*j#dZG zoN__#f^%af1kTE z_udX;=MB2dCk>r89Td~O5ZZmi?8VBjlb2-F?0n5X<$1`>1ep`773cQYuPkJU{F2fU z)cDHkSkOUL^^^aXi*!9)ojFl{ccEmj0M z+UlzqIP((2jg*-QUoUEOI&`O)|2_T3uI%naw+)e-m&twIVCIst_^`wm8|~NJWGrsuch}zRRAk@(i<0p7tC6e)0KtS#$2rfb7aY zom-^u&kE-f;yy6_?XmRcuN4>O9basn7g9OFHr&}I-fX@{)atXMsXP2~tavv0@BWpx zpXd3yr*dZ+R-EEAVNd;X=XP-WTfzDJHj4){_U!t2R!vy({?~V!=M;8$XBG>8-2703 z#oNhuQ}AStDE2IcTWp6oU4C-c;Uux%Q0xYH=OWc9$w$wcm~tKFhs*Z`&q$ z^2LH=ru`j#l0Lg$FAw{D@LIs8OSidZy!y3A+q*;Y-FL~t9M1P^FB>}O&+4pX?>CR! zrMN^cO7mps{jaS0HQGzJyFT5Rdx~*#aU;i(=4vM`sYgo}Pvm13PJUU#_+Q6HW1+Pd zM~7Nl$gEqJ&ApZ;tle|6Sa0(HLrEjw0n_nK{dh2b98!lQo><^f~VZ$yR%LuESl&vl?@8<=U zW~)qC5Vq2Pp-k}7RHG}o-6g8a`A+vw`Sp%r*tz+ITd(9A7dIYy-0F64$-8Fd z38w{DsYCS5Lqn$#3_Xa$ov# z?s_(dw-S3RdLu1(%0 z#?iX-2j}54mcJiwh`jhyn05Q_sP)+|?{AP{T+n5-K=8Qr6u$HK{)LNt$O&@a(5sad zH2JJo<)m-gk4~@TUDh zS%2TT!BnxaTV%r`nY*hy|9)cccUI2PT%3M#(dA=qx);BhvAbR}o4RF7(X#%d#h(tZ zc%J8x-?DbYxo7%cj)?qBet!P(%YT#BeKL&G*mF+dg+T>71E0o3kD;Jhg9Tjx2?ZD)GQg|0n)&~~}jea~&}x2)go{$T$X}uX;J7QowUY3i!&FjG1~Cq^an@7`kVZff$tU@bopPs zc=C{g+MZ`oqKCF^do&@+xq8oo<$hmhGM@G~e8?qa88F3J`IENB))Z@2>s~RYEiI=C zt*5teNg8|=e}4NyZ}7Rj?giIEW~eh>{}*;s`{^ZCRW_&NY3a`_Z%7o9#;NbT<>@G({wdSKaWeAmJ`#fvscY*;oh>~<07$zS8kLscz)bcp0jsr zr_!pWO#gCMbIJ?-@;qc(Zk+xng0bkWU!w%%#BWR4<<9; zQrQuvxj5?jwLAA8e~|NB?dfh*d}pPjXUpM$wGA!t=F?3sN4n~o7e9^Ln6&Sj`K_Ga zX@X&)j>j|ZeB2_&Q(|kDd^zji#|@um?Ytx(Uq8X-%f(rZKZ4Saa?i=>-}R`{u4DOy z^3bZA)%96fU-O*jy;S423&8~_@!lnFmtKxNfEa9{}gY{dvX1R?bn&McduzKJ{ZpP;d1fi ztEa5yXN$jEEBJ|rt;w~0Yuu4@r~QK-{{75xpYepo4DFRq4a@cBFZ}+S@f^EqAbU^D z3D&nie#^~>ZT67*)X~3JqsD4Qb@c}Cw#d>ZxdqYgA+eLY4fz*li*LGn{BML@M9r$2 zyadIY`7FTa?5Dp{d!$uZlHOIe z7~avF${gm$@NGsYbMP-`RfalY!)FVNXV7iD-n`hOEeY*A&9#;58bv!d zJ~Cf%J0j_QoQYrD-5oJZtT(b1*G~Uvf4YBe_q}U;=1u(Kd*|?-y=;r8CQNdAe8?f>b#~@a$79!yw4ddw{i^Gg zvB_BA@#@A6SGF-7IH+m8+n(8R6LXWJ%1Ps}`7LlS&+@|T(+^7=O*)khoO>E)pA`4Q@RaYOFph<%i|Z1WMd&SBt7m<1 zV(OLGOQIOp{>$?H&>ZnMHSm$;&9lCnc>k#c@4Pgh)#~-0Mf-oIs~*XFnb~V4oODXy z;e|KtQ=3F~eR#QdNt2SqWVUjKbylfQY&uu`mR@OCuA**|W6x!4ag<3_*emUUr7uUH z3j1SDP9xvliXOqw7jFx&m}z;mO?TQW&);=P6Zb~g3H6(s*+u%X{b_}wtrAR&i_BCNH}3W3Fu!Wi*{Aoo_rCUNm8zLf z=kWfvU)h+yaN5tyoyV5FUKQ5;^X78?+k4eIv>u(U+<9W{l!HMhL-d0kT)tbK{`lTG z_R~9klVZa?&!im6UM#fjv;DaF#_3(VDkjcs=Saw#K5;UqO|bMem+EC}Hl64f*m3{u zPwD%MU1qVbD$;rQSGCma!(%2z5d&pCC&AKyPzT1CzxrJJYG3|{KK|}la`~bMJ2rNF zTKC|lZgrZyvkcQV-^ICms~nWiL|qEGm;OAoJx#P}@ub`@9TzAzwePQdv#jpHT_N>;A(EYH+q3@MJ?}_=f^|wz4pZ-2+vD3Wr8^&u6 zxv%e^m|M4-t?;r@S6BMX|11v|B$saxci*MawfkmPtN5K=kMCW$sjs8*Zqcg|WcOiQ;<@vN5GJA40w znC&^MHLLfEFJpMdot>EUSp2ZOt3cQF(ogqU>u3GibmL&|)F)}rY-WnFPx*Lq{>oOx zM>*P!BE|Cx(hc6HotP*-Ga_+onQK>YY`vxBne!?wvx71lmOX1?kg+Pzl9MTY8aT$s5jYt&^1TTCu`xTUySxLq$ObHFBxn86O?LFYu%2+&=ei zAD{T+yi0e@ULbw;-P?|Jdmb=H=imM7>E*VeHp);Wckaco>+RRum#>_3_oEN*-X2Tg zg?blf&G(k-=4=Wm`@JMQ?-onx9gTHHbNcS=n%o?oW;VOqc!PTJV0#x2Bng4P7XD8<8j|UM=wf@jk?G%Z><8K&ibnT%}JU9 z=XhCp7VcL$(N?^$!+*-VvgHwSmhV0O^zUwbHI`*# zoHj1F(kfE#lfw1HV0pEU_ZrSEOSJz_mwS1mRYvPqO*v=UmB3Def4=f13#^=iqpH5# zWK3F^RmH^qW5L(h`~c%$>?<0hq;DzO=E+|UpUZt0{OF1m&G~dqmFjD*6ckjODMYgz88^3hy zF}CP?Um38Tl~1JPrp3$~`|?hFlSx};f9%+)cixL*s;_>ElZknqJn7#qs|!UJ(;|b7 zj%Kz?ESXyJQAugDnD3Ikw-5L$r!`z;$Xs{hhUn|5|F=oYwB-m?zH(AYn8Ll4ZPg(T z_sy#sPDoE{p7ZR&-<|(kj3%(WF#i_6b>qam6Eg+PtsiC79=NYO#Z;nhl2G$~_qT#a zBp)q1W&AGPLb+RJv&zC#JN9o}x@P5p)H#oqozTDinCVYf>Drf`8^g*Jc3gFi->00` z&C*)2^~ax;``Ij-X6j#x^(a=!GyGkne>{1~{|F(b>AOE}>#yiNJMX=rgE``cI?Oh4k`_&cFpD9SsxgB|A^QkFD z``=!DEPpmi=ulzsgZ>AJx<{n$FeR|eocgb7ziL>Y@u4lwd;E9Jb~a$+eepP{Q}uSx zh8<~_4W8^=zk6Ft`cC_sJA@)Teg~Yk`hLnz__V0=ry2K*zc%mQyDWXxxrSJ+mlfC2 z04f;O4Sv~2;;cp!-FMA$OVOuZy^4o#H_eTO2F`N-+VOxC8 zAmKVoB%`j87O&owrUxu$OP^?7^s_wPag}K+^HzaVk68|VskiB@S#dvNe$)}?KUy>8 z3-S)lNcmM+nRrA*`teg1j{YZ#r8Z}t_2&9oc^Z2i(_QjRRDaI3^wV=fL!u+|zZV$p z+s)AXX-A#|=V#{~)ym~Q+Bytv*DB@y_z5kG)ibS9nX6nKUGnDa!_#}^e@#z{uH`SY zIkRoD>XH?#PFHr^e6g!Dhov7rj`wMcvxtg7vz9K$Z<-)eR6)9&{c}UOXc=GLJqEW^+wfxCO=T`EE z(=Pnr@lbG?ZnD;^G^G6!Vc3o#!qf=hi{ag5P_jn}Q3W;T6)KH0`P zd^_#heEVea%-s*PY@6S>T$WmQVq@$&77MkXl99G9UxZ4QONefKaL@7MqoUGG8qe0Ro8ZH^WO3imr%%sEz44g$zu!)R!TIpt_-cl`T|bAcp}*H^pi?dUYRxjXEc+UZQmBRiLv3ctL<>>;VWY1ze}@sIdS z?KGI@Se17eE3}<9J#3nuR6i|_@tz4=h9k$~%=H=hDy_=gZ!h@Z3qd~dLEvhI6MsoLg;J!P#XPXi8a`WE+k zvvZwWtEJ`ht}ExWYHv()P08HSWPRgc3Zr9-$lmn}ZZ5y0EfjN0F?ONJa?>k^zoq)w z-Cyx*+M%OoHg9oOYfkoa3{4T-b46}S<)NnMle^5CZ*U&5`M!09aPzOKuBofImU3M7 z_Iw_3=QQt=Xz7b5&U^4j_HUF=dJ=IdLBlpo=gyBZk$p$EZcx}%nh{fYdEe4&uXv5q zgB_m=Ut67uDZKR2U#GWGYnqGs``NFT8jGjjcIi@l{{D*+ zr`y~~Cpx4LZHlXr6<%%ay)bE>RrkcTlj1Z?9^|cf@a;Ern2g$`gIhs{H zMVq%u=vx$5YJ9~<&Az7$t2#H#S|qMv`ZiB-LjGf`^#-Su-syd>5i*zg^C|ZRyBVLx zLhtT{^{NZ)TN?d~G*e5ju4uTG(HPh%Yy0;_cE;D@(2s1Udsdfm`n}Cw@rkA6m6wjQ zqvULk*b1-hKmuQK5vtoM4g@CmFf1E1< z>YUEXp4s&M?j_H)M;^KTeozp9@1aEuTiB%i%$!k`{92J~wkU^0AHK0lWRuyaTMcIB zxe51IFn?6p;ePp0m$1D4sxMn>TOFNda6Vw=obBUroZK7MxMz4ngf&(=7(eA3{( z73(=wq(oU>!B~tfA*bw)q~6lxAK|ADrsfBz?%&&?CSVxcec`zD%)`NjR(Gx}EO5AT}AP84Y$ziR!?d3H|g-`-!kQO|4j!~g#_R&TTJ$>@^3o$UDk{ls^g_be1bxx1LZHX6ET6*YJZ zua~&FAoiTK@b!J$F74dJC%NpWEC1i=VT&%Zx*2#i-?P)u**s73xAxb@&mzZfY?2M* zzb&=nmxR838Rz>`FJuE*`bE7qY|H+1?^M5Z#p9bSESh(w_TJhZ)A%#})XvAY54iR< zgj!x!`4$}&{jpu~>A936naQ&j3*HqDzffQw%%J;Jv%<{KU`DLc^RW4q0o?-YA8kC< z5uK%cK+KPK>9?+e3k5cJJY+2v(Ftq`mak( zDWUk@28Fs+OT2gRf4D5Wov&EZG5cD8b7TLci~Ys!drCg;(o~zZW=8Yt>e>}bc9xF{ zf0@+%ee;Lo;O6da$6vCm1=rtb{`GwKY9oK$sO-g65gL~ZUPUpTP^--;5ct3F&)(T5 zUZyU%%*Yv=;{C*p>&>5)1qG@P8f8Cj68Fj%essL*z0&6L6Zvza?BA{S`|<0n;+MrL zPXAi0PL=QCaO|4Mx5@h_U)(a0il&PbVy*6Qb8lUuxwB{9$DDO9(|f#{*)Jg@tK4at<)gdH(4w+c=XAmPxLB(Uj47lOM`ezc>B*Lhv{{EjI5lp z`c>h%gw=dK_4`$SJl^te?d{UPpIfEZYaYF&Ip2&=WNt#BjCJnJ3k4UyNK~6#@ZpWA z=yUU(vG2-^bDw{Tf7_hI+FTI0lv5@n|67xm%s(~PrnhN#Vgh5G<9;?N|Gzow!8C!s z$7lW5&uBd)+k2MmuY98TC5 z#(!fpP}oy+F-FZUwRl0~>-s>s+!uGI$4r#D`RJ;#X+izPP5TzBt~4-MlX=sZp(=1r zkG1_pnLpFr)vdX|Oq#WJ?N*hYS5{1Zmi7G9{Iid;wVIb|Uf88_Q0md;-u?MZSx(Py zd3Y$SFo;Qi>oPLyapDiz!t$6vLWv9Z_;Qyf|`;FN*Kc3wv zc+$?Ez3xcL>RBIR*`Iz1eY&~2g&~K1itXFqVxj5Jvo~`TMb~X|+WM`fj{mmkl_O?) zuU{Srjlb`apppE--btt9sPnmN8wx+At~rqQ*?R5gjL%UG!l6rjPtS4Ec%yKqcm9q^ ze^mY3>vK=YXSM0Oa0|r>UN&EQ=I>LHi#t!IeJN*6i_Y$s4zgKy@6sIMKNbhhAG`Tu z*4)+0uHF#%X~s62FC^iXoaMzk`^pb7#wnR;8y8 zE))qYv+DombK#w&%@IkJb*mF?7If$Q+r-7a%yepe;2zsD;RAb_8r5GYr_W!PCUnq_ zd3v#yr^gyitFWH6rK=XoKKW7HT{`KtZ{me{sw@#+e7$=;SAR~O{IKwfzNS0l;X*YP zo!QqdovOk**Uhe6s9q-J|LcT?^tvUDS91bLF${%@48;6+GI*5prFp z_kG)hCyP2anEm)kx3OYD$n2ek$Ge2>I<)@1_>~v^^5y~db)OGNgmE3t zNL~?c>Uc`3+Izi)tVGC!J8yNodcK~#dsXz$_x=T&=4r&;oq4@w>nA7ksk0AX*>Ux# zD+gCVs!95Co5m}pjYeV8mloc>8u)jUjNpWpxuG*MomFI}sZ{&3C>VyGeSSdip2FvA zkMsF6kFadbe()%<=!k^@A|!w0n^yKbX?0Ul=O>1xm-45%+vuDu zdl2OPb3%c{t!35mWryzb+^%3OZm?h}>p5$}$mtlkRCeh%MLUzz!d7wov43ZCzjO~h z{f=!xN&f1mT>2kl&u#9^y;gPVzWl?4*SyBL&TR*$?%E?AA#mli`UCYjejyAW%{Cj) ztiBWIRk~nh!)o=|kd(`ep0iFDY~`p~KJC_iqxFf?g+g*)UD$ohz870&%c+mR$IoUe)4U^ zh7!GR)!Y$1-ySk<(7E}_V3Ey={MR$0o;JnSRLtXA=?90Ei zyW!Y1_3XE78*8p`%#RW^G})#7eb0e?_rh;Pv6cP0!@+1acYPk4Z+Z!vRdU+*qw<-l z+@)rBnop_fI>tDD%HEUGn8;Qyo38qIj=SFKvb7)Q>`0q;cJ-s$9 zwrN!a_l`{ST^)(DGLvpUoiN9-Qr}r_&8~=ZCBoh3Qe}2YEtL4iaZ16w@T#GGTj#ND zkJg9F{Em0M%s5$PLfqlEOg}reSbHaDX#{OxSyJ&bU~hy>sEzY2DWQ6n!WRh>Dt9JNFZa1E!|uCaQl^0$(b8r`mFZd)mGyZ&Ns zZ6ZUcnoHKL$V{GVnuacED(iOf?up^II~aO}pOa~QRsAhCF`oJVUp!y@Fy3`;^cst; z>Kj}eTQ)?04bs@FrQe&OAaE`H_}8Up?7p1~R+?KCy<#roWC#09-9z^b!sn%=eUbZ6 zG_C)qr0t!^+R1CKTv0dYVSV|G#fxP|q?P63`RWsoy(tr0)#3kpGt<4Rjkl*{ySs#U z{7t#hu-Y7*PMos2&$tm^a?Q-QZacHL9TE9?bjGH`_kSzZl(Uobv`5i?YLS@!> z*`-~0c<>#we^SuN=VxR(VgnnvFaOS()+#sSL*dT=d$;zG;;+}fwrssK|5jw%nx>nN zrXRDGjbZ!|lcU0Zr(tgYuG3l~-?#7UJ2j<9M!lJ);~G>bMg}gUk*LvB^f=h z&i-(@ohrSFrGIww{ZkB=82LLQb|+6Vd3hm3{_39SrLT@u&FSo`nX%xX<-~@}xjJ0w zCTDyeSRp^FBWdYV0J5(|sxxJX>u z?|o(6502MTvTL+s8TcnHb3C70>%b~)E+#G*Fij>`I(pB_rrlvu?vlL;V!x(1KI}|n zOHMq<_*u_Acbm zy_{_9Q+Vm^qM)5GZ~svezrFUxgk48m>kqD(pt)x&ufQ9f@>P*5q@JG0)$8`>Tha7( z*Sn{)4@hWo?XQ{oX^+e4iBl8%aSvJb2;guTNAr`Z`a`UlOO)f%N2 zZZ~o7n+NxOSw3WLO}ta%sCr|^5$9hqna6Vc%je!&^-|#1uaHSI4n~~JYA+Z2b4jV7 zMB!+g?M9Oc&uX=9Pf(kam$71j0!ws=&MT!o(+o~77CzCT?R?{T%&j$3^;%aN^&Ym^ zG;4K0<=3bwNee>ks_mB~AKP;-BPgJX&EzZ`T^ruUQ-gskm$;a4q z{!5#}SpK`WAKFA*ce`+IOSNaL9=A);twNbNA*27z4$sZjDg{5kTh=^hx8~l^2XcIC z<2G~}`CYc%|Nra~Hp%(ZC8UgYL zonPeTi|YB$-1%^Q>IZAb1~-c+QRR~~Xx-9l}}>4x0-6$+uJ;5J z__X$Y+Kdn7Ot+ZtGby{fJM~KRm7Gs99&@i|e0qMw`Y}_oQgQk<-CdqeHO4JQ(~b%k zE@8G7*=4A;$LpxRR882K9+oa|r#0oxHHyhMop-99*ibo<@4VfW+fEy19&TIgvrsy- zNT7}LgXuHJ3yapB(<@#4|BtV`*}30S)pGACB_2zf{%60hOr*?<)9c&4LMQ%9d!55} zA?dw3vs+oR+|6~HI&a;%k^kY8^LF*3Y~%Oh+zV3|X?q>t{!2{i+`P({?_SQnKU3>L ze8@D#koVV;m!G-j{c`>~tKgRVr4Cb?k0oSO`x~`fxX-$2de){j>MAakXOGKvzf-TB zd-!1-+d=tb_u?v-nFxBG5Y??!ZPNVxS@;xt;=7hmwky{r9`Fw3`YBu)wxQ7LrvJ9N ziU|$H^QXS`tA4rQ&Z}>cpKmq=xRqS+-Rb-33`0}r_Dg;5)gqG?NGmxVJe73Kr!nu% zjj3%wzE>whAmPwd!*#v7n;)>wlby#P`)kpnV)j4H964qBqU%i^_HbmT&TuuY zo^kEOe`oV3&yCt9EC1fPlzDTpEmcvfPDidX_8z^*J+~=As;KSipNq=xRG)S| zUL^gKb%}7J0H@RRhr1uXm(iD2-rxGh{7vcG@;`m&wdPhtyZ?wXUc6`c~|7d67T1S|JF4={h6(( z{GaL5E$NaQZ`7o3h^1^?nBB;8_+z}7QGt7Wlj~ z{b-10irXw>P&x`mVN%kYC{ta zZdOMIb%v5j2b{ZkZHt=!rp0WP?Am>_Q&x!|MS8OwhNWA3avj2i$wu7pgXyc2rm9hS;s`t`mTYt~y zXtPUf`lGvew^^z7?7ik2)!Nior%)w3vw=OE!MMI_|LDWweH)^mkxoB3)u&R?15 z@%-G;9h*uHo{GAZv~q)k&ymINDm#1ZPUk&7crZWDZm;l>X;WTwJ9HZ{$QZI{s|T9| zXC?mMvfB6L`|}sSZKzk@e1E6n{8e7-Pl6;WlcWwQO%OjotMo@FK`8 zk(+1dc{`R>Wd+4iA$9W3ol_rivD}&{k;TE{Jn8f7H=I9@Ze3`0K6A6#wY^OLZKamX zu$@&`w^d8PG_S_tZum{z=NZoD&+E0}oBnwZ>IIvP-vGWCK<-+Y}YOg3L-+w*TVCsaz zUj1)3v)1QS9#PuI@hx<+pPz%G(|_yPRwdpMMwZRedrTWxKYre|@9MQY%@PhVMb112 zA(M8+CofXB2Nfo`axB~Wb;n5y*^^6C0uPj?Yt2(Rwp)0z{I>s28s`fljQaz6Cx*QX zWBFNjEa-~6;F<%z;n!;1lo`1$zYh3bGx`78O{zB+Ntw6RZ_?QqyUwO!$(3{0`NNHc zvR%XXiQKu`qaeldZb6Qm+>eTiS10e6nr3`?!Z+u`2dNbOXMwUozR@Y_evYP6vu3DS zWgL2<=D|x&++4g*tuOy;SLRHWYbP2N-0tLCtdD)hE0xoC{5{j^uc6D9 zuIBZh>QgcKm9Na7k8^*&OWWO3BrIN1JjW-*_?L>O+rlVc_N&Kk_B9z#?U)_K=P5eD zgjrPHBy;-0ck?ooS6*0tbMw4=@ACMYT>SzHEcK(6|EJIWCGk-}q4R~|i~1DVFE_jS zxMm#qT=PbM)l~mAe!Ctr&pq4w>w5Fl^SaFJKOd+p6h1tgwTnk}hOP6ry>~9m+P*Tr zM(n1C;M+f;?(YS6?s_(J#?D>l7iD+v?$=-QLSp7Q-6_{fQoZ*+?V4T@y=$qI?lud} znvS1S^@OFFq=KBh6>k1yuM_P&#O=1V_|Dwoj){2%i(*dHTs*nE?zzEa<_j?f`5yTT zH8~d=yocC;arysZt-k8f<`?=a!==^t%uSfwIayJGXSw~Sm#e-xFm_4E z&Y$R^`LCUK&7bE#l;(bRT3H;xbkHqaBTX`G-d$tInv`!l`PURb4PPj8Lt5!{@TAk> z0hKHGx8&yN?s9+nZTs?BLI00z`*Llfw_f?%=w~4>r*d<0o-2K*5X4ZFt#(gvPx^O} z){BCBUh*FHv!CsCStXqIC0Ff&4Kr)~Y_CpxU8_Fl?~=Q>Hp*@~?i&3f z)@oaj>wE*98Ugzc-}hI1zZ3B7cUU#IykSth$XQai-$c-x)$ZPS)T+k2he{C89M z(!+Zc8+v^!>-4PO{xvksaP^5eefHGviYaavw@F;7V>CNe{?%rJ0E%Cz5DS*PvL|Ak1|cn-u=t# zf5hqCdkQ8N@MuO<)~S8975{$PZBFOj3yTjue6X~8^~GwWD}1<$2tEsngi>yE}o)`g22g=$$9{xjXyyv7*+wSYsd@_l`;W`VV@_w<$P zGH2iOiDo@*x?|SmcTc^Yc4=JS8)E9XuDQH&N5m4oHK%ya=u6Fyx|n(Gv|a8cm93r% zzkdWiY+~P=^LJ^@i4>7-x6d;)EVj_#kD0J6?@f!{%q=Q$Y!!8ZBG1zL@}<*%&X^O) z?L4g~=5d?nPl?>68y)3UUTE+78@l<8LZwxww$tJT6HnCLNxCdu?EG*?so*K;UawSN zpX)yCZRZ8HU0v5?x;A0kbq&9repheg^7}cZX1L@Ym)T=?RD2%Wl3DjotdjVcr?S*b zW671!??T029j-rpzb4lODtZ|o5$xp#V=-QB)JJss_P-K7`A{!v-srFg=HJHt+UQ-*l# zb_N>*4c+N~93MLFd_FmJS>6uoeg89`-d#Iuuc2&~>*5y^wun7daep-F#)UIw<_kT3 zd7rw_FzLzmeTCLvybf0SHK{f*XREV!^DErEU%BsXrnXk?+9^xcXq?beIkB?veX#Kv z;lMju`uvZXB^n&#=q@<{5dZ)b<@`e*EUOd-f36)cjofVnVvPAryf-%xy^nZ_V(7<6Wc9*dp?d! zShQ27Y8qQ}pLkSZX18R?v{h$5P5$;OyX%#kLhhlLMsKf$Rr?*-TPfLAcc#{f|~ zpPt@#X1}=P?vis&E}NRNynY${673Y~sNogn=-jn6GPZT;#G0*AB7Yy*dP_|2_5bZ) z{_C6CcenC|W`C}3iL6r8T=8WB6JxaH1Sey|RAbk>7vJ|SRbO=SV2^*}w}a23Z}0Ug zUs$5WS$R--#T&aFlY}<82(M&W@F=_g)-S=HP{zQuz13MFOQtNFf922T+pYDo!j|^0 z6_aOAe&u@5VP$)n>eI`P?Te6Hp_X&rJEc$=_JzLJyx+mhO^wLX#qReljzut6B_SXzq z5UjbN{{5eSi*BtrH~$R#4mLi~O0~rGEw6cx8WnDR!SgwFOSWEyljhPj9uMYQcMCY^ zuIo|qO|o0jn=w;VcuAPz;;x5nrS<#wYajk|@#Wok=Ovow<1<>7T^zUU%Kh?sUEsET zXJ$WR3;*)w-?cNcp9$y)4un7m+0NEnUQ*`^ z*K))9GLl3O)`SX&-oLxUC@uDId^i8}sI3t_F4ik8H}oXN`#XHue(b zUY%$<(B*mI!Tp0dat@MrIhJhs_WQr%?dvNvue_f8zx>McYT=scr6QMgoW(N)9=kqB z-TUsb<60q&>1`HoB7Hya(wR7g-ugj(s@Wyg9cYeC~m(OgTyvd)w-!Byu9x=Ub3f|3EcHH%y z#P5Tq&o?~yDtajL@q72!J4*%koKKl@WaHi)ApwiM@7>fed8xgzrgw78wsJqC!|rwy zY8Oqr)%tH*`=vh-lg@wmsI^c!?@@84egxM?jj)4V?n#GTT-O|tsCrkYa_vY_-PXwC zmrCCn-p`*X;n!{=zOL3`$as6bI-2|Hh2|VbS*V;@!Go= z8umD!;cf6w%k@>hFSVs`&gzF!r(F-~Lx3`0u&4z+$G0>g7h!H5Yb=wVs%C>G{1t?ahBz z#=iJ)d(j644wibGNfWoTxb1zT^u0cK@e8Y0?IycZIhq!67G>oA5x==|Mvdx+j`r%~ z-&zky%@q!BI<~3l_pyx(hg0{SFudfb#eVqp;)Lry;#Ook`LZ;wmt4+PPcqZ+7Eo!;;!wq}y(kf}=!-5jR zjOhv2ZTb&3ZuwrPacW!R<9RDp6W#XwnZ~j3r~rFJd-igrB=%ajLmyOjg!7fM+jyK3 zUb4sH^`Y#qkw2=RtKM9Aa&|#UJ$IWzopnmz%NvD$2IlW_T~~6<=CxzJvQF>$#A(ij zPj-LwsPb$y<~53*6?r`L+C=eu^+#bmEISo3Q7 z$IONfdsUt!^-CM(czjyZD^vUY;+w8#?3O&hMSA4Dea@_fVf}iJe+3F=#0+wZc@=7Y@^|_vt^1kzncz>DY*cbkKyWm!t)bkhiEin9i!9Y*mN~Jmd z>&$?1;i^SPrr5szT2Njaq{JN`kbV22#I-FZUpB8Z7o1cP>ScK}Zn0eY-9O^@+&YUr zeniig?LXOO`gWJ44d;b(ea*RteK*Y5Y@qt=jQ6Em>sIpZ*%~xK?)b!eThnhow(H%R zHu1?-UbEh)HYSUERXcxn>|kG?aVtt^;>Muqhqx^kJwDU9bAPsQ-n>pXE9;^>^$vW7>oE2XcspQ(dU)1fC+vl)t|Md>o}^ z*1YzQp5Yx>(A=iAF4HW ziSD-ak{8&Ox^?TTr&jZ{RyEIi{CJY9gvW`EN7>TvI(Hq9E#wuva*ajs$#c<2iyJmw zo#&hR*H#_dbEj(VhxuZa4>NrZY5v%f-=epvm+?~9w8MO*Zx{kK{_{MJH!t29^Qvv} ztjATwnNOJCzx^|F0#DCRKmF1l`R7HBnyO#kIQgO49}(7k(S;YT-rTt>;m{nZNvBLb z`ilL-GXCVrE=WD6ZhFh|fi~L?=3U9Ro+z2^F6TdS)+G2-_7nSiv!Az^FFAHcDbK&- zR-l#Q_qzs$T?r@OUi)XWXKDJmm;D-A>n}f4-0|R4q1N&P&vlkgoRNF|DBsId%05m$ z>KXCwkskkUR9|admAH5BAKjou2TKY9k_0a~IGDDdxn2JEuyF_5)#JA36T;Ulx~TB; zhD+3sSI-0Y{$HNQe{|ROXMPW~CiRF%HJ^*~IIu$a(Jh6``$|>beqvw`pITROXG-@J z1=sNJZVM+o`Tt|uA*I(UK0=;rUPasRB|beT_}knrJ(%-q*VQ_PeV5);1nj&oBsbmB zdT}fV%X-VLRm;zEtt?(H5qC(r?TXb&vu3zc>hpqOssgv6B^>d^aa=-1#C>1lE zarbZk_2%$h+(k^cZ*46KQ(9zUCiCG@H}B&ePUk zyLQEOhJPsysfV^7Woc2~74R;9t0U8gS?s(WtW)+Cb);YLySnd|NG7kxgdiS)fYSxL zqV?jtBug9Se`#%qE%NZVxl`JfjY;R(56M^m-nE$Pv4*ECP(6D4!I^7&y4)7N{NnH< zGVPE4KZC3WbEf_;pFAdh+;zez;^=PEm#i<^m}TSyTGZzV?ELs*W>J`w)$ZN9(|iw3 zSi0|L(1#ul#RPv&>$5vu#SV9AoaU2$5qv>-lYyR3(v}p9T~oTQ^-Sr zgY%qKQr^CHnX}Ze=Y7t?xyk(x9CbEoe$eRonykn3M1V(k@~;yQeP?fZcG~iZ3%hLN zsSbsh{L|hNpJz!N{qNzrSn9ISo5~dFY4W-ao>!|P7Tulv##e8FYEkw<(-}|G^%V@| zzy9T$kQjSUy@X3|((SGJt3$WmdA^BNAf@=!yp=H@HojcMY_zQ<{ML=)8gKKJAFc$x zDBzHud%QEG&Ne39bj_~m%#YlzHr6u!Gu!)uy|ZTPRVA@1wa4tf5d|EY(HeWBBiv=z z{oHxeYeS03j;X6OQkwtmShO`Jt4>}-X!{&1wX5eo3m^XcfNihRrd1#Qu4rceaOJ4& zmfcq_F48#YIo~Jc|AamNBlBv%O-{~TcV^L9_PRaRRPynLIyMESIZ zauXI9JDuB@`Fwfze9iLflO+N>+%`R$p4e~jahJ~ITajiLqjnsczr3>W^`BT>Y==b-(=Ing*b;o9@IhGH+UZg~vopwiP$!_g>UFE5T z0opsJh{j&Owlr$;+lU0c{)2D-Fa5VvaUXBNjyXM<^Lgazeb&9%alW&i!&UOdhE`FiwD(ja47sECb##~)Z$as{&K&}XB=K$WAWmI%l9oZGG}s= z6YpCn^)Q-jljV&`zs$mz{`NlOf_J|+-Z9_0`bN<+)3bt0a--IDT}zA6*rRT<>u%wS z`@7hfrDd56+3Y`gL~fpuE`BiOv3Bj`p#2BMvp;$kE#~i7`?X73RB~1Lwnc3xP4)Mv zasFXmutmysi{FH-&eFF_jv2qs-Z;x*))IzE&lH*t&YiREh@{+4mFnktG1m@Qr*qyi zDi)9V_S3LnOXbcc+svM4um2zao?&-}zrES-|MToAv$;;G_&lmSSNZRWs)9<%;tjrg z7mA6V=&*eL_;r0p4%=+utd!*n+yUl%?>#2U?AoXI&tM04#QU>nt$2Rj;{qj& z%2}Nv{)17hm!>FR3S3~@@o9cW_qD#KocA3r)U4zXKRiWa!6_EEwTqQ>J|78SPUJr8 z;<&)C-L3AW%=zViyM^X>8Gp`}w|ZJQ@$26=3wh2{-*I%1>An`G4r{CZr|kz-~2)b%r_$;~Q1&a^3YTfg!0Wl=xPLchJRy54Nl;&E`5RmB^vX%~6| zcT8AWoX1_c<%Ngc-OmS-uGLuD^Zk-53p?+5sf7KIJ=c0)@27r?pU&E0z#V!`;wi^Y z*Xh@G9Np$37{0-E)m{4=yl>|QAKf`YYsW;-puJCd_IynLxb9WWTdn86E0Rlmm31Yk!F&V7WBLX(8Qs_)e*kPU`Cx5K&iPhd_#d~KZ?(*qY=Z2N;{rzI@ z`fD!6_Wy(1nXR_YiJZ&wdi|FT!6LFU=ZYQHB-U`1Es|NpUGXmBXmRq(zPK~THcQ4# z|FCxH*@FTOGE+Sc%FGMfc-(yr_uq?URjaM47)sQ5ip@^5tza+vl=V8wf_25QKhvi}P7>{6p!?Fdt9vOQ}q3Z%+m6nJi|e7LgwECjGmar_OfP;6;1qCp~W6wmbM$ zvqs4(kA#{=@sBT!4``Nc2$!9?OEFC#W=&!BSDV22KZpGPUHM=-sq4#I9r2eE0t=H4 zeu(&1=g~?LvkSI{x0am$m?N@xvwuR2xn|=cV@_S0`}Q+7ox2n*Hv5J9N!@+> zm8yj&Jls83>)@5hZn>{3CyUsqd%G`cHrjQrue-p>`G#T7R8g^Qt26e^54*CwyFcfs z-}=;swpkbN?Eab*__lP#i@j2-8+I8?yQliiO6-he$@2E4_iK+lT(BX(xH@LeyyE7E z)qh{Ne>rEo)PKglYR7x6UWE>mbsn#t#%WfWxanK)28ow@oc47k#+c8Y8ZuWsR{K)^ z(Rjn-_4Wa!VGI{|jX#U7-o;#Z?Addvj9s^KR&AUX=^d;0g;l+c<%HAU=AEmZ6M1Jz zOz52a%XDA&;X_8Q(f2O+EOZU~`Hn^RrfB#biv_G94`0mFUvBl_(ceIEUOuDp#ADWG zNBYh$S~lmM_apn=yzx<6k8`!zC|SC9nf4Yl3vGU8YjHuuBl4zeVe|JTr`zmhPG>4F zGyf%gv3}~tm0MPD-}rxOuONeG(2-%^4s5|vDT-?0$l4o{aiuBpS6uXA0QF^PG#rZw<87}-Xk53}o5T{>^MJ>!GSGV6yaH=fB}YOkB!+$f)Q z;#~iX+GMTWDg}O`lUHqCAAM)G_4fWPrUy&^l-J#wq;YHdgV-*^rweYpSZl`pW`cW)tjUfzm23I@)iG`1OEdZlre?02uRX`F=c@?(Z6P==r3srz@myT>YGTRz&p3 z-#_aQn0!3oxX5JY((Z{u_Sr|Azg}6gWD8sU_Z<6^=kyx5kW<9alS`*w#_XH@yGtbvA$3+{Qs$SM5cQ+C{1=C|?3&%l^zEp)b?47C#$X<;R~lQE zMMkPguG`tLz;W(d@p&(`=Cky6uiEP-#%kSPn4o;Z?(V<%O0!!w`YJn?{=W6I^8D{l zj&EKhvFB|_2sL!7^fj=X-f4Q%U-07H?T-Zh#O%{vDlHOWA8_`j<$D{0!y0X!^Yx;` zg5}S3^_;nWZ@xlbM5o#`pN|bUU1hubPo^rp50`f0GY@(??}8-Hlg5evPkS=+_$Nop z_^|!I#=MeSBQo7%n?*0zujbPoIX_FYQ&=RnZt$s}X}qCK|7=|8LB4nKOM>p6T_z~W z$o()ib8$S^Qn}~nkN+(D@jz;2T@2f16)kNgTuP108IxZEKnJH<`Kf z*~^M=ekWkCh(Gnn!o|`m{|=;uzkXom)3Nx2*lG85s~B$Hv2(SykUSMUuW8Hgo-iT* zBHil^bHdq|Sw;z1hPy9)Qy-OI(f#``^Ldd~Q#VUR_+D6RxAKOEPquZe$#>7Kg50-{ z{(iE(n@zR*_nYjp=UO3sZ==3m+9RV`y7nDwNY%YxxlT>Llv&axEX$d`GctrY-+s_E z>se^r+}-AkCUN`axqeNTozaxHTfS}^m(cDj%WVoyq#WYhD3D}JT= z9$shvwn$uKMOM~kQS);Nd3twmPW21WwpqSG((T=4u8rGYJ)Wl_b^OPNFN+?Zez;}R z&9`>mw}Ll+E?LcFx_40)|Ts8!t1J?Ve(9we_3(bB86d?$H|>Q}@Pv zKF~F7Ww6DKROZhcb)?F#{)qEyH5W~Jmht}EqpLSPU%eDy(aKi8WI4ISaLd|B`(BFJ zUY-|S`KI4_(`MU4_gCd;RrPk9POP6YwPcf3=$At~%iO+L@2?VMI-ME2y79-XxP8C7 z8>-iN)foKb`G4|wk$TTiP9AP8M~B@uezw}qT1;dyg)lXH73C*>0VnG<4{oVLdynos{iIPx&-AY4^7Y@?+}Mp8TAFngcD!;)zgBQ( ztvc(La-(@o(G3>^HYL?Qi+zzG7#Ah2v*^=pE^+w@e0%b>mo}|* zc9Y3`u=MWM?zyXt85h1-{l99Z|J2zZ5*Urtje{qBQ&~1^ve(<-!ylc^d*;v7{;bbe zyK2WlaTUe`v(E+P9gbUlM6~hD$=Vl{IyUy^N7q+s+WzW@V6`-A?FiX9OXkkjNjCda`ZT zrB$Vc>`!0yCo0O~`euo;w-4^9o(k=2i(a$3q)Q^PO`wC-m;L9pu9;lT0-=|Jp3c3V z8fl$4`}E5CY6o+#1D6iU+>*3o*({=6azM1YQ*f#FozyQ+OA~cI{!_clEXd;6w>>=e z<QcwPvdzLT#MeRcCe#7Q-i>F*Nl~V7yRd)33FP5S`_x<)f$e&~Dp7L4H zl)uwu*6STobF89!ZPd0eUJ+z6RcF@Rx!H%}pB#$UIsR5KUi|Pe-KEnPp0j3Z_nd!< zWzw^`;_4oUc?E5mZtOBRb>K-_{h2>~z5gz&bM)MtTGHGZu>1AG#*Wj6E*#H%pxPsO z`=pJ2)Q_3h9}B#wIHTvj^OmjEGwxq=4K=R#3!m70$~`!iN0Pg5`xf!DE5kbM^ckns zU9wx8^ZYUM8qur0j^C&4^!pv;w%;%1GS9>ONtf53cRMlNb^2yCi@yijT4MjFC%H9D zH*1(syXxpFxARSV()MjJj__P-d@uRtF|lt8cFZjO`fBzu=BsxDn+#t!Ry?>T(S5?h ziB;vxN&kNjCK_rs?~)L`!X9E`@Z!sbE6F<*Rc3vEX3$glB~er2*`M{VUM&tu+tYdC zz^hFCfZpkb!cPJ-cV86>t>^x;f^FH9_p2uuCxuUYFTXI*CoNJX)le`sQ7?v3=8UDH ztoe~ZZuvT`jODH@W~;W(_^VyI!`8m@$SOt_fBDm!Eep-Qt@TUu%s)S2;f`c0g-?00 z+eD|G7PzK;@cx83YE425efF46mw)A-H~-WVv42x8v<9b$ot=KD(Jw&%hene3KUK+{ zN{6+Zrc%NIQ8kL_qR54F@#sg1-{zba;*D#=E)F3CSNZ2Y`S?n{?)|Di7k&_PV%v6UF_WswywHWa{_3zS3ioH}vptepnAsW0vbxjM*BiaDo%7P{R8FCA`njnQrT3kTk{r2Z8%<@8osWE_#(ur)Sy1Ba{Ri(^ zKHL!X*jDgI$pOtWm8Vv7L%yg#*(PF}WN7oqd7Te`seE^dm$iK2;+h3>3evb5^cvTc zzKh(uMD_hl^|xxV;?>!;-iCh`efjWeg2k@C>&mSxT>PXjc2uy5pFa9%o1sW%JKK^M zl@p_Wap_EEiE{mTDR%XH?YnoLs@9yl@v1Rp3k!eoN%<>>=5D|FX-ytaj>yrDIbxct zCa!PZxoFCw7VUYqkA82uZ!D3-=6hoE4&x<1YM-#adS!3ib-Hi<6Zf8qPlc`*dOzzu zlRWd?hcQo_IZnxSp^nLM&IQj*kD9N$Hm|xwM5)>Fg?X_n=l+g8Zx@K<@bM+~6el?| z2kG^GSfg+B+vTazzegLM9eY-Ldcm7%lM`HxcNcAA_Su)S{*!HKxRVUGzix=%R&IaT&s2QpI1cn!AUIQ|!c}joGNRz2dAMWu?0)IW z=8ubiYeod^X7N$hT6NAtf7#8;31WBOGH_jgwqS~X&dg@Dtq)~gUiJy{uuVLW_3GWr z-8E^V+iO>!IAB(FX2aCX zPdZ;}d$xI9nf)@eQ=b}itZdEdEqRZZKD(vM5?b+Ky5RKtUGuE^#hUMnxvaZ=jNS6V zvaI{|yZkhQ@+PtUZ`{Nsop@Vw@&||8D`P|So{0TlG+jvl_KayyE>?-It_h=ZLJ+OOMM{xZ3h>vQK-nCD*@z-eQLOkDe^2Y|edEncV*QtR%;> z6!XW^Z}{$=+dEO|Zo{;vAEN3`nY?@&Ffmb>eZvVwsoOVNF2665nfEPU{cGUwqnBJh z_VWCBdDqU>xY4!sVozFI^tP1~@}^FAkbYL!wDXT6M@Q>gE}yJl6IZ+MRdZ!e`_L4h zDA~XD@#?MnRjgPWYwVXUYT0&VcWqc=eC!SDo}CXTFkWBuKmBN-Rau3tlgAPVTl0Ol zHCFHHT)L5aUB;KP^2c-Aw*KnUuv%&V@yO%+Z|jt!VxP8Mog!#?RZOZNU;XLp#RuEX zZ~P9_++?ugvGt-I6HNbbTYt-!I&E(|g>*dlZ=f5PxpSo@2$iZjqpLqE2Q-{jb_1aUu?7pz^V#oqM?{r-=k8MX)1K8Aq zrvF}fO!x4@sM&FUziW3)SmAZvxoxXt+?+T*C2!tk!5Sg2{ymJiYc`1~Ao50+l=h1m zzqn2*-hR01zF^;Sz2lh~OEL>mvn8&4YT33mjIH>Aynkbn@yUi8e8vT9|Ly))ZIsGc z`cE~d?DCqbQ#nGHgumNyCFZ8Y?K!ob@7Y2NgXvM+m!-v-mSnOkrew)G=A4~yA^z*; z*~g}Sp77Y$mv5!I+k8Cdt7uKW3;qeScN`bzMeJghf*Ah2SLx2Nx8YnrqBk`t{z$ zjqQ(wQg?V(9DCFvE3_ne^7g)6R(o`s%9e3vFN>X;Y!LbI^1J{19{B=ADV{SYhf8(q z%x=CF9eA+Fro8K+2JbFu^EYZeNi28z@>+`G_TN>I^-kTlck6>qe6@;ZU3{Wp4zuMR z-|zhX`{Meu`u3NW?%CvM-_yJBz~oAca&Ci_3ngP%mkF-R31N{_5UN?Tn{DG}&*q|8 zr=PU$efIy%rI*t-UgH)&^YTVi@$s^2CT3!V7rigpC@$}<+VeK>xNySvpHp{TNRQor zp!D;~myvhmRa}?%>#dfOb@-zizoklQt1)ZT1Y>4_BY}Q;@7F}s&162 z#sm84$3C3Unq>I@_6G$v5%s4&^CrifIrmdy@6-b^8D7Wkzy17l&wHQPt|N+>I-5^# z-6yuu_pts%_s?$2e`p>T@R%TUOt5X5!|Q`bLT6`lF~uJ%n$=Qo62mZ)b$VL$JoDwD ztMacr`0^x~H`sEMcLv9lwEq^Xwpf;K5iguzT{X@AG%w57$w$@He@^@ML+OO+joX4p zALyUn|73CdLb2J2&X;CHO-!lpf62EhJ@w<+lP4C`efU_>^s#W_sjC|&*6h$UKXx}M zc8OYj1LwBJ&x=eP?(&`$?G7kebH<-Nw)qTy=_@bQ&OWonPj#-`JL0pVs>@Ba{QZP7 zy+>2Flv}1wy|S;^YN9gdd>Kc@&E?Wbi*H36d7bBE-hJ!c@%)&Ir&W^TY`(g44Ud+7X*hJ+M_w#* z-ke{hx+>w5OeGh%{}KD&+N;vFeu<1&^JCv~hba>FjQ@T=_z^9<=4qL)`njm+CB3^M z&T*eS=Dlbs_u>56E3f@LIYTVEXpi~Twhs23*W=E-;{LxTcm1TzDG~;Ta(Tfw zAI)CTX|imOSIDw#rS>gOIftt+G(Feobqf$GSeDwfuqo5&P|LqP>LnAao_sZ&=knqB zj-JJ#=V)+xKqx zxl(QC1MVlyA`>^>f1LJvTUhHCw^M6Vx&-d9Z%^HOB~^>xYU>^N{Z;zv_3d0D z&MVoD@muXF-)r#N*xF7n@oki@g46{jMMaHWe?FgHr9Ibx;qIfyU*nz~-s5v@v+we| z54epUusg7=t8Nil`B_j^Kw!3y(@}#kUGAEV`&``g_LOc36wU5kc5ITiNaLjK{3T1i zt7uohvi_L9p!-u+$jd9-Rh5^Qr!nm@;tWlWC<}JJ@&5Mq-%$H)*5uI@?->r+aKSd8at6b^Vs>p6H$4^~C;*uSM$Z!?kKx{ffTI9F6<&I{5nfp5Cj%Our&GRzH+%m~+`A zNK;*k)wn%j-=>3&H~;8n&g)%~t-Cjkx!^&{$%yki_bgd(Gu2tUw# z@>6AI1^oFxZ%v2srQDvVu!m;C%={m{e!iXDIBCAjuGK7)kNspi9@2H0Tco&RO+r_} zk-Sx}JYM(4*DHQyjoM+ej{UG&`Q8_m@#@U0&FVIpSMAs?wWn*QRfCZ8&Dte<57{Jc zYJ3=V$?UmPVMt5*~)VwlKzq{W5 zwcL_5LUI|R{7-bhFKP}A^ff!i5p>VG^_m9sCH z624(eR2fTpm6`s|^G}LD|Bbr1(018`JlR{N7u8z6-My<^oTV$aTuqD72SEb+PFbTb@`zgw=#JzAH8iAuT_-(R&(W#l%$_uq8E4Xam) zZ*W*BV*aY+Pw&y`>>p&`OMY5+eqP8Di48~MZoN@`JcE4!qxUJ9U(zeKp4j?>C2+fN z$t8BnfMH4D2Nu7i?hhIhFB)BYvPE<6u?G>SwX|;- zFz&v_-~Mx9L36&6T5QGcNq6T!B1rb}6zf&3}|>K~uAwS8j0DSVQ0i?_eBBB1q()jqLRkG>S2 zUAvge`hRobTjs{%uoVK^vP3Ok-qSaG?sxnO4@EC|H*%bffcKNV`(hZvPnmTcxbZQF=}+y_sCfPc&%Ta^W=nZe zKV#>us~%^%woW~kA?4AMbfx^Eje5`GxA!Wu1&^=uaeLVMSaY}cg*|nKZZSz`kDm7w z)^NNf#k}iHN}k7@M>bLq7UZt6((sf>IK4zXcX}VU#Z`f6lf8 zs`bm}v)kYMMcRtb{)z=rrk=Z^(OGi3F;SOQF!6D?(*3yg+7(AOovZB1?0%x0 zXt&{!-sKlI+mmZw?D!FtIJt94vTk?P&+EL20xP~=?l17|SUc7B@TJ4D65MNMaJVPE zXk8W~%3^4=?8ut$+y5y%pY$t%MRUOnPq}@Ko=jc~CmMwLZWlkzro*|BN#?Oq!30BL zhf3A*<@-;F{8_(F&8U-I^@mJs#47)SsRuu93<(oClk|J7!kHI=2bauY6FPD!<;|6C zY8RTFXYE`jxW(k*ZTFik>XQF;Qy=raOwfO}?21WZ-jS@O?J7)M?ZvZhpASs-ipu$| zB*EV8b-H`<+gdMUFXezMXY6I4CNp0=7#Za5)Kv1(MYCvfZvxX*{`eAK{aBYdzbdXB z-f=t0;2p1?=8@0aw5}~myuY%BPf_S+_pb!5I!ZpRGuOS*%QflSu)>DZ z;*ikw9>FvBdT%I5O)77l7-4*OLPlqiz1J*DsT?*{@0$}ha?Ka)(Xx)-{oQYO@!O7$ zwx(&`H5UadB{C+S3bXd?wBAt-=e@IlpbrHLFXZogEewZ_@JUgpe%4?qOca=L~g5fDIv;z`ON#-VQpk>Dc|#t2mZg*{|zc zqqC^3@L%x7{Z$;>R(>_8l$d9EaMtI*oeD-h_nq$<7ydbvH7CpEPxQUNGI`6ILyf1M z^1EbGw3PSU+%Jzd9g9f1XH&HP;eoU((?j>V3Ts`E_LN-m{6gJSzbTg`FWgN2v0HWf z(dnT_rtX=dCHCTt(h6G#_I>BhuH5&FOLY3a;4558iXqSS4xE1_c_;acF~9hu#Ho{K z@nFZ=^*;2u#H|;b?#M z_Vi7XJkMVhJabu4Ioouh`RB{8I_@;D7I2ce#@hbmYu}rl_1CukH2S_rMohUordFW# zMK528@6XwfFV1a0{gLaAr0}zy-M+Vzx4!qc3egq)>HYZH{p+8Y^JI63wXArferF}4 zoAaNq9#>o@gs#56&7@=DhIgE&B~Jdix9L}6s#L9^Nu<#>x19Kj^*5c^J~_k`1aMeB)%kzy?8P?? z`NGNdw+hl%8U5#pdSw~K{!ylhvAQ>Z{?na>O(A=dzOekO&&~ezr04&#pvr58ENLf0 zs<-@h?aZ6_;H~IzSUZ*B6Y>A#%gV!nL_=a(h36=&EBPcLrI zy;=D~QDnWyo|wWo`#s7+37Kx$i;`qd?Pg7ESu)jQQtwPR`&<3Ra@upBva6}xn6PKz zQ4WdQ*HfQQ_&()j@v`*>Y<23UPapl{tUYr+QfHUG@@k>^|2q>3r`@gMTs>84&iMi?mtO$Yh0vcy6LKU_dfoA9(|=U>Zphdhc`d#ZWpONQ=Iwzn^w)P z_|CHaxfy5n;_8bY$9hfQo_sh}=wrw9_doVME)miH`g?g0!@-;>et)O*Jb9QMTAfaw!KRDqb>cd>9h3#Hdpy-HJa#u(VygJ^H2avxz0VUGn-$X;JEtig z<>cS=+Jirkh zST%|_-VWzDyJM1zde4N<(icm_u9P^>4=HoFa`fg3fBAVvhvzGb1o|J!DBMk!TH|m{pm@CpOjy_AGIld?ILkXv|_cPdRN_xDAxoddjqlAhfCii z{xUzj_{rsICC19n`(_5^X1}=^3r^;$&ShTI!c>U@**EJ*Wcl9ltdWv_3MA-#@neN5Q@9jOnCqG4A;D)eB@13T8 zW|LIESsbSvjeiH-m(eV`p^#Q5HT%n&K)2?*z6II8PH*?r@-uFnw8mO$|D|}HtEmSA zelS0Kd3tVc#jN#O`gg9i#OB_g7SyWW^CQ%?s^yJ(!hyOY{O|4Lp7bz%kP-ZTc8|-N z2Xo8{s|-}6RixCe725u?TKy#9*sCXkMz`6H&EuWiSQM~vQpzV8kNX*RM>jNj?3nKS z``d53zl>V*j=Z_!r7&mn+!sx(GoF7rqPFYNqKl!fItIa$c7-WExh3n~#GBI6UD)CJ zVE4uiTex@Gl%6S+E;W|SXjZ&(<57I`$0N*-=U-R9TXZ;WQ;o8*%iLt{(zzaQ7)Hqx_N6h>xAHh$&EEz z{8hL%tIlIRy~rd@Y|h+;Tsj-_RW&Mpt@JQ%%zKyI_xY0liprCPk6#@>@#4pdX{=LB zL{e&dr0zag;rjic&&5fH(so}ctrkpvA^>1dL!j!(yewUSo90o+>dOp*kpdeP)Ue=j`lNdmRY)c_UzHp`dVK4 zNuk6{SLLAHRi9sSkCTG<+}8bfi+Z)yf@AW_6`S<)avitH@7yYV{qx^nIlrGXh6t|Y zy~lOnRZ~Fwg0)lGpWME}BR!q_*Y$mH=-|0G zw{g?+O-8~&rDloz2~2+<=k0lIGOxG!X5?iF8ILbw0$Ee$Rd3h--_*M1-{)`Zb(+3- z{%795^4j0S%NnoEP!V3|%hmpxZPAp8k-Wc`PB3F?Qa@>W`&`|(1Cfs#UCSF>-Z|W8 z6G&X8^!E%5N4-os((*FP7PwX~uH({tDTu%oS%?!>4luX>FGM5udm0@uq?clfQ9uWCX}w z>UhL#*EQ*C!5KfZb&pb}CaqTf!@kK@k7H8Ew>67?F;s*HsZY`FRpXlW>kZ?_y+R#t zwBPO%m{8ogJ7%GR%zlgKD-PWFJCE(hoT{tgS=SHwZe6d!$mc9mfBF3Unc-jk<}No} zm}qr;wGIDT_M4fzOb+fbzR1B4c670cWUyNAf_b+diOFRIEt}^Vt=+YveabJjZPDSv z-|bar?m0C>w@u^rucyUTJ2&r}XPfVFa7GYMe8WcPoNG;9>z*$X3^QQ8+vE80&&@U3 z8m7CK%u7&Ia=LuPs4}^zgmKGd-PT)sKU|pImpx;V-l|1+rxd?h>*bIpvx~iGAM5mY z2eurR={vbF-{V={vSQzP76Mz{-UP>7WwM&?yHzzO2r)b zBr`c%TEKqN+8^HpgXTS*);xK(dW2PWlj!kLtlHl&`QWh?t}V>Q?>0?3v{9>g z&7sWC=WIQ0%#CUD-=UqCdT^ocmMwqHxMGjSox8B!R9xUqb8H45-`0ED^XISotvNkB zC0kTV#8Wl-$hG*Mea~gi8?@KWvGbR1@?JdmT5tEQsLjVG#AcWN5@+u5J!mq$(5lqE zW!2m3o;Tlxh2HA^tvyjk)6V1c){Cu&Qkzyh*v@bFQ!{_!vlB;uTfW--I972P&+ZUW zHLLDD$(etqhMvwh@Lcfgvi7odY|bo-JUwMk%iXzzOau~Z%G_?wHeD@Ul-fsJJy!2RJ)0duZ#^3#Z6S~74YadVN?>>0#wcep9w}wO4 zt|#0N5eaG#IDaUwDeC?ez4Th)1|xwzO>9ct7I`jJ^-7O*8s0REYHVhUV2JEE1=$9C}qewxea$ zheO?yc33U%Qa|lteelc6as^eMyaMK{v)6oo*B`RmE4H{v@C*~1^J3O}`xpP+vFxr| zj^4F{KVOSxnH@P5(f%gumK58a4;Pvkw%w^VJUnl!Pb~{~m!H$GKkUzLy;!sRNyB=N z%g?vi9o*UY*R96Z;7?l9{+Rehcf}cmS8%9z1f(v!uHkWPkJ1#wePR_eUfI1r@aezs zrMkI$DlB8a?AgpN@-VdM!{4(SYeKFh9f*`JHGe5?xP@JA${r4>N1i^Hk1U=mbnDpp z1+mvG7UuKV8U1kEzrQN`$d0p{PFm$YKD2cG+KP!ir$Xay95xFH@nusF-QB3xIj>eb zbNPoS`3DX}CCtzME6$)bBkhrgSFli*DhKd zxQltthWD}hwK2Z6-BV21cji2B?_T(|A@Gyc#e`{|3ai%NWI3^BLHMhXbDwX_yU+Gy zw!yCNzD;TkRy*eU{>)Sq6%S`sjGfu{>Wc85un&T2?-g^(EI5}idi<)H+V|Tan@tn$RxCXq_B0^WbLoS3 zDmGJRe_uOy*~B-OI4936m)erIfam*+7n57R+g2TyE_dHxzM$>3z z(woqv`@8)^+_&4NO4kyt-n@0KJ31$A`|&)X+dO@jGOKvnzS->EeG+Thv50 zoVjRnGl+~UNWhjalyTOI)vvZr7CO6W-vT55Z#R^-^(LnVM7!nfXxJI#$(g$# zQ~$Eo{Zq%v_x`!}_yN<$Pi8eWO=5qVa*eiW2Kq8A4_ZC{&C#{q^J6cCUi~srBIcXS zmvm#RgN--0eG6!8-ekS`gW&O{HD3xonY*gnt-Gw8?8+5z>gw+gPtJDK+-CG^42n6M z8TQPedZ)4VE+=l8D@=R&Dt9EDiYRpVt*deZqA=PW;T7JF=Ow~PZav{C6 z;u8b6)sdzzW{2)dM=j4<_~#C{@)`G+B@5^0oqTt$=G86V-|zPK%=>1jch=(Czd2%l zS_ikOzYOEq<+s!{zqvmlq7_SA@p0#`L$CQi6^ z@y@jaWh#r@`5BCk@XoE65ZYz#?o!fcsG?A~WH!gCBDMOT7TLR43-+q0gQ17?B zI;@t0(_CwemwxJ$6)L(eW$@oK&{(R_qSZqZSJ-eNlUhJPg1OYw>o2b3)>fd*GpWT?SBs3eDu9aXi7+J z1+RBPY`HNyk}Sb_2%J>e3=)k#13qX&6=$JUge7%w~^3$$R=>$b(h^{WnISz(=cfk7S=nP zH(#AIMJnmU-FvrYE#1Szb6Dk)cG$Ncp(~<}ncMpx$*!Eb_hy`5HB;t3BlZ6=FP7?E z%hxs9rulm(hu=TztGT&HXR}D&GqOL#;ySVDw(o_!&g*e|PninaM1S6sVHG=Jy>Z>s z1%~Ip?@2w=_H4_xb>B8G4_+2pBDF}S(II-K$I|-P(-YT*WZdTLDnHj}vDmKaNTG0f z_%n%i36-lp%N(zE>4d+GX|M3SBH~bcX33fj-mH7)o_3n+*;O%XSGxGUX}>NTehpgq z{ZsvFq2!`N_x^?E-VtzI{xOODRru`W+!fbfrd9V{Ixq0I=ZRZ)N@PxY%=PQHlxDI9 z^qEE(&*X67w!QW@ZeiF#Gwth5vSCxLj^6HGWfmQ5(bqaxq{G8B-#%#0$L6q@MwX*@ zW2)cFC$OLB`*S5nEQhn1jn85^i|FKCq4yb2RvwvpX06d|#nKhNkw@a$4ySnKYVNbl zy*^kw`{Ys9Z7Ctc7jcU+SC(#3&1A0o6D;R8O?F24n+|5}w!mw*IO4Qb(|4SH zA+Wb1=7=QcIh%;P`{i%iOU_**yodRXf!b<5D^>&X6z*fo=by^sZC$rH?&6L1mD~5d zc_g3T&ug9gr(|pXqZ7XmuvX2w#=PULk?WVIzJ~4F&&CMHmmHF8eBg5>_}SAJvwrqj zt?HVSaales_Pz0GlLOH)SJm8uUL;IOwhVXO(^a9Q_@;)>bAqE%U4!9c#a+2(p6)%0 z+g(zX_FdjFv(v{?X|3D8MKLQYlw)uGT{*q7O}HqY@kRUH)css>pTxU98CbIfpKq3A zetuBz(ToIJA5Im^l8%Eazt*#PbuTh9&;Ag)CZwuZSS*Ciaq5$`74L583(Z@QwI#av zO~rrZueoJ9j|!UYX1&#RH2st4F8)eQmfIte{dt|vM(v_bvC1SfU)yzZ>mU7S;B?>p z@}%|it2exLXD>Cow^wBA7K@|CMJrTytv|M2`#6j3ev9V7?vP-yA3N{W*69arSvvE6 z;oMcrCj9rRy(-8cwt2=4m-}ap(gGM-1GN`EXOpdXyd*Yb=S(5nU6#(L1MHY{E%2%eVH4@1!R@cw=^a=aikFq_5vu z!Tojq?2mQ^Z%Tjkr_RcGziZ+aE}IZDCMEyScE-8u4LolZtA@(+Rce%&cR$^3QgHBa z0=MJVJrTO0Kb~0hXf9i_lQT5q?Ci_Got|w9Je)s6q^~{rkjnoOl}E)JxSF2C8kt>} zTEnzukwdqGzPI!4mfYznx2B2h{#Jh7%uoJ^lgK*x*z1)oRb`J(UUGihnkFUxRkx8r zA;{-t&m{8~^2RY;E8j3KZwX&r_tDl+G=2Gg|F4x6l6Mn|9&D_-tta{4BPzDRNkU$7 z(eFEtTlcv>`&c)ZVaMX;;||8EXZA&gRHmrjn)c7i!e4w}^qcRTe-2gN`*~{NlJ*K8 z=lL`Fn0McqXg98dx9jV3<g)KfEt$?7O(vecrj?-t`*6zoPe6COzZo z&Cl3w;xprqepdFEluc##7aCSAw2GM)p|N8}>AFdarkj~bO!zrz(E`7!mE50sKEG zhP?RYs2Lfiezw2*tHF9>>vDS=2a^WoZP7O)js^*3woG?V zzxsi%q<6^=1udz9tj`8XOV7kP8{Yc3D_kp}<9pE}6_qIe6H;r-Bo02bJE18rckAw4 z|7u;qn_dMEB~7;cLT&@d{%uA4$v!54q72&y7$<(*2kR*a@*~A zK5tVjeq?o6-n%i+?(dD(|2YLcS(Wml$DLxnm@r#a|9E+9k2|}Askrr{o|QY&rmX)u z@r(D|Neu2K+$PRGjj1skV}%N5ed$=gTR&lX`kMsLQ05;8*7+`to!$IqRuEH;!=fO& zW<|~5FX2}L_S#)}xAxq5hf5Mmr$srh+241oJTKtNo24=nM4sn6N0&IQ+MxTQ<-(o) z@s~fgFU>K(CV1--TlHe!C%NZRuRmXSHe)MuI>+vmWuM-%PU&01&3LjlvQ6&@f53;& zC-+5LS0u|vg-)KFu+l!doKgDrhpP(jcdaV;IdR60_SUlI{U2ZaEIo1dq3Sip)sDrk zcP1(sNF>dfFqefZW$xsz2lHM}o>|W?seL?o)#v))&_6eCsfR9O{q}aZ342RxP4>E+ zAH@dlor}eJZ2JPA?d_|GvudqoSNGZKd)G@h`kfC`PG)xZndUDC_q4ckYg9X$Tjudx zx%IT9M|qL_%=O)QMXqyhZ_O>c`FiF#F}}}Jf@B+1r`$9+KUvFFVX?&esj&~GAMCX| zutK47)iuZ1pL$^p8^wZR&+b2~|90t8jZNRVCC`4@@?QCOfc~9asz%&zCM4> z^~lEh@N+J2Zhx}4^R2!+Nb(HZu5^a;{hUvQ`KF~Es(ROTYzxP}oP}FeR_NJ&;xNo; zKEG{SVVJq9u1qy^|e_2VTRL!*Y6U4f4UU#ICD|F;UZ7LX>F^f&B)l!Y_#jdO4S)t-gQKz z6!p8kP&zq%j?cyD0OiB(k1gLGq^&9pb zH2qYiXTPfOH7oBC?~Q*mq=aY7Z}PAY?&rAU^k>G0Ip;#XezskC!`*UPX4}J=6YM-D zFX;?7{5H4#3CsV08~ZX(vo~;LUoz3uWHXa6KXLca@~nvO%-R}<6HYob`KflLwod8_ zR@L~k;ECNmMGb@a8&4vPdOA8DYX_@(tcjiNz@F>n8_YDhiGOn38mARcSa>acEUbgy zHk@Q>ynW>5_wPK}3yYt>-zKRs;kECUZHDavSvL$;EU7roa-_eI>1>?%Lm6k*0AEo< zqsRY$EZb!w`7=9KcLk54#>+czEhmpk#&ym=#_RWT;Cbw@?|GczpL5i=}{gVbC@*c&no%zRE`GDz-XBX2G7#65U`~GB( z74N(br}fqB8l1l2o{xj0R`mf@wlu!uOo}b#Z~`zWctzf9?$Q9Hl% zwvOQSG>dN>Nipf)BRa3&ST?a|BG*n6(FcV|FE{@ZI>+87Uz_&I&;6aRU@^PchyRWi z%hqmuR%P{a&7pZaSe_m7Xvv)Lr+BvL-_B^2shz#aMx9yA|DW#*-_*85$MSkiv75jC zp^P|@NB#@Dg;M76$hYg){XVz$?$XZ|M*?=n=^SakGyh+YnWNheJ=c@J_X|eeXW4sZ zKKB8g`v#{Yuc~#fR_UCa;XQkzx~`m+i;qEFu>pUu%+EOfL$j8DSYliPkR2P{hqRI{*L=Xdk%=s3_Jc{{l6dL7msBgWUE-b?vEm4 zfWc>vMiFuIC+1?a*BJF_8!UY)+c9fePWZfpxW|djb5=^1c2-@Sw&=)d-FD~8b9Qah zI=Ld}Yj)K0nHT3s-QKw1PJgGs*8@A}Z{&3eKKN|i`k*b390FEtVv3ynNvBNif%$?% zGQQ3Fi?7u6h86zHQE#3nHQ#7`ljN<`X-)_&;zI@#4aW(6&jM?rk?8dG~ z&sqLaci?)Y=p&JuI4ik%ee0cmXWPlsH8>3l>Kk6LIy}u!b=Y&PAozCf=Pz2nKdiK1 zEpp6X+`0Yi8uy)H>Kx1yE|+@khzi@dyYA{<+qI{^@3jakeck`#$l7H~KI(d($=WUT z;n~B_8$_4BiOxBCQ_3Y~gT0O9`aQQEnLqx!&&#NP`Fx(L`>WdwZPq^aD{+Zu+q1Uu z_3h~k-x??;M4ZXzd#iQCRDECPjU%hA`&8<^RTeScUy-D#8#HUR)O;DnhYC;oPm07` zD=6RbJ6gEq{jP1<9}9O#u$fzxzNu_Gt~rTOXWMsymd{gXFKIv1)h4@`>Dpcc-v=9A z)_Up%Ct21_{kWKaRpC~pCtF){9c5b`mhs*D&brmb{kv}ci$cS1dOv1dnDDRl$Nfhf zvH#{@e%AKd`Zo8S+bR+7r8fCjsz3Q~#!sWGIi9)P#-d9s;j-Bc(V9ov$LlquLe;aD zoO)e!ZJ~XfHsep98JC)P3MQ+Z%IWy1WiX>}&ziqK*Y4f4>dN#B3%0I{x>51L;r;~i zdy}R=*mm5_=J3^2Rkg>Ni#s?@{=4x%{bb3)N3YZGoL)S;PrSc`BO~Ih*z*mADk^Sg zo3<`H!aMip;-7yt(-$7(zNt9Z?Xsll8P}T`sp}lnmsL(o4B8RSdp5dJKXBI@p>Orl zTUZYHnS7hNc|Ln>-*tz+^-FW6_?vGRVQ&_l#d%N@6!MqX;-NF+k-V>8G{3Uqwmv%lZ zEHJs>Bb2pt^%N)jzMROQ+)y>24;Naq%pOXWDss6NHl0wMemU(!W2kpL>xYy+3!x^7^6^*VeRZI{!TS zmdnF^yH{|0e5GGY-7^LC|Jr4rYR<)ZTXHROo;N|$!s?1A<2=ucYx7s^(mHH>Iep^KZC9D@Cx-Rh;hiU# z`A)9*@y~h7tmZfcoy+$k+gj9D=DI~?Ei$hypIv>vWM|R`kq<>S(yB`j+<(`tzB@Bi z=g_Smdn^|HDgRhM^%G9Wxhk*!`OYzWN6qo9t(X7sG_AhKS@$yk z@1N#li#S*hrljVI!N|tjvqnXr(-JzkXUETLmd&Dz@ty|tk9}q~HT)9$D{6ba6 z(WA@m>ZPumv%6bu-`<%5YUzJB_s&r>2-TEeFx~k)jzB)UCNl#%-Uxek+wXAy+deloobi?(pH3ZCJeco)c!KWlNL4D7yMPAzM zzwgxt-Roy!6S0ZCT-gdR9m?cN|DoLl|(bqdS9nEi)# z{yU>QYyQGLjci6cKb$%&qWZUd0?(D|^2_(p1#!Xcj`8NJ9~Nmr-x&fI-Icy_2KFA?%{p%PI>O}CD~yM?#1dWXiw5o zOZYX%`O@wq0v5+&<0outn0er<$!q^B#k;OQ_~y7Z=2MZ!qqw-Mywfs#<=-YYwCVrb zq!+e^OW00tb1(L+zuU$cWRDp$gw=ylDy&;lLW7D z<@3$C4P_s8UY#0ce^2$$k}aFrVp~PUh5juQ;8faOXD(~Oq3*M^JikSM+L5`@9uqg| zNSAN1W~`OG_vqxc)BhZTesACpWGT8TyFh;Sp+j2ybJOJmcgTDd4+)S6kLKx9J>k*& zVXm|oSLM?sn@$%UFKciQQn7mJk_ZffQU&>Gmn>E-}(R7)T}2L#nSWt z$H*AEGrY>Sby~tIJiTc_V)Vy??cV&sC#RnYe{3XIyx;hpTOJ{y-NU7PZA&fgWq zb%9?Gg{5sO^||Y-ry_P=edCdc>x)IJq?TRD^!u8Vv^%+y`RlHVi}EjeGFlD%f)1_< z-Mj59=lWX@W=lnc@pptw+@xx)5pdv8+0mP^L1&L?>o3SwTd{5Zl9;pW-(*gEW79Bk z&%T!{4P=jVL~N1yqS;($urPnxgq@1*3*GKn2`qF-xfy=#_`Kz_S6ZrGx8L_EFd#hY zt}sw?3VW+pj^v7yg$J};f^cG>@6`r5L# zb6s-V*U#S`W1PrzkgsXx1vcUXqLr;W4hcc9{aqw zT-(=^yjHMt@m=A&J?aLRSH4j1(pmT?Prm1D&E6voO+P}_mn;tY;*{3=B*Sacj@x!N z|23x{eA}|c=G<(CRhR9yYU$o?QFMr?usI+6X1~_oNoh|X@!9WP{~(t=S5_fo2e(~vU^|;?OpgVOmfA8k8^i!)BnI$q^J-{(gJS{<;Q#o#mc>Pv76!ZN{&4 z>-&AahEk3*yH|E?jk_h0y|F=C>3a5+qyu|j`px;PGFjtF?S)NWS9r5ON)N4fVVdx6 zq1L0Mgk2t6KZxCz+^-+OoOyq)&-sUiF|saMUcw(0FWtK5=J-~5-L}&y58Oj71^Z-E zN}o$OO_z(1FMIZJ%D zi$o#4J8otX{SgN=?b{9-+0Ae5Ww`0|vgw~^-gz(P`@QXJ-*XGtUtheKS@V5*9$!p? z+I|1s40GB9lXr?9+_x{Me$~FU$71&^-K%l1=INc1Ia5Ec{`tXl_r^KZ42u7bZ~Sii zG0Wt}wzWIc=66pnetYn~Xx?<5h292MI%}oBvZ%CFs)=8&spu+uKcW_DSzWV(N_4G{?2KnEzX?@R8qg z^Oh|ObL0&Ob#6C5rCs~N$glAGwFL9CDr={nP`}J)Ubfos;b{;zee3(l=HJ8k>#3UkwR1>42u!GAM^ z^>!|j?VR)Nj>YAorK*2!xWz7R`pnA^EiLG|P~3FFogMcZQ)W{v1q|8E{vpC}QQ_r2o!+-4t{D>}CR z*;}iu=hk^%Z~tABnC{Ob=<&65me%F~?l-O;w?3`1{@vNyG2y56auJ)i_r6J;Uh!Hq z(z^7k#gVCUyYgFD@BW{}oof<$t|Z+rae1!-i>?Kz&fhkz>D{NtdW$YM zI9lFJnD=USsN4d>6YbmIBndNK=KoNgQ<`J=ac+eEoK1GGgFf}ne&b-PKjA~Zl>{newH4|GZ}R-HK~Vs<#rb zetY`se--;q7Pf-jE7zSrwBi3hzt1+yI*k(dT==ga^pZuXHuNNKbkIC@$%vgo>+dXn zze{V~K^KN8E$@1?-zGl4d9K0IN;$~LBE3NI$2$-4!n^Cs_lvUgid-#m>7TZ?*df+W zyh66z|E7}YvqzdKFAQJLyZd6PJolE3$6V!uH?}+YXZ=|q@|iQu#frafUEvO)?c3W` z`))js_gXQv>dbh|8z{gz&7qmZ_j<`6TZ_&eW!?H%-DhFK?`QwcfaA zrs3AO|I=rc={mO9{C=Jsyh?S`3eh7vPq-I-*m2rnYvlT_M=K2(e!i5xY|e9Ly?@-1 zvtB}G6WQOJ$*i-@)Iak0i1dN1N9yui3q?L%W@@`%JL5yJvzE_6X?Jnm^dq-sKVRn* z$0v91_!Q^gny*g&zIG*H-jkr`7Z3Af$5m};dfwD_>sG?dd4g7!)@*0*$}HVIVcD&Z zJlZFwi7tGTI{(cK^A9>=J$H9_bR1!iZ+mU=>-mI9FZ_5jY*(HVll=PXAon!+!^b6< z63=PGD9ZI0*neAJ7-}(h)&5I=%ckF6xbJKK%~c+YD;z^xin(iN&Z#uCn%?6c{x{#` zoss`6f$g@JL|Q)9&%WJ#aL>G4{*5PXd}o|Iy*1Wq+KTTh4^MrSzfbII?!GA58%ejk zjhimr=3sfa=iR*9Gr#?ei9dEiC}8?u`!_eIeB(Ru=JA4z*~{fuKDfxW^xEFM>g7pE zpQ`U9Pq2USH(P(+96d{;gEbcqN6wCB3uZmIN_DTkU;6)j^OXKZpV(?XT~ACZfQ{{9 z^gPi?B4sYJ_PX37&%_O(4O`7lmrI3;#_@g#tz-1(cDuFdGk0(Uf58HmE2l)) zuUFgmZ3<`C?-!TuyGI}SaCIsFu6WJK3wGXG8e;i#Vos4_jmQ>ziyg;9{-6DMSKHF| znUCq!loPAM;^(mo+RSO<`IEoO`1n%w-SAl z%eQZ%UdA6j7_a9bFnLX)s^Nif$vwO5PEP-Cu*xmDcUJ-%*ZIS;@0`vAyp8tQ@7z_G z^G~CUGkr$!4VUI5gXA3?o^NwzJTI44?77RwnAfD1;hyBzeyO2BQT_yntxJ&RlD$`B z_D4w=&PddC+nw0OS@&h#|AHXbllID~|6Py1{SpBR67F1NDk?nZ z$d8@PTmofT(|$>^!qpS zk4)&vIJD^K#P{vT+*D`kta`is2ivO6++KShTij;W{1^VejyFBx!17GSbz2-q5gbP1E`6GTl?V zjROv7@7%CT$o$;vJy%qW>_T>}{BucwvFiG&lHzA#T=ARtbIj3A{x!?XGVCsYJlzgWc z&w%L6HFJ(Hh<#-lwlngAjdZ?iiJJXs@e0?CJ-o*I-Ci^w@$(QiJgXkA%E}a}_M@P$ zPx~BSwEcSNtg5JcH_dLHOqMRVwb8_K>C5xd7VCHIof|jH==!78OogB0W27ghoviRY zu`&OO^Zi}7=D)fVUA?s+(4gCBp6G$k^~@m`Z@uY$EL#0w{jQ~5+h4Rh2Aq9jkoPF4 zB}sJ0jTL-u7B`-MnA-L(Was`M+4{}ivL_F3RloVEV%d()E8J2N*&H{Pi$tuhPUtvu zVq1JJ!{bRavfpy#o|k$*O>FamE$3yH2LBYh-or*!EzZ3XY=J@qpt@_6s z)hx0y_9%FE_h=B~SEX|P?I zG3Aimi^R3=ie5kR_)`~4&TW-Emv$=tpdrw53>JU93H?3!l8dt{Kr&jyBi@F?dD)z56{4!B?*7UcP zIup`1?=hIY`=vu$>egz5|Ia=$&(2lyI(S1WZAyUgv-76?B|^Z(Zn&EowoeV2|9^1x; zsx@C(Y2iM3-IsS~*F6YW>r%eXY(d-Vl5fu(S2oOI`5dIL>+)J-qQT4QM;EbdoE6c^ z&zZmBx9sU16IBmq`Of{l?pAfzk{J)rC8*6heU4R&bI#H|^Jc%3ntW+q*=JD&E!LBt zlPwi0dD$dC=5uejU{Wo7d>Zq`xB8E^#VTYPDhsD4=u|g5i9BXgRu0|rvZ1q}A#_KF zv~D|F!;A;_wl?4YbmIAC;~%yQYa0LgnWr~6s>K{N`q{hc;Gw4+pY_;RC>}ZRHZQ}@ zDnqxt^^@P_@1^09UmxAK58%1=-tu`o-<$fE8G5DdQ?|^ud%|JW`7KT!l zME)HTGq!HgYG1{z@#t^40%Kr!sJ-GHE9d?1P8P`dt!m{gG_+gq;^KaD89R#}y8+K3 zF1Hh3L{HtzF%!IS+aqMozn6QMlYEZ|?_)Z*Yv~0k)#SQsYxbnyjf^?5DtO28hp$dr zGptMCIj3B{{BkKzK>f5G;eDC9d`nC1-8f`3o`~H%|MSXUiMPjgO6*i@DG0tE*KqLo zHsQD*e(D!xrf>QFFzsmFT*g(^wi~Rbizo*dJehZh<=3`1@!NE&Z`@!g6$qL=?`rXr z`Lixb{G7tia&T>Z=d}AbzQk>Db9Xt}{rHJnG$U{NwV5gXO~!dQ8dlDi-G6D#r@GcZ zn-#P&i}#<_QCPE+=RwBTm(6@@Tt69wM|AZs^3RnQuKp{xSosXs=@*X}<9vnemj1Qi z+UqruQ*G)Osa0B=>LZq~dSvpQ_s^w6D~hk4mXXY}HP*c?G$mPX&g{3(S7^-R)b~_4 zB)qercXC0o$~}R9)9sb|7A$hg_b!uLJIj10Z{JBHyGG_(rS#wboM#)&(%ydjW7fQt zbMHLoezH8{#p0gp=6hIPZDVoL@M2)94X(JDEUa7@zxR~E^mp5%vP1JWhUTvomAkbm zVd1;Z25m`3DaK=G_EbL0-NKg=v{>LCtFOLXr^Ckn)T5Q&Vl(%ot89*3^WNml!zVvj z(x-daU7dLI^t}5^6+TW1-WVdo@ivDcElTo2K&JHsDZPZugR4)4eE;x~`I_kN8KD9x zn~wfGB%7ki#d7Y!ML)F|my6M}T)s90GJ6ZQ$$aW${E~U;>=CCznKgW_7v`PiENSC6 z45-o4Q!ogc)i1sND(mS**Fz*OS3AusGBCP1dE;%j>FEbw@7N;|^Ti_WMYDG<=d%+c zQj6J}JMYV!UdH}sde6MP^MT3-*!PJASStOi`Nfvuv3sIf{kl7zP46}`K2~8W+gF>- zz4u>k!~z8ohA)9U5vJm7+h3^fW_JvWmr1lWxRdc?!oG>_7F%C1&Wq{f5UsjW+ibAC zaZU{1ntji16ct%#GaBCRUN9%}&h>3uy*%TuS{U%#p7B@h{dh$*STgf*jGW81q8l4t zmTh>ya!Hq`|1Kuo2ftRwKl%|@tYW9b6=ky+Vs=tr@_gY%2c+*L zt^2fV<*StS-nLR{Kf}DmXY(Z6rfiwA%WKNZ-J!>P*UzuGrF&`WLg}~qlV?~T zyDWXo?kBt68I~_SsXJ{L+TBeP)h^g>xidfW-<$AlQ@-uAsn6EzDm5=f^ss;leCPT8mB51U7CJ!YlE7~&9h$S9#3Qw%5|TtXJ329 z;6qf{v=_R+wJ)FOiDAnVOOlDMoP9J+US`c}oxEK6lB?JZ!JH z=k(O4PZy~rx_E1>{nca_UsCttGuP?4%l2N|z@>Phfyb?fU*Kw#TdQ87zrrC#?b`ye zr%vD9?Ymyy?sG$u_sKeshQAw9R~$%u<0$f+rAUnN%tA+k2dUc*td86?C=>vy_3JI`+6^22N_zu|9eN<_tZE0Re_-zEw3K!ZQzocU*$U4cO&MW!daVu19#3D#$2@*iRDwvIb!HZyq&82m#;0-`+7?Bk)XkY4;yFwte^F@T4-J}W1!{91}Fa6bv{{lAA7G=WUt|M$o}HB z;nES_5QCI?yOybjsr4OE&)%hFYUt z$msH5eUnziv7}jThEk%fxz8$9jp^QA-~aVp6*v@kZ{>91$#Zqw=KMcrT&!64@v?vV zq^`hF<-T@j_xWx&&m9)?U;1DCxkO%MjQDabi&9p@`ETQwM>C2R=7g%S`ZT=obE!U2 zWHk2%oBYB5sck28COg0Cs{F|&IW>7%Xy)BnoVNrvnV*+*4hdDU_?3Ak@UZyK$MzZv z|K6ND`x1oM}g2pU#Wswfa!}IxaZU(e3`hjAbWwpZfFX=&y_$ z_Yao3`sM5X_j_Y>D^%f{{gU3e1x`HHK^4;&g^$YLuhOV|>1`FWux@s9Tg8@rPC|i` z)<|w;vs?3&#n7rYr`X7}Z`OhGq#G4q3Qf=Zia+0B$(wRWR$t(VWb1DK5Jw9(lVjia zZCCX0nAknLamf)(y*FcfcX;c-~Wym&dk8akmIE3&?Dnb*lB* zo`n{HPYR0yew}GPE%k0U_rGI558S%=ZD;Nbub(ecCMUK}`o1Di>bktk$~fC9)fMk{ z-gw!3UgpT>%zU>~`ENZhO3sgN4>vfO8pGuvTRd+o-|LloP3+V@9CG{gF-rJeU90Zj zjjd}U_bVRVciFvbt!YT|qJ$Iw+n<>wz*6|_&a-7nhn2D} zRTYF@*?+pbykYBgCm*HK_vbF3<4Rf8eWCq$Lg=FitBc!ZwWhJHlHa7t5OzUg@%%kU z=GPl)iFqBK!Ql7B_Bo^Ri`kQmU!5^s#ca_dylU6KwqK3s&N|foT`YB>tfVVh-!<#= zrJSM}=k})c*LUu+JA7loI=y0lvF(k4r&uG`e?6Wa@p7uzy30FXD4I%rR&Dv2_-DcA zmBPfWXYKj8r1nx~+mq?idcO{x z|7lPtzAL_e|LGawZin}|@92+}P zuFokRXm0P`Hr;GZwEQOB!4?Cbq{XV0cjhVyc|E^RH*UGq^^4}YL6#) z8e1_-3rcdfyic`W>?u@8MFuDXo(J?OGYf;_J7B53k-4&U)sDQ-S+d z@9EMNoUW^Oc5OI6Nor^5Nw+Dhn{`TGPFSz8wrk6xdVgG{==5t2MW@oQI->uKg ztM*8ugU?lKlaA)((wz2pG9m9{)%dg~pLjd3U3jO}2~U^RiceY@zBcEq;FOIv_1$%3 z@w)sQDUGk0Ch*^x$XBsLM6NRU@w`GE3ywaEwHX2{w9T8gcf}eW(N~eIRu9PfG-t<=I&=rZo zpRZUy-_KrmVcnv1=Hmtz?|red3_W+j?~I66`=a(^@^6k$V_EY)t|dnMO^%IVl4!y5 z_0J{Ze=GAvNo?uSX)uxWa5UNy+iSc|x6h(=N=?GyJ1JhTYEy59TrhT@ocd2qR>6Rw zY18T^mo|@w2`z>tp7-Z(HPwDI>txv((`M$#znNmcgB{kN6`sefeecAAnE~>#2QD@@ z9r`e#?6{)YxxnORp*LUIt~{5SHm@$^z_(hLcv;DtJ{x~&vH!8k;t-vcaraNMiIvNv z@KyfWi&iu*SebMCx9Zl=W6O7EDz*DA?Ot5&F-vUAzj-J9RS%W#`R^F|=CZWr=2^*1 zVPQ>G=Pw%P^C&&w2$Q{4ayw@=gRyU5uG=%2lR5_$b4WS{zFN4mpZ)l9)kBJ@>ogS9 zv*c2BIqy#UHjQ=rL(3##E^FSK^By`Rt=#(}*R()l+LcFrih*9g*+owt&1C+uQ=fI3 z?f0|}wcuaX?<|(x?YsHBPych%^s=9oF(wIV?-bv*I3GOovhaHAllGKl2M^r)&z+=y zBC5b_a`)q?vkMOR<)s9$Oj)vKp-zzD*9n&uw{dozi<1%Z3-m587u;)Ms2HJLvw^GO zfalKr;g@%XJe~j9=;p%HOSONzmU)>oBl$SDPqR#(r%!7BA-_HE1p@@GPb~`Zc;L%FY@Z#t@Yv_4vH*C$W)%^rJlqJE}03LUpi zj!V7pXYGIC$R(F~KAA7)?D_k#iLJb+X;RBMQzM4IOv)jrj(6tdrMqNm{Jmkd|CNNp z$)8iJWt>+^gcS#ya76m8-^Ker$Ugbp(ZJhNE?nCCLDBuBzVqro%}Xaf+%DQa=~Z5y zW!%gzmDJZ8*MCb>PgSY>pvIHlmB0Gin+WD3w!obGzMo8vI5@ISQtCMNeQv?U2^H>3vh645_lXHzjw^qXbN0=Qq-%Xgbv}BZ z2n>BTbJeCVIZpSDxMtP7sR{eDhvD9oUB*A3xGjp}oh$ev`^MoDNzZ?Dn*3k*=W(Ep zwVagaGoyKVpS|CzC|TWmWVVcHc~!{QTeXkOCn;IZ-E>|te2-eg+LSMQ%eN-g>wlax zZT{!mCmnbCztIuiR=!(F;OOT~>X(CRU9ujP&4}@|=PNjS({1imA5O`Aopm#WnLVy- z_I;{)w$UW_VXxU@>0{#DPl_h&JZu?RX7XCb`$t@@-?vLkEDhci{VC|%WU#Db!Opi_ z@kP4NLhme`ZO30U&DC%R8}lk#OZ&Pf!t8o~^RFJcnYwnj<)MkoZ%nR_($F@l_w`~B z+Oxi(^j^fi)8DdUnx}U@UcThgf>-ZW{;+gk-(FF1?fQzWpNCi9nyjN%$TDTyrH`UX ze02pTSJ!ON=G965V3lH7c;f2n$(_rqW^B0R<`$A+I+&k_u{c-HeZnJr z>9QG;5&Pq!m)x~ncI|w;f>R4;qV$Tn_3AJ7E;ZndI{AQEp>$&9>;Hl~OnRbYXYDQs zxS#*^c}CpcX5*C$w-%J2Ut}PaEZkVbdv1kz#oNExYybb{*lTxW#>|IRYi&<&h*W0% zasRP#Vzbv~y}P?tn|zZtGV9o**27aLzGnTBy&u-`a5lYNzFvERm=e#_>8TQK%iim*v#uI6~QFmKu2hnIeCnN!ohv3JqVAX$@J=K6N; zpIC4AGh3dr+-}hyy|n0$jjIB4qfR?xlhQYPHmioFNhjRS`#t<>Icb5~`!z@V_UwJJ zX(qRCrNNN~9mmJ%=DU7zY!Fkwc;`;)Y4P6E6K69e-`jF&^13xFSN8`-tPfo9%xdL~ znir=7?-|92F1md3a@3p0E+;MrJS(cRth{!%`CjwAjXXazcF5+xttsc5p23!qD|E+X zb(rj@oaKtIPwzfkuqkct{{HutkxlK>cD=jTrh8!3yrfvxdAig19tJbyeVM^7pg&bh zKj(t@8yo)>`gvUO=TDUdtL!m2>d=+={B6mP!?Af++0GT8GvE|>`dFk-=SNthpDc&) zuHVJUr4y1C2=v(;n=;jJTU<7GxX;w3>0)gvv71(!ezF&tw}4Hsvsgau_qUoWCkohH zw@dM_e0_A0*PNQ8Mj@4_mVaY8(r|O3ulJOdUZEj!)B8)`9Nwe)_8WVHob=8|NekAc zFaLYjrq%D{nP>5Dubg?bY7am6C5w~M>*hDR|37hG@r=N(7y3(M^>iu=C4=vtoU>j% z)%aM^lAO|C_y5(*y{b8F+3V|zd30qz$SI#wKVt5Yt}OQOujkX_EuH_Sq;20Q&b@v2 zqYq4K5AMl7JbwG{idklLu`DY}tQCA`sq5T)X|A^Yva$F(#`~IIb9A%xioRQ{f6#ft z#mV|pb))B-!*iFPIvkx~`Ebj_bCsBc zy}x|^tCN+*Hk@&qdS$y>hF;mp*`AJW9-E%MeJb!R^B-5j)x2+yzTdqu^`M&NzSU1y zU&UwV+U$MPGb1F0`N*u((mW|(M-;E= zPkATJCcS)rL951gmXh^Fi)YGRa683a(pM%f?qJDR=EdA~}3w?iAnBo#Gj|Ss``v?HrADzXOVttjN)?h=`+4++vYwrHre(w>7fN#9z z(a-M=&*1eJ>e~6({pz{y6D2N5QHd&ZexJV+wd$7#pZU%z=C+~%G4AW{{S%XIG-h-@Sd486@~WT)gGOZL;-ovdZkPq?4aoIyn+PXMW|devq8K`1Q)? zz7KQ1Uogo%qER1mOt-Ca!~UifH@qx-xz06vTema|EQ&XOcVvU2+ah;P5uMYm4^^U}<%5!v2%wdMvz+p*>LhW=O-8NoWEO#F+)_V_Z{Wp9)_wUn7o@A;k_ zRdVx<{0_;!b|EVz}Q)AN2XBlI=AiWlOjk*W}pP zy%VzS>_2(>*Tr3G{${^mclzIFOYCOEmG?jB%wpC#9WY^=>tpYqdMkdaR`%VQqQ9ZT zEoI{==GFVGlo{4N)jar|W&6YIkSj{(qdVn72VeWnV^<1Dg^VW|{9c!PQ znR@ccJ)S213p+1_?6#h`^}*?T*VnwCfAFBs*_0ddG4>8BH|MxtzRb+FHSFiv;Wu6q!^X4k5z_Y|&epOlt!nbq)>_KJkqEJi0;vE6Ha7_C|{JLbcpOCiPIS+y42 z`oB^ClvGCfUAyPUSf73fXqYB z#r_iuuW8p>GObFlamgAAFi$4VU`# z@AIs=oy7$P=3Ww4?5numxF-kxl&#)oSY)PVJVrbSbtEe-2_t)=zcJtMi)6J?UOX`)K zgKta>z4GaDxs9!Ez;)3_Ush=)Fr7AUa4cOepD^*)i38G}t>QcnZDbd%pCrz1I;(!i zr-N2kB1KzW9s4U(B&R2}+8k^NOgkdgBGW0Fr2F)dz;72(6Oo0n_pBE-tzPqSi`Zq( z2-(DvxcjO{wA|OF&A+<&*pWDW*BeuXPH{57w!9uUol!&b%Ar~oabpdyDb+nqMgOz3 zIk}gfJn`LVPGO2??{WhbA+P;yMdx4tf7gC$!qz!U{0m~|zUE)6D{xtK&BfchF`J|LH&0gYJHMd7-*kKYu3Fy7?QbGR@@$&B=v?b7-?+)ex4UV$Y3-gjyC)BdcQ<+^HeMbG@6)rT9lT<%TG$kAB#xTPsHYp;~;EMv{qd%+g( ze!VjYPd0!0{`-{5){mO%OTRw03*WF|p*C;ZLYu|9Pqqi`s&&ttqq4W|a(Udg$JYh2 zGQT`|vQADl-15h^ZK;o>MDAbl;<4VfEcsH!f#jAor~ec--c;OjDK5cc%HQwHH^-jY z?D6~9nR6AALShx!(&~XHR|}gww-UEq!DamTQ}EtYbBAYd?);3n`r%@#>W4>f-)(w4 zJ4Lv*!Q^5ZPF2PO^=c4W<8BQ~MK-@|oE@tRr9Y@(0mD<``(rTmHi z{$S6kJ<{%bu4`7keA?P}|2gC1!!Es^G1d9C!j*^IpDz*Hkv=JA`kDB}?`HhD&2uVt z+V<6*0XGji9B#d7m?!?O`bVdiNPxzR4BbhI-~5C%)UUE?dPGWE)Esl*{<7o4&Dlj< zo3^K~T6^Vp-`?_)UCj4BE}1YPujAOCy4&;Q?)+_@?Ci4t%-U12n#BRT6<7cK^7YDB zxitGy$J4=yag3{X$VuvMT%z&t>L=T$o%Xp}E2bFw{Af9r!#bCPwcz{2msgk9xyYtrd;W=Iop1XKPs>k|uR_-v46Wx4N+w*I2oaE8kkW zdRG3Gf5(N?_U)8j%wAh_^T^ziHxoC>a_&vIA}A1TpE$QesCvPfpW6d&eG;!Ve6VTD zcI)SNn;+i!TE-?CBzo)mMDgO+y3Z2h=NqmzlsH_>yo8x8`0|d8YgA-&Ohfp^f3!RN zY!MGX{?S2*kRR#Y;K0Wpi&DuGmm&!~Xwy%GAtKLuqE#Y}LBYu7b;wUnI=$ zRjjM~{^(+Iz;V4t{@av3`}$m3v2D?Nw;Rix%G`PaVtlf%@6|n%^U|7^W6IOZomYIa zHp>QnGHt&$rIGP;?-Z@H^;xsxm~Q@YJuE)ud`Ohs=IN~8H(5XEo<7|q<;R^T1xqHb zu$q}1(x!6dfZ^$#y!9$Qfe#t#zlreKe|dTMS%E>?@^dFc>;zriZanUv_KRCzjGMl56RQcTBR63$DF8Ua|JaR`u8m z^CV2RPQH8V{VSF2vFo1C6;!h5xqUl4QZRCFNlN;9$z_Eqm*O3BIltOJD#&!K^hn?p z7WQ2C_(HRVr&PY^J`))&9?y#htv)4y; z{m6Ub(s0)6qJ^$;xW_Yr4KL!kJAGJJxma+=JvWHh^H1?t=;hkv$tyr-4 znvF{9g4Zn5 z#AuJ>zHig_x8IzR6I?D-@Jq5~d(n&SzB8sSl-k<;d)pZ^rA_az?uA-roK^V|$Lq#3>0cE7fLKX4?i;O^{rheRjWr@vMh8dVH3jC|&zkY5J~< z)eY0rw8i8VA8lcKz`S|3o};VGY_-=%^i`jgT`UoelE3VIRU!PURc`)g&RV+%jn-fH zE!O$5iHlX?vp?soh}1J)J5Gk2Et%f5XxoI8g})yha{N&*5d4E#IW}a?6SdGk(<^M= zh@ab6XQ1(>)m?41LiA0A-y5_}>K1ePyCnUn)Dm0st3amlPx@Bo`RtpI39hTT$!gH<*<5*mUKi8r#rIYrmb*W?OpWmckC}dH;-0w=G}u z?UI?h+oC^zLwcq49G4{VcpN#kQPiep_WoNciBtbfDb)Enjq~zCv3r#s|)A7H|+euqUm}2^>&`GvA16T_;vUiSJUZ2 z1J!BwBA?&*rgLl`@2_1P0kIcvbNt&T`|f;-ozKhH77RfJuDX5VUCCT=k;elsPD(t! zG*UWH;kGdv`Y)H#7D?72o2FC!6*ETTfi_Qto@T z_1)%X&Zv7EDrCA+U#@(}>U6@MnQyz9srpl!TGiW4!kZjtbnbrfFVtoM@7KlEok>a! zQhyG`)h|`=P#ipEc)r2X|$^kGB#zu|_S8 z`)y*H>(8&^C*&DUKJks_y7W#k?*?0r!MnyPCEe^;0b7?>3d!=4zkIDrGYe-}?{!zG z-Y*k$q3x>vi+~do>PkNDI=#)nT7Le^+631V=Oz|-_i=n?Uef%!$9U$3-YF)EFE16k z3oO_Xr@15OQ^32c(~jSf+^KT<2y=)^=AV+Kb9jwJ+1@_B$&?>F>%Y*`l`=`a2Xe30 z{z-~&lh3zT{}PZI>UH+vqvwh{e?32^uvV;6_n&j{|Cf{h={oc~|CMvmzqT@Z>Z=D= ztv@L2D|)Cj)8xfH$AFVxvk&<4pW6Lt#^3#HSCl4m`z+YNJ6rH&)M|Dsrjs=uT|Sa- z-?qv6msv~Ze)nF;@>ilfEB=rm=M~dKHVuAxDy(8Fi?3ZdP<)ER(9Q4fl!B1Ftv@ql z(o7w#W3*$Yt-4`kWpS*u+4A8M*GKc4lIO`5aaIbHy4$OL{q7}s_O98~*GYemOq_H+ z(}i=Xo74ID-%V$8(oc1qP&X=gpYM5;z1woeFQd0tJr#tjx1AJO$HXenS>H9=^s3FJ zoT_7!{wua{<>@u9Dg1MN<5{;q6H@*&G8S7~Pn{^%CCA1x@xruVmjIs6bL}}^*?mvW zF`cE?QF3_vx(-+BEv{7DS=#*j{tZp3+tSuwHhd3@ z*v|67JYC*bW6JD#QYN!q4z$14|MPQxwtLyy%Eg6>JTaD^ww$rP^6{AU+x@) zmj=2t9*i*CccJI2;Ct>HoLas1%o>lj%9O3XzVzAgNvBvi7RIfVz1O$bwrrzTxu$B$ z7s)ks$qXqHCK0<^MC%&aH&0MH#AD*-6TP!xgUg`>J71)lTnynT>8ttoa)P(>#7kMP zMQz&I*&iG~zh2{SY<=&?1vQOwb(y)F8RY&Q?y0V|>$vHwTWr@dn$Ifcu&cgdQWi$|KlqH+>=hSUGOPl^Oob9;@T^>z&voG{zpZ* zllhfd7t}oWn9XXw+v->0{NSUV?}}+fJC*oc-Lso2th}QZn%J1QEwNXcdtLI_k@8;0wsNCK+n2pxZX~Op5!GBfchwz> zMep`muX}#(nbtIqTqZLPtv*q+=QfK!#-4S%$2MtdUBTP7T>@Vxn>KH6Em_^4qkM7a zqJP_W+%FAb(C&YCF>>+VZ}+?A{5|XX^C6$*(ZqKb=hbLV6qs8o#ryX}!7cUU%e1y? z@NDIotAFD3pXfm5@Ex7=mWLN#I%me3!nVdeUqEQb#sq!m%jsA2leS+Cv}QfI>4v;^ z+IOCh|B}w?N~hhd+O}}<)J;FM&ITBi+TE)Ck=8x&vQKE2YQ&dI7jGRr*&kc5T{`1J zXc!fha)NPPb;4>c{_p-7w&Wd}YpqZc zmdaE1C{^>ivVLicXU)uu#SyvXUngW8G4*Nf_Yk$4|IM-bj|?+&*fqTazRL?w^^uECTZ?VCQgyWd(t}5=WS-pUW<>D}h7G zIKW-F?RC<{Z)Qn#TNvHv*NexSMi_FYZ+v5=@o(p?NXNv4t&Xkr{FiTW+z)=ay>DxT z!1*P*tDoOG=$q&G-{HP*_>5}}N3By<%@>G<4x3&bEZCz&#K%sN>!SY z_DTEg!`7po>}t z>y(_e=Q>aJaNYmA`rMi)AC#9)W<6ye-BvhvVeiF&KP~M%)=p<0^tbhzmmKM^UKlj- z`-utHeOFcYn|e!n=lD%+Z;mmRiOk}dW^&Lh`ebfVu(z2o|L|{_b*EY)T#L!mY%}9mPt%tQ;oG)a8>%yXo6c$Gd1uDs zNzTpO9J1y!xf0pA4?QT+P!apPtT^5Md+RHYy`R@|eB5Rke##)jg=cB;g6iV(2}hqe8?`~vf^&t7LrlO3^N* zFLOJBR;RiK`_$;^irqi-xxR3&ZfNxKn4&`0>6VHbA2}Oxw=6I=$bPv?xN_^+aP#ZO zw%rT*lGft5?~%dQ6K5+d9S+W)bS(V(fA$%BpV#-DZz6M(?!D}qb45Mz#`&Wai88Lbx>uCW`u+F3yGPfY$H(70 zc9{^<{QBA&{^qjT)!iXe*>}V%8MDIn)aWc;kwRM%evM1)50Hb?%w+p9gcGUfvTwQL@2&Z{M?- z_F^%`^P3m4YrQ+{B6hlFgGj)~%sYHL<}z%%A2hLz%ZGhi3E$R@>+Y;PuEL;iEg3ZN zOM2+V9a*cMPF`lKuBXnS>wfyFdE4)ACR|Hx;x{H&+&#K%U4*^)g_`gOg_{X!H?DbL=&%g_A4*(97ySUe{{WIQ)NpwBr$*<)!q82`7KM%%3iDo-2O&Vr`XQTI2a9_6I za??EWti5t^fl2UW*Rwf3Hp0htmnhu|`WPXaVKejGZ;Km`qRY>Ge%GBQWTCYAVd2~m zJ(K47#b+Lcmmlu&3_tg5t||NHx!av<^VVA@i@rJ$_F3tOa{M{XD*~+z;UPIWET5js z{bQQR6qA{oxWM^_N$*oxN&nYE=Orq_uAi^_zUtByS52m%Yg~upr}EESW%7KF_e&do z@k`Hd9NVQkQLox$=MJf6j%SYDO-@I-KOHKPa&Gd$g9? zo}>4TFQu;CaJs2OZP$_~E_SCkvAkoQKKs>V&J_Y_Ner5)`j*D|MyE6jo<2*skn~Nn zg>RC>wnLKBlb>Jg*4lPFfA7_RIH7&J4oCW}<9p%!AUnLPu=)a{abA93GNbH^9RA}h zE8bTx%dS3ob0Sxi71x%`0@W*}DV5xZ>((|-{AS&{Z;PC>p~4T*ldh3BLJoa7YdFuN zZpT+wr5}saLt+a0pT2P2WwJR_VQO5O;B?jW!p%*)CoEnhAab|o?4eBwXWfo$x_|tE z8N;vJHF3S}LYn9PO)vkWzq(P|l=ThciZz$K)D!D3ddM@HSIzzE9uuR__wT3J9Y*up zMicG4PF=ixan)SWgejdX^iEcZ@0+>yi;^?*y8OT2zRXDJjD+st6%a$&Ip2Pa0JbX#Y1DCOA8oaHwP*ET-T_;p+z{W8lm5{7 zWz3gvryL)ylKyA-)Lwd`u!QucU(@DaX5=cnm@+#$D>QE2-`R26qPq`&xMY5=IO~#s zb~sD=mX<4VE%nu_?%wm?o%%yL*XjhblF-vr>znRwe`4RUx#{aOU(YYW%ocq@F1{(s{zuvTb#G)A7Y~Pp8eFS5=w4QqLyT{`7^uGnbD< zAB$m8t<+>Xda6auSSwY+-EEHBv;DK!iw?TiheX&-H#nWNWbZcqA&vWn^QSF>}I6JL1xb{yMwcJa??lb9}XPq?&j@0HhiE$_k>e{*fJXqj=NcSBrb z>D=R7`?<|8&FHdetT9X4(G(^A_fDsk{JvSK;`gVkPoE&AT0P}g?nlR{zIh|w z|H5aUvdG`p+jh!tbNKuE|H9+K$13{|NoxL>+^@E6_O-xTc*)YoT=V)2wmlYk=h&X}%r@ic zTb)CT7Fv3Dt)9mFJJsfaNR`J1wz?UYZcYt7;qUF2eQ1#!*L}`>F2^$g@~(Z~l21#Q zOmKcYr7@t}QN&JMm$%P+(LXHkr^^7O0xhxIJ zahmVqW4U-uyr|S;uQ_Y$*)}t%)|`CV=J{9NbKM{Lt4^=dY%c!XQeE*k(xu9Cdhd^q z1)Y};?>+uy@5j>~J?Hn%x1CqZ-}d^btcx{B>FmiR)ynFX&#qpZpO=?oVYjoI*UA?}2mj9tuQOKrg+dO#@ z>q;@H2}^^{RzKL&!8pU{wz$s1qxE`E@_laJ?TL!fa;SNJ{>-MWtf!xB@rfCw3JDo>@9aH%xNn+OWQ>=hjp#KhkAvU^qXgHGJnS*@Ak`OW)?~FjcPl@bcF5 zn8tete*AP__e^S$rrYr|((^Ar_q(k(H;czKNjC8D9;+!OdaK@iFiiiXE?Dwpk~ouZ zbB(1_WuCi1-UE~6cU3((KOAE+{}SQQC-$< z=k-f^;BaD^_{s;DFSc)WdU5fIX#dQn%xQEU_@17Dk!HzzP$oX=kEuHo@4JNQAg%uf9i9#LAqcH3IaeP5Eo zesF_uZ_cOYEBedqqQ2i(c%B~3-TrP%U+{O2QzzehOPg-|X=>ixpLS$XV%B<(C64Jc z^u($*s3&UqNc?tvu_QLqtLL$8sO-_k>Y9T&{Iiq7mautv7i5<|UN>D(I_`Mzhwcl} zX-%OV4QD1yvX~{t@+0!W{K(CZk9EzC_|yFF^prmqYRn-QiyV}cTytleDa=rC>GG6y zWk?PACA@ma`Fe&u`fn~SopgQbmu+9x{0_@YQ~2XQhrMRn)WL!tW9{fqW0@h@6EJ-p|rCik`7$7OwFv@-QCPTZfU zQZxCg`j^RDYYL}oZG8S*!CF}?Y0~Nk(-OJ7>&p~aE>8?Anef$mNnE(-yM;y&F0ZZDs)!!YxMa~33(jbllFb`k9%{LZMiA)HYFf`i`3zUiR*54 z+~1r0qki43!?Es+xz>f3E=6uTS#q~yWm%oz*&Y2iPj2^`_EOg5*TQ*OcY1skuLv^m z-iVZr%j$UObW!76Vd{lj3s-GpZ+L0><5t6mxo_THt#m$kTc!TP+PYki*UfV_I;{Fs ztzp=__sVLc_X!p|ZhO0yTvPphbJ^2S(*FZUFXacJKFK} zsEo|!lvCQR%f#N_{I24WRblaeYOAK!rtc?iO}lt(*?Pubytcpn@`R`$`U1^=dxO1&}%7chIi_CjA zus+b@y0^8X=){uk7hMkBTqb4Tyk4fPv7R)wW37FKIq^fm4v+8k8%+03nY~H&Qm_ADG)yp&H^GdZp ze`KMJCG%C=b^L9|Z6y0U|0Fnb3+XI;EUWt4{^Q{w)in|t({}#Z;i6GJXY-}Q-ho$w zQsTD#(rM4$c5ktF&xhPkHd8-&2gPxi-%yWV84~k;qKHfOJGRz`dRKM*JtTLn+;f(% zV~gFhUoI(ok52IRY%|(;dzapH{<%zht^WLb7}r*Ln(6s(p+@)Ia{)nn=B)EuV*cA% z_qF)5bu(q$78c+4-?;d%i2pU@F;1+G4Dyn zj}F*doDtM|mi9iS??yz}u3x70t9CeiOigX|?@T)ULUC1x^!>JoRm&~@E_B+{&GxbW zYM(}R(Ka_Fd#2yjU01=)>dW0(Rxarqg}QWZtjxQ=LvwcB>FA?JZ~TdmI{G_esvM7RGQ9L{e<8vcvcuWbAAbz}LZ?2~l?yIr^ayK!|| zc-#J!tCm=b?RdEFZCi4X%a%w!0h9QyT|HcXzGnt+u4tWLx$K`Q>w~l<3TJiWZ^Z>K zT5ef=W`UklsM#_X$zH3~3*R4fNuKsc)%dLFG|dXjZ>f`8rWb$s{<`B-l+7}YGVb_| zxxFtl*U8V_^Qty(HmhF92J<$)jbX;mcGsNozkFG1_lLwoI=K&|j*5v`PL)4#Ti%3RPUx$3v z%bMEcsdjDN8|%-+6dk%|_CT?rDQ+k0f1dbrA#-wFuV}AVj+=7#mQ0sq{*V81YyE!j zlR0{O8q1F9e}6Xp+{9tIV@6`hgH#UFdj}2b3g+7XcAlaXHHA^YUv}25f6G~WoctcX zdiVb6o_PtI--#`rlC@ftzq*j~NN=XY`NiGqn4hQ?GOST8%RMYJW7ElLHuF_qv?yz| zp8R%Po~JA&=HNB2p3kgt|AU0DUe?!sd96sQa^>HyMz7}!1Z8$D`CaByyJCh*!mcfb zCx70!ZnWoPMDkJo`EIGH*KS5%o8z=Z+=OMxnM8)>OVzcJ-{b>KZQ0*w&pxGJ`Q=@l zPOGwmOLnM}24i8T?cq(UOsf}ul-G4&&=S=On)#o?zI}$K4|iXSoapoB=^aV-@A-~Qx@I*uf{e}=Bphs;C-x}1 zM(}QP-9=?14dL$3yIy`axNHBkP~>lCPn6dG!pa9_m#P{)k539;D01%q)TBjUF3niV zcx{@RDZ?fu$>5X<7XRS*X&fOFW-9i)_jvN^@J!|p42s*kPE;)@^Lo`I`-1P$nwzHb z>9=Pqz45X5a76sB{@T*HJ_)}?_G<@j{N=Xo{7$YDt5zI5GSNkxt57?#=;35z*(2{~ zZ%v&V8z!Zb@Yy>>@(XLu;`VI$ z|4UCXpODc$yrfRw_sN6^lbM#6JeagU|0`Hq&s3Wv6{}{*1)Qu6-!@V7DNCYY$n5iT+xG+>I{E#{6RQQ&Mg1q)MorknKW%=n zRPtuoqxP4-%#vnhKKlNhkC^X5d)5MP1(#_@9~3|S=GIcfAjxIEetS;T(^FAv{WX?d zlUSC((NYUqr-)|R%Uds^7bU*c|_0HZq+A|w^nO5qj$UXA)H*3~5KKOg4 z)`snzs~p@`hSYbqc5teFnwTeQyWu#^AEo+ zxGMi;yM27Ml2VCFieCSPqd&JE{2~6MO0ee1_I?@ZOR`>Z@?4cqXZBtGoxb6PO;zh& zj%Q1IGEYSH+)qth%DVid;@ayqHbv=PFJ_1H->R+2sJ*7gZGYH=y>Joxlc)O2u3joF zj+nJ_@>OLv<2i2vbtap;Y)z>>xH#pt*{Qi|8j{UP(>Yb&=-If}p3{bss&AgLbV=bwQ6Wb6!d`aOZ0}*K~K~&8eFeKCgQ% z@?JRm;>P0(e#kf&yfTjFD=1-YzWUuRgYjK-$dTT?zT&ZemzO8>DN5vDO})(dRO{Cw zt1YEz;ZvS9JxV_DM{S)<$$8tUVy{9iT)dYynM|wK$#~*0f2UdsQylN<{%6*8wI4N> zyMBAlRLChFUNCp3-ip^juH7r2mNrZc=6*Ww*WnvXUb1nP657IAViF}UW6Ya2Z^^L; z-c+AEJuJ5C^+cr;f6PwJyYIs|WuE-rg(6>E*dN3dOq~3D$v1{+mz_H6{P`uisl|$>ti{Ef-dFZ7}}r|DpK_`_0|GKaT|Qr!vi4 z`*iKaPbDFB32FLD(`9Qfn|9ZRrSQbaNb`;&IAIeoa|&4qW%d)=m8NIl(e zst^$`>-}=UY4!bIERM>2njc^6_jv8rtwjsu-mQ{6aCK9|L$;RB>=$<2dsZm=#oUTp zY1Y@`EY+hT7sb^TVxD?%cb`$cYIXR0o1#}X$Chb7twm4Iur&N#q?+PvReo+(zmf2R z?d{yF&aaV|SrXozm31mRF@$T5TW_UialzIsht9=07xs7N7nPW#EIoD6Io99O^-{}| z1wm|Dyh)SxNIW&z`{wV`rQ*J4T~*Fpo-gnEr+F&J;tv<+PUI^qDBZU)AkWrpB8OX| z>%vJ7oEl>6n$KA6FkEua-2BsTX@>}=pt>P?uyYMq%d_m@oS4Zghed0+Cy(-I_w zm&~cUE4N=wDW%V>_vj~Y+iy*;gO)sT7I`>xgQ4izca5nNBEB1*FEwtKHZqF7SSjGS zQ|YmL%e3O8H`)aUB33_3tJgkW?V!}g9@cX_??$6m&hNLrOfGGGQ4Jwl&6krjXSbHH z@iOl^bILny8S|~GJHM80%Gt}cuVY)*mjz-^s&@owyfBc7iU{KFFD`$${g=>(hIb1C zx6j`{OU7wa*DPa!8;35h3Ak|S4A;b$Z?u)7W+pDbxJA@yYlOe>*8jVgRT(;57I{5= z#TQ0TGutowKUnhasMDxlxa(<6pTn#b6|-#aW*5lcZd3l6(92jgQ**_E1%k#?w|16# zM6H^py{40`eBrMPnez;uA30Zl%{AjM!|l11)84MU{NTm5i8c`utx=Zi&c2;CrADYv zDEUvUZM~mWAImTPV;eqsn7_Qir=57b#h%|l?e)4PoNl7epC1go(pWQPvlQ#~g?}#0 z5kBKQ?_2(F>zvrERtGkx4(}4oF`LxV-fa|_(L1w}$j-F67= zw4c3ynp&@q6z9R@iUS5y;=d_&o!3kMB2cyO>*eo#U!~#>rY?Lt^YbddRFBdUBjYJ@ z2Ok{s*dB2_Z~KCUsmGd{`3`Yb?fuXq$Zs2>JoAM5zNM4)wbUy)-S*v^z-B0>xvgU9 zE?JYys-}4}=kr8=DOXVKEBdSaq~V>~g!g5JNp;7bsctg}X=iX(fEz9TJb$8R4D7byYrmw~GU!HH4`8R31`IQ}Vu~jOIUdTP)@lArr zi2x3vi%#EjyWVK|?fSSQ?f1NZvJ#7JTwcse6d#0f#D}jK z8!Evcb!2ms@xHvU<+%@@KFJF7dam-VaINK>*6Ti-%ax^0FpDpGaBhFT%%074I$T`u z>#PMlbshCD<*ektz`Jf~%>RS!*;ni$*D>!)-1;p;HmTOMhwt2{ZR+O^F3j{1UTk91 zmHE$IKT~suADf|-pu^nEbH3@GZDkXM=5({vlze%fKF7w~UfykzW6{s7)zv;J4&{cO zz32QanD)A@IJ@m(+Lj}|2jcfOUy+qK@hD$N>!a{nQI#MI_^>F z(un@xuH6!ob)UVeUZ#}2egnr=_0@~#Yzh9BaBK0>Yv!LCH|e@_UoFom%3r{y6#6;A z*5~UwVNSON2YIcOdeX0W9dKPf6KIC=9QhmT>sVfj9F=YPvNrd+>OxoCmT zZrV{d%u|8ZvS9hSFhj~521&kVaI@i*-+r)p;JF(DH+)o>Nd zgT3O7@h4gXMNZvh&Dj{ty4R!Ri2v;;~aS1!WqruFJc$Kj#X$HY?^+ z`t=R__Fh{m=xlY_zo#)}z51T!%!k$9ZU>$eCf^n)Ty*W_4JpSp8*a~B-u;Z5JDb~Z zcR@+ckvVF!{!~j%S9y2lwBHet9q+HO`tRmApTB`wWcMqp^;b5nU(=gEb;>UeEep0Q z7WZ#YyFWSjwXlbog2>#RB^yq9EtkJ~w{W(~GoQ9O7JXY6#-6>oq5G`3V7Qwh!d#}6QM|T|Qt(4Q1ow0t{-GK_S^VF> zFT%$b7rio2No1{Eso%E2O^UDdTF{}BDWCfv`n}i^{@~4fpYvYJ3fT{3vN!F2Qf%kk z8{+(GhtK?f)0{uwW@nrtEg$$kd)k>Yp#%G3Ii>1fpKh7r(iHtSw&B9r-D2s1VV@Nh z67!n%Pkkufqg>ECEwC$Xqt&dg56^@m)^aGlyj|T^5TX~OryS@u@$}^-ElQKa{8SFr zrM-FaSmexXy}(WEFADQtOcQfVev=-3@XDIwLaPq^y;F7e{6f!pt9v$VyT|lzZuUGD z>o>0!oGM!Q*)>6f@xThH8*Tjy4hIx%EPO0`U4B{Ox@S6Rp6_3ZDm^Lb*`?h$Gsp5J zd)1GP4w{|S%^TXzT1{IdKmAq0e-`DVK`vU4zb$|NXi7I%^1Yx1SJFS-DOBljX{b|m zp0ue?{9xItH}fO4=RJJmDx`T!{rz020N>l+&#ZeDyppjp;+E<3jm^jULhtvSJ+|ar z*txUTfiWsGu4W(L{bJC*bE94P%qRN#E$^;v-dca)s;B7nPhv)Dou|*Xw0N&l`+8wo z`O=H#^B!|fk)8k8A#JO&+BBAhp)TG(9qvB9qjY6Cqxsogde!;H4|=2Cn4Ec;awM2% zYCh+SU5gW$7%MzOH>8Ms4|eU`-Y-y}TJhjo&acW}rD_gdHS+B9MRZT?c(~v=1N)`f zDYDBw(s@`WOemcyZC7CSr1fWk;;$;n-CSN<^ese9dfg)4TlcK_Z@8#n4{v%${RD^K zJu@=j{m*>7g(1+Vy0|`NbJ&%_^-n8z&c9}_?{!P0xIemGXnXsw6*o3nCY?Hc)lHpg zZMy=WcUV_r=ADPKqF&bfYusDnd>5~4>@4OfH*vitvMkn%OZVpNUn>vq-q3V&ZJfvp z?|_^c^A;HH`*M?AtA5Sfdwu@jliuEVZ}EHIt>tQS=Nhpw{xbN@|10Wl@9X&BM7QIU zO`?A&tF2KvZ|c<7b95u?DM9Bd!M{Amy&JiXuW@4+7T22n*D7Jts;A1SZqfHEI>H3R zicEg~xbfk6LG_)_-A0y~Q^b^{vQ)4NAg27s_|s{5p5dpO!5Pe&(ka6`EXL zxPFG2+U67aa(=(|Ch@#I>0SP9>W-OwKl<}mIhMW?e;Im?i|N_ZvkT^|vfOQ4tTmC1 z`|*`*BaZVS{fd0IFBt4*622-H!y(10mi8-W`P#<@xh6Wf64INGyEaKEwg{xH$cb=m zJbY)-#o2AncU{wD9ZhyLY;>EOG+x#}Tun+|sChl$y3b5!X+I%lEM+y~4H z+RZb}Z)(jBK5U&R$R2$x@pt0PUyENpe|XM(T~JC`P-wjCy|-D6kDAS;j_p)w;1g4^ z^pn~eEU|;rF5~YiwQDMD~|46+9&#S_y0GAO4%`~Pmah7iJm*IXtmgN@0NW#+yZ|5SD$*=t>vJ0*7jpR(cg6%qb(O5Cs2SKVKK^1|)O z`%Xrbtf;;<>6_!>Z5upi9p_OlPUKuU=dMgj;K5UY%>S(CJEUI{?dhsGVUlX`$@xP- zMbZEB58CPjZJ+INO!=tBRxDZ1VfA5)c~~;PnqH^tw)bhh>|;j3YC;KFyt=tfueC z!s*cE>A)O*j#*aRPOYeI9&<#zy04?rp}BHRt($R{)f55Vg4$n zUc)jgeeE^VJa2Tqox8f>lE0$rk+2ZXm-l!pCl+5f@0>VkZQDxi*CKX>k5BRZ+P}wT zYMp+~rfKrRb5`tgzW;dQgfEloGH37EyKb&~B8S9Eb^Gg#6`bMev$Own_7@uMX1!6g zSTwv#B17)3xw?{@I*<2>^}B2=XYwo8IK1b2GBbE>)yrw$GdWz!-OM{xQtvTrS6jXH z`@9;Lm|Hn3uFmGWFZXYSPx`@s*M!zxnOmRnS}&zdr_vh8--N!%uyt(SoF>{|4 z=69K&FMYH3S@z<2RO@+g&c+Td_6a(1}m3TlQ_0;_k~> z8L8O*pf>yTvWl}$mn^hsn5S>}Hmz}Eugvb*Vl}Q)ZtZ#b?~?kurPi;fdM^xB?iLQv z$j~zHc{o*h={XH|zuRABgTJ>=Qu+Yxo=>G!EeRSEDN_Y}J}0;(Yu=w}tz>)|&tQbmq9&va9W^-x)%mBx@&BhUaM(hs!STV|(*{ zc7ER9kK6z7EnATDMWChTacfDN=fc0MFLX_qT4A#`(`L1o(`@$rb9c{)3EnSI5b7PM zC9~(nB=wq?Dkp{f6+RnB-irI*nUT6}d;85No*Qj?V>o6V_btYjbO`zUhr-0JzMwaY(#3z%qk+NsfJ z?`@AYwV#janC_c?;E49~-}i&r@`YCXyRmmtZprpX#zMS}*~O<-bQHO*AFnZ=4IODZCI*J#~h6yN@DNAbmq@*DCm^8bDQUa}`QtZ&0w zrAepGX_fUv^)_Bq+7>eBb(R#%n(NOdv-`L1dgs09x%=-ry*HO-{;{#=GX&;%$8{dw zUwVBCOPtG3ucfjAlR7wjTJOB8`+Y)&|8aA(X*SYfr4llIst37zb#9-6Mz6tZSW8B-* zWR{htE|KN9YZ#GleQ?&bFCh!9Ia6MKXx}{h+?*>>9J?kffA~AeGcX`!%jCir$EH1R zSJ?2W@s8irY4+OJIWpTar$|RFzI3K|#`z0>H43b5NpEZ3>f$piX-;9zhSVJQH<=9Y zduB6KNvT!y1U@^kbvM^rmk&;VFBis%gxK9PYgp{uB|UFvI9sH^V(sMWP3P-aMfM)?;pWNFYR}9M_Hs`>gb=#!1~iu1Df>ZD#A&whDOUA8#< zPA;EHxXz9rh4O;3sv$wfkNLVCr%PNdQ_wZ9@_b^vdf}-ZKJV`}e@^>l`;)ma)m-_u}Qxzk_qu%D}9Bg7-(_pMzWuw-*{{jy^# zCq+DJFP`~--|6*C|1?VevemNp)J7HD{ZVyk(SLI(-n~cHoeJ&VXvMvX^S6#_^ugSI za`Z zcDcLT_UPq&{;=UM;(ZI_qq#ux6dG{4U=I3f6C>gL{G8(zgayKYnoUGQ~- zmzdzxGLMk<|8rgQpC9>Q&avEnb>-wmr)(!oe0uHU@$J2aw_ik7iysza*e$U`F(vKn z#Z?b|9<1C`X=s^pW#-mp_51Jc%YFB`9#5c$iRi+omxT9oAWqIN#7wsOQ!+CWhkPPPfI*>)eG- zxzbC=&wEA~{sfEXt?lmdqn)iPF88p)j924G+SQvnc07yo(q1t&X;LXTOm)++&|y6lA<|- zzDD14=U~3H!|Bjv&qWiq%s+mlXRj$U?;DSa<_BKLifo$@*>gwZaP^nV%Kwfx-r;hM zxg=L^qVmuscLul3!xPncZ32w*-X4Bg@w8*&4A1utd+OJ2n$72zdWY@zF}<^aQy15` zFA=brxpFIK%jC;ar@yHD(wnz%zd4IzhyI~-b>l3n(!&;#+BBpU2*SDzM7cb z^iko*!XoZg<%_nFuMB1%TF59jxy||6>!%7%E8Jce@K55Lxmj`L({r=FF)Vt#ZOxvA zM=yV6iZ!a`InOr7yy{xy+pn(gUVT`Y z+jRZK2=^0=vcHx3_gIK1E<0VEe&w@!hvK6zw#r;*U8nxzm(b*Uc{}iQU<1R4stI-q zW-g~gGIj|1%vL)0dG@5G>{mng&ApVY`T3e?&pY|5rrT>)?LF0bWTRQbQ>K+nJJ$q1 z{C7QMeS)<*SN7#OJ7pYSztem4;CN=c-Xp&YB1Y-b6DG{4di*=CS2|B?xk0@0x?4|E zT4y~wv~j-hq<{5_E4Oq7cc(73t#WcTUv@i3?NVIMZ1Doyo;FC1qqylk|%YL?DFkJ)EW@!u-?6lT8KM#$@=@MC#K zr?nfs6&D@N`g~x?uO7Gk^)muCKi_sUaarb7sdw|v9;~dJY4T9SW6zDtE$U0|(z0))e8yg}GTZg#3@I@2(JjH7Uu|owvlf%2i}i`?GV0)_HAtx@0=r-Lh}Vzk4HP#1Go( zZU~ZiX>-&s@cQ;@pT_fY45!aMzkFr}lZR=4s%-L-ZLizzycXh3Q|H-zJZy8dc|}W& z(dN>`*r>gJ*&il-MH+d_{%nDNv0;HC$9~cSTjxTD_JtV zbceAy`=qTiV&g;STQjrlZDG{cd!*odIw$Jev#wkJUj7v9zOZEW8Zoume>gu2-@5$S zz2VTmY!R+mLINBANizj*(?d&^Uwlq*&(%{w-wUHJ1u%#_`LeNN)< z+f`p#mSw1&Ilnk_+HMQS8T!Xq(o1){aqEAQkyzppR}wwdh3VmwGGW%w%+t=lT>QDW zanWZ5yEy4uE6$mDI{#DMXWm^EwtL#F8tdHMwSCRC`!BDl{*+<#?Zm0a(v>T1R{eaX z@ps;_7V|psm(mSCPuK4HbCPBMxiXp3nwdZTaO}+f^6Ia}7rE&>elIU%InjGz#kKll zqPi>7r^Wu?skPBJfw%j~AuHRvLj5P@?ilgy>e#0~|JsRu)fFc( z#ov#X$G2Wwxk6pXI{nbOpf?LSB<@P7n}ufYIUp7J|Ju(bl`ZO(T+@<+RT@9+50~({ z^uQs)Hu&{gXJ#u+?G+(GR}>b!GP#v(9h~CjGH(*Ij_;nbL@>u)6$kV$r{g1i=N~w9yxDbUF^@0ryVEk zHaTv*-{*esX{WsH>(#syZmH|0y6pNU9b6v%a#2fTqrwBb&=?y>=fAR_(l+HQy;k4z z>C%(8uWLjO3dLP`8@J`MT=}~hthc_c+MI9q`^lPX3>kl4xlFxb!`vact8>s1u``JZ!W{rw-(vV~BEQJii}h;} z+q#J}9#%&8JeOX`_hdqv$()VDmsSyH0^wJLfm^=4Zy z{{_yo_qw^hmlCHdxNDqR6(Qb| zyrdu~Xu^cA$@6aBdc8PGsaAXy%a+Z@EABaFTh;V&D$1U+d3|b`keABQ-3{+}yX`C+ z7T@yQBDu`Rg{iI6O!?B1zCR3WhSbTk(yYhkQ%l-Z-@BGSNE}14Hxl#L|V1)OLE&8pSw#2S3-YD{D zZ^CDzvZVhmCO;FU8xQW@$s=xLd#3CO+tGxNOCq$5_7yz|Txjdnnf9>np4GDNeEH|{ ztoGG;oc*>=s#efw;CmiqeIWxt$1hQB|^eR=2N(r&9u6(_zL?%MJvpX2-k z*17tuHZQ{_KDRZ{TiWzN@s&ba1Y6k|<3kn;4qM+SvOQPy->*q8FKS&`Tk6mKaSY;x zoTB>T@&{H-x%_&G?3}5)uk07QyH6^{Hu3wPE+2&?`Rus$MXKu6M=bMB7oPF?Z+dUD zvPu@~K?ys~_6OmYuN_W4Z}2FIbBjm(M-9QJ+uA1NiLN&JYUK4@X5G@ARb3334elX| z_e)mVgzwf)^bu!ru5vkLeN%s@%(MC)>Gb)zCXwf5Us->x-JjP|9HM0Z+>I+?wRXt- zp8LP170l5{nR;yXzxHE4A|w~Rx$pV)=6<8x6AhlKx1DEyHYy6-6|mIbN!3z0Ekfl2G>8mA+W4GuZ=TbcvCmN^K6l1VWh>K;#?R52O$v=O8Nlf-n*WF8k)$G@Q6WQ4E>{V#a>Vq!?gH;~g?R5T< z*?IX|<3`Px*=f>zjvqOGtvelf%aTWV%|j!lXp_r28LJ$zPq z*#SSb;8%X(i}mkqF1k^=eCeTE9|XFz4fHbq?A**)_du6_<^DHQ!)_Y4FOxNCFJRlo z>&|Erc~QY3w^&@hbmf%7hp$4OCppiYJaKl=b&lhwj`O`-F7|5TmZrw@@3d0RC`DG? zx%XSA=Cga+Z`&XFZy$7hh>TV6_-3W&vCmJNEq#jF-z{7EWoNDWyKjoeqe*|G)?C$C zGNF{5 zeF-X_?|XIMG;c`e4YXXGzv1S;^wYmuC*Oz-ZJj92#jF^x!ssGPD5uZ8=;>1K5hY7Y zcB`k9u1QfbN-v*QX7cXi%(=&EM722;r z3%8!*yfB^FMfup7PfHvRYW!IBrS|UQ7mjw0@>VJ~lf~|(Mda!WyqFrkdkY8qR~w;^ z4Bsv}>#3htE}gRf&ehU`lXe#D>neSr&lh(*VIjS;?K9GxSSehO8 zXm090gOHaktdX<-Me^ql!5djEs7C#vqxob^`z{_SE#*Dc}}Z{@_! z-#zYl3YCC_iy7InYHRK<-fJ_8;b?#l=6E#*=^&I@YmKc?jf7w)1LfKj{kNX>|_y> ze&KuhEz72)JvFzP1HX4q{Hve*LU7lkuF#l`weQulZX4*V?4CB&w&?JS)&l0(+0Qk8 z{gJhp+^O|LGUZ>L#wUwL!`j!G=bxN8&3vTk`4qAALr-#xGOI4FXxSlHB-{2r{=%L^ zoo@wPT71h?tatUTF0hjNv~=zwmdV?9ublX?{#;dO#mPTUXERyl^iO`swMW1?F-}`% zR=_PM!=Jw*-aQkDTG|_(wr!g}PsXy3D~t=jKFNrQd-_6->8Br0cO->iowjWTPQE3`$6Mvwg$$ zdH1wjD@DU*#+zM*J`Z%n{`wz%c4p(hRhB#4KFLNFN4&UmvoGD&>Dm;NwVXU(XTG?p zfBV!H?!Vb}p8_VWVmID;o#&~|ytD%2=Dlh^`W)Zy-dV8Y1>0HIZ~RG_7ZXgxR-b(F zCs9579jpKOz?ArmxfYtL2Cd;24fcsXc+bnS@A>olrXfjx+^!22s-1Bdxi_MfIcgqKSd*}Ugy>57-E-5!?-?}VqwxD^3zI{GtVER(}Aoy%ja!xf+!Obh>@VszQAg2s z^ZV-}9*P?MPKi&Vw>(NNzy4k|T%{rQ;>2ku4u!l>u6Ab5Y*5^;oH?h`-OM)duIR?{ z*I#BQ9pX7Y_bAKGzzZDb3N>EJ*yQ`K^k*!LQ{tp`07Fw=;9GyQdvh1~nry6R zVK%w&>{$BdGsj?u@+9uowOhE=et7jeWnK{ovQ=Hup0D zu7{7;@6)@NHqRn*-89SY;0<%V+n$~Xw2r9X^E4~*$evjWpTqdYB7Zhpb#lMuPT#YN z_sXBdi9dxe9nfiwf28fe&1ms{-kg6zYc9?E9%&k#85Y8+nfcOx%qV=i?xqE5{VM_uiWALmnmh&6Fr;N8Sy_4{OgjPWa|8U za=nqba-%`k6MNQ^wJ(lzc$nQ?*svksPv(Xh2AMxYUZs}`pId!)HOJ|*OTBi^uH4AH zNaZ-|2Dc4z_9c_Tly0x@^Y|AZm{53ioxe_-t>dMVZ!C_nrRO- zpaZ#unOpg1=NhGTn3VsnjyyX5toFGEam(XcH`j2!n$f=Mak8&Q`Jd(=(x1}*f7pK1 z_3^g9-@=c0q!b&?;F>P@@rJ(jpK#rubIk6|{8w{%&#Ijpd7PQ+PrTM{Il3+MTICVzeSL-p+BmBU&+69#zO7XGmcpyYLeYO%55*NsTEzXw(Z*-YZNQm z_&Y;ns@6|-=GE$wOQ(qG{3*Hed&Z*5hwkD3%%k=x%%9(Ji;KB;*3Sm%8TMa|PJYh0 zY0jG+c4K~F%@^r?=Sxi{bjmEx+P!erYc|t_DHfNMt{Fwnw7s*0U1a-?9icPLl_JjA z{dPH7v%ohm<<*P&HQBF^SZ|vBF?OTDUTX{Cy?wnioiAOO>z63i>3!X#aqhrY;RwDDulH82?{NCS>!@gazduY9H*5$Buug*F-JKorAEo75hBXU=$`0sDF zL(5XQEHrjp5p2jyKU~(dv&PiSYhPrM?J~FZyL=8EVANTd(WWx_O7HSjZ{I7ecw0JW zQRDfyKD=^k+3W0cFA2Pu{Hy)LuUdCIEt`F3Z|Q44tK9GFZXMw8G-_sZd&YeO4rP{@ zOEcQLTJP~xqzPwM+&}QPhlQsn{7n_m}ncV5CesZRE@4>ozPa4i@ zKNX#sZz#pUeZX|4epAA^;^45C@+xNw884guTYh|1r>#@xHIc*X;yU)0u6t&bVbE|m z`ay$HprP5uGUxd({g*tgmS?Wt>FTfY()Q|=Z9hWVH|zPAPYsm(*7$T*z%~7J-rJuh|JPr{ zaNvt#(BH`YXJ<;XDo#I~m4kd-(agA7VF_ ziJg<_$_iP#^L*;-m;+bmP0khIc;P0sB<2mrAItX8HK~m1YU>njH717}9ji51*rB=i z#kSPmp0?l5)=X4$na#w(<-Z|4)_d#8kRwsvv8t%h?O|^;q*NY>X}&t(uyOuh*@xa2qH?zXy!G&+?EA96 zmwfsvQrK>8z3sR4irp;}|7k%!3d^blvi#LWcnw~j)V_a|vA8kTal=E=)GII8ucudE zSbb9c5Od3`*hEHizJK4Qze|qqw9QUpa(ds=toY2s@cX+*>+T(ImTmhR%fdLlUp()N zyqs^yslKf224>TF?-YERDPO0zT5yjKPeeg`<7r*J{TFQ1; zzZ&p;>;HD5tGqhw>kIo`o9}P=`S)lK_fnO%&X?k)tNECMC#gC-KjwMgbZXD%UmdaS z`){p#<18AJ>zbP4(4P4+&DSbby?e#-ny_9+^Utj+%`1(5v($b0!|bDVx!L{r=^B@P-bwbmMa;jyzZ%lW9P0HbGK}9L+5YUA#WyA>>;H|BzaXRDz%()L zkxbt=W8>L9$x2cWoqR=9JZ3K4w@$Iq@>trk-{K)&%1L30j?a@*Q^GtgCdgDgKJ8cR z(x`MNt?a(%`JHX~b8h|oQ$8=kKjvY=t2)CD&qoh`iso2J2f1aJv-%%g82!9SK<(1% zFQN+;dLR2GJ^h1N^%}Mg!+8_C6mGj%#jZN`BKUOU>mLWNuE}Pa&~ZCd_3o6%3*SVa zQIF8vqqTo#wDI|B*D?;L#HRj(k85_l%zJpHa0TD;!yJ>&rG?E|zj%Uf^o7t>K6f;J zHOeI3<&n%8s(!IOQNp8mOlHE+wDmPAPeBd`-G{@fV^X3id2{{rroZQ!! zu0P%vw#?eYHB)G7R*UDhUxw8iKXhd>szhcq#?2}a4DHNQWj&)acjL|M|GTtjw4Xjw zd+y2I8#7WkL?3_9IQy)7)9F$R5vlWg10zb;N2ygMUdW&SphmyPfPaC<3|Xt-`~8!D z{c+KYzM{rax+v&tzuKj<2-*!FY7R4i{kUZvYYzd9F1i%m**{s z$b8o#(xP0t?Y8M`=YzjLY*sn;G(=m5OZsrozcmpCHsQwCclSMzd#9wq6?i`(jn%yN zlxV(}T~C0?zs;W2^6w7?luuZ4g5UOm-p@m)g160MSYW$piTlPC$2qTNAF6XM@s;$> zS@O%gOlmbA^Xy;H@cI5+D=?Y@XaV^dV`^F$lF6p z^c`KQK510S7RCJk@?F^Wx^hLYhsa;ITUoE>SR0lL$zMNIxMXpgv&5!*5!1w)CA|D~ zu0L3l+2i}zII1|P{McK)bq9@Sn^pgJ2`WE5^L(k_M*k|msN(b15t{59Q=Fq)%OlS$ zo9p;IEl1~kR^Q#$TMr-FYkgL`Ae?>n^VEibnW_hu370w?n$K1{>x=Eu{5zZK+jGOr zyAm`f7R8^wx2Dn{(AIpON9yu=g_s$C((Qg;NDEJ||D`x7N&5G1+tVnyYSpWV( zjb0wTZx4>g?>KXzKJAz)lSbop4Hdqx^8EYQ-+XkQQs`{s$=Y#t_1VVbH`tFy2cMBq z&?xv69{+p8d9}{KX&t753_%UDYrdSU5q%VA%h}5yt9D!4_dxC0KPKA`f4!!(dFdH% z`E%MHt?VZXpO!s5H0gN7@9hSE*GUw%zfahu>?;u1oNSm3rBVO%0;cPH(D9 zNP2bmR^0uwo|Yyx;?_=2rv9Fh!utCAk3?~y9eZ@JtON6Mg@uwAU|gXMp|n4ii7sFH-A*e$>c0 za3-hR+_vXX)Q4kD!fH1Y77MyxNLhQV_F2pnxBOi$v-7{)3;4C*?|+UtIm?27l$3o) zDC)E<*X{Tw$#!Pd#B(eg6(7Bh+;mpTX49f&UB6X*YbM{gYO`sfVd$It>mExxwt3uS zictFhuqx)EXM2xsQT7G5`#0Wu=Da(-`)K@siTc*_eyTlHW<^R28&_&&_pDm7uS{`q z{N*Mq{s#Rd_q`4L%jVp?9NZ=#n(nA@!DV&LVm1cbtp6#$jBdYDHs#)6=5bR*W6zS4 z%~$k3-H?0iasL(H(OyICq?^kxbd}Ct=559H|4TF9;F?U@6W;ZxYx%n3N?xGK;+v*AdG_r!_81xux_a%pd$ zx1;b!^z-R&mpdGvtgBEFD5ZCGv4W$5>tu=h%1%y_LN@y@=&iI{$?@m3LuzwCrR`GB zqjw4dmrW>M!mIAMYx>5XsOi^ddkJrU-e}|z=Uo5#R^{Qu3HD#v=5YM;TzsQ!*T4HQ z4Tq&8bX3{c&7V)Qn%)|L@}c`3f^=Nup50v9 z7b#ej>dE;;O!V%DnmcuOa#*%0ZuZboKa$Maz&RyuRkowfwdbo8VnynezNGKsc^1v{ zX4l=FoRc*^x!29wspH-Ac*6r_PU*R$Fr*_)zQ`lh6q& znL69^B!4D4U(hr2T~qr?{=~6*wd9lczfTGh75cnw=E<8rDf4sQ9{aIa_H--%G^Moa zT;0V?bLakD@p$u!p3DoZ^_Qen4+*}C)wYm1^)y((CH~l}ReN@nFPyOBa}ZV}O^mTprHSd(@e)l|LhlTn~yO4&-zv|laPIy?HxFV;!;iGeqGNZ86-qgP2 z*`^^GoRT^+)r#F(WdfVhQ{`l?O}5;5@5KB&Q)_#&+jd{%*g4NHYfYiJoAbTwU<0#u1Mon4e~X!YX7 zhnc*(2U`ML+4j7&xg7hgefsl;s)u!vZiX+`y{NadkNYW_c7(wXd45~9^Zvd36<2g`!fCl>8ddXk%-9lb1d+C_2o%(KchcA_8uJfHsj&6>_g zg}CW6zCRPXA(`FG-PgTqhlZTN?2jD<&jOYmH2W3Urmg08eQ#me#%s-dx&r=FqXh$` z*#c*AnrS&m2&h~*ZgL>sN;tj!{t2ey&C7VVy_26V8a4e1)9JF$d#m0}40yfqQ{h$1 zws$Wrb2FUwHD5ohnf&BvL8`WdQrd32PnnK!Po@5;I=$vUA~#7xV+!NvXx8g1C!JsU z?W^UY|1qvVwjBLv^-MaT>~P#kW4mu0E7VV2`d;Gw>CbAG+2?Y~IwsdUCEnK!Xeqe$ zLT{(ri}tj&lLFYJwsFc|xVfD1PVK2UQx49G*Gxw5kFwMtd%(*Y=>EY~4PmXJ7 z^?xo7YSmdeb;e)Drh}i3vQB#IlH4Y>YYx+sImM=HeJ<=}X#V|nqeAT(SFt5b3;a{< zd7o@Jv*d4al;|{_xsCl=`%d5N)}GOGz4`m15WY;e+TDydb?SoiTV6J94gAHrO)_%H z${<@6tJb?89ky)!IjKO;wu^E5qGb2Kr4QbuR=&L~)vvy170>ch7d?KY&WvCemXoql zS6_L$`sKUB&S4(@Yo1DkR5dW~dONF1G9!8W+H-%u$|dXWhANoRd9v`!D$NwwHm+R{T@O)KfuU4y2f0l>HcRvQ%f?BKudy zFC?2vn54Moe!6#T-;0#Ya_vdK62$7a_*E`gn0L~n%3x|-*BwWO>6@;H-p^G@ec8N0 zd+XPg2f4kLU5gA_Vag$xwl+`6*y@2+X`LCd`{U6k)s9nB zoeTb~`C5LN?UaU-yIp{1S-sz*7kl3QcAqiT?P{fRn8KO(Pd{#Nn0%R6v;5T&`$t7f zE*P%(@%@wc%O>vIUwB_X5Dk2EL391ID$@Yxikyd&9wjPyCMq8Kudl;ANB8g-&D8yd z>rxk7`VsU~?oajpre&84)EXF4rzUy%9}YC;415%^Or!Z-`Td|((}Gz4UuJx@=6Ct! z7Y{9-U(^l>p47?oXvN*g0?ud2w|Q@;?D-vACjBhLt7}n&%i*P#;i7(0Z=8%5W%ar5 zO8l<-zmc6o>zDi%yE?^<>*acC_ulu~;3IK6*Ema*`OnJq%JToE9n;S&pP=mSn7b)= zexZ7ceoTJf&3fNn6^OW3~qQ)U0vN~{j?%6x%fCy_ zCYS^yt7=&mFFK%fePich-qx5ft%XznoU&eA_Qxf_v-jG`fQWgoIHbzADSVx(Ghw#3 zRgrLX%8hk$td=*F)+N5*8~af$cfM@+w1l-66fIV7lM+rkbDH(HlY`}ibBh+uc)nBF zamMbzi+yW<`_#`ox+wa#TuJEB^%)C}-hRPdswTXYNuc=r9is_z-#bQ@i(F<%uAD!8 z$u9ME$LhU2ek3ZqZhrs4iFKCn9_}R}NvC$#txo^?|KAa>0%`S9vb|Vz4izaOXizai0$r9yzaSCDB_Rv#V;-tvhdfYNF>KaX&Tp z*QY6$8`j8+C++4>%q&ogeA|)uz4%1zhOpY%zk1JIu|ECBI3bOFYQ4s~gk^^;96CGh zm0e5dN?$W^{&FRkk|ej#Tmym6sxP}Wo*qgzUA)@o_sUVN9pp2U-N zqHp;xU43>Vy->gQ>zT?`oWfZ>zdO%%Xz>49{pIr9Yd>z(Epj|kQOWmZN|B`V?I*vU z{JzkXwb&=A-YdX4`}n<&e;qe^t7YB1ntIV`{?CL%*~(6}vX#77_x^5)PB6MUrKfyX z^r^SrZ!9jI6QB0Q!DWZ~M_P?J8fR3>X# zq~_(D{UI5jiuSKQy8Q=hi5(=|IbDqT@syyi;ot4lh!98X<18_o6mtNzu~ z#}ccr*R^UJ9{Sq%hgJ3e6v+jre)&$@@tZ&5Q)lfZ?odxY?I}H)UVoonc~VmM;z<(k zHS4>r#HB)R}QpF-)a3MeRt?h|95_W)qKmR=v{cmEjN9_ z51szn^ZV0E4O$;rIAr~)K5Z8^E6cjUl{A7CLp7G|8%&E{@(BB z-XGX==v!^-B#Rj@Tdmq(Oj$kg+f%W#7meR*C8#|%yEa+G^y_aaAN6C0>sNhR=F>H4 z&eo|CeOHw}X4*@M-??5ge`f!S&YTy8d)R%v`_c}sIi_F`B>y1kL;1N=t;_bOq~!O> z7IocT{q)+G&0PPUpK(-H*>w1JK=nsuZKf5;`9g^g#VsvGU#xh>;C1`RY}Nq3P04Ye zc`^jWlDh&zgm#;_&pcfkWY4Nt{vdj;@Y%yJ$~WxH{Ji$^0pWxLx7eq@<6E?9*>$^! zj~_$Jz6&2xI=n8^V|K*)r-~K3QtcKB6$!LB_#6q_Vd~=Pcz41vkz?nW->iQ2xlTcG zsx0U3+`eA+xW> z-o=u~FX+!%w@fiBCc;;gsruqy&qaTngU`(okmqjeU%h?Ke%B9INTh6;4HR~7AcDbUz?$EV~yh1D&`Sq>^{`P*5a{80N#3(+)&Q>qAxtl%Hsmdu8^I9M<#zL@=IMNyX4;cKCatuS>EnC|G;&I*0wia zmL6#o_)yF7)a+!^%PAY@-g>%}_4_J!E3u0Lri|~SkJp>;eqeIb>}=q*qKKVMcW!dr z>fb-LYwO~(ad#P))-ZoOYi+#v+~e8RYj5w~nP8(;7`ZTKX5sX@i7V=l)wwS8UFvUt z_VW+R;#YH@=|8*wX-(E8)}Qf4?)@i3vW_ZF+VizU|Jy13J0&_Y(XzMJRIKRVemCl3 z{av-G>NQ)+$_*DR_w;(n@cT#b`HrOYm&;Z*e_D_zQ|tWLhxax&lf2_=mctzq?<(>R zR?Mz6@6@@WHs{MlIgviyWA}LrqPY(4yPS4y7Uut;Il)oVZ&zb! z?Acc{AAU~Q_&xpKz^VRHwo`Yi9T1sZ(BFJFso~MtPIimI+o-;X-b6 zdRR7I-1m8joBMLDoTB4jQ{CDYKj001&m_7b^1#NJHOpRgioXkvNZY-Ans7s0x$5B^8^t|L zFLN{7TsGA9MH{^S6KZkdcPhJAk)+0q$S+$o?c?{_zPz}t*Km2V&aWp;)9dEX3p%8; zGW?5aUJS2p&9Nt|j_z=ETe-(GRMaE<>Fs~Y+N@rVOZjs@UzwwCk$MPqeT%e&5h8FAr;_XJCXoMykD&LL!cTStK5 z&5_4_`W9P{OZ+`ox!_|sQ^m*PTiiF!GOzqsCSLpfYo!Qpfi2$*fqz%#^r-hOy{gX5 z9UJ!Mf%2}Jf82AN?}TVSxYcsIV$*w@FLqLbZExSz==}+v$Gs};cJH)9+)1;R{`g;2 z8qaa}p0HtDLdsDur=9(oRpC()_XK?H4<(m&}GHZCww#g1(7an&^Gpe1L+bps!=1{%F2CZn12YEW%8GFS(2d&+>`lQ?E%}kCP z&9V&+i$6Hkp5lA6WYe^hEC&OANla8~oZ+CR;T08gdg+q5K&BZs(^6mkn8b9jG3>(I zGi|RG|NRQOllx-bPua-~vv(%8^&V`w;N4_V$M5<2)g8|hRulCss_t#{{^Z4}#;elX z)ueNDQSjnDn^KO&TO51NbMtrphWGVuey7(l#dTJPx)wRg&n{^X=wz&wVp4i;`PR8; zx%~X|@i7)Tmp0AXvNPjTr?N#>5?5-Nc*U$`oP1NfW@X;u{HG$xwl_?#nXq1{_?jX+=hft?i;v!Iby*u``^r>w z`ewQO$qwzc#f@c44tEruo|-A;TJCXH>%sH+J?|1t7+iQRPILI{Xw`ULE$_?u(xwOb zu6BxH1wGnpq3eOA>7o!>I+ zo9NBG=TDRws(HQK;p_Z5W6GnmlTPc1UUReEs?A#6xNf?9{=#0>*nf`d!PjQ{Z`G3a z5q5EyxMA^?!1_1l`PyTeJK38ZfFKJA6r)MN8`J!eX8^Z&uAxjrNmz zbnMQ)UOBdzr{Di6?R1YSO7Rb!?2^ns>(#Uq^Y|9ViY`=3j{5oa&#@<29vw<;xq46b zsTjYG_l-(!d6ac;DZ_jJ4AZ^S7SH~=es_m5cl`NqcMHQU3uVij&W6P=zIjT|p>g__ z=f2m-XkY)VoNZ;}5?@mtSy{fsNp(er-B+3RW(Jpq+v-|1>+R}fMFSR9z|8{?^ZgEfk_=<>t_dYHiD%wuH&d;8GX6MoT_3D+!&!w)R zBCG{g3X?ALbPI9jDXf^uYH%#|>#Dh}Yz|FAzK>od?Q;+>s9(B&miO0*4BQXHzkb{k zI`w<$m)Sn6p9CJ(m5nYxr(9}mwe~v>iuzqY+v_o2_Q{A+f(k-forseZdB3QsH_vd&PSyrc7e z@SdvY_a8~Rmqjo(1vseq^_2B&tBeS$pO)e}XWg-X>bEwrNiA4;ytUt8-+Q?t`#qP^ z*=p>VG{06|Q~&JXn%k@yJWV~# z4jw!2u5I}-W?Sux(yx1V+`k=Xuxy5e+u;Yg`e9-}--h~ZUCUE5qmb`X!qlG!6`#jR zc?qvtXmE_-MtNV*@2RVm@}AY+7J8Zdc=I;ReC|cXl3^FPFL*LpeY3waL0INM=wj*e zsgHKvVeh~A!1Uv}rVm*$$zkQ`JxdR3xX!vW!_D@GNcxAb-i^_ZnldDlq;|3@@7YzJ z#rZo-uB`Zx!HM&;trxL{eG|+4lxTMKq2;63zgYF`1-$)sG|X-9RGRREBTRpLwQl}F zvD-^>K5b)f4>H^ET=;~^NirFj*|#Uv^kTjNO0L zU!JK7|JN;dTJ~#2gm~G(RSnuIN~WekJMIO&i41i2`=IgSo2~7YCrZBFe&<_j5OkNyXbxS|>zqsw&i3~?{Q*X0&)M$qJ z$mOia=(x{yeMYE)><2ULqk9%@Q=TmB@lLYg+?A@iNsnW_T^J>8RrtIe6=^D_-8O3`Fx*L6 zu*-8==Edzt0yz&I?mBW)GyCQ2oWK<+^RE;Hw#S)&Jp5jPXWoLlH*}1C%ldV)6&wwF zq#1qqq9@PwA9+lw8(L2Kgx9e2s`PSQUm|xlg5&Ji zZ`fWj?cI!Z!h!+5Zv$32-tn8ml>UBI@s2w0U;Z+#c6~D~pVUt~67+4`-qR8c3xgEC z$>#pF>wI`7SSN9spVh~V8+)3Cno5J?Ckf`9)$Tm;CR63(cF|=G(wrAsMI&vzr(e-s ze)~{=H+wvbN$OP_#hH7{Oy_MDi3yqf(N*nZjLFhnOIdcj5e{aod3asCB#=)agfHTs zqjRUkB-zMdt=}shrq+ISczB~^u9xp++tph{O3C}GW?XSuNR(27-`rpCs` zX9+#Mp1$j3+vR)ZWd{l-B&}Sc*SvSi_NP)Bt6zTHo-H2YC19woCf{nKbu3}aRbhkU z4sPWRou=Z8+?PxgQ~Kq>wds*Y+Jlv(iOcrTEWH zS+*xD=1fqpJ^T5{l}{IMzLk}9IE_%xl&QvFt6 z;2>NavBTk;U`md-eDyu&cR@G4?vOFm-goO@@1Jxohup2KK8dIA|B5uY+<8HZquTiB z1fD;){F}`A_+uhY@ucQ@T-eODIga7!;tSs{GC%X4sI{)#H0qVa6s46bKDEqSxqIK{ zIj8w+&%64Bgg%^al(R+8!tMSY8&1XLTsErNZ|mc|-!kSeT74`jWL>nL*Ti|7xQ@S` zv{}{h#Q!d7G1I$C@_oF&Uyb@Gq^GKqw_Hhtw{ma9hRcC=6Jy@U?w7UZoYM65iBW}{ z@TZ8$OFk6c^ss-)xjNw6rYXC_xVoJ43VsQsESkye_;AV9bsPSBI8|4FVdU-!G)cSU zci`ResJxt@4L57JTh1D_-|x8A>v+b3=f8t;i!v45&t8hU{PyjvWsH{sGwWYEbfjk=sysOBMUlNwL73Y5zEjroEk69cu!H07 zj6W8)4XhNEoDC(Vew+{cqn@#~?=i=TtkM*pt-a@8-a0d5qDE7I^4CU3w?(^CCr!Rq z!gg!foR90-MTozB5Hsw(1f~xAW z-Xq>CzrPe+-{9YIaE=~V2XEtthr(~=b{wgyGOQNqKM*hbX61}@tsi>Fe`-}3c<<~! zQCzO_^j$trp;K<*vT#M2nor%5lb2pRXOwCo?)7QL@4NHGbzZM>oxWZ*FMG?mXp7r3 zw5FYWYro&ohi}2NoyY#h{lC1@9=6GSw9*uC9Pcj?2O+Vgw zFX`>j`F-;*-V&1qLG^qE)tUjD3_o1?cf;7~cGi2Zi+^rs@g|<#yFc)%tz_bpY#*nS zVi&B}?ujTWOKdu-aQg1msZWB7r`Ye&{5UOsrOQ9f^&9l7tUc~|7@a=R`nTjk(3^+T ztr)8&t=|&1yxRKvu9tVt+UEPMy!g$&ph0SZ%EGE+ukWU`UKHq=AJLhSW1u+4$nyy& z=PVA*oDE%5O6Gi4k5SE*Dqm;2C`s2Pe}Cv}8znh28TIA8MU(fYSuZ{GFT71BK4+SI z&(&jFUa&VOoVa0o$Lu;=qPVqRdGlO{%EC!*2M#ezI-+_nd`0kIhWVR#U+lQC&{0P1 zdD!;yM{{LgaQw|ZwPL~_qbKQdhn>Tcl^3bm(7|`|6IL^A1h;%G#r`L%ipd z=G4VIF8ma037ggua_7vSw(XKyi=Ul3HPzv;vi5}pS*wES_0>}%671dR{3Gm*Bx=k%QKZ${c2w~(}CmCs%O8Bd^DNOz31BQTE!Emk7}{% zH65AE^zGHwmiHG`eDvP9_)Pue_%1;t=UZCV;$^HlS*ZaPGZjv3sA$=7`dact-A8Y| z!lp!uUEtm!cXnrXAiK4NsSn5fy4Rm3$FTYeu$=h2yLVYYb_R>%l+V-4#VhrVeL}S# zHr&ygW#^jl@JQBjqiCO^`YDPwOF6YFO>f@}`}5(zmWfMB4V@?$G zZp5{p5%NoP(wTlSb8HW@i|{kp_Tq>6ic1#NpK`nJzBF+CC^cRZ7O@E}EI3d0E+pPa{-OM&@n78h(Gtd8N&qCJf_^II_>p)?M@Tto7j!a_f_S-dZsK^Bz}2$Ix3( z=Q!1}Z~QR(B?EV?=(T_@juhKZEuT(ZKYH=l{cq~RGV-TN`NcVGz&B$W1>$w(3p2$bHGMH_( zT3cq#sx_Zre?fJZ$*)2^rb4kN({^lcbzFXEPfg+8BFzhP(=RbZN*(c65s9~OUHy9L zX3qGYY148imNoOMZiWtm{wS!R9p!iw+D z^^Y#z<(Ag$&M4iU|N8jN*~@cVJgaQgjW53z&j^hxk1jNgOW$xTVd{my|J(LBhBXK) z>h-+vIyn2rj;$SyZ!e26b?#1`-96pB5Bd{Vyb@YtH2u@dMLX78aQ`;1=h(bUQoi!ql8c>LYozL4 zlzsl3-e)KwwRxLUz@M3u)E!)&Zd(22zSOUhCr5tNSY25ieR|(6X{GL6;RQ#8kDUD> zrvGW~{0Y(guhY*=49@@mTRI|EqHen4(M5a~$*&3|4Gh<=mH1$0JFQLP)zTAAf`t-u z#djYGEXkdGYuk~_f?10!Pp^9%c8!1AkMvvDY9zDkx_4;ZTBH~9D0$^)&Yv!t-g1vF z1r;U9cW-;y$8EPe^jYNR>9I?nzIgKdM_fo&eHSeTRd!`7y$<%yJzcSfen zI_LLyA3HU$Xek!oonvWmsA-!0R*u%G?u%#JOj%>czTSS3{aLxK9CPJ1KIp!twm3!2 z#p@r-n|q*RPiIs4W`;kF)6biFr!=20RD0x6+Aq3Xqw%rl zu|w&S2tF9~^mO6SVeyNVg>6%+p$7hnBvm{vFM*U9LBjxfC^ znKhCx=e%!Tm+b3aE_!|IclW+6UnXA^`h4kP&taW#eWoXKjSN3^uXpTTYSK3KTix59 zZwcRa_0(6?bt-#XiE`B6W5UU5&|(ph}(emn`D9BKArc>@1R$<{k@N?(i3UH#@u zbGdmb1sFIlUH`MI&0=5qN8X1On}p`D3!3M1m31-*^S)f2qN`}MO8x2elGIPS0$w*$ zcYf@@<{T!X{rAl(4wpHL{(On^I+b1!!l=SrTK4Qx-R715&Q`c_=l*wFg48o%Z4UIo$ZSN=0iy)4vXa^%kLGk5eIj|Pe7znLR_+}>(4 z*OmJH4a%=Qiq?1jv3GL)GBGda!NSA+3LI6we{$39uKlw2vE?e=B-fX}!=>7-i06p> zq$`oHtq;h@Hyzyh*Tqv{|5Z=M>Aq?E+GkFCyR_n!O19gre(Oo^L#-Wm_&llC*id}0 zDse+$aqL`Gxnnt*M^~KB|JB))B)`*9d`IVJ`L0fexyzP4xpr#iDbXC)tzYcd>|C7~ z_$}Qr?C8Qf_NPS{RF8X{;8RqK3H#}Gf8xP;er=~OM1Mb>8~J0wveh4VoSb&pw}dfk zYsc*GRUaN7xqqecPt$3g`hMvd`9`z*HMZ)fy}NO0?zd%v=Ofgwx@)Sh*4tdP=*W&V z!>W{*E4b6Vm#%W?JH)iYb6Sa-eA9#VVGQS&dRAoH^vBIz`SE5!+15K>lBU|ktuSLW zS?2No>Fv~$?+yhwIb8avDIl~d-+xw*=hSw0`S$g(O7Bk2f4K6M;^{r-|IAsxZMCuO zb8A+`BgwH|CpNEqJ-2w>LM6qfCshSP-mI72Hoxvl5Y+r$sFBe({c7cpvs=#24=%5N zHX)G7CEeXGnNz8)eOlN3f@LM|j;S?;9TJnd7~=D0O{0R#_roVxyAGQMMaR&AYk$mQPE4yR*56BWamd8~~jXMNnzyjA1pzjbl1%vVRUKbiQ`_S@Q9 zr;F9MFOK-3dtvj}rva-y`Bn7p$NCGiZ%$u* z@A1{li(P_O``?RPWqNy6YKcdv%x15of`d#;xA4#3bmY4n(;FTKzuRdqW&Q7^h-quT zF1f{XROUDPuhf&(qMW_~UFXjI?0fG0^B@0T&1-t?{}>LsPw$T_EBjk|;ok+%DRR>~ z&aL(Ju;YLE`__bOS1&tfIaHrfx-BeuJk)Fr|J~r#9UnhD-rDDJxnjLg%*FVH+4H|% znC4dc*vfNv#QAp|MR(Jc{snSQ+yC@psC#No`Lt86ThhG#N4;4ew%&NxA(3T-9c zJyegmBg_yoOJDb2_`5d(J1_dB1kX`h=O$uu`qdo{iGLb}_g)9RxAF`-xZsnHl#osK zs%IiQ-`LEPSo^wMW`@F^4F`;t#AilcTF+zd-m}XlJ1tsW(%@d+3ZF$&|1~d_-yJIQ z&_PK*u*`1i*=GxheSM-V2mIJPJyDDtvr=FHgu6yz;E$QEytzQx~>KQ8KMU#?0iJrHJ zEbWWlzU|M>zslKP?(wTGQYd7Ln((*Dxx>!z_uH@g_xFk(S}eyUd!(d#Sx!!N>2Wp1 zzrP(8YyRX5i?8?lbm7(>aRaOKa^6J~t8PzY2`pl*Y?rLw&mqeBV;{ST)yrDD$iqj^ z$9~gEPruZBYC-&ogBzJ=s~LWCzE+6C);oI>V3$se?IN|Q~tYF zJI|al-}|C^$F;r5C9KgE$&-7t;-B34QFrdgjF~n1T6VK?ZsyK?_HWA0TG21}pKUF8 zEmOGm-P;E*Ga8of?_`aylz#H9koS=mUtHK?@7HD9ITvPyy+3#A=i@?= zqk{eAy`Ptix_mu6w}^i@YUIA_^wRhZb0;~vMmyHNxZ82lVau}%$2^_ShuyoeW@W0V zlI?UUW{uBFH)WN6n3BEDf6->S=W9f?MLAmPO$C($-%Yu~pL&;Bm(ljw{KPP~^pvGW z6OY{$l5G8ZjBNqqLZK>Y(~Hh_Ec_DB`uz9uf9$O;=8S5Q@a3EFxUL(^$JEw%Dt<2g!W+C`KDQE&m1mMu zqj|ue1pV(#^F+Mw?sj4-@7wkNt!B>ABk2Kthc5n(R$Xz*{ENe`uy!eiP~-ln{DW7D z?tlC8weZqfgV`m4`8nl`(pfev1tEgZK73I+Y~)lp*>(H*t=`X1Z~s?z%q(G&!4rGG zb0v&3U76cXpVibjeB)wSBDb*Pf>o@oefjlPu5PJ+|CAE>fw$sJ<(Foh>u}%HeS0qRW9>I9l^fanIV;*aO0vDE}zAys2QVDdXbWv-FJS)*ZiuZeDrw;>gxR$vzFi zGE=_Qv$=_yO^6lZpH#6cwUhqoZH9GX!-+R;jGxr`w2YP>)taoj`(O#*xYb`tK z{+zug>YWxPDiPx8QJnrJS@x&*P4A<8&!(*62yX4xT-e8Pbkn>k!dreP$3DH7GkL*E zjlhO&GU0;T-#C-~-$mAg(n+x*(HKJmlB zM!7A8$98N~_w&0p`#JOU`LWVp+UIvM&Sm$ybkcm=Ma4e$`n!_$cIJeNr-nra{RW1JQ%Xjo!uUoqJ?k^kHg|GG|ZEe`AbiT~})Qv8s>)R%V z>1S|z{Ovrm*xGvK$^Guu*#{GTegE_R-K}YJM1H*TO#d;5RWtmtQ})|8YbQjhPTjV* z!oK_RNxxrN*=J?WxSwHseENd&N3At&l7Y{RLl50yVdPJo(#CUHgzMQ0p*8dRKF+!q z{@!__efhs_*WEv-Ys)T4ytUkW`mT zT65Lf?R4k9YmHgGH(4h?xVv)eZ?5F+bCo=Gr>%;MoV_DEwZ++cohpO2uj!^`p%FU{ zrY*m8=AMo$^5gS z+-9qp&Lw4AT-dH~e#XMPZTF(eEL2O({m&fEDdI}@)%~qJ>rY&9_j2}aH>MOS$$fe% zW9JkQYxVo@(SP6DWbf@+eg8jy|Nfalyh^;hOYc8kkuH0!`?}%v)2U%>Lhsl&b8J5L z=Ej!5KZX-uTWcxWtL~cc>A#kV;mqIm>o1FIs$F>>690~)udT)2;M>=)r&uyQq;pbs zo&41mT4NTw@n+;9ImaNqZnphZ9RLo2oLw` zdHW}SVb1*Wb$!L$-}zrkuix!IV|`}Bmy(1vmu4K1dRXe8ylA(_wAC-3ItpKp$eA@o zp5y)032aUGR@MK`w7foFW`ZYw=dJHEWG=4cnD1|YKHJW7Qc1v$s5?h@N`#(2Qx@IH zkbly(_I%!x>>D%pIO*Hl>izcHDYrzM^{w)&Th(qGqpq_ZXI^tcVo$b&=qvyJO}rJ$ zJbUb74hg++uKQyvyFpUDc-f?%H#>_Ef@GS|!8h&HZ!l#gB>?b`Je##58MLBK|8b`0jYjmi=#j`tqMb zj<)9~TYK$~*?DQ&+|4l)p8n0xmpilnSLFJyJnzj#^)Hrq%sjm=%~0>J)eI|Tn|(%d zCGn3r8Zza6f13U;$|=#IH8AGZ?8d?uRf2qLQY75o$0>bd=a`e{6@Slv%G})@o&h(z z=Py0{*r?4;@rZnP=WOS)UYA;7_WhjS<9U8_FPmQ#Q~2PEh?sIvg7>t=E{P&PmduM1 zy-~4|N8*_*cbeOT>Q63WxiSYYMmI7Qe7YAS)%3bD<`%P=yYK(UpVXIrTKcb*lc82I z<|fk?yT=+{kL9_XzyAAkm+z0*{^<$1?6U4AbEzkcFP7Cd{}1JMT{-vu zi#6JJz6m~!+56R4dAdZpwo-WT(fXLkO*dMEr@NF(>aSn8{fFrf!%qdPxTL4Nox*xK zYwcdC-HhAS|B7Fj*K}F==-+N>?tZ(%xIe3tyAH2<*RAG#HTvSkR;NQx6oj7dJ-0@D z)3z%MroDag;MrvLPwzf*1_+B}d#~y{P_@TUv|wiU-;X;xqn4{WNvvAp;&g4frHFw+ z`^>k0eH&keziL%_u9!CA@AZRgHRR9c$^ZVz+x>VZ$Ad48>E0Y>t+o$JKHh&mV+Gr} zD{LFRR30ejd#6NyD7d=j@|~Z~X|+3Aetf-}m@c8V^sFnRi%QYf|=Ime5aCozX@2ZSo|Hk^&ukCKPiB5gUmbvouwSP)^uK%>oHf*Sq zI^cgo$=K-Mr0Mbp-?x38Z?bZO$j_k?}&@_#|3ix zZq45Oy|!d`q(jxhvh{z@w(MTtap}4EE6vC3ibA!PeA%ixEb@n37Ae_^UaC5#epX=N zx+@mXc1>CP|zwA7F^XI({X{)B(O^c4(@Ub`ZS3>0yhRUt7$(u?~ z@e59QFI*jUOmvIY&OZ&DUl0D-x5CWU=HTmCN%umhE{+}da^maL{dKd|JWN^_-YM3a z(mN}-XYtREOD@)|)>=|l^S0DMf2!94^LOt@sv}`EL1(Z*I#s;r#biLxa|^Atm0Yx46GtGxP4@u;$SxY~!5Zq?H_ef}+fuFYjQC{BL+u9@|o>;Q0=kQr={52;tPC)9wqxE%H zZ*}s&UDy9IcE$k-6VXJwt)|OZp5CiEc=J@Hn9bCnL+^PEmk3I-6zROa=(jKH3&-h1 zqj~N%Cl_%1Q8{eus_T2_e8rUo?M9EfpWT-D^Hte6f2TvZ+<~{sLVliR5=olQJCBsv zl-@I_c-W&6D8w=6&G)PN85dscxO9Ii^Wzrww=cKszgo~Qs5MP&@BZtzj=9`SGJJJ> zf0RwS)zt3hm+mv4Pnp6~G@0LD=t#}m`%=ad+BY3nr%egY%h3zYUdAo;`LADpN{P&y zd0!I5s{WUC&f`9>Xq~5dQp@k2$Lm!gvs0SB*7<&v{JzU{-G{b4y&5xp53au-az5o? z`<+$g8uMkIy8XD9zG{`Y)o%}ljj~f#$W*_1Uq9r+6xAr|@3gs97v1px;Lp@KvMQe|3|}dH>kZPmWWBRt?FO;Zvv=C~I%nMQbCbyW*Q4ip^YF3~ zHj96}N9Q}u$U5}n5nGCGp|M5dJ&%NhgqIq9hqiaC>@tih5l`42@$$vDErKssM0MU; z)c&Nvgh5W_?Hc#nBDWit88Us7{WIa?d}`)Pg9mfp*+GwaV>3leSg zJ(1wM?+x?J6;1Pto<9Wt?&c>55dvaB+p4GxH3zz>ty!DqvWMclM$}%Hf%BN^2^kbEhF)}D)onOK&7;Ub9 z^2Q+@&)9c8ZV|;__g-&0ASd=A$Kp!l*&~zJ`w1M5PMVN^W=&k^F+Ri7_y02F{q8NA zHupZef%asVR_Q4b`UOglV+-eApWpMb?aL#J$0<=e*StSre)0UC&sTPQcv-e;zmQQz z=hfpzGysHzdo4plQbEte{&r$SJoBKRmZ+;lt&YJ^H3YqYoB6Y|s8X;W3a{EGHY zaV~}W+lt)U+WCDsj^TE3=FZ%&F9kpG$14`-eR)3lOgsqz4t{Cr+mNdzvyqRYXvXr`A?k6zp+jC!Ks3^wfYbJqHn||Z=B$^ zd)*D8T;r-sHM;9`Jmwe1bp9_{b8$`dGD*`XDDy}N^^cb9woYm-bDl5p(^X7t1ud|-U%U3TbdRg}2W2M*3#yYWJO$6`apQWZ8?Sf3(TfQ?WRCOkjQ+ zzpvKCSMstU!B?2C8ns@lUdSc$VbZfZ1=%ydtE*H!?&bUEc`Jo`t|yj*wmVoYz*xlk&*kZtb7u3*b@qMSS;8T$_vWt7M0STMPVUEl98~DO^B2aC`+v{aQzWpiJ?fB43b)T3rAt0XzAjLmkm3HX)^_vfGr{hKGurODTGzba zF0JayJ8|I?pG{S+dtV23%xmDhc=#+&cz$ML%fGz=uL5n{%^sZ!D>-p*!LhuvzqeN8 z9Y1bbKT*WlVMAis^k&D7l@D@M^!z&fW&Wy8o)Z1~{a*&PHyq;bE7ohC{MK|*{!h=B z$xrt6xn)i-d>6rUy)s-Ws6hFhX#V;K&J53=uiLEn*mQe^T-%rUfYV*aZr^1;a47Xg z*Q1K>T;hjX)YTWCbe%e@Yx7Cl`d9i()Mpx}Z7a)ovzM{v?EG^}Z&W|@FSNcZAEDQH zQT*`ZX`Kc&8&kScmz|#={iJf&;q_b^jjz7CPb#U^*`Bk;=jt8pBYHA36sPZ%uK)FD z*UI~4Z8hhoKHlD)GVk=Rb`6W;>}szzEeLTt%gp^U+>`Iook)ojt@nCPtEa>TsO-Bk zXZF$6bGL@x`?+W8k+#?K*yir*tvK-iB=5#k&M7CC>g|wzvG7L8y&%>tb0)pH8u)0p zf!d3oYu7fb`aXW?_{QsSd}z0y!255zZ#>-c=jtuq1B%+Oxp(z0sA_z3?8Mpz2dgVm zpVtcRNqa0R*ArH3v0zGj!mc~_Cm%5X{H7?(uI$siNAqr~rnJ9vsV#%v-COr#jTTQS2`DUne1(HGHe%-CopUyK@au;jXf!>LcTQrO|75YG zWAElXf05L1;b30*#S_PaeWOL?+r0~U_k3RQdP0TyRJo(GDhj#uJB4?3UsGnEyf&+* zAUiESjCIztk8+J?dS@?*KKkTm5igVO;uZPV!Wgd2Uej_*qJ2T}fi2vfb{YmOJc3K6 zo;Y-sZGEct&*&q|3cnrxc;%(!ovQ&`>BSg5$uZQARLPSVAh{n^nA z1$_JW9F+T`xc*1ugx6lZy$1rUNR*X?F`-jxYUH#GAw= zEh;ie^O)D8Wrv)uXunyI9J2e@`s0TSq+1uRc6ev5!SU%!tlyR%14U1{?{Zel5)P%G z^l|*jkr zzNzKf5osr?_UU-)z1_sN*mzmUUsW-q1MBBM>-zn~_rxytWKm=J$BHM9thuY~P*J&JR`D_)FgF`IYyNWa5+wcvezvktAj`nGoKwQo*$`#LRCwbNOvU#)Ko zm19o|T$8_6@|wjaKmYvIJ6Q~u3?*SpHo1Tyxl3)2k5ud*zbgE>+(XXP0m8Iy&*7-uhP^Ie*P}a}>T>x;sAQ zPO)Ca^}7AN-#E{FIeG8zlazU~98DQbU)CCbJ?;}BwedyIyVLrjyEM!9a0Z=TA9g9z zBlh{`{x!3ve?D3DsGWae7stxaq8GkJUal3NJMsM4>jAev&C}oM^ZpD2|GmIRO%26b zC42q}uB_RoY4cnEb0%l45_ie^wv=!A8Kv)+cRsk9;={DwNG?5AVu!KohD$!(R%KDu zCjM~;jXeWcHpXu4T9Vo0J5~Cn-%9&Gdu`5E9b+ubKbe(%-09-hextIOJj?ajFFPFt zKIS>s`tTj_zN*`QW%HBD+6%$QEu)-{3w-9A^>Wt5PbU{X4fb)qk}putzIx8SJhybM z*n?konH%~Rp3yivuU{`)={d=CLHm$4P)KKbMLMG za?g+6|Ey$Ke@;C5FyFU2X+=wv{Vl~4k894=I&S*gdERon_QDlP3=BC97mr?_7{f2f z`Y)kR=&NPW;vyf33-kBnDsE(MvQ__c&B`uXLT+}kl5^^rH`7IzPIO+CplY;B!}}fqZ9V?$$?J>$yL=@andEkDy0Jv+gJtUBO~sp&pLE}sPQ29j z`Q!uft5?=@5FNdHl2&QAq8=Ney!;dbe&pub>;iO1Hn_Q7cVs_ z3+0}7(xoChN~OczuIONsXrk3u*?F69T^CsS_hIgVGvB#_mQ=9bdzD(SIJ|$>gb5v` zJ3O~;(X9wQ(suBtpV}#r`072u{H+h9AM&3T`2PKph}>(FUDGG&e~mIT>efBOD7MOu zWl?{@bp>r>PEGc^MlyOr%APB1kFPKPa^>{zbt<<`W-yw4Id^6o_hGN>xUOSX_dN3s ztG;8_?Vjyp>Uz2~YI~N7{K8WLMSRX$iy1rv`0rb7+rIRHo$`sv_l}kc{BGxTD&c>U zaB5<~tOk4clR~SOI`7=Uzx##5ORtiy=Bj???2E}WPA++3zgS`SbrU74jWcchE^aNp zrnq^}!i6WEi|*UPu-z>Dw=?5iufsDQyHDERC$7U>x+-9vS+1DT3+|!<|HH{GH=oDe zU1_g=cc0-!^Lu-$^&UKkb%_d7{cU_+C``xxmC5>TMmMs%Kb`)3iP40oXQpmH*KW>C>?|{@ToY}{iD^=g7j*Ap$u@q!V8RXE;t3o-wkP#p)SB#n*Rct?J?6lLiMSZ8;oMWcfR3Df5KWd$IwKV3_t)s1J znO4GjfB)Ze@etOGHNRbaBXZHXm)$4PzAFi=|SF6mua<8wU+Pp+Q`TO%e^By>! znalTj@j|xxYyUImFzYVO41Jw*hezS^lg;)T**Z=B8GjfZcBNek;CN`Mrz@%9lz+EH zXZoMFb=fVktM(SZGw3WoHY8c)ka4=K3u%i!rY#XosIdxsn%zVdmbk0Wv0!um)zoB z_039d?d^%*O@8KI{9}4-+mf1(m)_0Wzfa#~<({Nvv4?&(KW=}uenQ@y$DA)yl+_Qc zPKv$UyDqoeQqMB?wf}9|`xDITzRj3?WJ>TW>&XF2B(pxto-$h^E;h^W+>8|xDv!2= zEEa3y`NI~O;=T7pw31X)(rzKfr$6Sm+q{)!U-9Msm03wT0gZ**zH(M2yA@}imb}%H zE@8E2kMqk=7DuN`vp4x}^JBZ&ewjD+YsaP%1qZ8T$6}AM);e-qO>AzSdC+BZro2Vp zsuu>lM)_Cg?bh&{czMd98PfTYb({Y@ZGUw+T`i!mvA|wyY1HoKhgUaVH_rFlB(meuhtoyApNu&2 zC0E$n8SiF$HSKx#?$ws(1i0QjXH1Utwqx1fb$fofLDG*W zwFYKFvTjGecBw@01TQ~0;i)!H-+>QK|7HqTOuFT?Mksb?$G-fhdsu4!q_+!Qy0z}l z!qvv}csF$yuf6#7{9;C%upHJ~>+1#W49+fFCmy~zo+W+xhMT+9v%;4wJCf{kVQDD8 zV@l+yKzEzD!o0_SoBs~B&bNQ9E4guNk@h);-wQrV>gNAAP@1Uc5Rt=v!T)4lQ0>ZX z(>3NCUH?CTcaOyH*&bq>FQ&_CihiBYcgIM3rd<5KvQnrof~(?&rdYiIqm=Il$9*2gTEh` zcyN)0ZGQC2qYZ(#cRz_;w)el4ki+-RG?}=gf$!vetcoS?yGsbzshjOAJfJrHu&$@3 zR)P(WIP1SWU(a7RH10Rwyyt2Ww<o#p|q2g74$_ z)IKyFs*kgozOQ?6ns_wJ-{V_auBFa2sCUh^HWlo<)wF3|KsBFX@;x3s?>$v<*S{B; zn^krL(hLhHkpgB8tJu>{Xb;8OY2Q_1?uO8?ZU31gXu>JkU`>S+T&-vXk z|F}fO@i`h1_o9y8yIU!_?cBpMmFirfsXjh`UL<*+H8Xv);EF@v5mwur6{l_r^(U_O zvM>AECnz|-QgD^>X*qkV7sol9gk?7^z29q7|J8}@?8UB+yCY=OX8N33ZgV!f@C&mD zbAnoXnws>Kg*)@knJ@5?ej=D8_?Yvr)bZ0(m6mJu753dY{aya$hE#KXi~5_(=PvNE zcVc?mw)FOdj-@Z}B`>s;o@`R`YLSysoQl-P2^dMc&YyFLZrea?aLF4O&U3aUcGJG zJv+KYU>W<=xkv6jS-pH*B}C zc_8~@?VQsyvkx3~Zr<HpwH6!Pa*|K&_ z-;Q3)7c}6Qv2CA%Lo=Vbn!f4G0}6Jsi_NU+X3gJ!OzXtuqtD~~VmI5puU>s}Wktm? zrkT1wx^zw+jy|7s&WLfR+fAQ&`K>{9^SVxN-^u>J==mTuGDOI6y2z}b;EH!4vy749X@yT9y3%F%&!0H9r~(e{*JnrYQF2X z&sw;6{fbRzu62J44!L)-wZ@O5{#(kND=iUoi`zvGdtBcCs&cx=`=aS9+&4+OZa*xt zM9}{Tr}Ur8b<-_!t`|+?y((3C`Bu$l1ylB4>mK`R9FjTi?fYge<3!6|83r*y#tT0k zonj={q_I@LJ(9qcJ4+<_Q_2K`ulgOW>t6=vE8RFL9W>kVj;J$3ZC|}F?~Z@h6aRjH zzxdvvUbE zCsr%l7c`_iozR~9*jzID%F=hvyZqU^&YwM4IOk3J4*Az^F5ycU@82wDS6n0N?I(Sl zea-4OALi^nd~~p78p~6Wz6h0WJC1!djJr;L%NI0NUE20?{o$<0tht&tvmozkrccIUx3^erZFaK$)xTM}bvl#mEau*P z)SPou%&y|#XR(DFXG=`~5-h#Hp69}`jVIYYn&(z5$gjS-{?6)>hoM(^w;cMakuSa= z)UdQiwA<}ehW7msDQV^3iNVx6d48YNFQ6&o7%Pd43P=(j_)_v{BDzPkNa&e`jqWb)#1x2u1Acy;-y z`(g2SX0iWwbC-#H()wxMF|Dg^{|q-x2s05}GC%RL?Moq(?`je2bwl`fy>8?-4e_|X z|3rLbOPJP2vGxP$H;;X;Jj=aR*W+_+$j)=Y+n5UZc@|vR#q719e|xitld4wQ&Z{3? zM5I3Lm#(+Ek^A)bwAI%FQ&$E|u@uU7Kl1;;!n<=e=Q?gb!u;X>iX#GB_-3sXW2io^ z6(-EkqWbwwoQ`>UUh|}T&n10sJa$_nxGL$wFCM+pIVL9;blqC)-#Y)mMFo%LTCB5c zHwo*mZxu5(dDIp<`~AEZvSqA`&&*P>SjXsmVc#t^|2;+VN^7Pmvz|!WV6eU9*U^N) zV8@_-@3qdM73ZsZXI-1swIQm>G~Cbi;l9XgU5@cJiyuu1`g(X1Z*|nXWq*Vm?_NE= zpyXv#)2*8;u73ZtP@>N`yzYiytfIrJvk|AKzPnwn>nnFn{F>q4ePU-Mc0Sr;Skjwo z%+h@4re6K-)blTXc^(kfb?0KPe7#Tg=X;?aDUM9VHYHE;H!{Ax7$f#ETTHyr{$*eG z&)`qOm$x_C${yJK;_{T&9NRmD;!o{NkUJL{{o7u8`RsKDS-~yMd`FJk%4AL2Ib*KZ z_0XPM>zi2fB-{^_%zu2$RAY^`2XFJQ)d&AnInOSdn{00)o#wwjbp01Gwz<9ib|%^K z7X6jW{~ro&dlypFY;##}@0~Jd?Jzq(``BHcYksbtd~wm1-bs9wGNmkOoJpHfZ2fgL z7cM)Z(ezC2s=+1MX=R30a;c#OmtC)IUdMgoVd%%>TapZ(Ee7{}R0m9sXTHxq(KdPv=?HnV*fZ+&QoO%%Vpx z&K%IH-tlAgp>KDD)Tf(I*uQ9#ZFAzMjG1*`4zfgdbT=fP^ggkC_MHi*{j*G0uRkNR zI%Az?-nz0U84Dr~mxkYY;j>M|W5E_zy%QUqI(5FpEMYFm5IPZS_rlz0ee3&e#^u3` z>5~4-Q#&ei7oL3Xa?&Vlme|83QKMT9~ZrfC+RSU`-BxTz_w?1Jxk+$vsuX`sR zZ&{*xs*5S=RNn0!S9}`Yytc3EO>oPz>HL3Wr>)?*w~87;WenFNegEdI^-D7QF1mP$ zib6~q1NXL-;*%yF__pWjuH*kyi|@TM5af8^t{o;eyLa;op-GkM%C7y^Svw_X8O(cf zc!jLr4dXywLyJstp}#wqrO4i%*zB?Q)Pod{@9js!DwLBL3Z-t&-M{k1Gvz~0ek*@; z-JPv-d(E+P+e79wAMltbpTI4j#hu#q#L1{!>sG$oQJXsl-#ipAiK#7o?Qi|C?HAMQ zxgHJM1>=vFnVxd^qahtHzrw07=i|M5g7(+hjLM!pK3<<&&y}1v z|0{buEp+DGKY_KV2HNDu^Yr_AF!3+z%V?Pgs*3 ze!`41ra1f3iBHp~xPOdoFSoR;iP^jLugL?;d*v^-C=%IB2D5QfB*pndVlt z)AF?|-%i@Tz;|Ef-Glro)1F_RX5nmgKJ0i<;tt#Xte}WTf9jShOtJd0&n~&yG6g|HoaKB`Xt{byD^^qmPyRF~;M0^UJfkOWiaYR8%60B0kovTq|hO?_IaE zaiy@5amS|nr5Bv-D!bEpA2pwx6<)%`#s2%_@e6+*e_kSU`=iw^q1wN%mT`ovJ$EHw zSKQTAt1mad^pF2}Vr}|~T*WNm_423F+%~=a+57s!`k1K~($4$sD>}a6?Se}@59g*! zGKYQ%-BBwox_!+7>-YP$FcOVbYM@}g|)Nl zo;5QSX0dRHruMydmhXAm7_i^{LoWy0$`7owUnp(r(ySA8O1rw#XntVldhbgN50d%T zX4fh2da>>~o53kWWyoq;7Gr^~um{I$w^S;dQl?yZq`+1YcBs;?)m}Si1D>T-LnZ^iaB7 z_^X!pv1_eM?2{krS+xiz%82sEGrAnGZk*x%l1=VEqm!EKfseVrcK@+d_~$pH@vSh| z)9M8c5i?&iDL!B7GU-)d#IceJrOc`Jb(slwT4MZ??r)9yIAb^Go-@1V?X34Z`lQBzmpNWNn;h25nCMJKsG3EAKF z$>@vi{v4lgPh#&Rh8QmNso#3z=v}9d`e~ZEi#c8HFihBcziiUGBKL$tQ%pM#rJAS6 z+OEqwsC?r0i_=eY?v%_?v0~F^6O+(?Hs6YUr|>8BT!R`(d*SmF?(EuF7%=x!fx!aX ztxa8@s{|DHe${_>%$mn0(!Z)C#-FZMF?oQt{dZX35yYN;XT8>OvJ&l=X&tVo*~7Th$& z`_x1>_A`#gURo0>87|(pd)u$OnYU9rfBk=^38K$_+BE~|B`*-t&4uuAYy)<41KW7GADdF+KBJ^J+a zmafUq*1v1M|K->x$h`lf()04iYq^dlrYV2wzEL9R(7n51RfN!W)lbZa>a^mDj&A!P zV9x2japQ@AyU#V1TaV^nT>kOq={{i(HeTIt;SU!xU7x$c-6iN#|DMD=lM7#L`=pHY zK27*M)no7P)mvKc&M@A;r1sw47eU+ZZG1R&uIaMV#gCu2yhu(uaz&_d!+AdU%BS*z z(-*RR+HcduJHw=A@+OIpQ+G;&W>4o{XtdHz@|#mV%eJj^zsz5&#B%(3OJdKj6y*yO zr}S@lH@!VuTZvzusoHYymt#)9%iZs7vE|=z?91QIc+2wa=KS|7+Y|p~6&;@c@4dc3 z!OLQfDN?<>Mlap`XI}NLJkk^XMb6>k0&^XkHv7-XL5`nxEHi14pRT)`!%4{4{Nm&N zr+$Ct@H{X%=8`baVndUFd%Lzd7~l4Z%*@^)d}OBGF+0I63FofdZ2h6&V7uKkPr$u# zSk9FjbV>ttfqHmM(5SGw8#mhJGl*}8Z0YzvJF(XxIi(`fhWrrUL-OCLq< z$ocGcHU8iK)f+mP9&_^)!w#L{$@QbxgK3R73*3xU=n7*aFe3f$M zcz|5Y-NZv(&v$#U=RaxR^s>-#X_&i_pcA7}wv7K}U*Q=Wn7+2n6<_CmW1EBBl-$C7 zeES}*o;Bn2yM+1kzD!|Zud=XXSk5~syWi#VH*po7&xw6Cd?^o~n@;x5Q*}T1n0e|O zj*b5H*IzH2-x{FW9vS)R@$3F~73Y-gmKd=g-#mL~9*2j;cS|no8Hv1K0u%ohJ+15( z$xz*_KApi(bnlkWwwC_C7brZCQf2UIRxniX+f~x1vAkKUfIs!SP0oCWwz;gPD^EV3 zdX@Ko&_&JYQ?1|E?-bXGu3RJ-XLP=OO2p&H34CJ9=ds=m-{Y0KsH4$^!$TcF$eb!4s_#^YZjf+1Ly2S^FM**!)rD zhP8lJ9_@YLhI5W=<&t^f(_Cy1o|@7e z@oNUlBaibJ{AI+hRB!()Hqk?D{Y@3esh3~<6<+E)S76f3B;E%s$IfpOIo_nxA9c_% z`ycC5Ve1|l|BV|TMmm&iINJJBH*hKUk*}{?Y_xcGoLsx*El*3*)2Fu2JjFU*uyXDT z(htGf_Gdp`-au{o0&YQEh=joDmrhg80 zMwf!T?#gqSTb|Jp%wRIna?8EPa`5zpe>cojKRn4hIqzvz=aO4<AnIUm$_f5C@^djeY5Y$qI-VjL9bRNzjAS5d4H^Yuf^omD|V`VnR(PvxF~U4Luu%15Wl7yW&G(?9e?;?+5F7foX>zVi(>nH^Ldk!YRvn8(Wd zblsd6qEF6qPu=pauGS=A{^H~NQ>9nNrN$S`)|_zcr18Q-Nm~|%#3(J?8oT{a2gker z$2~55uSwHS+3vYSy54H?(KQQKu_Sfrynp|tUU2QgDHop2+P3t6tTWq8zI7LajDvp8 zlAD^za#CsAMy0)K&+S^A8$zaug%l*n{lssQ!LM?jk7NB zB~Ei{$Y)+q$aTP_VA&c5o5ndd&0;;dXS8lcnZ`yrxl}Ig|Ds@A6~VXJ^JkQ;-PiBG zC#W3NVpjX#e=xpmv*8Bsig#0@k5BxVA@P1u3Sl-pJBFY@7cH z&10HccJ~o;N!j%1;Ct>r{&6esQ8aoy`|?x=uf8uk*!!HVzTWiT99Y&`Q@s6)YJj)j zWK)jY_ky`MAGD2_GvT|b*5+1bslBZ8Tr_?Q$knr|9KI)UX1n;*DXoi4%1od7+a1~_ zUH77G=9KF7SFKBLoRTUqi&$@Q>0g@lif0Yp-P4YpKKQ5l*xx2Qm9#wJ`KRWt5ed*= z6q|LrJX?mp`}Usl65T$1Q~SL-wS2#=rn~frJ<0L#YtG^@E1I=1x_`sVr4xOv-&~lR zFs)~A&!g+IN;;mVpKrf^wZz8ld8dvH^WBn~2fEMmY-*3P4H30+-GSt z{`a!WH~tYBu75P#OGb0U>!ULTUQQJ$EqwjO&Tm%oWc8za`1~`^4AnFa&W(!j z`M!SkB9)#Kb{ASIcJ7aS(<*bfX$8N&RGQiz=BvW*e@_tf-zTFnpHcV2ntjU-r=^J2 z%vHKxbA4rngYVoomo{(P^_L|m*GS0z=suyJEVVaZ|6%m-tN--A(N&hgYk$>u*@HJe z@3p#8WTRGl=&kP37Tpa$Wlv5?)%aoYu|?@Xh{KB29Cj=P`~t@3&;4upUtu}dbnoeN zd*^CYc{ID)S1(j?HBO!1D7K_1c~zT7K9^r>(jy&fzQRqxk7n0$m~$Oj6&P=EeixVP zq+;!+>FvTFpR%&ta?wsrWvh6(I*R9X+pXk-MS2075{o3w8Z3U7Z&^N7R&7CR#{K$p zUVGN%n@^cud7HiC2>a{(+jV!uCbhl))80R)KH1~G`=jta2VS*g$qBt&CoJX_)@r6C zovskv9Vnsbr15W(?&A~tRSj+*>l1s@Ju%?uiRBZ{NLrD)}%=#BN`OD9(Ha8Q}51n9^na{pcuwee?Uu$Q&-(1A;$F9TX!|9*Q$G05K zz3QmCLD5lP=UR-z@tmb6Zzu-nD#aiUm`M$&2`wQ-GP|W%+o$q@wH9YaB z#N*hnmVPUhS8+;-x?2mH{awHH8vl=)$yYuX$6Q^_YHe#Y`}v#0&5NAf=gy95{`7Z( zT=dhZ^)*S4zHhu&F8V0v$KQti{V9uozGscTJgw!puKuI;=>4AEm(tD^>Cc$_Sz%Yr zOv8gd26Zn#E<09L_}~wp1@F%^w;zVQ?#?_9mQS5{s3&JdA2J zzxnl%CP&e^#Gb?djvnjsocz~iGu!6s?c!ByIGg^}Ou8F5Bl_2*%Pv>E^R|^Z<%=xv zlYDNvEQ6!|^uwiI!3x{img==1^*p_Fx5~Fbj-a60zZ(|!T|Deln4H+k@&4P%Eb(~{ z6g*CB%03eEdi~P*0*99yOb9l6oqeQ~O}Bmj!JLS2uX8saMg}@({bf}XyqVFvcBu*H z|J+H62Yo(jXKiPTs4%MVK5ckq?hBE^K#x;~NA_?krRBSPvn-Cg_xz~O@n)Ju45*W)a|f*AplIHGfjvR(FY|VNWv-Eje1@@xmu~p)KE( z*5rSCR^7i-P?H|`s_G0!OC|qGUX~3d2eZ|$M)hl*i~Cp=)y$Uhx%~N*zJ|$xa$j5c z8&}`l=XI#*$zHjfS=)MVxjgtZFKg}>?uzClrx*9<|G0H}F3?`4N4YqX(3> z{58MgoZBMo7d>IIzvZ#N*XurBTlt{=kJF;F2U7MfnyNBUSz5GSP12??;~5X5=PFe$ zJL4A`b^AZnnk-ReK5@og?YRT*&A*I0G)g#BcBVdxU%j8LCsmu(;(~Zu<^_GFwJ|Fb zYbX2Uq>Eo%D{Sqh%fVB%t@ryLiYgxW%Oj_FFMqzgOe@;;M(pyCv-@(M7unh^{dnr6$^AP=8s-G0 zFwylh+dj36o3vRj1gl*6HQ9a1W%G}IBEoL6BA?37*IUQ)m>X$rmt?a0UjFRlw3OTh z_K(_UztiMotlRs_c#iblC8fPgo$-e%#C1>AP6}6b^`2AxFw&p%!|rE$@(wFJdi$?5 zO7BmY+?L4F$5O|nf8Kf^Hse6R%`=;)?}=NJp?7Jo65H3jJ-3=iHhzU%no@^bFk{7@c7U5#_^KA5ZTVY)nF zSN)0u<%_lyFJC(E*I&Jzdo?axla{{Wnr8RiFVib2sbOVX<%F-g9x;;l{OMhsbD*Gar)Wy)xyN0>CQ=5rleaTG-Jw%a^gC_h&Up$=2XvXu zE*q@RQ?8g zb>H8|#yK0Tm!Enkvte?h!s!6jElYh)uJKH`?f5T(?@HDBw|bk-##CNf$C~j>{+Pg* zm5y^}CM`Zt8a=gXhv>X(PNC+!vLPqUcZ)sccC3B7@!6)p+7$^tx97@Cf0o+G$Wc`r zGc7f4$*zSOdyZT@>io6-tl6Y*d-m*I?$c`Z#vzke=F5^pM)fzXSH5R@qrCB*#3ZvcA=KlP^d}i5KnVzK5r5B^Z5(Dx%EAe$UVlMJ9YXkZP&WcPko*)-K(|kY!Il|-k3h=4f|rj1KZ}l zI9;HYrhSub>7J+GGbbFFG$&!+7mdggN$optTX)5+5NA9cR>+wzHCe*ZZRL`hb@xon zpOm+Vg(O^XmMzbky(yeCqoYd#kBtUZV1&D=$7X%I}V;|K}q6^{na(DN#-% zO_sbZp(~CWY30^kb=JC`Uw!NS{h14UPb_-$B;C5(MB3Yottm*ZIrvWYQE~6>)0ZE& zJh(KgTb>|XN$sv<=<<_?!mVf2Xn%H5 zjPdbd^kVoIR@$+5Y1Mrea*2J5hRxS0qGjKex{mFAx~Fi?wB|cS1ujjD4{}|Ecj!q^bXppBq`U9T zi@W#uB)XF8rpz|26>9&{Cc3AkEWo8&X-(0Q6NSfGWj@`Gi8L%P$uwe}eDLc@0|g25 z=T!}tT8z*9xxDVj+z->t{>wYEoSJy;TAF^m@nf~oTcLit9hU0Q<5AHw$j+Eo2CkoEbLuMMXy z9<^OqG-1+t9@Fg)KOWuY{`1f7TT>Lh!qa~3)!LI%d3PJvirhClG#7u^HQiTfrpgWN zg$tHEs6JNLBXhv(;oo3R^^IR`4WrcNP5xKEa|REKe0N32)2glJqI2&4o3nlWqpTx! z^Ow9>zp|>~h4AZ}jF&%Z-duZIr}OTc1>K=9`psmvD4(>C+JE3>@6{K9PYrl^-ZE$> z#w_@&{$aDH`=7~w6-;auUrfD}KV3JnlY4vq`|3F|?DpwJB8N79ySid>k7$~vbDK$t zK>4)Vmz#`2JDiU#4bOPmViNUIIx5aE{)-``V=gKehJv07izs$H-|Nm^4js1bT#Xmkt3QwN& zehnx4s+Vlh-yTUy&06zx?IY`1m*k}_mRxoB*XgnCDr)3%2=$v(;AUn~#!$MTEq=YP z|NN;k;xPw$zS^l>uvouxtD;E7f^XOUG47Ueez9pX)2)p=W>w@K?U>K0wcLF2vLB0; zB^7HbU1J>T4URwE_AGX)XHbe{-R0K{!;7Zq=6-tKn)AYa=7+>}3euL{RSMgc4uwzq zT(Lk`R@$d(F00%H{s_aJi++Ar_5Su_qx1e`#YH9Cl<&(bZxLc&^YE{cZ}@4~2mQIB zLGK?Ou@YFe-z9OShH%Y_z%9+?cO|F$w65zq?zc7I)4uq``=T0CZRWbWYM)^>VU7Rj zt9@6?H1!QbJ8S3UQx1wIzxAexevc1XRKJh;?4gz7!VB*&JGJO_`KRUgH0PZ=6!4^L z=Z)`+9vIvA{Z{C!@AlI0?d^QXmCP!@)fOt`9vVOA?vCT^cSQ~bubuo#FzElzWzDI7 z3j=B@z8^nuB!1n5oZu5rn2w!0upv=uT|h*`HSeed+2`>mR&tvkD0zDJ9Z&r4DNVgq z$tiIswtYX&bG>s?yzr6a=kq*%z1ctUxBa2SV7s^G+g}}j_%-0p8+~I91qY+n1Uc`x5A zpO7ycuTEPpQP?$^`&4&-wc*DV>rHN5zopasEJnO|b@H2|J`S}7Z!O={e5wE4pD=Bs zioU78qD7`vM8CFp*h$xS2{EtS489!E(NJ`qyLzj{1L?UE5{xbUw~eOl+_>V~y_PK( zq*gYvIBeS~GtK(fDTfF7cRJ!&D*jhndal`gz+HW1ZDm8`^MqIHkHv4Amg%c>|Djc4 z`Tl46&y&l=FD~qh(2@?=9xl-FF6*?@2hDklAMr8oSzOHPBV)H`k7t*uxt z)u#4D_;iri%KywJJX=K%zn^$(cIK_q)1(*<`LRyqmoK?nvwXixlUv`U74ukT|K#&2 zT&;6!M#z-kORME~=46FWx_ouXf$A@=6FR8ClcPVPM8=dB`3SQs$ z;@mWLXXW(M^^f!GXQ@7OHsckuIeV(||B5?P?kQv(v(;KDZK-D}5|%nEVtwEOpUJwt zo=$rg2V`yHtaZ%)n7OBPVM46I_2V2%R3^R(>760MTc`JTW`*~**^{PkQ7Nd~`=w5L z%|DCGI=>H>0u!!ePMg2VWz${thxW@?wmlA7l_>M~29u*pV{yyu`k(4c56@%Em{h6y z+^4*IfxklD>P43}*#&G?yv|*{_;tqlb?s}jJm-}LhF;J&l4shP_QI@Mx#3o0@jYhI zva}Uk{!H8j=JUU1zV2CKv|w}UvdHGy&;5_QTYCA*r?~UII;E4h?0&(MBr$z?KwtIJ ze$OwzkDYpRHZjU&TD6I7<^1(?>a@OxR40{hQT_1q_wm!AdfrJU_ojZmI-zP7lgz*R zw~v_H;?|Re9hM3eRIEOPlhF5f#1v;O@MU+q70qO-IA62;=KN2~&i^WPiRES!Is?XHn%xZ8&L z6MmJQ51qk%W#!T9g_?J)1MXEVUTPb6?WB^j_{RO$jpr`$ZdWh*82Vd7yJm((sMPx> zr}nOUZeeq@c-5;JbDDKtR5J02HO19!%Jj^iwR6_{)uNgg6uk3}J5Lwak9u;Y>g$G` zFO#h%DEtjN_P9^R-ri@g(J}d^r9PjO9V${d+X|NmOx(-+QOG2p-I8_R>eqkXEV{0` z<>SLQ_mu^z-pu`L(X*y#Vzj|zzWo-7N%MpLWqIuSx_jSd&cqK7o)y^gKXNS3IJnSw z6(dvlmev&u6<2hhxOd>>$|LNuWocHC42KdIc|K4x`1yX-{`8OUI3^#RfN(l-Zc($K9PaJvif#>MUmFZFAV(%FbVW=kGedD@zv4S7EAr)cMtC zkzKRI3X6ktvt5EaSId?5+*`KIBRtM(a+Zx<{*Bf(QTV6YoD? z*LUg*mzrjct+i~rNq2F_k$f|o#nB4|WoF;{z!UY^{M3Z zBVpFt*C+WGFT8f-{oT8B^vq^GPdoCtKjh!6YbWY%{GNUCQT%_YxQk-#g{zc8CcK=M z`TTg(lCK*(*1fbBGUr6QY; z=ZCyXOU=^x<-FYFnuAMrFW27O)^l$+Up2WZd-wOxyI;}{2=6b9I6T4j#BWCPqYs^Y z-@SQb_Qf%C;uG^_|8w+T`S2WFKFu@rmpsFd~X+8LvxjrPV=Npb{;y(no^v1O+P>; zg_TkG{6qQ6;a{1T9@wW8VO?=H>__^qm2+OmU6U6*^`%Pj_x){!D=aHF_*U(`xV!#C ziqoW)Sg&(8pY1H)E$Nt0yz9osr;WxhgTDUfsd**$>%xb;n$GNp4~`sADr4H?Q@41p z2Iul-Yo@w&&zcyde>81cJAaL2aaD_k$0z=%U5!(EB=(*C^|;_ZW3jS>?TODx)q0Dq zE@kU|*%Cd~ck)RtWp0~4_PT+*@-gLjDA;y5bDn8e%4vk%z7d#G? z74|O=kTGUFFLvSDt&hsZtCfEx)h=^vpK5ISm*>y@mf)v?2h0VwNQcYSI9+;ef2aAW z@w3QTUvtjgPzk&LFy!{trLR9cHRD?)@nXZ)q>b$j=dSL%7@8~cPI?*N)hzeT?8i?m zaJi~*%w~=8^RlVZUswK|x~lk4^7P%4{s!LBsf*uJ!P*w_@mpiQ{(E^-w%Xi38-x5q zPS13-_x{&a6tE*m?n8Ye`=8mDCw%34*RFnalDp!nJPnOvHWwi)`H%9y{Da2Ki-qs>hTfCxSX1s{XrK@p!S6UB z($m9nNs!ErpDYuS-Tc(P{CIgbP;K#C(=QJfgzwwQXTj?pFyAI^t5U(c@AVIkZe9KM zpkhJXCds8&mY;Vosb?%(e4&0us4eT`<7@t>S)UUB9&xqhYRBS?%0rE>t)3r_Ii+#v zEAOk>FV#cdnk62eJ&|W)#)UO261`habIr9)UH41n$g-9@Rq|^Y9>`36Y$r4OOlny~ zdVKlslahg|>*JOL&fZ`&@5cEl`R!}-S`o)lgc+x_H~|y}GkA`|^zXqvX%NI{oh4YYEjO z91+tqSef|lS-rQ|#lEm1bzWB2F;1zw%%7(Rir?ifnd=+SqOGyZph_`=aV(z0k{VUL2Zwpj~M8kIzp}9cp_Uc+|aZQ>Un4 zR!V6si%iASFUQzlN$fjt@7|R;6CNJ?C%f>bcE)yh&$N(%-z9I4SMPkbFFiov^mLc`4>tO9 zItT>Fo)5m!A@SAD&|7}a@8=tqCCFZMoTMziaQ!8tlkx4}Kev=5FI&9T@csO*M&_4! zFEuXAe83sS73<%=S6Hm*fym|MKei_p&pPm^$f?DqbE)%Jf60eI9~33OGsQLKR&lRm zF4vjFd2GoZEgcVw-gKR-CgCqt3ujFB`q4I_t}di2uKj%%>-QTUrkb0yd3j0Yr}_$A zjjz#cj+(YwTxF-xQ{9kDlK;AGdakSY?Avnp_inQ{9&erOzszP~s-AUc)|2>YM?xiJ z{R1;AzrGIkdepdmTFkq(Uym-i_jKM|&JWgMJ%5~8XB1vGZzw-Jp>DO|*1nku0&%%Z z1sCK!w%@;Vf8poKm-T(Sn4kP+Ou6JSOLyUdJ^I=w4r?CIbMfs-o|v;kd-@`|hZ1VB z%1?iX(Jm^%v}VTCz*`SMyojtX}lMuArQ^ z>FJ;3fCx6neYa;89+|Ep;n}?3^GnRik6b?I0!|9D^wx~a-hF-0kT2G3`f)gOJdSIY#w zDV^kc;8v?f1s4p`p3a8 z7yl;Ji^hjPcUSTVxpO__-2Z(2n}oW#LH^aB*kirYrf>S+UY5UB=G~G8lT=na$#WG; zC&m7qX45PDEa!k%XrG|nTSXI#NjCmn6X$(cVrG2V$~I>I6;72TmiKO4?v6ImsbzM5 zZp&AFd9q@QWqni2SLe!IGQRizT@dqP+5LD@;J=vEP!GlbQP%9nT4BfD{O{xT{-evd z#&Azx$o#vlWt*p-kJ(rG+b@T=)b%>Uj7od`fcOXTy=5khk$!@YJnnEa>^jsnQQX8M z<@lMeExc^{6P=3XCRxVw{A~T&)o-XgBk@F1_|BzyXH2u_2>*B3)f(|@lTEDSlcVzb z8mqrgHk=-?vG>WXAl4$y;;kExlu1N5MDCn?(B0hSQ%Jx84V}4b)RNv+^IRCv`pfSLqzJz zh8t`vPuFr>3NPu{`1A6?uF!Xjs{d*ie9}J_grjVZ5Uj_HQ{id|NDm9Z?D*`xsZ73KiAK+ zLyvh+KD9ixtM2CYUVR5`pE(*YS4J{Q{fJof>!NYax?1K+Ceh2`4?eHW{`6kE>Pb`T z)HgBFQ)_1JtarKQ%&>Kh;q*=4?^LE)woBeB-nVM!3RVrq>|YBd+N-Uyek7egyk$xM z-HoX^d!qa0SIs<}rW&;*>AGlaS;#-(+76AA)9z1vp1pp0S>7tK3a{whk`a+t_u7l= zGk@E5@_#nNc@3e1JB$s|=1FL;Iwz;LH{56xGESDF=HuCZk}=9=UhRr*J5 zL%igp9{K&NE8plhJmGW`YCYr16`B&X;(^&;n=h$pTFtNQlMb0>x1aj|KjYoC%WM}J z+nm?@59(U*Z+20duV46P|F~zFgZ2YuO zguPYajZ)LKXvPPs3wLjLbFDsmr-(%FgS~ zC!LXRZ#7!m{B);%k!twLmZm8wKMrlxn3L5SS9(bD;7K*RP3ehKZUn!3w!~X$(VV%9 zj^Fvf8?fc=(LX``2W~Z~Ow~WEeKjUcG|L#bcNHJ?|t5BP)vFMIXWEj8i zVU^dS6SvpSNbmiuC%9>q_mhRz8&;HAGIvjYtvd62g7?{sYxQYtIl@ynOlw-GemZii z&Y^}nX z&j&y6m#zpAX#Uo9X?mEs|2k3O2*D^LyBl@!=Ze+pFLc$v@ z#W_C*?p(cZezu=|hi~fgdmfE?wqLJuy*g_8J~=L7i`V`)LMhEL<5t zN|){bmUq9Mf*4I#{7h-kIb_SEg4I^?wX-r%3mA>e7XXNUKP zeJRJHlKyR4o1zfe#U&a0u&s|*$wb04;&OvrUB)_gq39)s+qK?u&t^)^mtJewUw&M{ zYNKM%9H*G&4EB7JesqaO#p~=oz-bsEclB#Qn8B6Mq7-wL)s{il>HB3JP zi=8gJ{Z<_0Y2w}c!O>*ft`&O6Z$J1R(WP5B;mM`nX}9jV%uziko_#KsRd1oq_nw8D z^4}NVyXQE4LGQhZhnzmI{}q$Gl%wdD&+3Bnb#`Jk2U(s^Gg*J?t1ChzAoa)+^s9~qt^yr6MecY!zANzC>H)3w^? zQzd*hdM*#?y0*h!V9oKTOn)zK)4Oq0IkoV|r?`HHpwmfA+zk~s8uw|i?chbI zmXW$FbkfxJ_&Yb0ul+x6aQE=<#8qo!=RMHSw$yCjy*B<~Y)0u+gEy7%6Zk3&i9|Jo3>h&ll9My&-*mHm7bPyI7f&{Iw-FH1|C?>^phpenG*9^^q^` z+w5OoUf_RdX3+W_x1JxkzWV>=YG3iH3+}f!THC%a%8yoYAxQbQf)34{jg$^;5y&N)s1%9CE*7S1#cFvC|l;F&Y#FE_0+;ygz4q;hE9GTbaI4^y(VInSoJ$f5l~@bCLX{s_RtxK#vpN5h<@?H0Tf?qz4ZVA&b+f`>lYE;uJch4-##?;Z-<{6BHfL+d zJn2sc^FFSca40sAN7c>w(9`e`zeJ5`LEh7Zt2%@h?+TUZ_w(DnHNW{+)rOGrs!1nz zs7(l&s+92L#gF@)C-;lrjEZ^p`JsQBa>yed#??1IEvFS#M<+t`ZYqdpQ+rK{V zBDH3&`ULBhEgDDP-`=xz{`}3}?5qnH9hkmX#^LwroC8NHZdv^+f5cM z;idJB|I2Qyn5*ym|EZvrM`w7Ug!K{c0-1@M&TX2O7<8-ivGs1@=Z`DzsjW@=_tmT6 zYSYPGrTg9nv-eA8s!G3+YS{A4_j>le519qGrn{W4I{AFv6IPj1huDKR>)W#WO{qT7 zbvs!3M9Q7H!57uEBNA162 z%j9=!$@0lQ={A^_n#G>7b%)no6+M+tl`WqyO^iF#xXtTnc-xFnmVyIkx5e;1@7d5c zzvofp1MSVclUC(NKl8yI&{{nMM@j!B(d z;fzm{{#<6>Y@=BC{zTV`7fvRBrJLv8SjC&e5_it^nZ5Ycnh8-AP5W=F%#wR+?KhFz z|3|Xy$=X?OcOQ7|%AX_MaO{rg|K(lHUMf!__+tI+Zf>cxSi}7Lrp#;KB(AsvB7)3+ zWEynr3S#a3WkMH-&0YLwmbUnt_W*Hvhob7Nos0t=fXlf%=pih`Oi{#oUaA-z;JEX~#?>gMj0y==VQ zjmqv#0m9qguRj$i?c-YYGN1poT-ENy*^lJ$jWBUgaM<-se-5_9V34j_by>&+IEj zOCM?dT6tgYFjMON?60%47wRRa&OK|D^h_&B_VFvWe`}|d9DbZ{XufRX&WG!rKDU1@ za8=BjC}V$M&y4qdKi=EN`N!lIY(9Kx)wvx{)+zCZ)MY=-Fel?g{)YA8oen_KR@XHJ8A#gsYE zTBmF*Il%rvuy{hU-b^#cy^~{`7yjYYU1aibmVxYTv-@>dRDP{mFU#TFE*I$iM~it% z?v?2Iy?vjuXUsX?;-lSpDK>4oz^<2PFDM7GYBpx9@Aj`aIC1NO5=YaxV=RYGtrkD9 zaaSv!6N~W{gO7sgRWD-iT~eF6&|sox>xLrVD`$T#DbzG;iO<;Gvan^%(qmd7%6~Q&?d0u#CG7n7W0k^% z28Z>tj9&e^{kY)jFH^q*TXOhwr+0|iuAM0Iwn=D_2}`rAx}1P(LM0a;yGT+|!MsF$ zy-#6_o-CWeBe?FLbHn6+WoDd;9LKF67H+HAYUC+Ar;2I2{e;{n9#3C?P&*?Rx_hpy z=#_j9Zuwo!zN{ae_LXV8+$uB8W(mj3Uu!=HJ=vjAnq2z#D(iHCe-HY<{w!uZ`$k`c zJAL1Fk(M;~^F1$?`fW)$9J59{mO&ro^uC=@7H|ah&v)Cdgnd2#M!<$GJi-M!4 zYm!7>draXJeWR0qKrJq4(+O3H(m(Te&rn%XGm&?$?1?#o|Cu~i{7KPmp4$I#@2_<6 z8acr{r(9!+qNKBLf;N2T*q5;*{Tz$n%y+&nw$qlkF8Rmj(rNH%-^xSjhD^`$rgW~K z6Zg)%_GFQ_(sU__$NnCZPqXZ-i>vl4kXw;F*US1ri~a>clU@h;+NK@rv(!(tPhHTm z>sCZxS9|$%DILpup}p>YIj*%$$4r;)IiI*`$-QTr?kMsFNIDtcvwCC&~MZtyisf$&b=AcsfJ-+!Vd4dEeqzaAh3(KWVu{i)Wl^Zj^;b zWWZMSP5JxEjw($)c0{bn)b`761`}lwlRF7)PPlG9Ol@vn*WOj`82R79=lWQQ&8NOy%f>GY{{ZR5iUS-?zpl^71l1 z>6Ym)S(e+{^E6pKk9iQ;%EDy(c)s@M2ag?QE?0P>x8fg*W|gaL%i4Wn?%YcrG@MVi zT+bxLCswzdzg?)|dTC1OgLv1O!6pa7eVc2GC zV>^SV(En#y|HATJHEt)%*FU&d-97Quj*BXIm>%rT6&f8RyNZq9roe#e2$nr&)qcXM3W;6%MH5#-NYT8T#p!~#pFfMMwJ6P8?2}*+bBfd7wDeA@ zOTC`piU04eeQk)k=ygfyE9*Yv>77S>GIzIVUCnv~{b(~W;uOuKq8W@@|D;dE&-9nlB|4=n60)Z@dolOj_}_B2W=(af>!JB2(i}aLT(Z5`%nlU1 ztu>9wPy7D8z(^(}@5Xe6gLB_9UimReKRsymgQtz5mOWle);&wq%2})>Q^vbvPPO=5 zZ}Af z=@wtbrV1v->6NDl@h2tQbh|vta#%R~McLh{%?#h0v)0}?)v@G^bF`6JqQpv$)eE}} zHE+E9;avaMBJmIlLs;lCpM8yIGM2y93q0`U%0$f$f93NM=JJ*nSp^NUfoekMGTn8y zs>{_^{ha4`>PPvVy^S6%ZnOb-#we)U9Y0+R?u6xHh#kep0X&G9oCDR z?N7$sWo~4e#TB1CTkd8{k%%(a@=H^?*G?%|v)lf1K;tX7mv@+tJ!(%`)y;TWen)oB z2D3L0Upu~aK0itAw31T7XZcfkd-dG>zP{tU?xK0Z)t%Y*^|brnjV3?8@cVy_&z6!+ zyVnJN-O!)UZzlLvDq7)WnBB~N-@c9`2l9kG|Ndv6F0?d0*Y(wHCi%I`d6-#Ozg^EB zHL1^R(}9Ax&?fgo6T`!HX3g_6YpZ{1UhtJ8qw<68`sSL`I&6CL4^NC;{`s{1^u6Df3&s6e0?R#XE^{L=?jTYOA84G*PbY6OW^2UinjEXN=w|9T{`*HB6m+e9S zxTZ{*lZi54-I+D=7q*G7DPP$b_^7h|g@WjL&E4`&uj05;-*E1lyFBxZTTR=YuA_1Z zV(FpFIJEoScLuq9ZhfMaYrQ7IL5g9{mt&i^p7uYzbkVuRZQE0%Edq^&PH&vbbmjWX zReR5GH(Yj3G5DrYd8FW8iwpDKz0p`{U+1ilelB1>b4GW7M&PPx8s|U0>nz@UwAo!R zEWv)mecri2fokrlI)TwHToqTCl=V24wy$q5xShwyvuKqq_crI&=S>0^H~#Km5^rrw8P zm##ES-D)t8v3yS8OvXPOWgka`97<7Fxv7?6Y9F}vZS-HCg>{k_Yi(c8^I>S_Iaau^ zh~f1d?Ta_^9+?NTElKG}X=aOAd#&$S+xIgEnpCpus;8`7nYLcyh2TtsK#xS(-5Y28 zYKmjXycu^d^HIK^ylqzIuI-jtOQ&xVNV<8sI`jsQ^JcDpDjfBdyJxvy^ZlmEqa!HB zbjCO{)bZihq%+dYdoLc_^YF?P!Jm_PQrN5yOYG+A+riy<{QF+^p51OD2d`Q3T16FZ z7Bps`7-sIeV_WJkk+VDI&HdJ+V7>8T>8Z!@dlb%#IjlXnWOKXQ6szc8SC9Nl{dn}Y zJ;#s9D_gUxa=7O!$mE7*W?ng7`^|3c>ZbdB+?A*19NKl=|C_>ZWnr7M0(MIt?6}=$ zaqz>h<9h#IPk!_H=S1J%4`2AV%APsqpyhXf@!YJHr?u?1M{%#3FmqCD!}KM$mt6;$2oBcuN*e#Khkxi_I7mnob+JEV@gKEGF>&@Qmho3yZCY$yD@6zwi)1U9; zdoinP&dN0hpPp6R&L4_4!q> zKBY?LxdC*JI_yI+?-@tw`YlIl9` zeE#}%%{mWSJafKV?mp)=BT{UJ=R+}{+0jWQ$F;wRfBaT>_~YW$^I2>^x!2g+Xt`fs z<|A{0b-l{J^qm3=ru@~l|8Q^2f+)Y>jd>n|lKE@$D(_B_mbaO%abfqDcny!YX+MwZl!olytyDUdFYvlr zrg8C_(6X<>sz;Z+J6+zD93t@~|3LpM(ah856>2oQPMn^XlRL+VVdjrj-v#aX7d_Y* zxBJiGO*5GOe`<MT^h$vk+{borHo$a&-W@#F`*m4(%_epfVp_&wA4&9+AqGLA%EXPJ=vR(D^0VT03mKA+Xw zB^&e)E0}N6Y}H&6A?TA)CRONVzxGvu$^q-bXRo(&F1l2}f4DVMqj}x+rCU9HCWgHT znecm=dSkH8U#RB1OL6%)Rl5e%oiub&tbno{XLFe24-a+A|%df0c+b8zoRmmzl z?k^V|&t$ht2vz~!Q6xUP(W%@1LQ;%$|$+M8=*>JQB1{&>}DjwFNa()G~^Z))Oh?0MbU z9ebvtCN{D90BcfKq_19veZY#BOTA;X>SJ^+HCd$FwL7kUo*{4A^y}8|kJU}-iXH1_ zJGxA`_WeMIYI?+$dTBqoYceeLXWy4JZc}-q=~ujDW$yiT$7-LnW(1ctUrrKzQt8T- zXyPK-u2hsi-Dl(0#S^9KdL;F$W?kODvHs)i`%kVYaj6yF$J?d2`lx|!ar|hm7eQ2t^UFHw8ytDGMx-zp2h8ztnzZ^X4Cu!#16~>T>w#F4r2id-PD=V^{uC;${^@rQIskish@BVF?wKFolKG9%P*Rz!mSu^4D zJ7qu4%RLJMelzlH%72-dHh0RagU#>z?!OKGUmsZ0mN-E&hyQ`rYR&1F4lmvo@oZ~H zY$)@m=`m&^mC{SgUrsgke-IgE8Z&9h?g=`jX?K*?&gpdeAa&ka&;QD7zVvOkzrWL1 znET!!WN)pFM~dy@e=TRNP8(G{{<-9d>Qzh8AN-AP_V8CSFLOEOdFbVf^}TjSHa~auUt53gy_33lzTT|7w<&6Sme1Uo zRJAx_PgU1nA!VoKf`A^ z%{;HzX)Z3RZmZQM$sJ!K=*`4v`F``#hwJvO{Gokvl?XHl8Bx_f0mKA$`F=hWq#)$^!%acacFGF3CN>sM(ss(!tE{wd} zzyF8~T+WuJd)dFqc}{=TBOh76S-G-sWD(y=Ka@yG%@c}vx170Y8cw_owQ zzvqYErd@2^Ute$h5_NJxonT;>xl`-Hx9K@Ay}S(8CQNhwl(E`lUw(98+T6M@7r~WP zsuE8lJx-TBdzksY)%fZy!~4I)*GfdMn8CPfs=0*sifG+$R{RVe!d%<_TI}+9!F=V~ z?rTS|r?(1&+7yn65$m{QF-*JJh zIHGlpT5a~;ML(`Kw( z;<#QR2LB$Dnl-*>uDXAWELB*u=lMe4_eX5czR68G zbyU>Gs6^n!i%ik0jFEjy*E_4VEu8%7ZhY9K&x<3%{9DcH{`{4e+2O43wcJPd%JcXC z^k(ob+xRC=x8~aW6+c}gvIHltSpWHTO!pSS70I&uldpd}8^v~Y&J(vK>mFY?DHE$b zZ}HyOCoR)|C(d(t|EYI*PTuQ%cPH|*F1DytSCPASJ@|^@$!GW77xkGQTrKdjXKEZ)r?+!|=n+bd%C=jf+xvls0>xb1a_^_7P1LeG_5cZL0y z&DxwE$KuM&@cF6GJu#n2Et6JzHtHA7`s{l6^bFpx^~&6Q%Y!yfFcz89a;#cy=F@yf zv->X&1umBFw^+FL_b&bu4t=zhOtQZK-J)Z?FdiPI``#({9>GjSl?5U46 zrusfD6?w_cB|Fbm=EJewlbYLhn(L`>SDb4t<$L@+Ri)3M_t?K*euqBlF23%}oy~Ij zR0`M4QW?u$)%>S>oX&k0YSuciBWUaDu5TrGC0N7+{gTRGpR8J)F>80Atl|6O+@JbO zZ|W~kGvPjL_g3pCUw2Ko!9oF_<5A~wI?Z}+dT|7p?e$y4%J*~5r&9@GlO}e*zCC}H z{X5~P-K%Yl8GgIY5xd=`T3-H}bIvlJty3yBr~K^gX-f|D&#^vrBS2@(mS-!U{|?QQ zZF0%}!9Mrz4M*=IGZ{qI_wFrgd=hEa_W!wbneVbIb|tCn*&feZZ*}6YGs~;5?zb=O zQu8j<^!+{g-CtP%*wSpsie*CTIl;ai&KHI zwlX~NhQcRnq3s^`{&qdvztZckTap4JHxD0Y z`oK8*)djCr8$=oQm>%22A9F(V@1y$@?OvC?obuq>z0MbR*Cls&e$Ddwe(!cy)x7eP zd;#|FPnVzj7W?vyQtE5fl{RjC5?u0!m>*3!{?efD)%ub`rj>`^i$v~y$-ge<_x=r< z8#hEfpXI$+H>J#W{{F8o8FQN3QnYewr-zBuUBA~Mrg3e}85zEggeR>T{r{%c@h>h( z7ky}2yWv`ViB8tFYenlnu3Rmjbm6t$x*1Ci=LL#b6j{7;yUr>${Y4wr&E2&o=JERt#*=jK zOq|01EUcvY;)WA%BHA0y`Y!lF?$@H(xfqB+eGGY5KdE!rZ_~nY$#nE~@Ka zV#jfOTGK}n4n>0l_AdmMNgQ|9-d38p<*V|Hm0!J%KX>^bm40yV>iNgd8_r^E5B@8o z{Uc{)2Fp@uv!L)d$t9cl?}rsBsj%4QGyFLyFgCyo8J8sVDOr)7h=_Z z@YdhgOP=jr@;KnfF`kmi{Ao&Z-EKY8KFKV1w1`pp?!JDz&ew3`+oq|jbR5DwDl~b5 zs!b0rNfDg0tWJ6JOha8s{S~1zw|?}|Ryma0+3TsNIC<6DecLxL-&QGiN#kgWb@n{9 zU1ChnCabpaW+wPQVObTw%YECAp6|;!@2~99Ke}nP;MRLDVwddV(*E;w?V18}&aP>Z zacf<^RdOASmeb}uc%gBtiE69TA|cM+_8lu(`of==<{W8WopCs-N!5Mx-QG1^7qlZT z{+V<1O3s#dkHVZS;Dc!;GeU5>8jS}1Mx3ON&muVfl z|9XZ_fWeaQ%*QToIe&cmy3WqvEmF&F{q~NinR1?^NV8YUNmO7p-+j)L%ipFSUh-Kq z{KTSEZH6q-N9)rT*FL-(GhZdPXFq?_XY>AIzv4*(EUu4=uRi@Lc))c^hdWDY{<8h6 zmbfo^x+|u;z4&9;GE+T?zRcfmV(#s~RP^fi0-?V*SXWB$Eb3gdsIAg9V%iHEUam`b zWUfDWS;63&7SnYugT>RU?A+ANcU79!oNu+^{?WDKOtja=JMscX?SA(P7F8H@q&rC1 z%GQyD5@&}B&x!Y#9 zUblLGpxEW&Dcy+8iB7K$X)v*@%`w-z`BnH_OeSxwNY9SR{c-{ECq*02X>8fOX?wR- zgJQ--=0Jg;Gdvgan=Q#-SE5>{^I#3{!wHT;uAfet-TwG*zUKRX=Cl8r$ZT}^v}8lU z;R7?z*f-suusQoE|2fuJ5i8ae&h-gD*EsFr{MeMvG~<@+q`0$JTz+(!hm_lM`lKIt z-h5I_ap9}i9XuhYPCvStv-{qKXZ?Ix<@pJ||GJrU4()tie(lNAX`e%u`%L+x$P=+B zI?L2!xGi6`gf=g-^3ubuKcx^IM)BEZK56nr~V&C)u)9k_9!T) zvc?H+(f(t(K=^sSfW)y*-&tSdcCXmxsFca4mvLR(XrjQ(RWTpe*fKpy_C0=k#owas z@3i+Fm?UZ}Q*@+eifi+>$j)wCB^}AbZ+-X+G~#dR9q`(;O24%E!xbqfjrA5`t2I4S z{@JKqZDjmgUALiddd`lYr_H{o`Cpj#WBLl!#Dd7=9h2PaqOYB26^)zuGREH9UPhc} zvGtBsQ`zq1tY4`0_K_7=NS(F0jcnob-mf!#L}&EnB!rpwas8@_Fi~whc1n8Jw4%VT zJn{Cm1v=8RuJQ%BPPl8P>ALmN>El}&g=}+=>DNu~Ggzg6VCK^~j}?{(P2ipXKw-s` z>(=I#8Ey4a(VujCoh*+oh>#0 zE27M0ZTo5UufGYic1)PP!D{zzOaHI32DbOl=gU`e1U@_@ZuQe^!I}Lmzdb6?mYp!2 ztISe+Y^&-5gMhQ=F4ovq+$y?u>{W>&%ZE?jpKfa2cG=B-(}Y|${ladiYY#sjh`qnd z=i!>>n<;BlSe|Su-*q}vpmy#0qOh`*X|9|}u9{co82l-?`%q!QY=t>8E7^FBB{qE5 ze&>4J)QvOAN^MiCnpwfhd#hCMt4Br6?kb7j*e>!QcG{bQfXgzDo*A#o?bqI~%6N6& z*g|09`3+8bEk=J1zfW4KZoX!J>&4w!*6L~^g>~`#Q=ey_Jv4od-dr=a61D1$jNQ{u z*6zsIxla0`NacwrMVpGV)86&YRr|F{(M-Z>)03HZt{pxrA@llrar5bu=cn#}#m=Qu zQ*+R20Z(4a;ntX~+*x_kZ`}U=bLY?2|LtXg0V)~SavL@z1YO*F@`XcZqt8Uv?wz+; zz1|d`OTHelOlm<}??EA-^>!z;g1KMbdCoM)fAyDj_m|yXyt`1wMo%L4NyJLM1@=Li z@wuJhJH0CNV+0GB>zvuY9QYw!G`mFl(q4Uyjv|wJD=b~svQD(Wv3}8)DcfIeKd8Hp z@dX=$HS;&ACryhvR*M-wZG3FBlt z6?XdEk7nICG2`qOs|Sx(wN5df0@|t6#l6dOPQG>ne{q zH=f`8uvX=Use@^v=Z9>@T|!H(7rC9hJi*%fjL!YvmZi)JYhKxBOcTi~SshpQdqYKn zjqv$1bHhbX7>6C79Q%AJ-*%NLe`L)vni!KE!d~W`nelM(mJ?pTeqDRowD5kVZY7sK z*P7`oB2P!fxGQeDF0^R#g4HRkuFEdhmj+InT!V$vvB0;Bsz& zmEoqNt%)%)&IgL$y=SS>{OjttrN+^TJ;N`IhvTRRbR>=JN%bE2NDv553PCwH3y}wJ*Ir?hAmq`zp4R;8aw{4D_8*{`n=HA-B zFU3L(*POjJ!6z;FOP+c9()DL%>^vuIxQv;U-G72ELmrMIDY<}<$!OQ%))!v0eB@4X&o{euU)kfgUs$@sQ4;#>#UxzjaI+n~pv>*|(uEan27J9vf5NXpbi?7aQ|tGavE_|9+{>`d4Wvd(s}; zxjT6uIW0>JIDV>;V|pEj|GW@e77!oN=S z&&2QycGDkG*+<2q3JW{6ty>&7d`vewH?!{Gw?i=z*DUx#71unIo3v}Pe98Q_9-Z%pV*3wBwi9re>`sp=SbDX0ooyPi@mmlM*|%_UUwq zFpiBKGcy)lzjM;3!lO_Bz?(VYPkr?aA{#gKe@R;OSnN#qD>2Vz+lp_D1^FzJGgtbo zvHFn~V1I`rkhRJ0=z(o_e7cgk3(q$m+xVgK_jKm#e)f-~t+p_(eInTwd~@+?fl0A> zIvIhbs&3LvPqqu6S~D$}L9n5wIed0%2Uk$wr4%mC+N$|al=A~OoKE3w{t|RwKW6*? zvi&a}ImBwdTzX`W)14;sm?_cb-%dC+z5B0T5G`};-+n(+H~sk^pYW(^~;ZHC%?Sn{T;erRqW&)%v1Jv{F$XzZ=SYL zEjP4Nd+}^H^?xS?Hs|e_r8%#nXXWvemshknX+GE(5gQ^A=yyPhZ$`zL<`36?CJPF_ z`}W)G&dEfs=_ZF*uJU(Hy4!udc*Bfk$9Z(c<5KG728Vjz>_0L^2fS{E$yOvR zt6p2rxp)1=J+t0NZHU%9Y18RgmU{L6N$vM9PGyvAbG~po>y4$-AFD;pac@n2R^K~& zwZ(uxFnN;CHCqE$eufMC7?+mTO^Z*x7Qg9u-iIjM~YFfD)C+zyo)+m;;N5?%J)YFa|`toBd54T~Kor1_aNO*XWR{~_}-V^{1x7e0pMALC5}Px>`t{WUPyQD7Z@xr4PPt^1@(|F*ztGwY;;*z8u$dzu`m08iba>i8m4S^ZQ9 z8;5jLo(|(|sUw!9QwoFaB0io7TvHo%N+``>vsuFtQ8|zNR11?kZvIJUJDzXcVGuq~ zC8|QFoK30=KkB}>=;1%xgqOF^y`4Kf%y>`VJTYM(hekbh zzweyf6O6i}HithhQxOEn$I=FFd|kvs=pOspf%8OARAV*>9h>B6qrA$br3j z(^%pYlikZ4HoKHR5OG>@EH}hUZ642lsSg*9efltads6@R3#&Ic_7%*$)c3VjMW5rX zSn}1DZ9SzT%JI67-(0`M`uERo`RN~bZdekxP&;(pyC!d|uBIB@u3uUa2M?7NL_40U zk6!Y;R`*@bai0*N^vtWl}G+h|XTQ^xN*l-o2XwUvQ{gV=$1iQQObr zZmW8)RQu@}DL&8l-Ocakztj$3UCR=?EI``hXS4y=;uXxjFPMMz@fTOREZ+CZF3tL3 zg3t4XqRe_XN{!V&yeRLKyt`hmM3gC6TReEza`j^iHXi=l@lC(axHawKnp+%im2BqR zzh>k3{fXbFV3&khQ}(p~s$r3D+a#pU z=gS}X+NDnUvG>>d?&GmF$8Xqo_}>q z-jYum7f-|}NX^>*GSDQr*q;|u*CAGc-sypmgRW>H6YP2J~? zR>q@W`kihl1hj86%Y9CJXEV> zYJFz9F;(sSBmP?zOKnewhObRqeeK)j$4L(^EYj^|cUZ=1q>#w3ct>dEo_5FDe3U}%<~ODq z|NZ;}&qV)NS@KJn?aR*9LV~Gzim$GA>z`P_{3L6t73=PvSN_q9ebtquME>L}-K!AP zzO1dF9p3S9@-q+87}7|6F)mlm4R( z$2Vx4o8xdU&%-e8V6va&&9q`$|BVsfFC9An%V0@;=E0T=I_G%TCDfd*P*+&U6V}=& zEb+>uXyMe^Z_MY3U2uDRq}rj|G>Q$>)Z!PgUQn>(lEvoB!9(Tr_{V@2YXopU3>#Bz-yigA2@>?v@^@^Nt6^oR6|&=y#md#;qZKaf|l+UB~9Xc>baM z=gBD>Q96GuLjt>=n5ulIO-b#)LqrsWwe(XGHzy zo6;RI?^^iFi!u`r9KNdmOYM#IiG4<EB zy+4+bn|)7d)}{RGzKSuEO$2*fmnPr;F!fVyrm+~yhuvjcws_St&hwa7Hq-aze_IuM zlZjWpp5kPYyZ>$PMK|X=wr{?l(*5SO?W*3PEg?1@h7P|Z@83G~zvyhhv)@INl#LZa z9!g|S%8|)!5ScvPx3zw={rA}$6qzP3yvg(-JmH7Z3Qzg0-VL88UTd^B{C|=3 zQAT|2!LxUYiYIh6{%iZ#!y<98{j_2)yOqImsj6$>7` zchur(+tBe~e}(3fJ9Ayn9u8}jPf-^SabBYHkfrYF*-DqQkMiyX?KpI<`jqHgwvz@G z$CS-|ndfduOwqZ%?Q*f_I>#TjZp~lfPtKVdWzXy6=-%`E(*)^v7aIAGWS?ZNB%ZzVN_KCdMSV(_{iQQ6W3v7v^^AMb z_b!X;H1CltQFwBF^0TK2C9dxodjA!#ObjkuZZ$J}#pjL8!G)`%(vQ2oy18)bCzA&g zl~{IEFMk&5vr7N;ebx|>{XQ8nS7QF1jp;l0a*^`tYrTRhoQ3MoURo=cp4)qFP2}YC zdkrUSI1we9K};j4USe52Pqx*={G_~TEr z%g!$h+RDf7Kb|>d>pYpsto~*;x)b-#ZuMhNNP4vE{<=x7M{hd3R@OficPBN(?27KU zx#7W`+LJFk==yg)cG9RVnftPOVV&BUy7tFY79ZWXXrIw?CAW2&^V6ngt~`{<(PUB+ z8aczgr2J3HmGJv>lvCF3U0e1pS;HdK!rL}zLQix<-TOLG!}Ox#92j^{mh0pvN38y}HJ9b*X#tfo6YjsvyHhJ3 z)~E65eLlYH^tG37?xd*jEHd02vQo&%e@12CL7|5p+^<3emUDG(;8-|yhQ);2KFpPi zeYS;q+}*nK&}N_Rb5=K`KF4-us@(H2E$*EBVDG}RdKF*$d_Mjv&Ax3KR~2%%pKIMM zQ@Xn7(Zm(vLJZwId2*YhPoCVJJ6kJ1-uS77(Tg1ouUvkIS9f2{3y@vJ)pF$TpLM5& zp09AxtT-?y?_5az$4P;b1|AxEtjjNd+4ajfE<7avw13&zR{q7__naG&)?SJHw64NL z#&22Mo|~s`%k#3y&)TGPrNT3*NpQ<=&*?3(W*QS0TA%eRH}+h*O#G&fd?nMaduIGn zQm4drOjA*}yk^Ly`F?rw>E6Om*VXk0vi>{M0GdwrZQ!!<~HO zLY&Le6-)MZW`&ak8cQcIi&-0dUeQT0sLC!1Jd4&*6j0Tngd;H2S7}mt)XW;t|;7 zI7OD(W1@5-x64k4e7E=dsrt{nl20G_yQcW>-|)K)GNJPAXn_(I_>?3o;Tg_ z{>gYg=!eRe^gXANC+**wmO0s4<+Ao(gPgkzbJxs&cqe7m;)c7|qUx-qois~lZIyqM z;=I~%E7upz7Vg9!3O^-I^`2Bd(dKOYH2T|rYwq_?*ZR&?JYyeJXW%|*-qWiKZ=909 z=6~eph*E?8y_lSem+l0 z-@eXywz;RstR9W60`*qe(@t-+Ubf`KA=8K-MsLnsJsl9nCb-pONtSxsRMEdh3Cm}E z%`y(=X_))2^iFyBr<+Qla*@-Ux)SdtZ;IvL$NKHEaGcz<6ZiTod=<9e&&X|^5Prw# z&W{-iULlLJY~@RwOlr+F%v5U57o43hv#&9Y=eOf0lM^cqH(AWL*DYw6bUWIxEB~14 z`sMF`Nc{>^cdR(PAv>b&jf`IupM}oHQ;F^olfIm8_4yU@OD}p-%L>-CgEk?5_usc~ zUq9j7YRx~|zkbavKCI1f?6HCSEKbbIrY^1{ls=a=&GZD(|OaZA+Qq+&7O#U1D0sD(Lh z@iA_Ujc|Mvw9_WsF{>g-K{qeE@s!yzhO=uTXP=HZ>#cld4Wq{74ZF-c>4arb1LxJ>?%o?phniGMt< ziu(ypE7|-1lz>pR)XqJhCT}iYmF_c9F~#j_zj8;_ysTHx-#Y(ZZcetNES#>JIk5&DKEB~DqE)(aS+!_&NdcecFFxT^ylXkFhqMF7(dmG=a9W#r=s@ox+~`c-B*&zCG(`^m0pUA{4Vpq@MbfsWr)6F z#ex`R1EtA9PB%ZrCZ%RRQf{={@%;h2%l12gPdIn(>Pl-`vg}ENN>*n8!!O@0ehSU6 zW2Jh*cMO`Z}e8>%=X(KJv&R4ETS5%OWQT9K1eAgAD#R0Tjb*-Z@Ru4{rg)l z9(VAD#&Gz%?TyZIu%ljBs&k%MCKj!8(zD+C8!WMSx*?~Z zePPwE!}ru~&S#C{pSvz{=HxnsB9)zUEPIxU9tzyn|Wbsc^dmU z+N~^eJC4{VJj|IV>@}^=IbyPzm3{ZbOHF;;HIw)kekjtlS@EPV;jpjTq6?RcK0mJB z^Wb;c!Nc1)?_BzRCo1rbINwWKRhJ5nO$t5d&ir7yV_@yj-YK|1bi2^wT~|52?&(%w zmkZv;UtPS(D{bH5oUO;)+kf9_y~^~ZQf1lPun4Q~_l*quB=3Dq2s^&=#{~Zg6JOM1n9bkhS!r;% zEZ+9uk>yI~Om}a2w7KnZ!jKXtO-?gWi9mT8ab zq*c`4W)!?tsQzxMXuU|}zrlsqYu7FDuT7d1?mtJN;;mE@Z^;jnyw_F5AAg58wUk|Z z`10Tndy(rZnxIRBslq+;~^PXp#pG>cI#=3tO zZ&AFT%H|RoGXI~R-J_|w1{|)EP0}AlZcToddG_Itjhp5RRCBeSIQsJTM}gkbt5?oQ z8!~;4lFB?>;+qn#-lk-^(^Vu<5_~O!hg)$1`O?IlKX9 z=KV387&*b{#5?8};;HAhT)M~*6WLtZy~*rSgDl^vi`V11wf9;HS!6RFofO9KG(I$= zM*ZH^kC`hwlzg%;#(Y};sABKdl%~|G4^?wGCx4fi%lxDFe9Y|4OJv07i+f41TkA<5 zF}yU()3xa+=OvkkT6bn}$nG)w-P3vFSLi&k$9`YR&i578W}S=A(VWin?4HldJd+?V zt3)%m#IJq38}EO0kz2dN*uQ@2?q8pxE~P$MzOhv7)GpgU3VU6hoGwdRe0sV|?@(g4 z+ec25W31nn?OkJ#_*F#R`RLa#Tb}=7aM$&kvf25^&&G10qo4ZXq@}Y9(n4bH*<{A> zZ}6MEU$5lz-YGZzesX@=x`FRhuF%a#Hftw(%qY2h(f7y-_2Y*^j8to^bpL!ket2&6 z_iPXQZ^2WpGMUT)T0v9?jzERZ=KIP8=c|c_e;q8yUU~i&OP0aZmLB{ zgj`6!bylHv-Ykv1#WHsJ8)97_x^uGhUrf4r?X}#SS!#Q^D>~vg%RF1ntJ9&p)^Auf06k{MpAYQYp?SZIteD2EI8)&{ zehD*IgcopePnKJ}uTxI!#Gw<1%rj>f74g|yiHZCDQxJJ`;fLjo7eBJSUSAhFVf263 z!4hMy%2|E~GScf_Wop~JlHo7(X>a(oD0l6@b2Hz+ED7XZzVxop@h6?RZ$6i%UOfHg zT=u5<6=}X_SS1oqc4uq}i(&D!eI;tzDH9+2$vJY%7IeNw2wn<-o&*Jf;3M7JuILPJ>w;64noFr+@4Y z=&b1L@=?DaY%Jxg@Q(NFAK~jKzV^L;x8zNRe*ASo=8YC#<(7ZU*s*ZZrcDu^*_Sk~ zi*UNCUA@ZWe#_hO$>IY&W{eHY7uQd$$_)@#`7ix+hg4hB9uocLC%*?&LxeapAkJJh)Y-F$N{l<-_TYq&Yl%Hu z+x>I*s@qA{!jIOT=$xaR<}4KI6#YQO<=wiBs-u@;Ug-Vv+?M}+QODl!6OVGaE|^=E zt!xf>+1nL&fBvzz`9hhC<5Zj3WRI+4SpNNOPj~h#`S_)L(W%ek8Vhe}dKmOyb+X`e z2@|kyU-X2dfuve@?b`ZMss55e)`grD0T%zmv8vm&h$EArk?ELkC@t zd|VQA{QsFy9;-+9*|xFjv05$rbobEP`UUJoYqsTfJ%AAOHmExVHzi>)+ISeWj={J!mlr(aoDPpEhO)N*xAkS=fjHb)h{sjWIm7c%RQ z-IRalWZz@MyH4!?nSy7cH?&XZ} zk6e%XrbVR7+`kx?HTBTi!^{_}aOd$)HQuQa~0>0b7(aO3VI`~I3IT}*lVZ;6&( z-7_PvvhV5@<*)naqFIrhsSxntu1o5BlJGm zY@3!;VV-d3!NKP6xGKFh=3wR_jGkiC(6+PD^4reEN<(wZCIT(tp~*{m5Act4~h2{A(9atcZQZj~w^A{(Xy2r=Am(5%hZ`v?fk% z!k-nN#0pP+=v?P{#wKU6Yx3MjX?u%LDc@t)i2Av5Ui93V9`iG@oUUiJNVgi@I=4>t zf93|!m4!>P-t2O|p>$#PrH~~8wsKAkKPyX3P5UwuOdYso?U2AOC-|&k;K&=>75At6N%0>#9Tz^QRr|63<=V&uUw&S)A}A z8%|t1xSPN4 zGtKz&_x8%K&#YKv`2=5`UBa9H@Zh_kPnDf)uJ=vjg*fh=`}#NRbb*xAx&5gRejRbS z;*j|;CT^>XN|fdWp?ig)`U%?FQP+66_FNJ1*;M-SL(cohEq~3|&OFBQL%q>OW&Voz zbVqLOqVqc6CM?YM^|wy+doFm`T#50~>?0iaKP*c6%RFuByuc(!ro6a!HB(&qa;voC zidz)?<4n(-nloSReA=QD|6Z~4eV#nUVOH+u7WeuWQ<4G>&lfHc*WDfUS;5X!>zL!Y z*?sZqelOWiy2w5LIj4Nb>f@@rK4@2%FfL*Us$#p}-qaE>^Qit5W+%0G#SeG*6$Y7E zzUb;a7W^aMbN@8+;L_?({0H4C%&zCN&9dFUwA#dc=Edy}^FK^Fl<;oh-}u!1o9Fs% z`Tt*R`iaGr%WL8qzN8*jEc~~tLupEd-lgo;{Iio&I+PzH=g1pHZFasBB2wR{cB z_1?4iGp8Ne!Pd7}`Ns_7{kA$!a?g3k2c437b4M&lzvO+=gXE{DH@%RHmerZkYHF;0 zX~{c_tluB6hX2?RE1mM^dXaa-8C~lPztb~jT%X*Yr+p%;sO7gH-~Ty5)-mok-uU`X zJ$WbH*vuvU#+5BBbM0T+9ud1JJY#vp681&$^PHogyK`53@!M6p&*jHy}QL@pYOqcMN;Rky=Y+1uYXil9xnMHpv_(O^x`hooVLTewzZW{^-fmxR+}j5 z&38ktseN_}o7=QPzbDL5kpkPZnlG6Z$~){b7h85SX_YABgx_VdNe{FRhW=0pnHO;A zxAYSBnMXITxO#b&ez$BN!`H_Pqm*|F-Ov_WDb^f#rQLPDUO;)-mDC$kVj12{czi6i z^8B>hMc19>S7{kuW}H5+_jnX>dlNuIKbu3pwL+|+5R~9I$xHq(|i?Q8Y1FLvo?IY z{YPN+x$11&$L3Ra9}xN%u7AJZI`7)f)T1Yslq_AUet4OvLy25=Q*Nu%mkD0Ejai1$ zK38%&xzgKoFCV#dl0}fSZszMM26eM^qT3`?c& zN{PC;axrY-o>a!i;PSqWqh4C!=jF5++MQL*yED4CXmAJbad>6X{aebW~EvEcJlfq7cNuDQEg*B@gl+ka;cr>a2g&Ihgk(vNb^D*pSlnXg4a z&GnW3YInV@3yi|2794O9-?z*3X3ur$AP%*ozy3!s`?T%6HhDS!SrKMtTQ2qN^Ec+* z4>}U_^~BDqO-ko(?B({CIW$4tHQv`CD&YOf>(~A3K1sj595FMd?D|E<2Oor_+vcyC z`o-wN*(I5!!tE1xYHiq8``%t?&iZ%r`&3nq9(q`9c7!K>&qT?1`KG*U?)NxtKkNyK zba7X?_FXn~;tH(=msi-`YH~Zux=lvR{p_dAx=hi{*9(;2dz^pdKV5jK@|!igqhBw* zsI_wL@ot8-3tr@Xb}ijo&G_5-uGfWX7Pm{RkEXQkdG_d?3nR0^zYY5j-W6OF`7KD1 zA?$!uIQxRPzOy+(=9haX@Tu>f_&@v|bMf03i4UB&7}Pi{dC6TU-!voZ{h}79&uiRU zR{NW$aUBy^T-ZNJVPR5AtlO8IGnXUJ&t*&q_3!R*C{#JgKQDKQXtLmV?3@?JlP*!|nsRCuFRq>im!a&pHs@5gJVCo9e_m=L#d zlDvrMrWZe2UoSE`fAgX5_9*>(>=hedvA$len|JnKB-8rVtUI+L;`5Ghm(RAC(YZcM z;6`LiLRQD6DMxs>eqPlp%in5xOsM4L$4!otZQXutpI}(MeVMQG-(5v#4#+*Un=LSp z?SJshv-i54c2r$Ax%sShI@iQ}{k}s7WM{LiUu7p)5$kjCSYxDIaq;WM7rf?bSJypT ztiz-8n2X2aORVydDxTA)c23<9Tk!Fz+1ed1qVfM?grs)} z{0e+{Jo4hHAM13^3Kzt`zO(J`{I51sIA=e4y2ZTOD&N}8{cP4yqT}F+fe?*`mj4vr82&riVA03Pcb;nah02WdcvbmxdMU>iFdbL5&yEl z&vIYA{-0Ks$A_g?96I`N_nWx7|0^FU9ZK3VW##JU-R9Xob0a53o}Rp^v9bMKUscBJ zW8I2xb@-)^o(MbnbM?BFt;X4mw=TaGF`l?$=6=pc-bTWK*SEi%v1lFRR1KeZ;y0o# zO53${PQI`I#a`8VFmQtf({BNj8@)3Y_&lGN7k%QK(09ot`@TM$zJ`C-} z+3FI@bX5PGGyatNP|9?+jm7iS!)6yJ{VX_Q)77&SeV+a45cq@ zuP^3Mf4yV+!e!Y(D=dtazi+NQ-zn`Iyop22$1>MXDNFHz&#_alfB*7)y>=n@7HUIRp~18D9TM0DJ9llBxHv&#ztr@qP0F9NrJ8L-9SSf1 zJ7m6Q0^`w(8~wNw7;SHMo%UR%d4@$i>iM+KG1J%chizVMeTCER$l|w&3oc&R>b&X2 zk^;{sk31rrZbqMdHHGSfcL=R6`32Iuac?@8%%OG*f?oVZl?li3;W`xReKX*+aXjk9!i;I&RtzPjSK z^+f^oH#Hj9+nc_9-Rkg&M{Cv9Q|z|?JsD0l%k-Si)SH@qK5UUzQLD4IWbyK0uK=at{_ za^btGxhx0c&RpH}_b|tbOIiYjyquC+5sh~5K7Me>io7JUecJIww^f|phPSPsm&0c8Mn&Ml z-!Anmev6bCp__B2m>zcaEl=!9`#oV_g3gQFkJ~?6aVr=cnw0ppboP|Z$uh~O7hR2d z!g=-b-8;q2t@@#FdR1h8ANaN5)+WtPB||MX>1j;GOa6zoaq2oP+qO+sqV$KtJKg3iv3^b&9j)tIi^YmgruAlv=>+KfWSD<2sYaqvwmj*zRb)48kFF=3&E=jF{eTfHx3PJDIDlzrOs&puv<4j!NSNim&Y zc|x2{Mq;?tmR%|OXM|iE=Cw_@C-&HCgM7fl4J>osMI5%O_?GOpTX)K*sjBVDzEQGU zPabnQI636mlsA*re6&Tdp%BDoHbWWs-`r{n1HH`L7)hE^P2#A^eId`F}v`cD04JXP)hk zn$*5XEu(S9t+)eE_H0dN<1Bbk-5ydsFUH0pqjaU$CY?Q%{{qWGS-Sfb^$VAO^628- zcG)S}QhVXny(f3Y^3?8IePu?d63gkY*L(lp+LHWWisF)uH5Qz^LjKO(x=2eyg=J5t zQPSb5Ely`OZYrsDU2k7sv*Pfb(*EZUd_oiW?6YDR=Ow)LoNbVE>S@d)PZ#lk%QbVt zv^F*gBpWT~ja+=%XwxI6-!FBQH#|F`@z&x_y~?a(L9cTS)|`@xF|91~d}uT^?(E^` zMhAbyiobc>AM|)5qk&%dI_CJ|#d04m+(=0aOUTe|d%Eb>$0n7Cb21y9tp7~3!J=F0m&R$eMN-A%fz@-ADT zbb|K#t2vuyWC>WiT>AQIR>XemIc#pZJ6C_Jn78bh#i7vXvWY6&tll=vTQ+NbB`<$U zv(2t2KPSK5^XBd1yy*)~49{gBalV$N$a+uA;>U`>Xr~EIOAKmWIxp|(QF?M};!1BT zHM{-qwmcIrQ{K2~Uf+yIF%}W$`WgI%j#jX79K4Y4r24qsr|_n)<|>;>3%Nwjnk46} zdl_>ixr}?WX!5Um<&PR!dQ)%QzhAP~DXOUZ)P?(O30?KQN%!BdSQ|(twIl?sY3gi@ zovF^gA*bL>u;#P=HP71D9WAmcn}4!Iv0$;hk@L=k4(rsD9ET?@tBBg=CXP|OV|`NTdW|W zdfOcyM(L*)&L-@f`RecfpF*1r3K{kX3hcSWV6AX$evtRYo9hMtCAmr!vh;=LY&YdN zK3OZ|_dC9QdHakHCls%|vDcwNc~yDV%uUnY6jXfwmLj*MiE+-#Cc(ASekW%iUBIYv z@ARBag2$h;-}S%Vu{-$d{Wrh0ocaDN@vXJr`YcEBl-RY@ujemyhnfDpcE^lI{zvu8 zCE}mX9qDmed-ZDiq$s^Fdp>O4uwd#k>6f8y8_qVb`Z(cfiu+}b)4$BT)4I0KyEo-K z?~^y-XTI)`&FT9qXysmVZIOA8X$)(j<|XmderKjGZn8Od&@g2Z>+82)|2$jk*HgBj zh2^V8@aEs`FE8wzkha6>NZR^!0jC}puG?yrq_FOWYPX8V!I?tcJZC%3e@fpe*Ym@* zJa*x8d-63ypI?at&m@|jl-RjH9Xg3=Kr|DcsFmu zKIh7#Ro3a-d9QoiF`HvzKIPaAIFcr*Dcz0*j1@k?>mq%UuSE?kqn5Dn;d;IyV z=MOTkdzxlEnWgj~Ql{oghyFueU%4H^PW|_^xEt!)zw;^Iamv5IeQ9>gRlh){giYbX z%VeT>o=#Bo&Tr7Su+%6F>$;@(YHnaYn@x94sKpnz{WCRrdjkIcny~Y<_NV%q|LYxY z&TyQyE^Nn^?-4Ka&fjk-s{ZW9D41+sA^kq@^R?Wvyh=+S##`$5R9tKh9`rt*?G?2y za*x`cX^ItL=k`qPDmXNC#dC#{Q`cX||B_{~F76hYy(olTEqAwNk@l%=^FDhh@2qmq z&Yd{1*Z8xI@v&wV#~Euvcc1#aBZh;uJSgzZ;xp%~y{^li*yg-n?!G#!^w!XGJEt7p zs+ylPd(Af16M`%=c+cK0Y?6O|+Ir#q9%F@d$=%s(xgq+~{y5EUT*0z+iGS(LnISU+ zJ}qwE7HW~c=)t)^M|%_>&U)7!S`&G3vG*dL6aD+N|MfPcY;={-UDtP7N;_cdIunl7 zmNOKjJA7v}bEO;H_bivvI`Q^UPIwu+wxs7()5j4rUPtzG-8{6WuI7;T=DDX=TiJi^ zjMtMo%2U!%yYf%?OQ9G|R^`A`tp%5Nyx-87bl&5W-gX7n4A+49U*`G$ZrEAXC%VT~ zD|O$R_f8l2kKXNf{UNjYs|R!3YQ}y}QwuFl#(Sp(<6_owIofJ3NYOjvR(BE(x))K2-!V^G!BuiMvoZ~kw$+Z&f}oMRmLlP@*=*g7lS;9s)3)h)Y)l%BZr z_I{eh^q%d4;XiJ(UvloggMU9_7i zI{EQyX6z&pQDHe}(RR@-`42fXzsR32k1P1Pv!LY0#-shFefO8>w|-); z^%X7AVVBlrS<_H7Kdw?GNQUp1T2Ff1Fj*U1oUCNvRB&-u$Mdk2 z>k4*!Epd~2*1WFruGL3{%k1G3SiO1quLL;$bM3znuHju`UBF{qe(LU~>D-@wF1CNH z&nmRx=!qZK}<ol0TgVX6F8MirDhAfM?}NH~yt*#htnv` z?4Nyl*QzJHLSj)Nj881h+P6>PU1$)P)wNAFi)BO5)_>Csf3$p2Zw@|k`m^iW2N(YF z?r6Dnc=OMIb(2;kcg*CJS}SAs%KF(fmL+Q+S|)Sbzq$D5VS<**ZZ;>WZyD}A$?N5_ z+V`p2pAd}M?>OPL=8vK>-rJYgb?lPdvY_YNVTb8YbgwAKxSd~p`F*q0uNzC{53cO$ zQqE=2s~5ju$^Y*7yhy`<V$VXt=8HUe)HgjQ12(=d91M)rRO88lK8oyY2AtO$9S5H!vLTJ>Y zC+Ct@=-uUBs8{$li}7PxQozTjLB}?nUfJ=kWAa=-lWWV1qSr7KzUcV)^~=lZWw-vk zJ)`=X?l;{o1qWyKg`QsMmBcgqebc6<2XlUN z=$~#swUQ}t)+bisTZ^6t)X%te`IWrRr_}npJ?-h<K&H;UX)u-kyA(v)&(0xZ1|l%({Om@R549@7=Z=*BwfX zC(exS)tIz3E`?K=`(p3@oBTyL&TXoZ_;h^Px#e@0Ecm2bH`BAnZp-_)#E&ZVwNk5> z?dZB_;*@<~w}m0&!D>-)|NJRa&#n~=I@BxDegBW+{&R0<^RJ0YoJyMgN9A&bpS_ztTyr;BH^++8`+DV$_4|Wtm+0J-6{ux0 z6Q5-I_UyGMf3+I+L}iFo{(M=Px~KVZxf1UMk3Y5wUrxobuRof$ZAG*8W=RL>s(h}j z*9%Nu2q;9gwkb;pueq0UBHZzSoWgyFG%gR`%AR$879YirclN9QyEOM$m!^iwB(dnP zYm-}?Eh{(wFF$vEOReGOeeLD>^?80h@rJ$P%J;wWSjsdRT({t7YD|?}+w1OhF~aBE z#HW4|i%*2!SysnB?b~Us$QiHY_IM}B8pm!}J@Le%_mf`VQO_~H{O(M~Zl=A?E=wyq zL#+J8We+b-et2H?xpZ1>PfFj-2;)kZzh^W2Zv1Oh{i871 zc){mD6VJd$%|+jfk1y9_E-Rd!9=bSgL94pq>Fo@+k9~RL=e6>{x6bM`jZe19>>|&f zOk2vze`BGayU*?UfgNq@@*f{vwrum&kczpsmu=efTl0RUo>175a&W#mW74-zCmyW$ z>oV&l<3Xo48NQj`{=B#1;`=$HZuW99Ur%n@&|j89=FUIFV#wzyAdA7R>cn>_~&U(8fU9X zP0W#8UcT|5h_}VV+eaTv%(p8#^QvammzWu;f7uvcKK`sW&+E|1PB~VAbqnTbm|h9F zB${~BROm?PN9CMA4*q1$Xtk1?6LuVW;3U5&`pYcC8650;&%U-v7iin5eu-2ot4SsBQKXt59 zye0OoF{nU);^moNeuzJn_|tme)r7+iJB|1CZ(R83?}f*C#i>GOIlq1-$d@a~Wi%do ztnz!|ZH2El`4n5lR(qcjj$G?p>YbcsQT*1u=<7Xu(FbP~R~P5hwBFbnV|8v{LuY*H z;`p`&=}QxDG__S0+|0f@ZMuwr-kt;g*V6xly_@_sdXj5|{Oy3ZUCY|sf0Xs?cTC+S zdtdz6zbyrCi!bhd{w#Y|jMk1br+wU2{T$TickU}>dF;7<@(Dk-5+MaFqD z++6w9V)~hv8CP=lWPa_t+#~p6p4y3nrhk9wPT8=FZ-v5!wVhL4THQVLdw$t$4xXc= zQ}lVehK0v8_N|wmlouWrkoo3oo+WMX$DjB9ZFY|1q&4FC>R~tL&DkfqYhlRQoidM0 zODc2^%Cm-Jn~>mkt_cU(9tU^qo{b>6u|WB1i7p1vs; z-C{8LW2mg-A6H?I760zfX+99_s#^2FwBJR4vizJmPi5`q&3&LVU1q`a1MS6|LYQO| znmOP23BC?^&Acpee$y6(h$x}8`F8WpK6WqL@>Emrv(~xVc&dIbOPtpNer6Pe>O-P8y}nSwyfpcVX>I@`n(TyJD_X}4Xl%-X+G zMP^s%ve>uf#;*Bu!0hLPNQ1vCLa$p`sp>y_C%CS^X+esd+`~;bzZWfi=OW=!l4714 zP~yZazURr4wjzOx3?I*Zw#++xT6gRJ?xe3X&rUmBDYHSYhvz+;$c)btmZ!t^Upk`` zJ^$5u1}l(w$RsL;Pt$lvVzAz`cO@wuy+7Jolh>*m{gJJi7O;E8ON z3oBbE*Rgjl`L&{>;fF@gy#pz2p$DEWdy@0@`rEe0@n7%z^zs;sB%3Xo=)=0Box$@)iX%yxawKHLtoD3 zOq4rt(C3YYy+r=^2U`wUHVd7Uoc6itk8YKw)%9;nnhm~RmbaM`Jmc$&_tO*g-k#gB zR(ERCLiMLMi(@mEDxJUTTgZJ-<*U_Izk~g=KC-@5$@BYv>W;&)%G#Uhm(n+VdOS;a zPffZ{dH%xHqH;GGC(RZ6z;@Ir{@rzDTQlxDi`rj1)+XMXrsTC>pK1cgGv=Q?-3=yWBc5_uJ)U7H6@V z?;dRS7uZ84Ut~^NP@i(>Uv4;(@QbHU6Y&+Fq!dURm(GFk{>Ny3VsMyTuNEt+UVDYg$;q^XFQ4*M{j= zLeEeBWwIbBi={*NkmxS;uDXRgo=G*7T>mJ#P=P=zYQ!cyNH%&Bl9k5cq=z2Qs zlIetL)jX%e*SY5&?GgUj67Lo~dDRDtv>l~YQn6iHcaE>R;mqo8aJ6{bO0DL!6-v!6 z3Y$a&#gE$Q3U&&t@chZ4ksPFXL%HMe4!OT!XB>Oy1z(VR8hLfcr10Ngu4z2!7JKsU zo##RB1?m1mtxAXTZ?}Wb$hYMskl$qa$d%Ft%-2^VY}k=kNK90Tjo9pNLi%HbxUru zv9IaRqh(2N^HSC?S>KmoCYrE6E3f0TfO5C6i@HUaMY3VSmi3W;J@;J+IL>dM!)qVw zrSdiYpv%Yk&kFmRR!d%S|8wxbif8*DP7svjxq3r3e1^Roqb9pz_2XU7+6CuFw2Soy z@0{ejl>2i3iKCx#ZyRJ8&syuev((s6yV`!QvlWr5l9*+ovVJJL|#RMSU0NZBR+&UpfD7lC_?wYwzupomOXszJ0vh+4ZpH zw(dM3UjN>Wo7+4b@}te79$ zv`FK(MI{s6e+6aDOt0fT6LDRB!W;gjNi6@0FAMCE-kKyX66}2avZ5p7mANzZMP~cn zYjttB>XWuZZuiIQ>%TiI_{i~!G`7s8kuRFV-!fbKaREa9LbaS6|h5!G( zDh`^ChwsC|8+UH~J{vMUEH?j8&-F#eRqZCm zEH}AoIPd4ZI+gR!Qg!a%+xuctUAQLKnu)jnRWat39bGZ?wpHxuV?9mDj4PD3MOcU5 zN|>vv^;?LmIx4z8)+zho`rW0kzN_}$X^K9XsnWG-$NNg(KOauqZNA5D^5UMH(sQn3 zkI#9xFN!<)wWd^W?}?x%n@{N22b_)EbRdqWQo!_w$40hyVH*~lcV@oov@hAuZY9s# z<(EWG%0?e-JwMNx-FY#)Y>vn4`B8ll!m5Ayzo`1GpIhYFt@*FMO7_QsxuMJ2JTER^ z>c4KQXr8a9#Kg1(6^yT)7T?h3c(i@p>L_26-L1dxcvl{J`sbHv${e?Pt&}rs9PYT= zwp)H`@{YL7`K$KVcZY@7OTJpN@JCl|Nxrl1@w6C$4ePQcRxsHf4`~-WQorLsO8UnA z=eCHs7SHvuyVTuq{s>pX+9)-nm5~QScP_R4eO&VDz1RP}eS&Q#`y9QuH^Z6lbos7s z(HZKSBZSLh9|y6mpFC@N#2&tI(Ws_~z<7?iy9^5+nrWZCHD5Vz!GWo1&m*&*?kfzB zQxn?gW2^d`R)*{0T$xi zp`a$D{{3>sEymI54f%odg(E)7u5*>#y_(AM~*HBtHv;WLI z;cp5a_cczf-07v$#G9zMTfO`1ze?$(&3=AuV%wj-Ki=~3j{PJnB{f##UIy-O!Y_)g z9ipy(Khu~Z<)AuUaNV{mk*+JB{I-y0tv#76(86|0+N$|vN`KgPnof6{aqZt?rAf#6eaLZW>zsyeZtXk)%vb?{uzxsucuhNdw_b1*weIX>X z#d_bo508!JoQXB=TG0Jx+l5o&|^zanc|*j_Q!J9%H%Zu=Nk1Qsk451CS(IMs@Q>we(|fh)4@5x;M* znOrR~Un9e=!%1LE#r5MdPu%WmEHab(tJ-BL%JKC@DC6^f&mYF3@ADd_{Oc^=qE->#aXHvyb0GPbc`&{wpP} zVTT;MY9HuIM2E}zOSPZ78ppotLiGPfkN;$|)UQe4k&-ljP{Jb?t<#~n#^B1C7T-rL z*Jj+fn4+2Rcj~X`BY7)!ZvC`DPv|*|h~34j`qL^!L`54`FS)K>yFq;2Y16NX{`KwN zpO$=moc#88o|FmSHqK}Ut3zJQzuyIFg$LbQQ(8RUnOq1Mx$;a!KE>qZ^zNhDD zQ@~6G2_4JX5hss$+>@Hjx?;eZDE|e8+XERr)ehy{TUAPMsXq zdV!}tHHF4~cm1K|%%wN?+nTS+A4~r3c^Ag8^MA-ewz{y@^JA{vTg1TA*|%MzalIU$ z-n67=ljm&q+_x@)J9Xai*&M~e+j_SuEy~V)zK%u13z@mD<+DdD|uNGS-jt!}m`#%)fQ)_=dRMCmiRisnuSyd()eu;3Q!2 z@?m)+>vfKZ&-ymsmi@ma_i%K`#^y1qg!{6+DeYQeTp3-0UFF%fLUvl1Q zQ3ThTD&vQ$ktOflLPQ?Sz3H8Fi72>*mB?juX_x)lB!Fa9#L2sa_=GK>mBxr1cW3 z9L*U{9d0}BwET#lR*SS?&iBXrN?ZGR1(=SX_AX?|{P$0~d79A<_lc{{?F|;1zS`(g z#kE$0s_16s-#?eSFJ8BMd6)B@^vzDQcE8BnlsEaj@fQs_ADh1($7*l?3Vg=kCGc%Y zv5_3_smltBt7i7~n`5+d>cp;Ic+ggM=wHIs|1LVBg}smX7fwz8`A_IGUwf?h!^DM`y1)OF z5_(@$Bqeg*XCec;lh*PDE#@zDWEDeq6&{`{qZ}AtHtA&l(T1d^w0CBE{2x|4WjndP zd~cAE>C3OZ3Vv5PO;0syPhjQ!_$WVc;lZ!$X}a?TTufrW?&PeMe0TEUv);OgPfHqK z>s+7BlC9|=R$QQL5z%aUUce`Csc`!ur)eUV(^3SFPi}Yj$a%i^)`Wm99(8pZcPc;R zE)39e=6t+N_EGg>3&FLP`;A4tUi`YWtaUP{MRxBW_nAU>43vfQDuSz%?)Lv#%NTf4 zS5*4GgU0(EMP#-1BA-mFwrQ{1TolBw?0;N) zA!yhBr*jgRwrU-EX5_?GteGb5cHL`&-RAZ4?e6T^Jn6ULfo|4c=O0bF$aihuPn91M z+6+7QGW~BmcIKnyyU){VYvb2#=U5V3yGVll-dXM~^R$+>d2L>B{uG~AJ1Spx zwE88e|9Ew?Dery7)J3}WB1K}#XUt!1-a1qEb?Bq@)=RpwA`>j^%{rb7#~b{VIpH=# zLU7(yH{Yk_a-Zy$FnrISxruRu=BJx)vwE&0*Yp-#-t@~PKbx<~v%?*;d|GNc(M5XBpuppp$uK>tepEQ9s@}e@)tT*x!+nVd5E4@9_Yzc&xISZHUg^6& zaGdh`$q%26cb2~>I5lP4vj6GootKhb&DsnqEX!=xbbp_I#p=eda=F;^w-o{&`A>Ut za0?@Ag|Nl3x^DsNLOn|=N)Au3>^UC5II*7L@HfXQ_l@=`-+DyWOZ+tL|QTv{tRkpo;ze#+#e|S%$By zd%EJwuj~519zEW2F8(D?~M zI7+?6=Es*sw{m|9I44Or@IUL5`EDw3Xlq@xX6Zha>d!*y%bG46uYTP(b>W4a!n+^& zPu+<&}Z{^x?Ir&o4%KeH=_PxtDy2!m?6YXZ%@^MB_@0)tL-NK^g zEHXELJrzn$74BnN)3#FOo2!@k&b@V6PJ3>)-~QuzH$3r5Bfki{oc^li7f+=zy_YG| zjoVcaB)=ysDC5@g)weSB@~hY~8N#=3y?xG!C2_MPk3zAD)@*GTmuD&pTb7*4-emG_ zyI-M+-4VT#ywjWBE$d5V&#F?{i=z7P5dHmV)L!j*P_TVD!h_Flh1@Bz75i=`eel6F!$gAMj_D}bBod`|n zpSS0rfJUd|blpZLy}i;h_g`O))Yx)JE5Bum^ZrI2mYUgsG^pB;&!6)}Rd+wfZ2RhT29kX?@=+LpXT=YTIZL(IA zl_9tCEvCf<`?Hqm{`=*C)YNq&b%yie!d(qA&oD3#AM@q!ZPw1741dtKw|_ShBK zuRGuvba~E8{p~{fwQJ63iXLK0(f3(h^Wc+&^Y>e>)0M@pa@7pzG&e<2|8nW|8(y2ye(eUUuy5InwxNQ%|b5G{Cr(wF}-6& zpFVE)SfC)tx^Mby4S~H)?n^rI=Kq?@qo1+U@z}Oy%5OJ!?t7wsTG)5>{NAI={J^7@+-f% zqIte3&(hi3MK>8LNf_o!$g*_Ka_$S*>bzLm;+(KJkC_$z`ngCyCtl_KcFRXE;;&lGzp11ZI!)rj zqYK7e4u}3rw4Y|$(`a%dz3uYTtZS2xT1>ldkahOs{nyo&#|3^_%}Osbnsb4ZLHLaJ zjav+l(}Ld?+`rfS+ka)Hli9b2Y29rHRMJaNhq?(_Xjg3f;^6v0Dp>Z=TDvuuu6J@R zIPAYMw#xNa*TS<`7Cwo%5vRL_>)_GElh#GO(=M`1?UFi^wYiR2Y1PB?p-iqB@>YgV z-GV%qIX1n!seAa=qMBy+tD+3o8D!-A`6TT3wTS4lS+Gk#t7YzwaC7Hcr@ssLXD_>FSo!vR^I|ckLrG=% z0$%&BRn5L6oVm(r8Ie(z;0Z?4sx6qRP+&iRVxV+;F|#XfVHLbv|Di=ETs}$-f#H!E^p!eCZip4=Zwd!Vs)F`uYVp+=h<~qrEXJ`f>Wlw;VbvP zKVf!v7930yP2TIe_GRnWWxF$u91CN6K1ZzdPLzbpA@1bPE%$DCux-l>DL%jFf6>)X zpWjSW?|Sl1DnPEOs%_4O8j*%6$0dzKj;;8UyngAA)Loh_uM|orYXr4=?N8R(S`ncV z-M>%$ePD{t=^g3k?H?uk-I-;WrL>|ZW>(qPKh8CBYV$I-c+P4MJ+GK`Dm2}yN?z+^ zP3qZ&&DL!GGVSv%y<1dH-iws?yuVNSRbuiinUuIGyIy}@ZlM0+i-=pAzf@!9^z$N5 z7Q59y=5Cg_e`n6()uEH(xAiqQ$E^5V!7X=9IXE-m|L0nLg$>3wvH^RH_b%uSNQJxsho1xoI`UHbN4Se|HiE~g_l?K zH^=-WE?YnAHrH(r-mKGnCvfFR|6;Q*dk#uTA8ttOkxmWza{gql#=FS-M#nbqbFY2( z_m$y_2RaEY5_699|6E$}GdMx{B3tl}+QxJ7J1&dd5#}0<+&`MwyWmX&1KnaW{+-1t#;hI<9qRx<|$_) zzD-GH?wM%{_qLfYrP`~`(q+vko7fo*;%I*>snSW*_zM3 z?emlPb6V0f^o-dB4)6SauWHGP$6;ZXif?m%1_j#LY)zl^M?dK)Z(R9}ITq$-_szuF zmM(v&b6s}+v{k;nXC!18uQ^VaJN)lvRf|HAaIfLi9dB%T4EF2)jJ%nqJ%5Y3MBCK3 z>92*urY1abZvHsObKA9DF5d(ddr~K#I(Txzv?9}=o-Z!t`TsO}WUA=Ja^zaO;lF3) z&Jk7r&#v7U=~ei}K=0K5RlXnQ=N_4Gp7oscja2y#xik&w(8h`luO~X4+Ql=w`a0wE zz3muyK zUO4-Kx?{thqRH`EO>6!xoZa@FtH@|aUXFK6Vaxji?*y%{zA!I(@$17@JKL*&=Py@2 zvUAVh-_zyp9{90_UuJLQipHdw-#pIkf9tEPyH)s51Ly89lM}p)S4BNb*59(BW97tO zFN}B1*T28fGPv;_v+>NA&e6})UHc}^&U*b>`f+;Sp*flhRhIr&O!oY8vAb^DE$*ys zp0NriD=wA?dd}FipyKp-#nQ4Pt5P^N7;Y;lozhllD)mHauU*)avXrEATRUeo$6w^v zUp(2lq41*8F1FNg&pX{$R6J&sn%%EYd)Tt=-1b8Z zlXlKtktM#>D?K-1#XM`JoCfRO0^wN((t?lrm2>=_-`;xEuK(?M1&`b~^*cL6n_~>5 zxBJI4)vU}Hl3TL4@#4n=n?G|1o9?LiDY%;Jgx8+l9ING`OIyN)IiFn;_HSj>wpj5e zSHb#J)*XRNg98aZPL2=v%&iIX|F&dd{plIK2kvbzzmyZB;v0YEsp^b#-m5+4Dqo!c zaQqfnQ|H-#3@{qxzgd(NuYeV|&7ad)+NZl=%!B_Cwlu!Tqw;y}up*(}#jMw7= z_gkgBl&0I(RatyVvyS#MCduY*?s)l{E&Ruht!fqxPrmja>Rz$`)E?y>TZ96Z|6XGr zQW*MW&gRKpjlD;s(_FfPKlGhGHgR2P`b@E3lF|LKOM1oH%r8&>o5+-VQpI?|&&9g} z_Wzf2NH@-#T6|_=NJOUg>DnETE^n{MGVb zt$mt*+`S`aY-d}xCn)hukjA{vC)dhszMp(Xcbc^5#^%;-n!k5_yTJI$dr$uz-uoB# z-rroVcSD!Q@k2?S0`J8gU3#`5CzCWbH{Md7qfxnfsf}V0o5u69V;v@Yc62$do#mfq zHccZse8$|x3g>n#y`ve^D=)pnwPC`X853Wc{7A}}5SS2XqCMl+WwV=2G09Ih#r=-d zPM(>*PrX>?yY;oVKrgJqojE+{PuTN?(NiB6K=Keg>Oov^;U-`x2rkxBrDBAaZeQ=xbmp5``=4#q*K0{J<^MV4HZE0uV?Jf}%_SnIR(h(P%)6V++u(aWRIvAY z@cO3BJo8)_a{Q(#PCI%>CO6rtVdi!Fu!-6iZU3h~W4%C`*O?KgaD>&T(IbNO1)#{WUv=lhj; zY8(G>dHy+D(aOdJRfOSMy`1#(|l^)Iz5d}_W3jCJ}isr$*fHHx9{M> zWV=s_+3)X4Z?j%+_IS&puAhwaf?lc16`mC2;oji7iHCFjOD>6;ZJ`{@{ihULRlb%V zO>Vy%-G9|_OS8fK=vDJqbu~5J%iEdd?#<$RRf#QZihq1|;bS{pvt2iOPslQ^-mE+G zd=2k4saI<&B%@3i88T`rw>UAzSEntI-QDAU_n(M)qQKh?Vh%41YI|BAiwM1R%{zZ& z@20#XV*cM0KWv{-*uN_zCUK6!tLLUTv$f$M*1?5Wh#Ucisuz{Tbe4>}vh5RN{-|{b#IQ zi@zKxjm!>IVx6xw&G^&5rQF#EPpi34|5h|Vvf}Lc1O#fxu7wxCCz$u2K#)~HsSs5 zs{6kLS@HfZsf}Rv@LtYeBIR#-Q@6<@$R_9b#ivKDHhlZ9!?bpNbJ;}meZR}Mo?G40 zJ+XqluI9heVy;i!&-1KyJ#Y}=vt1eGBgNhsw!XdkUy@FH_~x_}ruS(Q&$@G%(i@_E zC;5mZh`QaXf4}!&{Itj~0ZUlUs`tI++`t`dceY}A(X8A1#SJ@WDrJhfxpKdg{_IrL zC%vcX2mjg}`MD`kj-B57of-9dXUvo@Fr2X^@#n&6PaPigDu3(!ZN}w3ZRzoQb(7WP zZ{*cC&V14&uiGT)Z_@GUzO&k91(u(EUFE-(e|H_+_hPAPtF4^Rn*x>O<$I<|M=)F! z;+t@)&hFjD`=8d%<2_v{eVi*t^3{fFvxC$D7kwM}-h>KAih ziG8Nmu%zB^Lj1?uSMCWoWsAKDoUL|LQ*gp&2F~KYQ$@3W`rTP3RJ*-9d2L!bL-oW z%->)COIzEv$U@oim@w~NO zO0(H4J7W8!2DBZraQE--ymepqYRc|wEPGy^BpOtM*WIA86b>or4?b;ek zrquH6t5&r?oGv>r_u)`2ll+jImS+_Fpm(Rd{X~y-=YD#rY@hn8Vu?%l zv@7#YmK;cUoM8UgO67xA(|4JV_X4uny0^OgpVj#z)w}(*MFP`_D?hm>2A#Ycdv*D; zsVg&?jh`nKw&}%1WOXPUta@bUW7#LTRD1Hg*UL88imF5gge!b+v!4HwXRqp)xfiUi zWLd45bV<2z>hW3Y_U}KK!18ye-b=4P6S6iQTEyj4KdmIkQ~PxN-m6{lf48eCWCS^s z)ZKi4-?YI;c1mCB2J!u;?uDh63#*$47);va8adPDi0P+IM{5~9TrR#zb-AoL`?dAS z<0fyJDl4aFy0$rVo1bp>Jgv%hf5p;2pF=(`TO;6;+MKQO(fiPWTV<;{ivv2HXD^qi zYGulIscBC0pEUhs)&7)5U)ebxay46nyu4n%Xg3RZU@_~}zfG(WhT?+#?&h@*?y53y zZaQ?}k&pQ-{^|vx`R}&&-gmsV?#0LNj@kxOj_8JF)%^EZvTAZ4@5v0&j!&}5(Gjjk zC*PVfZ)=)|TwGD)iEGt;Sx_ZxUPf z=SALijQT7ce14{1e_`0Vx0NfR1C`E3M{F|RlIdq{Eot^4JKsk2q5Zc^!mnmGArP7&F_5_;lEZUdXZ^fLk%@n-Ty>?*4*fd!YfrzVk@&`W-%r}q za=sO;x^eSG@MA0S7jqAtVeu|tT`seFULMngzkFH!&%LMj=_)Ogx!b6B{!jk}=elPt z&p6*bYwa_6*cey)Ho0fwk7tR`F0mx&ul>ON?C^5S_bJmvcRanAdFAKV^(zG*R7sxy zlou(*)UN-EBkO{HFWUir*86jpT$OXrm}vFmvdGV)LSbhwEotHoFN^=G5$R<9*GZ>> z`IhIKtQEX(f))K2NHqufr(b!;6j@MvdiKGxlOh&ot9_U|IP1Nufvko%`X*xwvYF6{f~=B`OLkJOkDPti}#l2n@sa-YqE}bGb9M^zT&JX zx?=+)XR%ir!RwcqHvCjUM-WpV4> zSBIpeU6zWw=S`TCtKRY{D0petcmFkQGrzvj|6^BCAMA6<|C`Ff9GPXOjQAQdWbfUd z63Tfs(9Wne?uT+f-w)4E_6=q`1gk|$FclqhEYNF!G6Aqh~Bo!>Lm=Q8f zG3%{8-{D0P5~Xh!$e)QaQWV&mAtCx_+XBXmw?7=|{J-`8gw}np1uI{&$?uco_;~tO z&+5BMqMBuD3(loo*wuVuvwrJ&Cj%$*qzr=(wHCW(uWqi|FnJ&+g{7SHH~af>}B_sUOjX6 zPg!8VtH=eZRYnD7okbPbZt^8t8mBC5bW`~+>DJ@2_rSvLKCfi8-VXUy(_tH{l+rhHuujy=C2#NC6`aGyC9KnaDOF7-!%RN z;afAVAJcquhA~URWkRCnt!-IzcXV-es)zENVZ78!KOH?2!%l-IAC7{uSRgH<#_j+rHJR^zR8N(o%`Dv~BEmv}$sZH81;I zqEqu{Vr0hw%gbr+U(KKODXH^d;M3ntuV?Pgf9w+*^=x$zwq z|L*WJ3qHr0`$YYk#w#Dt-TW>37w5leyBE%n(c1sreQnh;7r8{~sVylxnF2l@OuJFt zJFmnlS#+I3x^Dl*IP;MEkETnmIb_$M`|#-lzm=KW-E7sKep|9i_hj;~lRcBx&&uBx zucOO-Ho01%ip{j7(<`}a_5F8sLZ%tvaV+dxzIA#Z;o0Q1gE!06e1Ub7 zABZq|y()niaTE&3*_G~jUU{pYS=m0stnJ&5(v>!8Gs8B1c)BJ3 zg>G}3*WZLIA`4Dt>4dY|Ww&srWUi~NSwGz-WLd?G;Jog$tD;JNGT-#@og}Lj^Q~ah zvT70YWtUz~lb@HjF8=r*p`DcrZZ!Rhv9jR1TpAV_-MBJ2e`EQ+%X8N}(O%iut;_rC zZeZH&bN5&5=+_kNO7VT+nG&_FMZlKv>iL}w;`f#wS#mClGqE~hGN<>UmZ$rEUSX1V z`n!DI!d+872cM8UKIhk2%~Da(BXSMXv#J-~`1kB_uF2_!bJmT&jc*z-zuMQdvu}az z_HxEO4QAz!94n@J=aiTpn6q~F`6+^x?URKccQQ@$c-eU7l^)ZU720cgm}S?hJEk39 zpe1J9%JA&=(&r5R)8BcV7HvGV>f4FucMrW)dCb*>Fijn_nM#m@PQoS(2YZRgL*5}}(<5BSva&6Iw-HspW# zB8|K9@rImXJ8f52v30U-@j1QaLh#nOrw1AqD7;n3PFLUnRTFzHhyD?5#~t zUS3W7qx+93M&YvCr}+uXUTUQ}x@9(KOc6XY_rBF@w)AZ&2kpzk<IU};F$WgOwVV;JRA%fvy8Haq?2?`N zm;C2`Jn~YZUU{d$(lEz8FFW?HU0UV8I>z}KL((;|C-u&0?FZ90Kiplq$^w_&Z@zURe!3M=Y{?BvNKQ+fsU7}O)@VYri4hHHT z?LN7M(ci&8j7d4&Df!&Oe@j<+&&oR<6P~g=L@d40_Q;OioBECCi3V={;OFdo=t=m@ zl(U=bTsd1;q|9)!Pg=HUr)AYO+3k`G{^YaUmgz8GWc*-g`ei>O%f0HyhOsRNZmpbY zCHgF5&a*qNQzc%pUgL3MD{MAP`ZL#~H2w7_p5DnT)$FFNjVXQb)h}-55ytO-7$ofe zNBW#S5;P%1rEljt{+bGBfs4yIjrtEQo88>=GD%O!FXrPdmP4PGEI*f0v*5d?x1Qjn z+vyeiuNO2sw|tY`Ba`~$^{%!yxaKWWZrMO zXI}KG-p)s+sJ>k+MC2!@Ntge5NlnhJ?|jt%P5l!dP%(WX^OLCurIsGKnPE^9W2azo zRaJA|@qnF1y=I!6MWuQ-#xYVYwE1hUoRJbUGh36$M1}yLO^F(;G4ku zBaZoI-#K*|%r<}WSm$@NZjMb(-L%c~zr4yzd9rpkm+{4~tN(Y1wLCXdShT9{ zhWnOHNBFi{Y>huvn8bMA#9Z|DqE{R8UQ`~@Ui~QN&a`Bg4_}0e?=^RQey$U?u>I<^ zl1Fjdo#m3B|<&-#3;bhq6V z?uK2KpR@09+TPsSaL1jU)rj>Ec@A#iC=g>O;GDR8UIH94E~@$=@6jP1?PJ;X(e{NsX`vR|64=-_zSqvmy6NJx*J=BTHNENw z6ZTxss5duw@1OGQp4W@7MGPF@SU-1G23 zB*I_v250WPJ+1{|mn^)rsy2#yF}nQte)e--w#$WIlRy6F_K`mEyI$l#jFE-A%0*G` z58?7EP0zyf|MLlGmp3Zk+I!QZ^C;t#)g0Dy?B3MHY)`TM|6<0cP$oUC32wss=bwIS z#v7QItS5Bw{i2jOkEJf9mFufpc*_^fdLj60%Kx2($q~2q?D4b``fzhm)P>Vs0e*k0 zOMcDmOA=rVTzp$U_kqWy`+UgQ}DR=3%b*#Pl_+D_NYttM-&#>TK zRXVGl7{nL9RnFpgv3VoE){?5V2eqEg|6iziGbnE9rgPr++iJSkH?}cs%sQ^LhM`Ah zqLtsv4Q4)E#dJ$=JcFK7U-}mM>iq9W= zymqzKGKX#7m%mrQ?NQqP<4IeO{sZ@wj;410gH6n~gGiTQi~($~VzH0FH}uAEl5ta_vP{?ySTbbZFcipYi zDHo(qeezPjo0MS|$k+YxMC^v5G)X6C$s*g89Fd;!&u++GKKXg?+qmR8pPxyzRIh$* z^xdZ3A^y=cez%RwHy26VF+bh@@7y!1)=%;&8~-t92OTo`6}LRVqAzX9{QfPU>P&Td zCW^dB)kqTe^M0QC;obAX-<_vaG-`kUTgQBppND07Z~g||ORUm&6?Gh6^j~_}>2~Vh z>P<7hOf%ngudV!QYFFg;#HJo(C1 zd**4aKRb70?abtjidPm0?btL;W4~(mb<@x5-@d#RyRBEPaj{?4cBjXyK3?Ece09xP zyZA?i%gJ<+l!9ut{$M%dABJpS|67YIS8o5Zt8~wPU4>}x0>4E}MO<@}%ATLPV$66Y z%4A>c-mX`CjIV3WjQB;ul`U_?bLV?_eLqvTpnASkid)mU$8*9t-Ua?H7OtzR`k;SY zo=+{ZY?=B&z9$Nb>GOZ2cH8=V*F9rcbl~5I-pLjVyt197Op;DLY!lygM66P=>X(|} z7YPmSH)8K1w|{&y&+d}D<~_DYI(H{9XevG7zb$K;x8{_$vZb<0#Pu_US603XI`7Ef z_+xG1mzmY4zFx|lU&ZXc@BAkLy;$KVLaUm2V_pf#zt}VX&JSkk{Y`s(Z{91*NxAgl zn1+|0yTH^{p7Q?YjLAO^9twD9crQ6{LBQs?$AbT*A8qEUU?_CF$S_Yyx#!;j9_wir zKJ_hIGD)Fw;Z9kFlz&eZo-IAh_9AZn^%8}S*jb6!ZH4+jI$5e}JuUM)@=Eq;w&r)4 z%PU#A3(Mao*1!66@7K5M76<3lZ&Pwe+4FXS+_vx|=Q-3bDw;iBEIX^RjyPq51rd#;{C7t+NopPesMZQ``D}dBOX3?(72h+dseSOVNHICW?vILyR>Z7pHA}vW zC`bE=Es0QWym|Nl`!(0{vW4w$qHLGHX!2{g6I?wZx9)sBuSYJ!;s@s{F0nSZ&iT2- z%*+44kM)Z?O&nL>4$(UMxXU*Gz>aI8-y{yb4ihXYj{lW$%0SLJeZAU&=$D~whlJ(X z-WU`_#W5c)O8MZJ+f}!483t3xO#hgCQQwT2IaI&s+ zMeyYdwJO&$tFMLp@rzds_2_TQv*UgK=GnBM_UO>{dNXTFI==t$x@5DDH7!VwJMT=6 z=+9g6@3MN+)g~UExX+Yrr-jOWw=n5deJs4?MjK5l_ic`zWzqP|_w)Ov!y7+*WiY%n z{poHUyK_0;x+?hdQ?8}G^xn{xc_Jlg`H~jaBmGZGw?KhF&fuKn_B;-)JvJUksgUOPQ$0q?({&Jzbkdp^YT_)Ii7 zd1%!Q&)tKEn4BUPSvNfm zo_wsc!EEjTJ?5jQy~d*5j1GxC@4jAjm$?=%BNXpf!|t>4P(|R?*e%j+ zF%4!X?;TiFki6>Y$!|;?+Dq>{Z1d-vbfo;tmFIEZVdoOH*RA#@Ag}Kbc^+gwQSxuEqJ01UcBFLbtbp+waWq%?#6?}Z|yy>|3{UTsz9bLFYB@c#CWCyaBQMe6DxL$Bzw zZ?Zzg`?A;aM6O;k`9;M$<}-p@di?*bcz?|^Y5NlyTgUpFz5CXg-Hzl6b7M3U*m%5H zu9SzbJ2<21aZ2x$H}M}nUA2&&_cn$3+gJYHXa9JoE%Hoy5c;v_<2y|w&TCtiG*z`P zc=+e4;m3T*SKp)O{xECu;>i3KG$B+sqIAO1z!W=~wUOsn7a2U9r1N&QUA4y734OZ% z_woKN|FL}ThI*eD+`nceiafuX?QfTs;&#FGrMA_g$J5-t#Ages?$C(QtXi;2O8jCh z=i2DwJ;uI$%K@5U;rQiD&PAs}K3ubM(aQZI&5TpX-V&w`T7CDD&Fdafa!?l($@guVu_?DjscP zly=>6nETyT3#}XZ9{(C-=UBb^5#F{Uhw2J+Rp+ zy8HZnfdXlER{n#Fn`cRFGe6Sgo_{duX-h(|YM8{djen2-Xgj{*_jSj>sc~)(_PsgJ zZR3`*b9KVKj5LjlVTqTEw|}^Fcw1g%!c{9>;kt;dttrnwsN3JY)L&K6$p2PK=RMB{ z{Z^6vd-t5`ELmH_kUi(THp?uxDHiP^O<4(5vrfo8tKA~9Y1`(dAwe(xMd}@X*C?Ne|`@b)UNJY&js?6a?IS- zmQ=-Z>DpRDwSV00(~oN$c`vU2S|ux|UaGz-XuH(Wmy`R&~w9 zYbSFPkmC!SKl=RaxM0TTP#n%v>*j0vC*gOQEeN*cRmbq^FGrswF z3eSi7?KdsIiR{1LCZtx^kw3?vzEezehwvdE%^$mhRwhig`S<3p*lA&=_a=;$;vvOT zTGs7}&|{18Ii=QkE=#Fc|L9#=>y!Tl%AP2&O%gK*df(obvob;C)pOCsayhd)Hx_Q( ztbS$jUN(l1nLo{L_&Dg!*vHf~El(QH}9uJ$% z&g@{kk-F-JR;yNC2G^AA|WdlOY_5lDQDR`wg2#Bc*}lR*k$A_Kj)t-bLiyR2fr1rVa~pJTiAj<-0zL# z@8af?o!b)EJ>^K~4qGkq?&?L=yk+~1Q$=>Ct&z+qJi$FXd3jxJ)rQKGr)?LtG0&-0 zX3(7xze#!8hMOCsW0dT^ZGN1k-f|*g_2l@VfJH|-PAa`RD)AuQ({bIAB@f@!is!#} z|8(rnwv6p94p-kCk~lHJ)@ado`GBkZ4O!==L~)zE-6-+>@2w^+{awDR7na#-J%44a z?QL?@Ro+_vS@`zItp{)AHtKxw=>7QU9FySd$#QaEucrJ7-j>!sMd8>U`R8}74>o12 zsLwol^S^-WZQIUi`D_0MyT5!8?Koe9$)Gdh0^i3;{0G!U6kk+Z2Q3c0#q4<0Y2)js zZ*qMCm%Y|p_o*jxwZ*Ngwc+cYIPp&8%wW0u`N%Oh=daTzT)V;UsqLU4p#8b3_Mymw zn(NKedllOKT=tNS#svfHGu3i+B-oO9S*VdI?B`Y%>ItxvtS`HJ&v&A z7gg^a*U37`7Od#r?`ZL%`0ndh5Y{)+quG@ zYd_tvDEQ)zwd<0e)(JfRT*&nE@b3%D)-_MoIJ8nnZOdUNx8w5Lb1%%#I4~>d0Aq_m zz^~KE>p1wn@-e?Ka8)qs@!xgZ!!&ebiqr4q>$A5`eVDT3`!+#=iD#MXbiLm5?w9?e z+4mzq)>B+;(yuRCd14G7SL+|+$=EtEqE%-{S<~Nx{4DC>K8~}J_H_Q@KwWf;O#&Lc21F%?~OOrloT{-n9dh$IMpEU+LD;Z8I zWm>1JzkaYdrar3knd9SacNRS4++k*SS$9f#t!_o)%PD^tn)LjS{rQ=lAFyka^JVeJ zTJdT>t_7dZ_+uS=SRpvKYw^F;Z@13=;Mg?Zq$TdsNw@fSg1r$IpCY|jwKbQVR(Ukh zZ&UsLe|_viANE!EO_}xgh~@Tow*vO<3(Q%&b`je_c^1{_(roK)pZs_BICs$JlKpA3 z|GC7y>3p&DpIN|{rACIY{^T0-F$nn9CiFhu*3k7keVVlPY^|R8C$E}iU+eufal6gR zMK?ar75bAb!gD5IP0N-aS9Wy;=ihy|iaU0n`R@MexzkQGX~ax9pgRBB!N0%dx2G2^ zirTNc%lRE^({K9*PK9}0`kg^W3Ev&}^nXwOEPPrh@6Jc#od;)Sd`($UU@f&@r7 z$pG%SM9ibuij0hR~1KUW@Qi?`>huS+(uT3Es^y3pb1 zzb`4zZ|)O(omk26=;ppFsuK=ML_aNO?EYHc_9~C>#L9gqXKaZ2nxMU+N$URHKUVDT zZa(2#{mt?D+{228`h1ET%qGce+*-7Y$4z_jyG`Ei`*XQAPx`pB=$DzvX#rKu)z{{n zJr!rZsOIucw_f(ujxwKC-N|$RkXFCVS;Rl1R_lkvi5K_(`F#CT|7ekuHqYl$5q92l z)8;uJ{o>JHz^L9fwe`_MuiAeNJ7~wOeKd736apKRW(lZSArU zrWt4{#?AHQo-+s86KPUNQ!U6GEfA1GtSIq62ur+&%^0_so%pE`8uq0nH zEIcv)#_OlbFL``Kt2$+N-gS~^_*7Q6gd^eSc`cV|IZ!W$%4!Gt@j?} z>UzEEQP}+h298>LZg3iE{8+Jx!K7(^?a$SczuoT?EUxe|wK{Y3b1Ki)rdMLY8Xq0I zIBnwF_S|Q=)W%`mwB&gHf`ZBa%%-%LzI@mGQge^<_5QmLqM9bB&Wd;@kgclE_ut3D zQNq|nv}}9K%g_H8^vbMX&^f`mgk(0@{4U#+}dtDd0N8b9ml;t2S(f|mNk6jM)j?6EIZ^uQ%jiY2ieW!m`&UOZ z)dpKkwVrZx?#nw9@1B@&y(QfD#90&O^|Ibdhl0GXNBN6?nRpqQ{_ghT){xrIb!ki5hTC_I(a|*5faG??F;EXUFG@H+qh(VVrBsdGJQYo94(r1v@$m|K|HB3Oxzf z#3Lrc0yGQ0b?&3=~J2D3HKCY}{oaU&-v zrg7WhyLRPT2VIZtn|C&NQo+Qn)Rc`Y$Zj>^Y>9VdndMM~uMfi#rk)Ot}7f z;g$_AtPbd9uH3nIr|zq$zgv3j?cOZpjV-)jBKJ?#KI**f=KWze&YkbL&SZ4_M51EU zWVYBB-X5zDY>>3N$NE=Xh4GHwj|&&`wLK=ip8E3EZ?9XQ&qWw)x+1u5joyY?WuNoP zWcvD2zaBUKd~~*=`>aj<$6i~{e$4y&z>x`hM;Ucp?z}#H#6VJ-@i5;GgHsltcrw?m zecsaYU=vrh#=b94YcwTxC3fboV_Vb7d_lBA#OGF7o1rY%R_j6*l|2lzT+Xtbo-en@ zlI5^^!^|~*Srnu5vT;^xX7xO^ z{x{ifAM@?E9?-No%6O^el)u<@!RzZeY@BNjBwy#-5+U5_G(Y@J$tm|$muGXuFWfDf zH}Qyl!HtQ5S#~7{=3b7)cP~AM=iXt5x%VdLe$cXMbPF)b}j@8*Xl|^k-ix$;MGr>8Riy(^mCd=Uc2#xVVC!U+y(sGuL^s9IrH+IP`!}h`L}nvOKuyzDi56(P$v^2)}wms z19!u3_iq=tyL=Y>HY~i!wD7rUP~I(cZ9QK)dy20_WoJR9ch+^F#HNuCl zDgS&yOZx47ZJi8r?_6@2q89g6aqq6fQR}RG-YnJc5ZD~S6xVb)biyfizA%qW%M#1E z>spw@Szdi}H2c=D;>MH%a_U7VBI6!?cT+DDWtnN!@yWEZ;lzN7mbW>X*)!Aa;+r?p3d@`ion7?l*}>b77^ce1NGnRYvy7+j zE`#yb#XpS=PM$9oKM=-OF11X_Ky2>I4{`gLw(P6)v2ZFpv3u`#{XlvC&RvVXJQoOF zqwfFU=KRnivT>|XSe<<=Th}0 z*6sM~ve^gHb{WNgnY8YXZ5hM1@Z|Rk)@WHwO1m5JQ^;r)UqGQzxSJZ?q+wx0woppFv_qOR*d?%T%@##=p>a8_**(Ob= z16F5_Zr%1IeBEQF36m5ZW6r7NX}7wl_(gBq99hXLbs)*#zFF&?$gT}SlVbMGIlBM! z7p5eS!V4BLJ0c63@}(X#6(onUPJ8+DwN7PJXt;+xONU4L_1pe$bwe0ueo}L(dYfnQ z`|zaPz>QBLraV2M?xNJuGpK`XsBoqv}L>FHbI|daj}lK`3xuO_m<7xb4KdGnKjW04Kcr) zf==)+nw*ovcp_(=ZI#KXr?Ub!%;P)z$Mw;dH|v|fW-9RQsX4uu@m{4=`I75@S);Ry z;t#Ohy|6U#dws&8y?N&iX3XULvwH0v1@4&a4YR7cKXfxO*xN_RhtFMX>fg02T}aW| zDD1W38+Ef~+l+MXN*~O6*ihKZ65bQMrX(xKY%5ZFw3%U;i|HE_x~!lpEmy`^p!(@B*!jPGj%=4v!!<>mzoxn zqUj{luNG%SdX*R_WGvM;{Cw(0SI6`|DTU+F7hf%rP)zv#>WkVsxsD|tLuN-#?NZl! z%Jpa4{x9=fj)*DiKgem^sq*V#_oh30{g*p_)oPQ-)9&+^Y8GVwy!?8Rhncr$RDVN* z=p>=$n7|t6n{hmD8;Xxz=I2|v&iKcT*h{NpbyWZL6mMGIKKaDq#}iB^|9d=1+5e#5 zr(5s3mrh~NzvZAdBc@}Iq2#5aW%t9MEV-AG_w@KRe{)I0Ope4`6|bbr54c84&nPc{ zT41K^(O(g9{k-Mn(vN;kssGP0h%{d>=5c#` zHEy?d@39a4ho2pLux$Im;`pqf%Wdzr-E;|j)!C}RT<5srdT8U~;zZ$16BU$_9`KvQ zL^{kmsz2p&G4q$JJHFk^SXYw3v|@@-+*6&a^UAFpBj0U)R`Yl-r{K4DOgbDKad%92 zg`O7N_%YJ>+l{6Yi|nKC4lKMW;;WbA#{0d>Bi*_`Lj20NCEX3uoU5xEo2TEsd#W{t z|Jq%5r{%k1&D?n{9!;$|@@&>cDZjS&iBYQ-Y|;4BJA0MTOp_l*!k=|iKln`0bvCZ$ z)U~q}HcYMh>t%IYqc36YnLU~fy1VTS<8v23aXnt(|1I*i-;qN>D-GRt9ycsj|8}Kp z@#k0UOF!!yRvkIFHv4N<^UThxr;BqRA9-=@Moews6x*xC&bN1{y>Pw0tzTr<;eRT% z#}7`^Wm8_p#q1Hx7VtyXE54=N^=!q{3T{EGZh_TlTE8Mo^j zKh6z&S#cp$fN$1uqtiR{GYn?UoObxU&<4lg=Jbio=~{bY6}AMt7yJ3_e1)W{+vZfI zH@m-Vl`dO#F-pyeDUi`j)u?yz^$QQVmG7v9Opjx^e>1|RDb8xi%7>iE%m)vw`gN(c zC3C}Py@lGXO1^KFvR_>nTBE(M{^&!$P2s=VBi($yz81N(@eJdG+;FWDyOYXUh4VIT z5{+=EQx)cBJO2NZz}MMJGy^K9dnYHHb69*QW%*gE1EJISHzUqgBAuY{3qdYFvVG#V{MA!qK z*{r{obeEhGNnXE|TW$8P^Rqs!h&&a{$9Uua183#>lMIeBQc7InoOzt-iYE1c7wpVB z*%PKNbIH!)@98JUUDd?-6#4FGan)Dw+~tpcD);7&;l6ttpXfw|_We=Y*>|x$n8k*5 zx)=L7385=le?_@B%+!5oJ|*qlot`yCv!t|=_MY4%Q7}Pg$#r|p(iw6a5>I}rK0h(@ z)y5!L(CJnVy>{mZM9brWD>f-A8o0tk)CE%YH8iM$uj8HHpWXk-pY7R;c<92VI9lT{v>miYuTSX zFF$4|+n}TKey`mA880(VrW&9B++C=*qW;dQ7q{10T>pFR!}|p<9&u!gHf=fiWRh*) zhZhYJ92XycTd~DqPaLb<+RGC=cXlYpIM{sk`F!7_N_XlSS5{}Pwx-*q8>a5IJ@#eZ zp_G`T+Xehr@vCV!6i$kCeZj97Q*6DcHE>VC;7=eusrf38VK z_Sj@ZUH-lLWX<0F-8{O|S?vvr71!r*o_-PXZ~N@^m%jvvSgn}O;8D-EUVF)Dy-LZY z7p`TQ8dWlXu5vaNDPDE_ichW6Vdtf~UA?n{vgRxnc3Gf#$n4Cws+`W075}G6PZq1X z_Odc{=iR*xg1X^)KjaL!E_*NW6kFcWlyYA5SK3~adEVtpa}V#Yn7m$enW=<_^U9?s zUUY_Vh~!&|w)I`uekr)jDrY9^MxK)I9%qCqmFKKF(|3K6>6Em8)2n$;v9<2J`j;tf zde9tu&X9!_!5ou1SKQga^VR#jVCUB~chMbBvfW~<>ihrcO`Gzht3SwrQ~OzrskHyg zkl)_MdlE%M9^RW6oBDJA(yCPo3PSPu)6K)a#`vCzV*asF_}A`L_3dHl{*gkB92VS7 z0&IN^Tn!GgpA>ig2zu=_x!Y20Z`gUGg{B$Kw|5$@`&stOe~Z=%KE8O4|DpMv|2;kD z@39Wr^HN+SXQ$QVi>eHf3wabZ7fhdE`fG`|;QwNy;&0pjDd$T}I=N(@;QkP^yfW#! zNcI!#BK!V$a9O%YNj}QG_Evy1;M;kgOPqU`Z47>}Qyu}`+#at!13A3cu2UPhS_t?1UpF5lB?*s0!oEx_- z$kV)Ny6{*?My4t6?$d$W^OdsxZ4-(l>p%+3{-B%Jvw>1O|1 zZnDLBqmXmPjAsNVTwNfn=RJ+Hpqlwv)u*r7`U~F{_!uZ#o@uh3C`wf0K+*YB2e zu|;GC-MKkS`k1GLGo#DgZ(mp*&*YJrZ>#a}%ro&dTo<;rHlEBmFQy3AEVE8g`K7ilqX={r+7MdSP320;Z@Ng4J#+wY(G>mg9vZ+PMm^Xi97 zu1{|%G`f8C{!UdVN$uTJN+!><=-9FDYx9puTl?at#+PmF35pTh`}*59P43c5#j%HE ztZeS8Fg`yn<}Q(BeshBK{_Xsd&7l1V3^7 zxkfSJf5E=MwAl}4t*z!iFDNthJWp@hOsnb>mizB3e!ttRl<%c+^%~3N&vP{F7A#Z` z^xJl^W#xnACk>zfVtyII?7rvdz1zWC{@l?OC3JVU(WDqSB>7vCI5G( zRL0F+^*#H{JI^BSY_5ov^6R!_UQLqg&2x-a{dQximGGwHVHLr%?a~SZF268zD|c+$ zu{L>P+|uc8cRsX-HvG7t*r(F264yU9rLrM4`~AXmZSy`xRd2P9R?o|_au>1EkE~px@XhmE+x-XFP2`Ec)9s&qRf1~o`Q+`E%(gU z)-zYAe>)@dBz;ptkkn`YIMbB*(_HqlGUcwn%R1+6O6A{RBkQdHbEYj5sjR)J#ktF? zp}5fc#zmj4H5nmn*Y~Wwnjj=6%qAA{ccJp!x}+%MXBkTQEAI*l&8jwWJg2ZfyJ3#N z`l|Unn;zX!zcPPO>eHkg^#qG2GE@4eJ#*{0^MB>ZXmd&XOP?Nl9dCZIB-_sDNwlZ1 zz}_++>l^=ePNz9~Gj z{WF#7_A>5#`aWsqK`+fG`<$-H_A%`YV!yLLJNU>%!^-AUH+Nl>u3*{PlJ(nP=IF6m z`=8lX=g3JqObsb}P|$7mpe?WTHlx4NpW_+w4H^-ulV%n^aJtVi-OuBT#O8fId+R*H zG8St+>5TrEx{$MX$Fszi@78>|oAx)HxzO_e!e8@$OuU{Q77gd3{?6<9C|6SQnA`8@ z!@Cki_8)AnXcOKrMvQR ztZOH!r2fx(weKcZL3;GnMWS}qPt+9IZC-DT@cA@%*?ec;DBq(>{0#+J5qv)`mc8q6 zk~ttT@Bi&BF+XE!CVO?sue94%b$`KO@BLb?8@4}oKKj(O_T@SeKk;pQJtuYlRy{EL zMC@rHNsfz~zt3!{G+pD7x{Ar%jYxlDr|2HT=hG~mKJeyI{T@zv<^-mjrUDDRog|^C^|PjXuri>l<)13 z`qAs=rc--NO}#$bHW@{-2_4tYJ(XmwFFvOz_~N7)hI=or6S2$Dy7x^HrSIxe*KW@8_>yF!Xk;~W4&bYRv=C22Dh}HDC&m300X)_|%Jk3kDmzPoKf4r|~ zL+DF}yiaYMh38(pyZ^iQ=_ZBAuMXAL?f0A2=yCa|#uXch!>i?kY>g~lDY9G^w^9}_ zTY1D;r_=1H$@&fToS739|MZ?ZwoK(ozl4IkXa!I>Qj4n!a%} zPXNcNYF_#I&(5TM+wey8_RYlq{pSun`*;VHb3+vTv@ya&o{kbTOf$dUM zpV%4c(;s8_*Zh9ssw|Up`01kNj8jqt-5;v=u9_m${)*AnZn^f27QvJJcXgX@@=1#Q zGidnoD4CaO>eXK-pOu}F-P*BsN@$|U^H&|~FaB?TYOzmSWsLW-UHu_^Hp8D4G9v`%|^~|Mg04iFh1w>`D?{x*__o zrI#r46~$@MJFMGO`ezv*KIyeaLoMLpI+-J9Kisw4#*{WuZtsF5fh#AoOuxmiN%HRA zbzMxQ?bRWbA`cz@6=B6i4;PC(>;Dxcn7N{)xOhr-{=u$|vmOS`yZTG{!8^Z0yF%h( z9^35n_;!u6+*Wq^pNixgWu@miW3NblvpU#V`oku-`fsg}&Lof2G(I!UFrCI}W_j~p z+_!nxWB+JQTlefQCC`s7t&7v%dP;Ef-Q;VWO_M)~9ZB2JJg4*4jncQ5n5r%<(>E!W zzn4+P)zQDB;-!%|01BNbElS_4q2)wCBpZE-lnspWd+Z za>eOqfq&~;)F#KqCX^M`ebTXDpU?PjW`xVHgX%?rPtWrvJUab)(duigPF~@a<*z?I zeslZSlUW!2j|cBLI_F`!=I)-Vle5;={w?}(>dCGfTW25Lx?$3rm&I*D-3m$%&hMNk z@2!98R_m{dphdSXK1rVWc_mkcy0^PWA9KpYUsf@zrx&|Km}Va@ckZiu*`QOif6aZb zgXxODqpk0mxNn;?y)DjaaWQjW)6A21as_Lw-W|QxH)+xP4UbOm1u+(`LY6Q}&nV>T=?J`<+9ebbmPw4!SBoI74=t2}uW zj%Tmh(mB1tkjebnd&9^8xxW!pe()`17X9p*EF{)n_AX3Pt7KP~z}kIUp5Dt2&rm5! z7EH1YI2b6Q_nq5~;dJ$vs#E<7xBXt8DB1aV$FhSO88Wo|V{C*c-4X&T0F;@VVATKUBD66h!33Rv$fc)!m?^)WbQ!x#@&6 z=MqPqS*<9yrS%azM7idl8p}bT=&`+xhr1hK6m|FsdIX|TA+SO_3>QoT0f^n z?{*x$8MSL#jPosldmfxY-CVD@E#p4jOz4~-W^A~T~Y<_fBO5H z^Bj|e%&YG=t}L3SE$z6L@&9ryf7@AFya!EP{k5ZWu3Rt4-ywM}bk{4P_c^J$)(h&( zv!Z2Ei~HxbZWrVHQRp&F!8}#2;hpKSJ$J4e-Q&nfj{MJL{`lTim2KUozY5LPxY_R5 zeagSKxN$+OP>XlP1U&wtRe3|15^GSR=Z!o>vv@!k0L+1$H|G%}EE_Cpp zQudmhvgyLvFZb728gRUPV_tXZLuO9*&5}P$np|?6kM4clcOv$f=%%VAEqD6Aue+Ab z+R&l-{aojaU-!yA6dqU|e4=sd!A!YRhd!${Oo-o-BxE6GyXG55*LrEIq@~R}ujaGtSSljyU+_I>pBQD3c6{^NyrhRK zXQ(lx9ysz=`k8ECZIJt(dov3@RbDMgV!3l?cI3^yPfHI-2E0wL>ZtH^-?Qz1@vq;% zg!P-77c7#v^iF@?)uUlLT`fhPA7k9rTudr+ygKUc_UioJximDyu%Z2ZEr{Q0SBi}mi*7v;iR-U}#sl|I!jQGaP^82(|$@2~=& z&3n!%G5D>KIC<)h*A9!W++Tvadmi(0v1F?|b2r%-Wb{|O{IAvh`t85;9q|fBFH{t4 zGrp7`_Q3k_?Ay$HlGN;e&9J%aVRB&Nqta7queB}mO;{yWkK`ZPo*v6Fb=n%i#lJGF z15QpU_0`LDeabI)l*v{~jU}qZ>h=3`7N3Nz(v2!OXIl4Mi%!u$kdbo!w0vTPdg~4E zWloN7_&#>*6DVHN@a{}|x@8Yvg6Q;>8i$(XJkqZfJgxPAE3bI&b`Jl;Yp*{YnR-p> zr8299(pmr2@_O;>d2JLHc{AUyP5=4mM2eAarIkYM&w#v1j$04TGVQqXWg_#hzOd&4 zzIyk4Wev6*-cz}6?~S+HPf4th-g@ZTvU8G09<`-UWzE@A8CWBiwa20Q?k?|UK4)G8>eZU3)^-dfJhpjstVytXj#pW`Lr zw?z&MOP60Td3ep_X_0OEmTet+dCl_@UMam=Jm~=ETDG(6SLFH?DQ^Dqrd#yG8eI$a z(2h&j=jzRA?tE0#KM02<;C~jeu;Z{^hV+BGydJjPj~)bbD%R)L#(CXZ^@n2 zlb=2N^-xan_f}PPyO;ZKXT>Bw-cWN#()aVvi|Z6(G;40P)SXXjS+o1=>%!S_SI_H} z_?7*Tx~dXsEWxq5T_-T|miw~g*%KY3^>ujSzD)R&;WW9=f8yG$?{-S1Rc_0E!0KGP z>e|ah-@ly)cKd%=)oIf%*Yfrnzxju$ady1-!dG3}bF`Y}2Iq~u4ZHpuJ+HP4`TRlR z?mO!V-)H$R_17penIBe{y6>)i=$el?mPg!GBzT(pUwmg=wdDSFqe<<_xeqNp533&A zcU*7k`4jWE&8&ERuGy7I=fi0aUT5pMM;@pw_+3zHW7InNa;5F_<11$fZ<}(NZ>@|% z*=mOT#LTQYOzIPQi>H3l%4GHNlXt{#gG5IXyJ**6LPG|7pr?Qi>b`R#VFSBq4b z+}3)h^>)qs{F|OUmEC1;X5G{Lne)X->xk6V0KePCjcgA>>MUIEzPmX4f8=@r#q1M* zwc1XXT?n!5OqpEMy?pZKr!UmF&y`iqwOckV-Q}dj!tBcD zf0?u`(%&~!@}4rUUbXvJ+S9PPt?SL0gx1A~8=RbWY{hd`7VXak%8PUR_PJkR`|vt+ z>WjNKFMHh;;lBD*F-Ge_iNAlZgV*nGR@*bLELc|`_T(_<^ge^N>}F*#+qsNRLi${gXom!FFyt9FA0Z+{w$`@btz0F0W}jSo+sHNNv27)ywemG0$6OMv>K$ z!3X%~Ro;J|aNSUA`Ob!_vr(Qe->Gt_hTlI_$i3R(d#d8?YjPKKUjJjAYq=psdbjD% zLrqEZfBtVg9=*OQYTniNz86%w{IMY?j`cK`N=&wp?6yzSnKjTQ#i zckka&`gu{uVW)S?IFz;3o4s=Or$p76J+x1MA;rtgHRWH^_bp%aUYTomGwy!l!t;2J z(h+l`9lrlp&J8}w$+y$!hvwhzk~?=kZP_C0y^7CHLGJFJ37508jdWYG4?ov;{BVEK z%jJq$YmF9rs3{b^e^GkU;jhf%yOpOk#g=ZH#2c9IexUQtg@32AlmuO(cx~rQepU8# z{;KaD&;FhN9dstpa<6>L=cU&V@-#788Pw(O(=RTqyRgYl;D`2#M2m%cI-AuVv`w{s{+4Sgi;mN# zFKrn?{hb~UJAGF)o=Q~lT)_Hz@)tIpH;?$&$UI#&BU>Wr=)Jk-Nv5kqln%-pH#*vw z&eENBoAuRn7Jt>`nXep9G1n&adL&)iGwJ$nSLZGKf_de)SI;>Zf2Hllf8&3$V&`3_ zK4(jne&^?E@GSb)>htO5h5H|#YH@M0-g99q$AP8abWL_uKKtoC{g%j!RhCuP47;;+~SdcJWuA7~`E&`p#FJ<>arwDN*YGlKDh^ z`nLB@8&|(pS<26O{naMk*^^hu1ixj8nP27nI3|=Op++azQ}X4x;F~rx-WanyUnx8B ztE5^|&l{oknnf1(8!j~|OnM|bMQO(A`DynnpW0PRPhpYwP~D$7a=$fEV{JCtMTC*Z5#8 zsky>gSg=!l^_%+8$9b(&Hup1Z==BXKQ8>t1EGgq<7aX{!)oD{^+`&t8X1@<$Z3<-H z^6=E!pQam2o6C3u)?9YhTP4)>Z>#@RoBq}qCp)k6ECxbxqPh}XKUON|PO5&qOv~ie z<^xN&tz(zIq`CjT$sE7D)z7}hF75L-oZxaO@gU=R9DbbfST*UU?scyNYT;*`{+V7q{0e4KNe^_AU z^4c)t)b+hLPH$J7b7J#Nwf2~uyB3$kpJ-fhprc!O|H<_m^u4&@AqSVtKU(at!!cYAo2Tn0`%@wz_fd zbBKZb-tw$%wRcp48Rs-kTlFe9Sv`1HboH%>?`kp^|0XOyUzu`FB!YR)97jpUy^pWF zUGc(q#hC-s@0(g({>m44Bgv*lbF1~6HMK`op}MHi!GHr{BP*xG$CJ>tjwn1WwZ?Gxi3UzpMy;mUE%L*MTW)1Rp5 zk`ntid0j3g^Q&z}o=X|th-jGhDz!Y#crfMa)Zpwt6OTIh?KLi}@soL-`|3@CSl*o@ zeH)HgTubivuIBuum>KX}Vu9iR$xFAjg_S1yt(A(9WqjIWxBp0NTE|i|kA{P1rslLg zNjcE8FgsQ3>fHxoM%~^qQd3?|lg$J_Ot2S_((AK!jmbKi zP$T4hz{l*`-#JGvmfSlshJQ+wpkeOskO~zqbPeu zU)GN%bybxdq0MX9FT4_b%P~*NG5zxS`qfU?V&f)V-SEM+(%XISPtlK|3r`#MA5r*v zpmegOlyT0tEMxaeK@-JRt>rWH+OXreTDIR3b0N+ekrlG;OVpeU9G@iK{;T*xrLz9z zqaUmM)r-Xs-?aF0@71TAgGG(=`r64~-r>&CVpg@6BUUsdliG3k=-@qp7Tmjd51 z?_;@Bw~>qg=Lf0hs{IU?s zr@cku%y*0eVftGwfk z-_4nCvncu#B;#n`Hrh4h(+tax!TwD!9_{;K6zqLG6o}TW^*E!|?W})Oik&2xs)Ss&+ z>vSDIGFyKU^MwAI+j*8En;E37e!b7nD!=i;Gx_%4hP03Nx}Pi4=ck%;%{w7@>5A5* zS9Xc+#e3eb-Sg#!s=H#Pcxw54Q$v9j%+;IrEh#msI&gYIL;>?g%_B^Q7z{sqzTlbZ z?E605E#Uw8xh)xtih=i1o7!(>Cngug2rZq+vLj9J@|W!QP5&?4GIwJ!J@tNW&cLN+O9fV!SuYY&x`H%y&Y8>k5_;HxZY;LW^eZmR)GSF zLfSkNk9^@UkKhoS#G4oz{Lu05*XP0e=H|@P*^|{8b(T$#b@D5Q{aZ};U;nON-0gT_ z;!3x5o|Zi3{YScX%P-8a_Ki4kuU5q6$jX^AiL$z;&5R7ar_8;x*G*o$X_JEATlT)A zDib%PsPH{=5z-bu9X*oHg$hd2?k;MdLv;^QC*D z>t5t47Nl}6%hd^8`%<<-T)3n67uUXPE+<0@kAGQlIWOQXPrcW=Tkoo^d}_AK%C7uq zEXa7SwXIIEqWsO;ImIE{&s~1;V4g5r=kb=AzIA!e{mPl6%S#rSx&QWWx!ymqjN6GR zba(tDX78&XI?w;oSKWOgNtkujYGpsMpK%LLyKZ~1_`CLe3#M~j9&A(ntD<*(^i;bg z5zR1fV%_hWh2IZ#etXH@9CEfOG4h4%n|Ie{Nj!cZ+V?AdiRYcQyRLfdn!>86b9m8W z6U*GqwTrS6Y`Jf}7P(li)tA0sY|W96jm$UKpGsApS~GXs*4szKo8vxB+@oA@b|bIk zpQ@_@Isbou+*SI@e%6l9ZN;bb-td<^K5^y%LvQZ3iwtU!W(5Zm4_xz!?w`YwaPOt3 zj>Lvd{cAK2u|4)llwEN3+=k1>KV}{f+t2c~ZsVKOl_Kj~%ai*yYX)o&d9!O-%yMJl zztZ;GzOJ&akX+80I#p3R>Y!b%a`5e};xz z=stN^;`gro5zbnhw|(4XsJ9_I+E7gH zyK7@LDpT2`c)Zmkn}t1u17GEtmL=G5%%5nJaD2My^5Z|me=}S>x$WL|m6-E6R`G{V z)kL;+Gep(id3fl_{_t>HM*G`;9hnuP68hIXX}I@vc04=tv;DU2H(g!$^L}!xtm!Sd z#8f$HzQ^7pw?F>U)_L*qS%W0=+Dm*hoU^Nc2fpOHQ@YWkV(#wk36FI6R$c2o|MQwi zqDk@OZJ!>!_|n#+`}OP3Wl3x|_uSij+APi?`A^74NjK&=c=^ z{Hx9ro&(yu&&7ZB37N|%xgor*%V~DcoZhDqcX}otwwtiy*R=MT?`N)mv~QYl{jrv7 zmskY#6W=S{tt;$(&FSfWUaQ#Pr|#yZNA#`ze0lEN+x5HLihK2R6^jf%!Gm&JH&);F zo8vI^uX|&H!d^>j?H`Z)!{j5Ef4+A5+@(EH{nmk}r4IbDuF_ZfcGfXrL$mlziKDw0 z>TdY4fI0e3_o3%u`VM7#wz+=Jdp;#M=Z*TR^qAj^h1VKZcCCIOoqe%s%e{|||EDLc zPH`>Xl{%|hVoFfxF~f_VGOgz=vi4uO&~IIk^(yD9`{zxM1AegW3|gT$rAn36<8yNs z`_{5+=jA0GI=yn!{8S5b8!rA7de>I^qU_EJ&bzz1`aiw;BhUPa!)MdmFVEE%uyiZ> zi_Z9c#F62H?7ywA7EGuU@2u&tFDteywz1fvp!O{A1%t_(a>cc_Yp0R-HS>hY{19cHv%gGs$X%#WOt0QH zH;&hL?JJdAzoQNY>mHQTmX3(}*W__Fs*~@_(puNqVkJ(|v;LMuT$I}JRDPl>yO~nr z`TS>>o0JpIP3A}_W^PpeTV#2y?p@lf=Z$lJ6km^Xk!6|?64cvpbuO#D;vCr-iqdrr zHFIbG`yzH#-AILfS>UVN_x_w)^HE8vU--nMm}^V_C(d{2qk#mz_Z60dXxiVIx*B>bpfFus4b{QvT5=IR9NTd}ppx6|k9o;eww=3M{flHu{U zo{xe8cm5Hb7C2St5%c=3(G8K?dsa_PTkvteRqKO&y594wYo-P2FR74RB`(RqS=pr@ z?aC#Rk(t-H`@Q%7J8^Ph*SZU?p5$C@5v8wo`G|nj+Rxteg-(5WEZo?raZ%GQZYT53 zKbzbwO?5bw&RY_~h`uS#?cG}cgcm49UdaL)9>%o=8n^*1f zzQ^=WZIZs7v(oHZt?^%tlhc3PHM_kaEhNEG@_Oy-l@6Xs?yT{udmDXhoWu2ZtlM(d z^5mCa8_w)YxSgo|K;zERO&g!|aenD7X}qeI_2gqo!e*COpAFoOeVo^0cBx~fBy(Kh zyqdEH6W4z}?(8#7>ZZM=;o^7OcD-_(a`MQLI3Kp-+;ZCdW*0A7-|atkcwMyH#M|se zpSzasTzp;5xT)!`?ko`nzhydJ3D@lX748Q#e}6uyY1?b1ywm3+cTcnY9bs6=6E9wW z>bYv){HD4V@m#?gFV-f3|ADN!3O`@fzMk@j^SQzI-*wmZxifjEe=}N8{C!bSK#1bQ zSmk|ece15C?fX)hI6YS0<$PRWvR8b4ynf`xhb97-R5rF=UeVPmUH#)-ifUiI$lgmw z`Fx&TK015ekMdTrPe070+b1wzI`ZK|l!M{{Ti3-jI zPja=R`X!AmjQ&4nXBjn4Ikng-9HD1F}z!G-Far*5;J0~|8&fQkEr+UM*M&nx-H>{B< zQE$_DS+aG7$J?6i#fNUpaZcfx@ow^wC9B&i?}tB7jc9qo6!LS=)Y}reMXS6uM4}JYozncb zgv-kL+>}n$tOF5E>5cxIrQL&EPzT$#V?))V=3C+JZ?UY@;==%zeCYhxVc6|JCaQceW~`Q1kP+Ct z)!;g3^pbllA=%5zn7*?ZAMz?HbANg^=h=q)8aErXy*}D4;1Zg6myg5OeQ$bmA47XU zZD-^XgFX8Uw<+6a=!omu<+3uKJL$6Wh`Z_B$7fo1T=V(!xM14vl9}td4qwQQO$d@n zohh=?vh<*tnB0?(6K~`_zHqKpe*(`2O;#7(n(T(i&5!=i+xpW!=K6fK^Rd;>vagvg z`m#-`-=&JtATJ?z(|ghGxKqa`ys43q7L+?$t-$HC?SGof6y7c_{bi9;N^M`aTxV}s zeY)C$yV|$5uYQLm%}cn>9ByhRZLR$A z@~b6p{v0`*A6dlu=y;0&OVZlik;Sae-!SoNI6-Vb>m?hEH z_|og9_d%ZZKTPEpaV;@8axhp{*>FC?%omCip4PnZw-z(AoVEK}=Zo!s&c-?(Wn09? zl=WO)OJjY&rH50dZoKcy_A2o9liOd_{#z~XP7uvuJ+*Ak12*SJrJossmp`BK^3nlE zhQwdfWKVvSF=d?aUxDN74X4682|mic0=Hi4F+IGmwID})UJsX%v5*??y{1*%hL_Ht zEZOw;zA1BgRE$mSo3~MC*Ker0DgEN%KiLC+yDrB$Ov>PJ%)I4&v3=93+&34`+?aOG z)pq)uP^T)j^ZJsZO{Oas?@(fGTl;eM!cM`<*A33D+}StNo8Mov*}8F=9_KgtJ7>;V znC?t=(s;F`{;tl^TM8w1=O#>v3P0C2=fTe(rlC{oXWeU<`TvQ!XM2vcPuSvSuzvqTHmAoH z0?jv6a~TicyrE?v7ye;J#Pi2f4F2l-fB66YXa<+{!HW0^av?7=5~c~>{SXzAGwa_i zuk6XCfzevid7f(M?sos0Sw5F@>kM?8;ukD2J9X!lSFqUPJ^sfO z_j+)+9bhmKv|)|9EFHBw<;-RE)sxmUEjqvD!;|G-B#naxw`(ig5kOx7nX&6 zwrV;DzSl->U(TqeAW)%w#C}V-+2QEOh}OP<=`BkxUoQH=$fonM?)dwAFFrIEb?{`z z-VtSJwUz5REXwfPo2zLI-#x^9lgsx|8yUyA9=-nY~}_@Hop z-Gk-VKQ%u+b?^C==}UX-9zQ!YXB+e0V{0>8yHmeCYX5#R@7wn0*Pkr$>EEau7MvQY z*i)Khn-^LacW+0Q#IdZLemnh`cW1-zah!_Omznx)@iATLUDK{ueqw!>UTC$iR_thg zjK4y%wxZL_)~v_(c}4Y3Wnkr*gWYPIB`g2O- z%ARZ4V$5f992)wc&tg4&$?qqNrpD2J*Dw>-DeBL99)}s~+ty#8h;W>PEgBH60(s<}NRA*y}OVSHtGWl`_kXn>ypH&c62f zJMYnAqZ#rIKew#2J>kF9cVYgN#Dz2Grpd)i9^mQy=X$I(^P9q^Hrwc$+6zA!#UB34 zKDy|q+MBEPx|}Kt@;I9^KYw|~-23#>zN>Y2HJ$T)w+L}+`h3lmNPe9V@+I{5%<%r| z+G3B~waYfxs<^DzW0ATae=z;5;on&o)qU2RMgJ>T&@h;qkhE)Nkn@6>2UiumkPY#c zzSHoY#eCQM$Cs+(C9a3r>fccNkTqWTXY2J-!sg}zqQ%P^=~>$=CgVy`y^RAr;H21i+O66x#hOcvF_2ZcDs?@v90YU zmy3mO#uXLGrrOhMj~-q<_e*Bq(xoR~tXt6_R-}C1nlH&DV3HHt-IE)Owre`&8zn9C z$=dvS$2-4r2GwZg%A;Y%9qoVXRd?PG{J?(n_5J9ND;Gq+I;b9J|MAP?zZ24Lo;~aw znYpvSbne$bSKGfVUi`F>d9I?VlZlS^N}hV_zL#aQ6U{_xuSRwo7SG6bNGx_q$i3O| zrNufza>><_nH+w%esaD2b4~i{2GMqx#aB(m)vh0REBo@%%@8u~D@w7Rgnc96aOSZYV@*A$d*0AH*w|}#Du_e#1YWt$Pc>i+F@Q|)gy|dWs zcl+#~wNQ}5!##DH?%H5+`Ocn-{@kOE9-Ir8aXGJWHno;#lZQt*`Lz|`G@lDxv{=Jtp>z^H(%(Kj8Le7gT5BLsV z{L1<){`qsO#IWr1XRIdK$OZ_-)J0qID~-`rR?P z{3b)s@#J*biAn|fUkiSG`V-I8)ha76DM^<4I}>ZN{Ke^2)d8HB9xQ1bs2fB(Wo^FEvB`T-~SeH^#C*t|M+>g@CPd6Mk^ zf34lS^uOwC8M`+|mp4E3+hwlcdsgNjyF&q|&5rM1rE*^e{)lB^d^@jB)%sum>QnAd z-doG7J(Zr#Y_y!aW!0r$yEmP5Vn6%!P4nWE3~}=xel3<$1?>|1J=}Qo5{*JG-f7%m z`X>I|m!znG@O3xX_3}~-maSd=HSNay#A{}&XRG>5Jp9CbUU=iv^9QoIrv8=qpTMA# zZvMOUYT+c;&QW-lEISa4W>{?XmpL;LhoAk`e zllhz3{;=BgZrbT;XUTk|MT_kwC z&0_MQNM0Rlrmr=*TV}tQo^-B0`+(#86^48!miJ_=il(MZetRMJbf=EMl$^|IE$oG% znZav!A1s+`R2{Xoj_DBNm(MdJ&+T0l$b9V3iSry?=wU80ze=e)i1 zcCDQmHvQD2+lGvmH@4+4dWscIc%^CmH)7A3c(e39j;xLwPUbSNNSyxrFCWj%ov+s) z%xrag-yfz_$0*IS0{D{WbM}Z4PE=Muj;n$l5x8L9O^Xwh87N<|MB2+hCx4QJm|Z zk=OQ;@KvTOY;zKF(~4gxDtkJM#r^Hc{87FB%tBuW$(2P1Ufi}+6PXiHJYoHYrfvo^ z+v|^e8h3n5y(d_e=GJ_8+jc&$w})moXP@tPdKIwb#39c&)~kZ1O#Qug=l%_gj;?63 z;_YYFIkU05d{N&aJI;&SP3Lv6Ug0)Q))3#EmMI`_c|b&9!k1>3N@hpjs;!GmB%}+j zr%CCDZ+LxZPYnB3-KV}9RpL^2rw9BjWZv|hUpwN`1|{9Ui~{FcSm)Gk?q_p}njGe7 z^v?c)FGow*)4c+WPUkJA9PbR=;OMw$$Faphrk+3hps(WcV{6N+xT+zny=~=eFAbhkJ=MPS zzfSv!--|w7o(X^QiavTD;&4cK675$Xzw77QulG9bBi7E8oqo_+{*H~+yaQiFnC@iB zSiIf%@OU%9NvAa(busTnNuWq@qgs9K-cVO)=eMm zm`xcYGFI5#-k-hX9Lukh8)m1>xX|Jp6|-_jr{Qa*ycZ=gvG$j=zO&^2tXmMe_~zt~ z-~2up_$+3?u>2YMw#-EpSBQ+kqUvg>PmYy96 zKP+`iYj<1m_jZT6vt>uEp1fcT?z!&zgNAG8)J{xVpYLjyzNuQT;Cj&Ud6&w)AnQ?aryTzw6Xe_E>o4TLY1K>U%yX< zLi6rD?iP0bOHH^Ueoy$e+_Qi7iO;`_p1U;OH*C7|WF~J+*1BM??MiiTDy4O7E}qL@ zmXN2z{dt<_TJS~PA(|Dk^VEv_pXv)!klT^ULNJr z=NEbIy7KF2cT`j-1K*=ydwdr_+yZ&JfOBvbXw&Ragao0t?^w z&dcZ5ZWri$e!}L`=e-AiT(7ac{MWrl+@(GvM`Ep9j%c~U#B1eCJ*RwDzFkuO&gQ{4 zL*32H>@VE{9cq8zmQ*~?6V6OHCb-XT_5zXJmfmXL^XOIXRUfxAnM3>4e4N$%j^-a!5)3^K8PY`Er80T<1>OpSUf& zx>LF2;`N;dfs@^tHh)mE{hIdK)~vm0Mhfed=nRu%jZZr@dUwoSa*^fv+sT`^G6!|+ zT+H6PGLq@@r?it>o^0oSF|X4)u_ofRJnKEr=OW7uR<3_zHtVV+<299HUlERjcdt%d zRl1-w_-9z|k!>dNE{T68{p{gcJX@gMn=wszE6d_}1<%*No+lAdxa0li@P}@n(w8-x zzBzYm$CPEM4pq)|nQGR6^yJm;&JM%czCdruvcdhT%uj=MFyP_>= z-35!otUX!Z>vwH+U3PeH*WC@y2Lg)a?au|tm)}nQ6!MfW-F^Nq8>JgMNB*9;>ECro zEcWutS6c=CP7x3DP0#Z6^f}J5;ZvZI&BAXvr}saYb4Jws!i0q8jy#i{pVZz6u-J(! zt!lr!Jl5gu?Q0iLo$TBby|(L5HA_fe^1Ks!iYxMDa?hSrGnXp9?8Ry|v4@dMDx~f(%{M{khhcn+!S9vjcQ(TdSPRzHf zKei`ua&0}z6ZtoPrt$o5|JFP>o3h$iPPQbcUtR0my(dL?cG>bx^%4{2)-(y^N;#6r zdVX^KqlU#^BC}RHr`zvvv|gpdp-_1I-qD1Q3&Ot&<;Px#2>n|8IcAj}ufX?iL(A_+ zqHeBywn)h0-o#z5L2-cxc|XnC^J(UtkV`+~KIodhke;_9%dg`^>{floIkTKL#j`&; zYHiZ+y2APt9`VpB?@4{{Id~v-_nCU+#)suR6HxdT&qB-yVC*mI;g3 zUS#EK*wiX={>kJwjL98OZ#7=;PgN|`knfqoY5ZjU3y1Pk^(O>XK5Mry^d7j9I5A{a zMfIEH^h35ur9$zu!^Q5%_%Cgm{t+xzbpS+BBY@uXi+znO9`w9Ti-MC!SUsIcMo z`HT6Vw#O_FI`*yoc6)64#GgxV=(o9E{1*E+?=7EX`va3z2QMvOYI|pjuk(~Lxf$OM ztT@*n9Nntf&Jy@2V#4n&hdyxL?0)e;@{$KDyXLazuL3?;Y4a<-cD;V_$F?i2ElYVM zc1nuB+Wbl4QTDW3vkv-cG(P^Y-er}{GR%o27x%2K}7m zTPE)oT37QeRcP+Iu)_`Qjdcq5D{gAbajWUy-M{{;t<^u*iMr2g&Rst^XKia?){^dH z#U~OSq~71Xe*gNc*)MFCtorP7N7#W~ZPAH?bI+U$E0?%;{I%SY%HUOe^H+Cx*!mRi z>sj$GrThP(jlPzyFN7bg)nM5^xAL{%WS`e7y_EJA9Vp5^!H{3Wr!!CYZrs0BEYog2 zjr_OHPxb7ntL1+$WqEzQblz!y;I!R!|L1uMhWQ7)`=4RH_1#wU$-)(1gICF zAG~9a;rAc6yt*dzSn}U*G~2q-WyX&iG6&VBOit|IVzn@r>E^y8o0eEd?4LTdqEskr zhxXAqKbJL4VVM1=EA;09lhya@?=LH@sr^>gl6qH>eb&pjz6Lf@_m)37`^#{>n&-}V zPPt_ZT`Yno=H>Pa^7(9HVd($%YiAkHiFs#Ka#ap6?o)aGFMmzzLY4`aU7oe6-OtZU z<~V=g^uMa3i(YSd*CiSD%4EI^&+O`!dcBQXO72O2(7ZfRyzb~~PZ6$tRz-;`WfkTw z`Rg5XY)|;c1(xC7_RSYW!mm#H6Wx2)t!>G!%`2CFwO+EGWASDtDS2Vd$l9iq#V?)L zUcFwp!eZ`6R|ZFii5rD-LY4O`Pw_k3X89vhTl{ulQI?4HyJ;O7ziO%;@T!%zS?rM6 zbMO$?6@%_J>6wdqifeB_-rK3eb>^J>RiXX6Bu_94xfC!}9=&@%V^4O(n>*rPGswk?jK2=MJt}~c3SBob$-)U#%arE9afl< z#NlxJ%d;h?Rv(pgIGDe9hlGlj=MT9r8QmH&HeB|TkNtRc>l^P>!yS2l!_J=Zm~rac z^wl>)7c+g-d-Q3csBY*gr}E$}2Xt0CHrzXyzWDHT-(K-B@p-K0PQQ9&8yxR+{m~gY zjU!GQ)^p7MKEZva>(h^Q4W?PyJCtq&eZKMNBa0#Hi*4!2dxcM3dairbk5O06P|QG0 z=)&jg%{pBFT9V%gIzEUxGJ7-A!Z+7-512Y9sr(GTBE3V$sNE;($jiEl=))b)cTeBz zwkq~ghWn4Rhp!bjIZK7;|Ms}cl_~Z$I%z}qj{p4m6MRn}U35*aPP6*`o`{`{&mQ)A zRXq4O)mTk7W7*2IoScMZr(a}59Mk&xOtseWN$sVH9XvbFJV~(L#cJ9=`_oE~bd7Cn zA1|v#?!EM9MU0+-jdcV6?wxxIlg%=AYaaY?^8Ng4dvA1E&i!n!T<~%mQ^^#O2cK8! zczR!QF|rPfVS5r!+VI^Nu~Lzf1EE_;gGAeRcbPi7V%l z)4vmOmF|I6CwdJJ{=IFRbnRH&muzRw--WLKdEN^+`Nq_9y!^09_1@tP0kis#D|}4! z;!oV%SMVtyiUCPy2d3s zU(C6x=QO;3V;1W3_I$8)sjXdonr5G9>3@?{v6=35QWvIabbP9+cC}g{|BV0DPJuU1 zEa$v6dFW7M%eQIwj@0n)=huHYusV05xeEIy$Nn8@k&V8In_mClr@yP{R=!iu>yKWR zckBd}*0q?f=uo|=!SJVZ(zy-uj;{YIe;|MThTmFqzkEr5?Rq-!gva^H?{hmNSvWJ8 zF235s;ikVjas9NosyXG}Q>2Nt)vpt}+*-K$7{m1S`CD&)6<70I z=kwlh-ke((mQCN5-Skdx|53}{;@D>@;YYcj>gs)tENEegFF17kz}jG=DKfiDB<4O5 zcY9an#Zs)c_Lp45LhDnngg!0h**KZ&A3KkEz%-Yj7QqPV#vXxYp}TEgzIqi`9el{u zv?k->fomJ)Zn#!b7-(Ne-%&NZl%~U(pwBrxs!n8V{KYSl=yk@sO zeE!Sd4pE)T{c+N5@ z+TJtWLhH`VgMVDlChC6HJt}W~SIsFWKaNlR@rvmG+eExEyGXZ@{V=A3zc{TiP?Kjtl(wV|huNBVgJ z|Niv}H@F*3_$-+?=l`1UCThCUhFN|a7=v#bEnmFJSn0Uc-WVm*H=6Z~E$tlJxz|Ns z($9!nayV0~<&*NgX&t|+^&5V0oiR}R-2Uuhq0p6t7`8H*+(6C5n|v=1JuFq!E#Q1t ze^Y7y-8gDj*ZQgU;CvQATuJ3uH^=5W{tkTqHve6ShEoND0l0U1i{@`WNh!+#&_d35j^}Jmz zDdN%6W6fH3PFq!&ElfHx|7B39RO;H_X-;PAJ3iZ8oZ%p|C4TQVfwf75Mei{iGLl^#3ami^(;LnHpb0*VW)Pq$d#F}j-QtI)KjbVgUU z?d+?e+8fzo_OJUVJ~b;%@$<{qVwZSd9Ac-L-UMcUD@f`q&^r};8o zeUx#~Ra3gaCf04(Tq^fYNQ~+Ffk*xk;{J~=_pRHvX!239s>jwQVK48daX)iZoPV%C;x|L+{j<2B*a+m$DJ z6{e*8SZWf~uD&(eNAjGLWr%jH)lH3O)5X?o;s3gg{rSB1FK3zrKYe;#WKe6_E8%he z#ixt!?e@-PTD$ypPOENc|8lF83vJQIEhl|0`CMjY7;>UuW$Ba;7YfUBKb2*Ko$Qmg zwov&clr-hx!WBoERQEf#2|Q@_J0d*!R?G23*XtU)9*T*~vYT(_opW;PF10lcO&U*Z z-8k4adOv#zOw)emzJl@p&8rQMUvCtemA569;b-3B;$MEshT3YsrmtG^((9jfRCh2-}h7hg%m!W-~2$wqM2n)#lAXH!N>9 z=}d7pb3K@PA=0tZ>&)if8H#__`kmPDFk$EMj1z}lr`sBPg&kpCc5}(E&>*=_PXbmR z;#qfV5*ylAxdmk(<-P|Vhw$*^1Iwc3$bX?C_09>j0ImAu+UErOK(+}?Q z@~O3AI=s8zcg8*Sbp6$PuB28u&v{-P+O#mNk%f<=Q|R{JCzp#>{WTT1aofp+FIwk_ z%SkVxV2?<(ShrTCmeLm+wl!GZuvE(XlVy_A_Rp}a-$ zxKzwU;rn+C{xnMlU9k#3|3oeR_LBCfDed<@9y#UK`SDwXw8#R!)jG^~?SDHR{qk$q z?i&x+-LyE-Y#5U56!InCzV4j3q3)-Osgl(Vi5hjh`Z9ag2gpl)z4If-B`bQ%Zmt4@ zSiB^^w%{HYMcN6XW%>O#XK)A_UENuKJ`3e<)w7} z>)N%G)J>jG^*@}jh%c9`LHjL#T03j_-`mxk$9IQ(VY?HNSabKl@2u}ei(U2w8cELo zmmFt%Fn6VgP34{P^4FD{IVbI0tut-LCCeC>_CBlVSL<)J^PKoD;h}2&Zp!~g%>^4I z&6ay=#5P8jm(KDK)&2QEf2y`mgWft;8QV8WWdaE^ssg{h-=!`xt#GO0p-)c1yH9_v zw=IzG$Vu>v-?-nYI3oOLxsvDSz6o3Ji9fkic`4+=N%j94kDmGau0NX5*3Dd1pCs7B z?|$N`^1fa2jxyGZ)mSde?tQUPvgdcks@X9?%B8m=Z(M)nkp1$_HI_?~iF!#ZuGUTO zoVH1aWzCxJFTc-Up}X+Y?u~CJr4`>7u)N+m`@4mxg4MK5W^X2N?z>n$>GCCIu`d&9 z9)8&1?I+3Xpj>tI)}(W-LTMeJ?;bgxVYkrceEJHn^OxQZ%#~oI|r(b1zwuC)9)*rYfw~}kZeWxF4{eS-%-LILhT($A5gLoI)wN+W7 z?{}THv8>s#pn_d#;T1EVAj_T0Ok^(la70XYz*ZV)Op!u zH*eNGMayqB(W&S5afV&06nI{-;}wg;>*IOF)`wjDt7i7)cqMedvV9@`x{?Vn>KYV21#lSc8N2)a)TIU7M*tNb(&pQ81nLcZsiM> zx24~cxRY5mq}EStwN~s(y`QD!QFZ!;VoqCk=0pMc_cKfM0~xe>0=EBWTEhEDT;fF5 z>ZI?b7Z+dUURFKfk#d8i$INS$j5WI%INkk(cdjY>Yhe2+X|Ye6*7nF9n%iaCH+WvX zefIO4gubt9Cif=4-MvD};DNg0ei!Dj3ZMG6t>+{(uPr?nurg<@OZBsm2gT9*M@1LpW`?TNTv#sX-z9n_uMW;AVyxH6I>v!FZrSE_7<;bp^T=hzF z3md~R{mDJ+TTPcl<|RDd-%?vA_iZ-!C11(2;$qbv6H4QL@a|jv|J0X^c25?=D<_KG znifT^xVy1$bCB1>wnwsGRtLIHS(6$6GRi8v@?x-oy~jft0zZXGdVVyGw;`prXA;>PM@DwR`thd z@*Qu5S;ALh%#BT^rGJ!cm@?;H%~i(O0NYb*?Ccyrg@)xGJW}P}Rr7b^i%+$eTkHp^Ltl=btbSYG+MCu*OL-Yoxn6^-RxrQ0KpB+n7uvEaw&mNjwfKFJ0Cdt>&@ zar&wPS)w}p8C5tzAf4uE@ODe#ADg=+Fjd!u>84x)_t*-<~NopnL(ke3vYBpubRj2 z^!wlQy%!<^w|rg46e+mIPt4}T+Kn1vE6%e<1l;=aZq@RGYcI~T^&{==9()a*7$hj)kZDaAx z2aMb%aj$qgb8=6umnz%uqjj=b@b16+#TDs1Cpv2m>76?}t-JigX;ICTUF&-nxASZ( z;#j|4PJY|Z8F80qTi)*Eu6-zb?x5FY9pi>4w}pcePyBQ#yi??`C~NnZ^9pnBdDz`E zT3K|Nf9u12jD5@J__VX!4FC3`<&^U8Q_(@~>DMmUu%_&oWg97VN6-4|O=Y9fM)%z^ zwKIN*9-a|kV)Td4zrH;;c!~JLa~F56pI~uL$^X0af4x`oi>-XPB7O?!-Q>P=TI0mp zb!~Y(v8Eh-PDjpl-&|y;rdZrEhgawGHEX}sZzX;DuLSve&b3v_`YZH`S3iC8l{Mxi z{|)q9o@+T)Es331DL?Ov)VryR#8$;=@Eox}&B!Uf!NWh)amJxj8*Z-u5wx4-M9s!; zg~1MA*Q&n#UfSmrTDE!P@zsJR!N-Cf7(=flzgX90`B}m;eh;(ELXX4I>lQ0TAO4}h z)O^?Ec6aCBgU@aic~{&^?%+J*VY+u|l|b~AA2&YaZuzyqM^bx}Q2MXBZ)ZKbw%V75 ze^_(poXMgmIZl(D-+Zj#Jh!39M>wbdw&UJaY#ZBp`aIp4__k?2=8TnDU{SQ=iu8-f z*gqvNQZIDWET0?1Gm(>1PX1er^@A&GuL%phx|Hd=G+3q7#&RFCi|vsW_j^ob7cn?r zopp)h?>8Tw<-fU4O?aSLFxAs#QnI|>+oj9GZhzWjvBvsJLBf&VUwk=j>u;9$&0iZl zGcCX)URq?&4H3oSJdFH1Xko$2H4y!Snx z|2Fl>e}8oBZAAKnWQJey&s16kx8`-+ymabR?~bND+e7$oYzpO+U;FcvrdZ2@Wrve4 zau_aH@#9ZqNutFpo7F2fcz4HCRLIPe{dNC+>ytIVgrXVQ0?teQaJ~IoX|q_EiqzL% zUxe5vCFIAnwOxMrVYg&MGRJC**Ee;1x7I8^Wh(fBbJL6`-?|JIt={%>XOczHpJ=78 z*JdT;FgSQkv^;PxeZS+P$*->L`Y5xQ>z`ccl8I7$2fZR!nsHcdTwO3_*N=r!5=TDG zd!`Yhcxjs)L;jsbKUW=HeO)Ba#k~7iRL}40vmUKpqg47Yx%BidohGvtOSoChY9=SV z@A;HimD``f-Iu;>NfyV8_g=jdw7qrrS`(Wo#$JIFXLJ8s-V^ys zwf*eYD4#8-bGIkic(lGea^%(&%^L}+aq{mBSt^T{M((z_-}Y>x=9Jpp-Dg|QN?!_z zUBJJfhr4e3pZV=_?!PZ{-@f>0qBZZa{8Jh;KF+F}t6TSAy^p_|!rYx(-0h{8`lp?~ zskJX6dMQU_iPiJlf$Nobx>idX_%*o&GzLC>d-00Rt24zpOu1;HS`v;2%Fe z_>@H~@z0y0b7#wcfinwwe(hhJ@w4gTtQ;w(^L^i6EaTLj7I5UbhUqlDRXk-oUzSxb z+;Y|-eOk?g_m5V8n0QCysQih5^PSxPTh$usR60r>{zj%gIJ4o@*?l?J&hogdI8}MI z-8Zz~b8y?c67xOvrEm3a5vJf+cj$87)JF-v5c zoH~D|eq^bcreA8gmA2QSyB?1gUR!WG(T-b+v*lfk&i8qD*S~E)k!@by@3UmqwMBBq z_dK6o$ywU&WqBn{|DCV?-aQ^qS_~Av3%-oMZdIhLqLKTy-q|Z*{`~s&QyGM~g9{@b z`Yg4`y!EiqsyBRX%KS5;>z%%@5RCe>>w)=i!l$y*Qa+x*VvUqg&a-@p8bx4RO~MN2K)w)>3Bne~sRUC`Ka_L-2T z`dOacJ3cRBYWKY1d^Ps|F2gTVH|DGm4?OVhMog^zlg;;d*A+b2sxe`4>cw;3TPv^a z^^U1}^ZIkds-RspR`0?kZrbwnp6}lLebrX~(&gV~JI(A-*Wy?*ajE#MdHXI_PAzQg z5?b4GWW7^^h)ZSlR?#n4Hct=L)BCjZ*6;Kc%8R}oR$Y_6+U!Fj^RFox?TNR}oyZWH z&YZrF+i)Y}EM@zHe_V7!5++9pt$TT5&Hd>MluzH8XE-}n?7_l^oR@nqM_DJWS`qA! z7#Xu!J9M>d;^K2B_f^?5nXd4E_~O9dX>B$Wx{5AHMsZ%T(B!*u%J#w}wTlyLbpkKW zS(Scp`mvpRr(M6++*fZnuiw@0@|{=rZ~lLHMA2-K>t2h5%1+E*jtZ>!r4- z<6NC^!rm<<8*Z&RF(vWo(=XpUCwJ{RfA8G8V+Z3Gs+?JKFy`b$j;Bu&Z+v8I4$ONk z$LpAuQd%b_p#ArFq1${>i>VVV7f!YgjK4JTY@}>U$m^*=9Tq`Bep63zF+7{jWH;x` za^D9W?yqLBesKRLr+qZ!&Lv)#cY!sm7B|HgAFfZIJas`#z~^8~c^+qL_ityNlA3w0 zz7V<+|F!1&_C?>mzj1sKIVqz=?ES_`h1Y}mZ8DBOKe_C>0sFlG$2rYQ7_MIaQuuS8 zs!DAX)1u@f->sScJY>wC_x|+~`{lP8U(FMowmQ(UzpC|M-fLfphyOWF${B3yU25vA z!rWLYcI3fzzj*(kDKoa6l8$6EtPd+Ya58pBN$rnyyY}*JY&apqwZHjsUqs!3Et@ZT zZZh=NdAzy0c&eX|UHz^a-m;5Ehs126qwk&5FF0Dw;mB+2l6+D6mt0}8b-Vuc&``!z zw?ht3FWTbPxmo{7dy~Cq|8JvLUCGYN3WcJU6u8|lt3IB&zg=3Q)#;>RD*OMS{fEvn zX}SbWIIy3gSbBo-Y_4T-pXa?0indy>ClM>E(8pnLQdQ6_*(`jEQBJk>o&r9W!r9i$ zmfK#$c&_+=>Eqoqt&PD?SyR4$kkQ@j{HM>*{S;?H%RHmBqVDVUj}3N~D@?d>*DpCd*rxwq#m^Gg5k*Sh433)dnu<kkyGzc3WYmhS$w$0xgBwvMRXsj#Bm{)5Ra$-JDmPR`4{cu#5ZFO_Ze&H1=o#OTuTqFtBt(tmT#*tKt7 zhe6GI0}+``vsL|fWo7(2XmXCD{_{@3AK&ieoV>oyuxk0P@LB)5w=Ob!6LoKMa5h7; z%cNAhHSFG}rX@VjfB#_Zxvj!m)8qxuxCqX>Wu^KcQf`yU!S(~`t4}p)&eLB|J5zD~ z9qHU;iGBNnY`C>_T#nrcVVf_)pvSVsMouqoo$}2`%cf)**SJcsZ8>GwBj%lx|NGH9 z*1Ohs9P3KtBI8bVpB8br9_;6xf z5r{i?*zY=bP}FIG$e`b0jCU&?*tIR@R!!QXQt(x7J7?H=|8g}K^VddqK79>{*(dw( zw2V$}0rzQ!O7-?7Mwd4;J(sS{p5u;Ku40>suYLk<-FK=Xw0r zo9{2X?f%H0s+4+V*71;{b6X!^&6k=ftr=+2Cq%>W3LK zc)C*V#qb;pn?AFJIeTB%ExUYalwLsQd0+-0Ne- z>zh?S+iOg?sNJ}T|5r?G;?vkWvWBra>IOZ0wcW3$R5^uYRn1;Ky`bXDM1PNlcad+l zH0}JMu44YmWA&x|-;cFVout8}$-#OxcjG*dDJqg#Yotpaz1F>E{M@EPN2>L!29IlT zviO6|o%6SzEnefZyPdESFTb06Qg)a8=+_~*?*nz31f1MQ5e^MfA-|w>G zLZ2uTx0Q%+)aIr$mzwyrE!J3k*mNpHEF)#cLigPlUrQg$F`s0%|J&1Pa*ulIt;PI% zwPZLXPMp&3@^SZE+pAae*JN$TVa@rDQ%VdJZ)aS-T(9o>xq0Wl{n?JkpRe}esZ(Qi zee3n4PVZ{v&wESSnt#0Q&#FJ67y9zzv~{dIc0QD}-}Hg&(~7H-Kev?~3krOn(3Qxq zv+=E$dR}DKuL;|OE(tz=9Td!yY87z*$X}l;TBkpp-o(CtYs5AGWo_}&Tb2oGB;|iu z`#(HTqs&x&&S#~y*Uwz{G47B#^IyeA*_1_Tdy(*tsdwk5HZPuP`uSAgF-E=OBlfb^ zA*a4ANzaxo`WW74D#boQ?X;_O=AH)W*h^d%T00mXWST~29OwJrRM{NJ9HjH$pJC>; zBd_Ei6dVYIZ<7=na*RNjh*NXC}_$Shmu%e{BL)rVTE`&#jG zk{q2=zFQ{BDz=zvU5vL*eD?2lahj&|kyGyumGn!W7TCXft4njm-d>U4y3E;ES8s3L z*r9jvk5K@J=Tm61x>X+UkoK8Tb}GIrFTeOU`^nuK>-#5voU`Z1z7I+fhi9)n z=2Y-lso|QT;mva_M-<;_mP&mw4OFnr6Wk-VgY|KFk0O>HP`j1rD^gT zj+bg#CHFbRd0e!P{q7BYd}Hmyl+CA(+&b*}sq*o?rTGs0M*64cN?EmBez!kf!!a-w(((4-^&bznh+l9Xgsg0!*K1I*wzHh1i zv2I_ltIN}uk0yv`zJ5P-@$W#h?=4f`@GSqJTEV5c?7;$=eZ7)@oEd)3soT%om$Xjd zp}*m~jrqZh=DXi~O*m8^u=}=cZ}EW}QznSAN0dI3Eq4)_Q270Q;h|k?Z^W1Ft7-f! z!+OZM+4AhtiSM~Bqnw{c$h`QNwp^!}ah@vMpT}z--)opO{nLhXyWSXPiu@^3mA1XU zE8~pJ&2wL-DuhpFSDXE^>vaY*hj#GI8y}*nX*D*UCajwOZ^Y!&i4Oi^SaEEr)PbA+s1Nc&w&iq znO$W8!Ds$Ob#fRfhD{SZv@YS@*UCL5vNl@|JKZ%kusks9@gv6HFD@CC9=WqS_tf{K zsn1lFKi)F&W9gfNOPy^5J|##!2-5#>ve0o$+y(DP+jUpHI=K41$iKVuwdc3ZzNYK? zeoJ)D##Q$9lCImXEq0Eb`ESjK>HidJKF-p#6^iLOt$2@-VZo2&(&ta(9xFc%>pI!7 zf^RKn?22{VR=tm6Z|yIa4P-yDZlTERh#PO7tKYmBu&PLH+3x8#{MVk9VO$a7^*tl| zwC+StlXWjuQYNmI`K9rIK}>(<)Yk!8saF>-pYNb~)4q76v7G+D=j;hl(kBje^P7fC zEDtXJ+E#DfxPnz`K2P1|zp=kWMOIIX2xrJ}5N+CHk``R&nC_-sDdW%d`oZJ2y*~om zN^EB3rtbg4{U=1^`8-C|1TMR?Y!S{-DH_fm!vr4B@@-SU3?4IPqXmbp2fW3 zao14=fejxk8wIah*PSSIi4ot{lPh}jvgIY#Z@$_m+K;@Hkk}=mt!wtn;r(;v^SAci z))U|KacRTW1M6L!1}{z13RdG$A|+IHud z{rawP_-lF`aISLN4n-md2q2wl$|JV(b^uUCb>V*Fr-#@Bg0(L zC++L!ge?w#Kdb*TYqHw2HLun>zir*a6Qg6AB=r2+Zq7HUEJljlrjIY&=die5*s|GZ zTS4?SHI*%|)Z*HndtI`7w|(yW&rFLioJiQW=N_-tV^jSkqdMKX z>;k*lf)|_i`q%a{+SWI^`aC^-=F9nG;Tz5#eX;a_aEh9My>lDSiGHrMCMVhKe(SB9 z?Kf2E9+dG3uugB`_gE+KY^%oShoNkb)#5HSGTw=Za%DJgylCIlzo)bIJEZPia_=2` z(CUA_ZzivsmD_y$9)p4V;oEAT`$LL*T>{Q_ZhREO)*bb6vj2IRY`KVTx4S$3&8m`9 zT6j&>dE54hsaXO0r2byeKGCnT!6MD#&(mVz^HFnlhUB-)+D)0?t(m zyKgTQI4{4A|MHb>`&4~P*d`{{a~gfSc&1>Tv}l$0xkZnwGd^7Ae%m<5rf^S!gS zw@I+=V_s-bnz>=J*r`cMeM*m6zuerusQY_vf6X{*`w}&$yqRv~M!^vz@H*)77^& zlmz_bUA@okMuE^_2?Za={Qal%RMv_uoAgOeseXdpspIz)*t^>pPhQ#QCb8h%oW&d_KGK z)#WQoW=!&Vyt!3Bb-hr+B6Z2q_5^~CxWdZZrRyK0;sxRQfu!kQDsE1#rIEcp`m z|FqHzGxmVEk3p~9ql}CeEdBXtXI+}BD^K|!5%IaAnS0cwm|tw4?bW<@c4@H8g3q;% zyH3O$U(0@{_gztzj*Rx)+LO6!;v1JOuC4gg^qg@b+x1O;7E+rIPITQOuXapKccK zuTWLnUmaX~)Q;%$0+*Q1s-y_6ohHhw%I_FhBFV~sI#+M(Km0KxS2P`e#6}hpj zXxGDo^MhBJ8vnSw(2lood7tn?kFxhpI}UFPm|g7Vr8D0zPOv#L>ST!h>UVdxY|!qo zRmx?(_?U;MQu)tY|EUH$*l)ej@twx1#vhhg!yegvy7u2EnF((Hp1sjs&-megsbkWk zodYBUH0u|&gyIUMt<7%>p$7RLAf4^LkO&1mUUS9Ny>oxC6-gOWBqW8Fbdj4+V4f7{) zIX0(5cJKaBxOq)ciO%fl%yVvk6*^O!Zk<}ekhJmRxgU!<6AzrcB9Z2rqwHbN`*c~& z^69)n#UGyj;d~L7W6EV}R~~A2Q$|b2#(L%H0D>9z3JY8|VCiv(pJO2aICN=K+ zu~Wx;CaZAC{*8+wPiSj?-7v}Ph2{Uf(c*uM{(N=lU&ggCV8ZHc%Ys%V7jCdwyfl$b zcfw~Gp2d%M&t?3=wesllQ~oiZ)mGF5N1mmD=j`5-x9M1^ZS*Ki zIFlHD^v1E*+WE>n-+rs+?=ji>Z{{0|f0CiE7(W)>k_!62MQJHh*8UKCfzOd|7I+4$ zGFHj$_}I7GyhSi#tD|mlT*$fjS(VM}^qX`lwywEY9w_-_jv>RInJx<1@z0K#wsNr@ z`*>#O?}9a-RJwJZl*v7tdb&COve4^yDN7i63|E|VIUbr^!Vd4bU0LS?P zZXTj5j)hI7d$06No{-CD{tqs zM{m^$mad#te$jg|zrw!uMM7KNXhh8o=r8&!Hb?5~%@eaTGVgg^*w^40t@Y#aI<1r+ z=530CV@?#B^~hr3i;BPfmJC7*R_v77GyiK#%g^sC8^vt{Pq6FF>TR?1I<$y;^&Z>j zg$L#(NFDc22-@u{^|eh~aox;a+Y{K&vjuW0x#k}Kb!b^Z%t|qr$n&MjA2%7^G5+dw z-r~KT)3n=581G+G(3%$Vm2Y2N==;uhyPn_MwPl{@qI2;J=EP{*%-C6Rw^B%@`Pr{` zQ`4nR^*`^wU~thRIpO586x->2>x3WvEaA-gBvF^O&roPZr)0ma?5taJqRUzGWOT|} z^n;&x>WB5SSNZ$B(X;Pa_;^~rHB08Ewuc*49X&D+Je>El?O1JTYvZ1{XU7uXdx+1_ zGxB-l1Cy)U=+kG(3B@_u}K5o0E%c-u`KO!}QcLFJZfr>|dd$ zexGlDJ^TEh!t8*CZEif*N*_n}mU%5Wy#D6lca|)5XRBxLcZ)vp_SMcaCr$P*UVneP zymU#y-g^qZ!G_u=r`x_g-FxxeS!P{F(c?QdH}p&8YUsXXw2EFk<8IZ=V3q%Jj;n6> zWc}P^{V`r6xqHH|FL$nfyRmws-o?hp6}K(+>HOW$8PUC;`Nm^u$%`kyUfr8F`QbXo z;tS{~9fyGv{SeM8@R{q2ABCd=GqL$viRR=nq?w(+bu5 z%`N+GMiu)7@||9#QM*I^@edIv+ci517M+twn`(KN)lzx(N{{$*rxy}D9lHCPTV~8s z*ME6%r9p?sFMearu2bay?f-;@vcz1N#5hN@Y116b2|fjLTo2*VDAer^-_MZ<`X6^}6pH zt&I0tHB1q{!Kc1^t96~M^$O4QteL-G7Ru)Bv7H`#jPtKe;f&&#f0mD}9b1FGE$Fi} zTXM}$rtPQO(~{U()y~(I$_`2V5wn`Xe`e#o^+HQFuh^{~H)&by-Lm~2n}}pH+^#S6r-N--YK)#VsqaeJ=_pd zsQg$jdjvVtJx3t$Zp>9T;%lHcim0S)%(gmJu(u`cpY$l_K6G$7a6vj%&lBU z+-*`@@7z_7xWyfyL;@VkJ%mF?YH}VyXc>HqA{W~m;G?*+Vt|mf#;9;3x55w z-j67@y77HD9K(EwGP@bx--(d)9fIkyF&< z>FWb^1XecQlJ(g6GUR!8Q|io9w{PFqzM^++T4)w?XRCFo%GU=H@@i|g?7sAQ7RS^n zVe|P)k4?C=Kgn+H)XC*f6Z@E%PG-z|Wp8(N1HaEsuCG_UH(X}%J1)M0!90|ov3*X% zGZ}%p;H-{wzTdYO=C#BKScJOWVtl`OQ`+t=`8ERCpHt>>S#F+r_1=1QA&rLr>mz0a zZSy&X}Dtt@dKm=g&=()guJrAJk2bu%0?2fa})$ z(3}AC?T!7-57O8e_ib01+gQNtwx5}MDtDJP`zf6N~--`Dta3fcMnh(Xy5M!yZMYM%FP(IWB&UJjAi#meIuRI(L`~ zFAJ?*{JT<4{ZgBZ!p!eq_svthEy~DyDQu^hugg|zUVb^Jko3T5OhUI#{MMY-%O7aY z+`X#5_l3;V?UFq$8eE&1z2geo4_>glQIyZ;x#~%iaiduLv;L>P5qFi-XKZNx-nS!X z#rs*rMB)mh{>k{w~|OT+C}jN_~}=tDegJ!?`!EuJ8=pQNEMM z;iQ6qcHduLgP!sI$S95xV0op5mf@|KQ+{+9Q7U%y<)wt&|p_c8N*xdslqhmRan z(-%a=T%J6UtT{LH@m$hP=)%xdfG)jis&=KqXtEbm^jX1mT~ zroOGWT@(*mG=FSnGd%NRLB!ITsZp5%e|WAgZ-2+6Fl&#WJ^z{&ygmLx1*e+amVUi* zvU-+Y&;!Y*TlOfa|L)KY{46VbzQs25zUE?|iQ$3ik2bkJez1Mp2h(kxpCek?T%P`a ze{p4tSkFb(GQW_yt!pg~1ZQhsJS}MYzW3Y@mCGfQx|aT6vy?ux^ve4u`+k09>Yn#K z{C1JT*V(^I{&VvLo<95hEu-WXPZlf2(^pR@=<>YpUemwkiU0@K*Y^oWr@To~>-|x@ zQu)GytNwl|vTsk#6#9PnrE76A_tn0?D-zioopp3;mKXoKKF6%X(c@3)c3Ty`Cv}_) zWV`Fueic+#;&Jda2)+0;=H8JPZ&`Mg@~+r4Z;5wKT~8`;Y-JkP8L`V4a~ z9p#epxE>%sn`hcZKcTtv92|X`XYH_%xz$nA=KS(Ylg`n_|9)F8HTrfxknQs%IhB~1 z^A=ghKAd*p!>f+e_$8Kc$Cp+A?KU_Nm63I4AJ<1lg%Iw^C-=>F=6E15LHge040e-{ zgmruW$Nea}oqJ(def80wBCG2sJ^J}iZ}&9T=%S<6Et}si$$Y%dwk}lLYUi~^cKrkU zedSlQM6dmE%v?EbtF7$L!1RdU+*kW%NKDNVkGga4w{%^Eh5O1w?$fefFZ}ny`Ey*V zR?VCn>!$Bju{?Tht6JW?pTfOG>l8bKj>>4bFG|qt>5n`7((|$M%zy)zI+HH;*~+K{ zl!@&M+^9Wu?&C6!GOnlb`Bne#*LcZ&dn0UPcSdJsuKQ&Zt;bn&DeomF?g%ea5=3dS* z?6}n!oOe+B{A9=N+8!?3A53y>xNfxX)i$Mq5-Z*JXK!)l=)a0}6yPcg^8YxykM;KF zd)#&!kF?&I)-!Tz1|Djada|#w!r@xllwury z^M)0%+Uj)$-#6?|`?2(VOW7~h2a}I+$HyJvw(PFyYWuV3nD57l7LW888opdP?x3a~ zmtFEsnC-RJdQRPT{>X#Hb3%UKTt0hRwDFH=v1Uax<`zyd3cquO>kzZn%}YAMyymm{ z-@mBfGk)#9MwD&VmBgKsYF#o{=d&a#+i`mHy`A6LUa_gA|N8NXjuuVD3h!z&mo@lg zeVOivfoFSYRIkn-1p8SvS!zgDx#qRs z)cX(aT>bH1bh-P5HK)Fm6ne78F})1dIkGZwfk^m~T^pqG@3&0tWU^V3}sY*2d z`PJ~jtw~725`hBx~1NB`#U2PWC-{SZ+8u=&yxK7~1o z``@dV2QD%$j4LpfOEl>4w5@$^Q@L;%*J3}p7|ToTb7NZCp6{1=cV5|{`n*Il)5PO@ z=4!EAP-0T?3%1;zHp+~f&5>FcZ3RO zruSN{%71#L`{VKT4|S(rnf%j1Tlb!T#^gOK*YfPJSbzWf$whn`mu~&zKkqPmckQxg zk|LioSMa^cnz%_sBsVSK?#8IHjJ*%kS7q<__iAHgmU+8;q1XHd#m6auwpvyX=DFTc z^8Y7N91+{`wRzpq>Jy*B%C@o2w7#Gc9D%AocdoW(E$kS8spJ&F}m;wL$0LGpWVO zSD*HN{MpppFr}+6_I~P8Wid@dw@2sln3XrA^ER@_T^4;|bVBIrGTEpG-Okw}>mL60 z5ZnIblfi~~rzukAQdJXT?k%jj;3cAFY<;2gfwM-zjGmI1fT`yHjWooU)V&evx&1;y z{M?ImJC@D7oIB;MAp57hNqf)!%oY|n_TOJBp*p*|e4)UN0`JAwY(2%-F`Jy-rMB>v z#w~HL_^w5pL0y%R-V7#*$O*!GiW`XuM@ zolZ|~zqydpFCu2X>g+Vp6JBOqOI6C$CvB~{vh(A_4;2}?-Lq2_FUFpg*ZX<*(ySPZ zVjp4mEBEDcW(#YDSjwD}N|t?Jay4ozBkzlt{YqB$M#+H+yS=_DyyLXj`yGG%@T@8O zW?p4_?s1`QRlq6+$2HnqnYa4Gl#Pt|E=ld~{wnzLNEydA@w4+@|4d9+Q4;HXz&FSG z-sF!~g{yyXwUpgnbvZUFLfGEqef>|C7py;Iqp$p7Ro$s*@q3|pK*L(g2jvzw9(2B% z?Ds>(UVDW{GEA{B-(9Z|{dAe^qNc4qwc^YH6Z}?+BzbNw>+@JEmoxj( ze%@6qr?@%}I(y51k^e9J-(2`aw%p6=IZWqR3qE}EoOP)>+`RYHPsszv_s08OSb3-Z z%NzUP`{}%mjn`hddVSa!>neFPAob$C&aM4nyUJ$m?!L!Z>~-_w{U;ThA37~rru0wA z<*fA1b|0Bzv!(4h8rgPCeJZixft2tH=g#@;=i8FcY_64DeORhgWQhs3Y zi{rwKILB{`^VuIo{@WvUSvFHNf392Bl?O??U6y5fE-t*-$k(JOx^&OvIqBC6CvN<# z`cj~OZDMu8BH^Me_D^bDn%iOu!`}9#*4dqU{XVooL}b#Id5anLzq@w+$KU6*8$!fv zYXhEKD%0FjvSpP~yQhL?%KeL(9-CCwzxWsvDiXED;oqB;#Q`@$dH8Dd!z`Dayn6c8 z?)1BM48Q(Q(~VlK)FOHRgt+d~gOgZ7kJ@iY|x>{*AQ~ zIh{-YU(Bzo|I;pRQPAm^ap@_C_{S)#^~Sf#SpG$BT)k(e*t7Ws`>Q5TySMlK{+7Id z_W89Q&*m>E{=k##efz_7`3o~l^mWSqKYj4pP0)4SW&iaZ-)FS;-m$y?_@Kki;!)1 z?Xb&3r^>=KGv))iH?|92SvPT7p;UB5?aHXzYf^dNaSCqTo8h9hw#lqALg_@s2DbS! z`<_T`VipW}y5i}n!$MI>%lGD6vZq`w)zr?_*ID`cox!W3oX4^*zLTXBmP-9S_}0=c zyGVcGUdv;u6Doe~bgBwSN%23C5Ms`FYvQU2X>-4Ap6-6yx&?8k82*+wd)_#? zC+AhQXaBBE$(Q^+3d{C3too@cy8foLF`LN5)yn2BudR7kuh(k0)UDf_zA`cU!Jac; z*)^*IUG{8n=szsp86vNGX6^N>ZRQ8NzwUm`%Joh8b##cq`oAaNaot|JZOiUcioR}@ zwo9HD&T{=+-R`JfR(B#>KGXA*w;I>G_S$)OuW878?B5x;Wtqozlih{wB^=+?PWDYa z5NO9SA$pcvP~r+f?_W%tE#!;t)-GFmIxjtiNlxr-a>d8(BB6c(?@g=Dele5~w-?QIa_6b$RqJH;hT0C%B zQg`0P!zOyg(a0s-&6h5Hvb-!CARhBSp-kB>wP%IakM7^MVlPBXz3DxEspEmndw;>F zdB%-1x9UIMAziG!blrA^^G5??nO@$$ZMtZ`OZ=gekGIZM(72Y&?0Ub#gk|l$X&+{m zeze+Q|8vpH%}xg!dq2gzVB2(L=6c&zRxh7_c*KybB60il@i3+b^Z&@L*kJZO?U}mU zO5V;D-3+g8r2Dy_sr{3-C(f_^gH_sHMsG9yeUtdV&giL%tYa#>b|FA1ut>P_i_0Ow zkeB(d4+bB-oBC(kpT?IJ-;%$iaI3vA4LxGn{e9WOA1|M7Jz;pZVPZh?Lz&o@lZ2S7 zO8hohaIXHOZ5x)lpvC9cH{0TOSJrhOd$USx+AZy`DmJIe#h%>qI-#?~M}6&*&lOIt zH`hAFYh}z?r!!&Af}H;5Ot&ZQU91OoYiM3NcmDDpyJv61)YL*MW}TSVWwk`GmH%>w zcfdQ%+YkLO{Aj+)E%=mk_tf_cD?gnJ_iCsUIxY75%{DpyLs1NG4o-gl$DwZulhEzi zy}PEIvXlI0=F|3n#E&{?_e&s~u_(n;$S6!uM4TC{q-)Qe-nCuf}5pP+EE;N$dcCHYm4B;wkv z&mY=(N#Gg#9EZEl+ET8GSw6Fy^ZfC!4s>WZkzpYYk<|u=9rmm z?+)43U(!mE1dSVlF**}{R<4debo|&li4S`$ zKU{X*WctJ4#q6eA%TK&5Qog@AJ$Le_ZFj$HUzBr5y`J;VH@|bi8?!gBjQ^p+`eyPp z{_;uRyngb}n)b4w%TxHi?xVwxl)E11fiv^o&SJW` zEKBB-pk7#|IsZ#avHOJ&4BOd)Kr)et+YxXC(K3s5X#isHGevapl z1y?lR&)6?*=Oy_zljHk+6?HC?FE`y4+E)hZ$vn6km>c@pFm>Jf!t#lEkz4QBZO>gi zNqWVN_x|y2##}nV&EX5Gq|VP2IdzZYw_Qm2{!qUe{ZH%M53X@EGqbKba<{7JeC^iE z$7d>48!@*RA4C zsXa9o|Fk~tHLLpDMY1Z6j6dpq9~9Uy?){|iv?A^7FU*pdGbbPg9t!u^4lgk#=efag!sNnj6*DstOYV0#=Xa9OcXn)TAZ?zs4 zetRA>Z%>z6e)mezX~xKqQ+?sT9(z@8`?R1#aE{`gQ~_3wrtCNNDu&Ll6%JpBQTo65 z!kQ1O`8!#;vU|%vXgYX1zMB z6Dxmtxnz<~-Q~ypds*i6iL46b;fhw#31;~7Yto4sB31SdqBr*acrK;w_^)~S#OD^% z{FgqKn5$It`^wx?CpZ5vmF#QZb1Cnh%;gLVnUAZzY0}>Na)YG^d3}-Z7+q#LD<=vUk zxv5U)k6zx-TR!2yh8st_ZOWKGm>=a?7##ldZI!YLd#C*6Z#V8ddv&NZCi{rG+}*l& z4sH%Y5}Wg8y$No6dU&Ju|FnRZi+5iMNhKvMX3{H_30-Gdn$G)QQ1GfA{T>4RZ-&uOWK{)|N>*qVKehTC~lETHtwxn|zqsfg4GG*so z&)9}vF=0J)e}Top&v{?;?;qb|8#h%y*TuEp*ZA`-mP7L*Wn_GQPG3~V@gsbH*HxCi z-dXLnTJ~q2rpQ)*Y&zpqV0uK<^JBp&L#_5$-|Q>HwA02 zeYwvzRUv!!wmQN4M*mE%JiFYI_Wz}A82kT~&ZQ!ClG3^P2P3nlv&yDy6Zc!@YV+Z6 z`kmtbt-Ei&Z}Ul2eOw7TlZ9`u5wxABnS!mbA-Of4TSZw)?f(7?!)|Uu9oy z{dy+6TKhTk``f+KpN1G5NS}G&Shr?k*se{U%l^r}xwL8G{5*wBnY6A~23@oEooHmN z$`W1o`OyLyz0=pe8869X&b$z_G<1uY(DQjapXXmar?B5PqB-VEQ1$P=%D9bdyRW)3 ztV}y_w$j|u%vBY(uyEIpvX?wl&X=&-z z*!#9YYMyzH@}e~nIZfxdEv=aI=GV*#b8bn9*(77V%*<;~#8vNuFSprdvDJs2ef~gI zQATW9dw$Mh;~(FSZxP*hyy$AWwb*6ZsN3E$T`Aw(ZKl)(aK_wfKfPeh?Bddl_ww2~ zM{0CTKJ65rS0I$Gv|)Mt$!(=Bte3Z6O#Hm**~MSVXWg0hlvlD^ILyr4_0gfn*kA8ru~r&&?8gxME$j@STSFx3=mOl$zfuE>G?1u{yj&#J-njZ`Q$;($PyV z1$7=+Z0u)e+|rt`qcbAn#0itq`Jr70~C}R0ow;rmdvt88WRnSE;)V6+akW&^U(BHHkZQlRaiQu{#^Pp zQG}&^&*l)`J8vaymm0U2cAj&bReMME)eB44?N4&vFQ1z1I+3s7iNl+Pd{U8r7-J+C zF86G+=+km{xfF3Q{*dbqf0v!V{v=Ay%E|rM_kQbt%ZYMx&z}lcme{>2_<@o`)(zW~ z_~gA0rh4tXv~nrm@}>D_v*D2n;N?HA>`OSLPe*l>Ai)GnN$n6|9ndv~Vh*}cX;J56>JEcsyV zdS~avb3%+_EqCNaXRA)PUj5efoE_tiCA%KSG44}W;d{G0e2%2|fxr}B4z-CoUg?P& z{>)i$`>PC}d}hCDp52dHNu8vF$HO9Deqnjt^-CmuO1)XH?ajXjURp(;yVH0{a~0pg zuIVp*eqAfNbD?17(M!=AtPZpP`C)lbJW%*cmGv!N?y6a@S0)D4+z6}i*>}O0F)33T;j92 zmp=TFP`}ox^n&A#iv|W~Jb#xIe9Zp7ZPCT5FQ>c@^z7LD?y|IuP+L@E!S=L!ZO*En z7hPEQp-D~b)9s1ujyBhp8DIT-`+-{jYQ}b1`P$u*r{(S!WxlP;ei~p?tgUYuE@yFS zZTkJYoo2JnrzVLOTzGx-+Qzw?Y&@=BcK@sO>9AG*^%~o<5HY6=fw21J`7Pi7GIR)~ zY6S0pySz^R-h88_j|KUnj;Kj4j5&F%Zw~Xr?!M)rB8-dg1>Y?_DDLCGkM-qyUKNL~ z^*NJYa7gk9s(r3}ZaFV}*@@d-tMyogOZd+ws8t5$?Qzz-eC)-e`xYMp|_ypp*BHs-5OC4v?(wIA#0GcUAvS-|5YDW$Z~66E)?-Oyn~5 ztj@T#BcVF*1jE~yGv`eW3jQw%741|#sVnN2Z1T|C&31>4`(cybT!(A1pW1zwtHB z__^5`^NLMu6={hVWh`d~r_IZ~8R1ee_2J?-Ge0je%=KUOyRtr_MsVY^>%xlMN_W(H z?6_EMetRl8Cv4t%`*(uae<_V6<>?<(I;*$t-*xrkZi@|zZba+|xc2yL&Ei=ft83p| zig;%R6rZ@;zV6aOi!XYdJ-WI2RXw`@cjwzWTijUuR(Hw6>E?B3RQ}g1c0H0cjLh%L zkNOnmDs=Ks+8Wbaa+34b@BH`X8y7G0%A0L6e-0bG2#!*-{C-pO;gnkpGm7SQ@vmB& z6Cf1r)F1BuQ{mjQi;p=&@*-JgoIZLybH%|ahTEPqiIy&i(rR2<`Hd6dCzP`uQ1w1#@G6uq<5F-S}Nq-$r(0d=E$1l4&cSE#vyX$UJqw zcc`S{*?f2TS>A;=b7$={JN+)~v}d1^so3A|>*6h!%_!4mZ<^?mH7hw!rt#9er5?g& z)@`2~li&JpJ6<)j*7_OKgwxlu_pg=hXjx-$RPckN&*d#gGdIlR@G4yW;)dDJACX_e zwZ-qP-g{H-Y4UNIyB1qk$ZmDFd)6j<@NBuR`doH)nQ5NfRa0MdtLx5>{kHC8iPgue zZy$6Xlw6kZ{@K(BKG8RibHb;JG^Q+II6PD8Fndf*^7L7%I-53y8&5cC`SqtZ+t$5N zpQ1}FSg+JSIR8Yq>DE%Qk{UDJQdN1anwt9pLhVQLA9MXJ*(dTsr9%IFELZ!qH!2PK zht2J#RDL_ZXhX`5Imgu2JPz4o65RgekV}U9AJ@PowH-kjHZ?t*to!XYwckzYJP;~y zq(4rf^zer zZ1?xAHlNs-@7b+-GCh97DZ%~jz3BocEOxEqZ~Jg=s^^^<2ON`jvurjF$X@a?OKYX1 z(OPYmNo!;0nHRVns4)GdUL^BAVXtqZN7~GJ{ETNS&u-o$+c~YIK{Ik|Pga|g{UU+d z@c*r)^FJocm|PtDd@OudjO=t^Zt5Bz>>n!qb0)CNC&Ex5Z`uW}EoB%hK0hYrne_qY|Dk zCa)ap@JzSZTJS0REOzEzd4Est|Bg3xCD-NZ`WrqQb{y5!yHNCD@9{+(1z&!Id(9Kjal@{`}4gU$6chC?|hr!I&YHH`Ewez>$lE4 z70k27NK@%otD}$TUGh$-7P zF-BEgbzX75a#P2}D$AJ9pJGl=nr3Fx&E@jyK=LLFoeFuuH=hII*q&){OvqteBrD)F z|2%`kQn$pl>t`9>RZm>*Fu|g9(uQLkmCqxiV~*V7O<_6qKk0L{?h>nj{#SOcCy$vY z&pQ+BHM>z{-bHq?jBfVDu8J0pTn|Gp&dsoyF0h$FdC>&UNv=-%Pc!1xmKr1;YjVB( z(nE6hGl_KvKfQXld*GW-NwK5&mVqzGP{aRb2g7n{kN_& zzUMeLTJOCm5K?{l#nD{BrfTgLo8Lxa&EglGUo`W|*-1qlP3!e+$``!uCYgIcEtmam z<*d0}2ft}?xwlVQcgd&sz60Zy5C3bWCA}tXGGlRX`0UH$sN;3rdFmX2^H=^D7|l{h ze0g4JUzzxmBa^LGzibwJfBc80P)XnMYQQlBz0VXIi>BY8!s!wdauZb+Oj zOulK%n|LE{M#18>3j>Uq)-xx_lnD8zS+cMleH@@wV_)g0+96aju>Ip7!8;`LI^Qyvob^~Q$Gc*2aQ8f(n`6bugI(XDQqfd8H z)||J}A)9p>jzV&+L!6@mw7GIxiEaOtIapT;{rZG*<)2Xywv2SAi zn#oW35@N-@?y^1j#^5I>^gCuj4y%abnHsrm26|gNu8Kad>Jt9%a9m{5<=%I-bJC<2 zrq5vPH;T5~5ir|*a*FVU>Wf!e(xo(?YQ3pdc_=z@)+Udg_ZQ65V!in0(H28d1Cx0F z0|8I<{EjFbYVW&|>BF*M4-~M7ogyzLZ zu?uD^m3SBIIB)(}arTqqWdQ=4y4xOH_`V@EuI!_n$;bBZdt$2(uY11T>-gTf3|()f zpB_uMZ;*SxnPciZk#z0}Up%i1$~PHo=FW>hthDRR)PCtt$MuhCs#hS2@2~b){&Jz2LDO9YVVmrt9SfnlWoTwTslKE_tNf*A~H2kjxwX zY;)$T*3h}Gy6f{!3O&>Qdnm>?Lee2(Tk)bJ+JV&UQ#VDCHL%L3-_mx zU+S(ugnI4DRUU9zm-?}DWlb-*5#`#d!L)x@tKs99Olv=@RWDETU0;)D`c(4mwLPnL ztE(%=t!tm6sGK=F_tI?M)@?i;_d`#aUNqLT-oY^Y@P}1l7ZWZl-zaI;s+Vp%;pe$M zzf&WhHr9OWS#V&*UzT%W`%97)3Io4I#(llKT5}QX) z-??w|Bb>i{de(S3^>=3+)4BC0*U9bs$9VJaoS#!Y4JJ z#2P+3aQpmDMgNSyT>&o^zVdvx^Fwx0XUp-R-+7nTFFhhU<sObx&MG~&J;9$E z7If5w>u=Yyg(b!tb)9EM2s3l*{SXVCZ|2-Q-7{eA_c(@BrXN>Mo^nyumRGaSyv@tI ze~)IE?uoh=47-^Ywg*V<)k$u2ll*)lQnGpb^_-`Ruf|_}bI&9}ZOx=J2M%oBcQ`z^ zrMmIn(y#l)<5X^&WL^s6WiyqvG2uP^y>lCvbAh~3d%IY7n2f3MoGnN9>^x&_)biJs zGj;j(b3u$oOXTh4YDoJ{BdqV@kPmO z`2_;k{WH8ae$Y*-kea39xTg9w&((!adeVw^Tf|~DjW-{+T#%8*^?0R&9BZOZT<(rH zW;-4&y<*6_{Bl}^WLeOw{_Rf}CeNC3wk1B%{od!NSu$UhCb47*?!4Q|J~w`%sH)m^ z?(Wl>%g+3KyCC`2R2G~+uE!B?iN1o*Q*!UtzlfZQIk6_0K9OwO@e?Y7I|BJW#bft=&=z}Te6`SF|C>n1MBbS;0wvC}=yHzqVCS9Q%rdGYX&RF#6bY<>b%CYo)TeF}7^9Ckg-$UBp)mxY*w(r-tRd4<5LB+?#3XgNX z%5I!E=}ow!<)NT|$)(-1CA_RWVp>ZCC$X>HYhSQVHTKoU^4bG(EB%uXC6(|Nt3{T3 zwi~SAKEmVkKQj5&+URGE<^`{v%l3U%J?#0-d!M5I?}f*n_4i!Pjn_})pYY~L)j5SJ zX>X>aD6HA;RH|jU*&+TUl zD_&lH^KeEOL-Slg$JmX_f3B@3ejsMYl@$Hh!`KZqTaJ^ z`EQMs%y=Ogljv6`GbS=El-T~{#Zs-ulFzOdNp;>Xh`w6Py6s)~0+~tg*;JyA-LCe! zeAB8-d`eR6r1H~~PM%!&WA5#$gIUEH-zFcrxiIL3@A*3)CY)OK`(aTLN3+n`qo2D9 zer;XezvR32S?AYAuTp0VYUzAveoDgx!U#EX}ihjj1 z_^3H<6ITDQT>6~c#9gwi)*ds`HlNv)&-KF9a@)O{bX{YaFDZ(t+ft3CA0IYeqTTlX z+V`J-x}Q##ShQi$jpeD!CI~ql*K4qe`aAWczfAF7UEygJ)k)cm=Ujh%D=uC9$K|H{ z#}^y#$X_qW+`IjB*_C&jS)bcKb1x6~-kaqg-!ok-i@zg*r9?Yb@<-B>@Xo}?5$D8y z6;0_nGxf%wveu{7C%1;Y-n+N-&Qra$>MTiIvXbgW9*Y)#F^(m|Riv67%8>DY{g!{Jp`dv9?cx-oW@5h!z*JV{ZVg-^uOj-Qz`Yc0DLuW^( zBb&^Ao6k~uce$P2;`ob@=(iI$?MUQp6OCnjkg}h}a3aI$=ME31r=GOX7x-ckBCR#c ziY30^n&n9MGYKuGBQx&cR??o^6S5a4Bcojv`J z_2T#mv%-VUxie4B@#S7ou$A#x$4mvGh^I6C>u2O#?><_v_S;pDlLi|-?V~$6ABfJr zJMCJZZrg;aCs!)>9DG}8AhcfZ$J>gaXFf(b#(|M(LG_M-)oAD zjlM1ktNT*)prPzW!h?#039EX&mg~G%p4zFMpB)wc(8T9w>iO(9H-sLSooX#yes7MH zd3EpV&sVlrWLJJTJ=^QQ%9P_uS*5?sc5SYAjao9J*1krQfvf!Q--L_$r(517G??vs z7W9F+=10@&zgps6FEWicR_-;d<6J2J`g!Av^-b14ikmm|O-MTw7u97dE-aOPd)7tKzB%LmhPjXR zIv)GfI4ulVcjqwYl#=HnS~8tsj`z6kRK$qKy-#7g?EcHbHk@;(^;0IkIeL$t=2x@_ z&%1O)Cowy|Te^*qs2dUk!C-JXnH zcGjHT@;OnL>t=YLnXpUJN^*8W?13NYAxAGQnfkkXZoKomm8=mFmfxqoh`Ey%$XHm& zm*2hgw6O5a7U$_n{0mhI-RGD754zN|-9>BULi$GmtOxR}^puRdp+(--w;M@xD3 zqBUzaFMcIF(vaAkkG=_;9-TcrXcQk5pCEEV{DY3U5Ff|X|_HXUF&bN_Vhs|eowDMuNe_+_tH z!_na#JMGVbe>tlR3tT%oKD5SkgxNo6=3+Y>C{rJ2&yB_EckAESed#lc;99*x@}r*mtYaLf zr+w7Ao;trqgk5m$>ItD)i@5{#vwhe&=jleXhW7v06e5$uu216mUzZv9m?1ZoqKQ>IsMki2DTDIobj-Z$j9!ZBZwgc%jd>I?l-{Jgk-Bh~j(f&LB)pNpX1sU%sEK z{}=ep2JSjlYhTv-L)*iia+w&ch0|;civ-_<@ZYCvOE%bHB`Q; z#A65d_FEr=1(u1u?5b+I%X?J9^Yiu__Gg~V70lbrQ?~qdL15}P>Di4fHs^ow7H;5Z zIX3mlw%yCj*4k$UhPwRB_pO-n$hjh^)BP3G?mm@otq;TwM(>p5o>6@x{@fi=1GUhM z*<7hl4L%<%c#(9wu{=0y^|iBIpG17`a>;(^YvEdcyTLN?>5@I&^S-?ZILJR?&bP}F zZ;viKAF$)sKI^}#rlxcCch^KTv&bzuVD2MxJ>s%@>(w2*%T6<{zaIX(L5 z-Z=a?UcP1GvA4c+&h43aD}PHm`|B-p?nZxq@^0_Uj7MiHx%t2SINZOeceZ81!9B&S z!du=*_BH8koPJRL@zc=GeFytY7y0jxu{2FM_fKwFciq&g)z>x(NMCzsrarOHD`?h) ziE~bdJ)N{Z-fmr>_3n6`j_?+hqnCw#K6xXX_hTKGsNU&mEXlI_46^)1`Q8aue=fLw zVgK>JM^`qyzil$hcapn?UOS6vKlEQ2 zrEi*(1{&PS7p7K-V}MAYtn^H|NxuBFZ=vpA`@~@P9}f4AkS1|&rNjGiWa zG<#V|(oDa@$^ZC2EPZ(|WY6NGO2vQHX7c5!9k4K}$TH00{T_KW@55xvl+|w^&3xa+ z@xP1l(Cgp?siYsxf%gq+EtgyAZ*81Zd0>9g`_O-HKa@C{%kk}~$-gG9@pFdptl;;~ z1)q-ZR8BG~J^1Fw_Pxp9cxz5vvz$A_B5M7)(_(&CStUN)`?p`il(=aV(aCHFD}`B-1F}K8;u+lr|naAvAMc+9=~8Po8QwRcPwY0~cf-JFL<>f9ZPB&je}2g@ARAybi6n#L7cC-?nq34ilr(?=Np9s_fHvY6us_hxb}tSj7ycArZeq6 zmlfJxZ`kS}|8=!r)Wnb5-muuKF08eG-ga#A(cl}o24d51-<|U35dSf?AG4WL#h1;> zKJswNZ-=K3WxsI0{`^j2v7+7bnkPRkADmD7-LgSNWXYe$4dx|vzNw!MuiSgdzVCm9 z&_VB8a(4}OpUs#Mu`1{95v|NyjiT2T=UUBu=azC}?za^aLZ{{_>!i!uRk|M(pTG2{ zklfo_tujCOr`3mDibU)`YK7jgLCQkCePcfSQU_WIv0egC;+ci`H+ zvDp&yj5bXvt|`0Uw4Qt4{JlH9BNaGqWCYD!_Hnvh!?!D}O&?uL95`ouUH-a7D}ce) z`!;hxsQ24H9S8FccE{ZJpTMBh^(cMyh7WUB9{IDf{`Atcr?)mK8}jwf(aM~)Me?|1 z_DRP!+0PE?78mTE6g5>lPq{Yv!>^4qj;(F&{nf;z_?*i$uvzRM&xMp1UaU*b?_8&J zr{T-D2O?+ZKD@^AQ?0UpVnYu9zrx;@DNCd^OV#HY|B2?ja9n5Ar3D+08+31xvlqX! zQP=L$cCC*L@6^s3hRy1)4m@-3n(MD7r9PWw{|@TP2|j(g$7#2XqXB?763KL2W&)odAxlhSZaRa-$S{K9Vc$5mW4B32B`RF9*PO%H44oP^|-2k zbjFFx)AN;=7 zx#Y!B~U?+6-c|%LZ$EAxe8k%nos(Etvn@ZBOYX!@;o+wP~xan-WY5xDG zSJM9SPVv9Dz9nhh)8v!&nHj5Gg7egyM?&e+kF>vZ*XQ~#?8ht=4+-xQi|EB-y*O1R*f?bamk zi;MnlWVw5IQ|Pf@dWYwnoptZx#7*p0rv;C_FxnEi#`KoA^YI5O%BzmO-Y=FIs+DnP zt#X{$Zk^AHm4|mntqO3cDElL=lbLhTzp!P``L*TVd!oJ_1 zKeV_nOL{oZ#-vR3&cw7P&iBiGtMfU5)$B<_7-rX}u?TxH`eZ{^ImJ#RJ~^f+zg@zxA}P_9pQoJ02DU znc7SYpLlyt(50JvZ-cYuG?i~uh_ic|Y{}^FpnmD?LdIChV8u063nxl#dUL5&JNuOs z!>sPVNoShQiNChqe1Ctf+XKeAl6FFz%lIe9wh2yOmnfQY>Re#1C2PuN*1s-!{t5Em z_8eGYP#N_kWudUl!}njGo?Nx2+N;DRsP~rN+W7~LGzT#>UgzI>J0wv2U4N18o@-aX zzb!63BYxeD$GG+91EyQ^Ct8H;^_rO4G>5ZhNBGZ^##bk4ukGG@FQNCw)oVK=SP!T& zZruC4b$X0>U;Ad(se%RnGgNzdmo}BZY`wZydeY4Q6#?N__U_nrl2huCUqNGC>LckT zCJ|N&UGi)`bItE8JYij(y6%6?pHjc?0AvxOKMPYu#Ix z0}Tzu)43;v^zOZTY6s8F%Q3z_SNA!{Excdy%5IibL8kqLK8tB8p^`FvHnUlsa)r

{ax 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%0Ai6Bp{w{9UQS?yhScQO|Nn!oA?v;o@M6_E@DUL& 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