1370b324cSopenharmony_ci// XzHandler.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../C/Alloc.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "../../Common/ComTry.h" 8370b324cSopenharmony_ci#include "../../Common/Defs.h" 9370b324cSopenharmony_ci#include "../../Common/IntToString.h" 10370b324cSopenharmony_ci#include "../../Common/MyBuffer.h" 11370b324cSopenharmony_ci#include "../../Common/StringToInt.h" 12370b324cSopenharmony_ci 13370b324cSopenharmony_ci#include "../../Windows/PropVariant.h" 14370b324cSopenharmony_ci#include "../../Windows/System.h" 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci#include "../Common/CWrappers.h" 17370b324cSopenharmony_ci#include "../Common/ProgressUtils.h" 18370b324cSopenharmony_ci#include "../Common/RegisterArc.h" 19370b324cSopenharmony_ci#include "../Common/StreamUtils.h" 20370b324cSopenharmony_ci 21370b324cSopenharmony_ci#include "../Compress/CopyCoder.h" 22370b324cSopenharmony_ci#include "../Compress/XzDecoder.h" 23370b324cSopenharmony_ci#include "../Compress/XzEncoder.h" 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#include "IArchive.h" 26370b324cSopenharmony_ci 27370b324cSopenharmony_ci#include "Common/HandlerOut.h" 28370b324cSopenharmony_ci 29370b324cSopenharmony_ciusing namespace NWindows; 30370b324cSopenharmony_ci 31370b324cSopenharmony_cinamespace NArchive { 32370b324cSopenharmony_cinamespace NXz { 33370b324cSopenharmony_ci 34370b324cSopenharmony_ci#define k_LZMA2_Name "LZMA2" 35370b324cSopenharmony_ci 36370b324cSopenharmony_ci 37370b324cSopenharmony_cistruct CBlockInfo 38370b324cSopenharmony_ci{ 39370b324cSopenharmony_ci unsigned StreamFlags; 40370b324cSopenharmony_ci UInt64 PackPos; 41370b324cSopenharmony_ci UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros 42370b324cSopenharmony_ci UInt64 UnpackPos; 43370b324cSopenharmony_ci}; 44370b324cSopenharmony_ci 45370b324cSopenharmony_ci 46370b324cSopenharmony_ciZ7_class_CHandler_final: 47370b324cSopenharmony_ci public IInArchive, 48370b324cSopenharmony_ci public IArchiveOpenSeq, 49370b324cSopenharmony_ci public IInArchiveGetStream, 50370b324cSopenharmony_ci public ISetProperties, 51370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 52370b324cSopenharmony_ci public IOutArchive, 53370b324cSopenharmony_ci #endif 54370b324cSopenharmony_ci public CMyUnknownImp, 55370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 56370b324cSopenharmony_ci public CMultiMethodProps 57370b324cSopenharmony_ci #else 58370b324cSopenharmony_ci public CCommonMethodProps 59370b324cSopenharmony_ci #endif 60370b324cSopenharmony_ci{ 61370b324cSopenharmony_ci Z7_COM_QI_BEGIN2(IInArchive) 62370b324cSopenharmony_ci Z7_COM_QI_ENTRY(IArchiveOpenSeq) 63370b324cSopenharmony_ci Z7_COM_QI_ENTRY(IInArchiveGetStream) 64370b324cSopenharmony_ci Z7_COM_QI_ENTRY(ISetProperties) 65370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 66370b324cSopenharmony_ci Z7_COM_QI_ENTRY(IOutArchive) 67370b324cSopenharmony_ci #endif 68370b324cSopenharmony_ci Z7_COM_QI_END 69370b324cSopenharmony_ci Z7_COM_ADDREF_RELEASE 70370b324cSopenharmony_ci 71370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(IInArchive) 72370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(IArchiveOpenSeq) 73370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(IInArchiveGetStream) 74370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(ISetProperties) 75370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 76370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(IOutArchive) 77370b324cSopenharmony_ci #endif 78370b324cSopenharmony_ci 79370b324cSopenharmony_ci CXzStatInfo _stat; // it's stat from backward parsing 80370b324cSopenharmony_ci CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called 81370b324cSopenharmony_ci SRes _stat2_decode_SRes; 82370b324cSopenharmony_ci bool _stat_defined; 83370b324cSopenharmony_ci bool _stat2_defined; 84370b324cSopenharmony_ci 85370b324cSopenharmony_ci const CXzStatInfo *GetStat() const 86370b324cSopenharmony_ci { 87370b324cSopenharmony_ci if (_stat_defined) return &_stat; 88370b324cSopenharmony_ci if (_stat2_defined) return &_stat2; 89370b324cSopenharmony_ci return NULL; 90370b324cSopenharmony_ci } 91370b324cSopenharmony_ci 92370b324cSopenharmony_ci bool _isArc; 93370b324cSopenharmony_ci bool _needSeekToStart; 94370b324cSopenharmony_ci bool _firstBlockWasRead; 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci AString _methodsString; 97370b324cSopenharmony_ci 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 100370b324cSopenharmony_ci 101370b324cSopenharmony_ci UInt32 _filterId; 102370b324cSopenharmony_ci UInt64 _numSolidBytes; 103370b324cSopenharmony_ci 104370b324cSopenharmony_ci void InitXz() 105370b324cSopenharmony_ci { 106370b324cSopenharmony_ci _filterId = 0; 107370b324cSopenharmony_ci _numSolidBytes = XZ_PROPS_BLOCK_SIZE_AUTO; 108370b324cSopenharmony_ci } 109370b324cSopenharmony_ci 110370b324cSopenharmony_ci #endif 111370b324cSopenharmony_ci 112370b324cSopenharmony_ci 113370b324cSopenharmony_ci void Init() 114370b324cSopenharmony_ci { 115370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 116370b324cSopenharmony_ci InitXz(); 117370b324cSopenharmony_ci CMultiMethodProps::Init(); 118370b324cSopenharmony_ci #else 119370b324cSopenharmony_ci CCommonMethodProps::InitCommon(); 120370b324cSopenharmony_ci #endif 121370b324cSopenharmony_ci } 122370b324cSopenharmony_ci 123370b324cSopenharmony_ci HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); 124370b324cSopenharmony_ci 125370b324cSopenharmony_ci HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); 126370b324cSopenharmony_ci 127370b324cSopenharmony_ci HRESULT Decode(NCompress::NXz::CDecoder &decoder, 128370b324cSopenharmony_ci ISequentialInStream *seqInStream, 129370b324cSopenharmony_ci ISequentialOutStream *outStream, 130370b324cSopenharmony_ci ICompressProgressInfo *progress) 131370b324cSopenharmony_ci { 132370b324cSopenharmony_ci #ifndef Z7_ST 133370b324cSopenharmony_ci decoder._numThreads = _numThreads; 134370b324cSopenharmony_ci #endif 135370b324cSopenharmony_ci decoder._memUsage = _memUsage_Decompress; 136370b324cSopenharmony_ci 137370b324cSopenharmony_ci HRESULT hres = decoder.Decode(seqInStream, outStream, 138370b324cSopenharmony_ci NULL, // *outSizeLimit 139370b324cSopenharmony_ci true, // finishStream 140370b324cSopenharmony_ci progress); 141370b324cSopenharmony_ci 142370b324cSopenharmony_ci if (decoder.MainDecodeSRes_wasUsed 143370b324cSopenharmony_ci && decoder.MainDecodeSRes != SZ_ERROR_MEM 144370b324cSopenharmony_ci && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) 145370b324cSopenharmony_ci { 146370b324cSopenharmony_ci // if (!_stat2_defined) 147370b324cSopenharmony_ci { 148370b324cSopenharmony_ci _stat2_decode_SRes = decoder.MainDecodeSRes; 149370b324cSopenharmony_ci _stat2 = decoder.Stat; 150370b324cSopenharmony_ci _stat2_defined = true; 151370b324cSopenharmony_ci } 152370b324cSopenharmony_ci } 153370b324cSopenharmony_ci 154370b324cSopenharmony_ci return hres; 155370b324cSopenharmony_ci } 156370b324cSopenharmony_ci 157370b324cSopenharmony_cipublic: 158370b324cSopenharmony_ci CBlockInfo *_blocks; 159370b324cSopenharmony_ci size_t _blocksArraySize; 160370b324cSopenharmony_ci UInt64 _maxBlocksSize; 161370b324cSopenharmony_ci CMyComPtr<IInStream> _stream; 162370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> _seqStream; 163370b324cSopenharmony_ci 164370b324cSopenharmony_ci CXzBlock _firstBlock; 165370b324cSopenharmony_ci 166370b324cSopenharmony_ci CHandler(); 167370b324cSopenharmony_ci ~CHandler(); 168370b324cSopenharmony_ci 169370b324cSopenharmony_ci HRESULT SeekToPackPos(UInt64 pos) 170370b324cSopenharmony_ci { 171370b324cSopenharmony_ci return InStream_SeekSet(_stream, pos); 172370b324cSopenharmony_ci } 173370b324cSopenharmony_ci}; 174370b324cSopenharmony_ci 175370b324cSopenharmony_ci 176370b324cSopenharmony_ciCHandler::CHandler(): 177370b324cSopenharmony_ci _blocks(NULL), 178370b324cSopenharmony_ci _blocksArraySize(0) 179370b324cSopenharmony_ci{ 180370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 181370b324cSopenharmony_ci InitXz(); 182370b324cSopenharmony_ci #endif 183370b324cSopenharmony_ci} 184370b324cSopenharmony_ci 185370b324cSopenharmony_ciCHandler::~CHandler() 186370b324cSopenharmony_ci{ 187370b324cSopenharmony_ci MyFree(_blocks); 188370b324cSopenharmony_ci} 189370b324cSopenharmony_ci 190370b324cSopenharmony_ci 191370b324cSopenharmony_cistatic const Byte kProps[] = 192370b324cSopenharmony_ci{ 193370b324cSopenharmony_ci kpidSize, 194370b324cSopenharmony_ci kpidPackSize, 195370b324cSopenharmony_ci kpidMethod 196370b324cSopenharmony_ci}; 197370b324cSopenharmony_ci 198370b324cSopenharmony_cistatic const Byte kArcProps[] = 199370b324cSopenharmony_ci{ 200370b324cSopenharmony_ci kpidMethod, 201370b324cSopenharmony_ci kpidNumStreams, 202370b324cSopenharmony_ci kpidNumBlocks, 203370b324cSopenharmony_ci kpidClusterSize, 204370b324cSopenharmony_ci kpidCharacts 205370b324cSopenharmony_ci}; 206370b324cSopenharmony_ci 207370b324cSopenharmony_ciIMP_IInArchive_Props 208370b324cSopenharmony_ciIMP_IInArchive_ArcProps 209370b324cSopenharmony_ci 210370b324cSopenharmony_cistatic inline char GetHex(unsigned value) 211370b324cSopenharmony_ci{ 212370b324cSopenharmony_ci return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); 213370b324cSopenharmony_ci} 214370b324cSopenharmony_ci 215370b324cSopenharmony_cistatic inline void AddHexToString(AString &s, Byte value) 216370b324cSopenharmony_ci{ 217370b324cSopenharmony_ci s += GetHex(value >> 4); 218370b324cSopenharmony_ci s += GetHex(value & 0xF); 219370b324cSopenharmony_ci} 220370b324cSopenharmony_ci 221370b324cSopenharmony_cistatic void Lzma2PropToString(AString &s, unsigned prop) 222370b324cSopenharmony_ci{ 223370b324cSopenharmony_ci char c = 0; 224370b324cSopenharmony_ci UInt32 size; 225370b324cSopenharmony_ci if ((prop & 1) == 0) 226370b324cSopenharmony_ci size = prop / 2 + 12; 227370b324cSopenharmony_ci else 228370b324cSopenharmony_ci { 229370b324cSopenharmony_ci c = 'k'; 230370b324cSopenharmony_ci size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); 231370b324cSopenharmony_ci if (prop > 17) 232370b324cSopenharmony_ci { 233370b324cSopenharmony_ci size >>= 10; 234370b324cSopenharmony_ci c = 'm'; 235370b324cSopenharmony_ci } 236370b324cSopenharmony_ci } 237370b324cSopenharmony_ci s.Add_UInt32(size); 238370b324cSopenharmony_ci if (c != 0) 239370b324cSopenharmony_ci s += c; 240370b324cSopenharmony_ci} 241370b324cSopenharmony_ci 242370b324cSopenharmony_cistruct CMethodNamePair 243370b324cSopenharmony_ci{ 244370b324cSopenharmony_ci UInt32 Id; 245370b324cSopenharmony_ci const char *Name; 246370b324cSopenharmony_ci}; 247370b324cSopenharmony_ci 248370b324cSopenharmony_cistatic const CMethodNamePair g_NamePairs[] = 249370b324cSopenharmony_ci{ 250370b324cSopenharmony_ci { XZ_ID_Subblock, "SB" }, 251370b324cSopenharmony_ci { XZ_ID_Delta, "Delta" }, 252370b324cSopenharmony_ci { XZ_ID_X86, "BCJ" }, 253370b324cSopenharmony_ci { XZ_ID_PPC, "PPC" }, 254370b324cSopenharmony_ci { XZ_ID_IA64, "IA64" }, 255370b324cSopenharmony_ci { XZ_ID_ARM, "ARM" }, 256370b324cSopenharmony_ci { XZ_ID_ARMT, "ARMT" }, 257370b324cSopenharmony_ci { XZ_ID_SPARC, "SPARC" }, 258370b324cSopenharmony_ci { XZ_ID_ARM64, "ARM64" }, 259370b324cSopenharmony_ci { XZ_ID_LZMA2, "LZMA2" } 260370b324cSopenharmony_ci}; 261370b324cSopenharmony_ci 262370b324cSopenharmony_cistatic void AddMethodString(AString &s, const CXzFilter &f) 263370b324cSopenharmony_ci{ 264370b324cSopenharmony_ci const char *p = NULL; 265370b324cSopenharmony_ci for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++) 266370b324cSopenharmony_ci if (g_NamePairs[i].Id == f.id) 267370b324cSopenharmony_ci { 268370b324cSopenharmony_ci p = g_NamePairs[i].Name; 269370b324cSopenharmony_ci break; 270370b324cSopenharmony_ci } 271370b324cSopenharmony_ci char temp[32]; 272370b324cSopenharmony_ci if (!p) 273370b324cSopenharmony_ci { 274370b324cSopenharmony_ci ::ConvertUInt64ToString(f.id, temp); 275370b324cSopenharmony_ci p = temp; 276370b324cSopenharmony_ci } 277370b324cSopenharmony_ci 278370b324cSopenharmony_ci s += p; 279370b324cSopenharmony_ci 280370b324cSopenharmony_ci if (f.propsSize > 0) 281370b324cSopenharmony_ci { 282370b324cSopenharmony_ci s += ':'; 283370b324cSopenharmony_ci if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) 284370b324cSopenharmony_ci Lzma2PropToString(s, f.props[0]); 285370b324cSopenharmony_ci else if (f.id == XZ_ID_Delta && f.propsSize == 1) 286370b324cSopenharmony_ci s.Add_UInt32((UInt32)f.props[0] + 1); 287370b324cSopenharmony_ci else if (f.id == XZ_ID_ARM64 && f.propsSize == 1) 288370b324cSopenharmony_ci s.Add_UInt32((UInt32)f.props[0] + 16 + 2); 289370b324cSopenharmony_ci else 290370b324cSopenharmony_ci { 291370b324cSopenharmony_ci s += '['; 292370b324cSopenharmony_ci for (UInt32 bi = 0; bi < f.propsSize; bi++) 293370b324cSopenharmony_ci AddHexToString(s, f.props[bi]); 294370b324cSopenharmony_ci s += ']'; 295370b324cSopenharmony_ci } 296370b324cSopenharmony_ci } 297370b324cSopenharmony_ci} 298370b324cSopenharmony_ci 299370b324cSopenharmony_cistatic const char * const kChecks[] = 300370b324cSopenharmony_ci{ 301370b324cSopenharmony_ci "NoCheck" 302370b324cSopenharmony_ci , "CRC32" 303370b324cSopenharmony_ci , NULL 304370b324cSopenharmony_ci , NULL 305370b324cSopenharmony_ci , "CRC64" 306370b324cSopenharmony_ci , NULL 307370b324cSopenharmony_ci , NULL 308370b324cSopenharmony_ci , NULL 309370b324cSopenharmony_ci , NULL 310370b324cSopenharmony_ci , NULL 311370b324cSopenharmony_ci , "SHA256" 312370b324cSopenharmony_ci , NULL 313370b324cSopenharmony_ci , NULL 314370b324cSopenharmony_ci , NULL 315370b324cSopenharmony_ci , NULL 316370b324cSopenharmony_ci , NULL 317370b324cSopenharmony_ci}; 318370b324cSopenharmony_ci 319370b324cSopenharmony_cistatic void AddCheckString(AString &s, const CXzs &xzs) 320370b324cSopenharmony_ci{ 321370b324cSopenharmony_ci size_t i; 322370b324cSopenharmony_ci UInt32 mask = 0; 323370b324cSopenharmony_ci for (i = 0; i < xzs.num; i++) 324370b324cSopenharmony_ci mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); 325370b324cSopenharmony_ci for (i = 0; i <= XZ_CHECK_MASK; i++) 326370b324cSopenharmony_ci if (((mask >> i) & 1) != 0) 327370b324cSopenharmony_ci { 328370b324cSopenharmony_ci s.Add_Space_if_NotEmpty(); 329370b324cSopenharmony_ci if (kChecks[i]) 330370b324cSopenharmony_ci s += kChecks[i]; 331370b324cSopenharmony_ci else 332370b324cSopenharmony_ci { 333370b324cSopenharmony_ci s += "Check-"; 334370b324cSopenharmony_ci s.Add_UInt32((UInt32)i); 335370b324cSopenharmony_ci } 336370b324cSopenharmony_ci } 337370b324cSopenharmony_ci} 338370b324cSopenharmony_ci 339370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 340370b324cSopenharmony_ci{ 341370b324cSopenharmony_ci COM_TRY_BEGIN 342370b324cSopenharmony_ci NCOM::CPropVariant prop; 343370b324cSopenharmony_ci 344370b324cSopenharmony_ci const CXzStatInfo *stat = GetStat(); 345370b324cSopenharmony_ci 346370b324cSopenharmony_ci switch (propID) 347370b324cSopenharmony_ci { 348370b324cSopenharmony_ci case kpidPhySize: if (stat) prop = stat->InSize; break; 349370b324cSopenharmony_ci case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; 350370b324cSopenharmony_ci case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; 351370b324cSopenharmony_ci case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; 352370b324cSopenharmony_ci case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; 353370b324cSopenharmony_ci case kpidCharacts: 354370b324cSopenharmony_ci if (_firstBlockWasRead) 355370b324cSopenharmony_ci { 356370b324cSopenharmony_ci AString s; 357370b324cSopenharmony_ci if (XzBlock_HasPackSize(&_firstBlock)) 358370b324cSopenharmony_ci s.Add_OptSpaced("BlockPackSize"); 359370b324cSopenharmony_ci if (XzBlock_HasUnpackSize(&_firstBlock)) 360370b324cSopenharmony_ci s.Add_OptSpaced("BlockUnpackSize"); 361370b324cSopenharmony_ci if (!s.IsEmpty()) 362370b324cSopenharmony_ci prop = s; 363370b324cSopenharmony_ci } 364370b324cSopenharmony_ci break; 365370b324cSopenharmony_ci 366370b324cSopenharmony_ci 367370b324cSopenharmony_ci case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; 368370b324cSopenharmony_ci case kpidErrorFlags: 369370b324cSopenharmony_ci { 370370b324cSopenharmony_ci UInt32 v = 0; 371370b324cSopenharmony_ci SRes sres = _stat2_decode_SRes; 372370b324cSopenharmony_ci if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; 373370b324cSopenharmony_ci if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; 374370b324cSopenharmony_ci if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; 375370b324cSopenharmony_ci if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; 376370b324cSopenharmony_ci if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; 377370b324cSopenharmony_ci if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; 378370b324cSopenharmony_ci if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; 379370b324cSopenharmony_ci if (v != 0) 380370b324cSopenharmony_ci prop = v; 381370b324cSopenharmony_ci break; 382370b324cSopenharmony_ci } 383370b324cSopenharmony_ci 384370b324cSopenharmony_ci case kpidMainSubfile: 385370b324cSopenharmony_ci { 386370b324cSopenharmony_ci // debug only, comment it: 387370b324cSopenharmony_ci // if (_blocks) prop = (UInt32)0; 388370b324cSopenharmony_ci break; 389370b324cSopenharmony_ci } 390370b324cSopenharmony_ci } 391370b324cSopenharmony_ci prop.Detach(value); 392370b324cSopenharmony_ci return S_OK; 393370b324cSopenharmony_ci COM_TRY_END 394370b324cSopenharmony_ci} 395370b324cSopenharmony_ci 396370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 397370b324cSopenharmony_ci{ 398370b324cSopenharmony_ci *numItems = 1; 399370b324cSopenharmony_ci return S_OK; 400370b324cSopenharmony_ci} 401370b324cSopenharmony_ci 402370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)) 403370b324cSopenharmony_ci{ 404370b324cSopenharmony_ci COM_TRY_BEGIN 405370b324cSopenharmony_ci const CXzStatInfo *stat = GetStat(); 406370b324cSopenharmony_ci NCOM::CPropVariant prop; 407370b324cSopenharmony_ci switch (propID) 408370b324cSopenharmony_ci { 409370b324cSopenharmony_ci case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; 410370b324cSopenharmony_ci case kpidPackSize: if (stat) prop = stat->InSize; break; 411370b324cSopenharmony_ci case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; 412370b324cSopenharmony_ci } 413370b324cSopenharmony_ci prop.Detach(value); 414370b324cSopenharmony_ci return S_OK; 415370b324cSopenharmony_ci COM_TRY_END 416370b324cSopenharmony_ci} 417370b324cSopenharmony_ci 418370b324cSopenharmony_ci 419370b324cSopenharmony_cistruct COpenCallbackWrap 420370b324cSopenharmony_ci{ 421370b324cSopenharmony_ci ICompressProgress vt; 422370b324cSopenharmony_ci IArchiveOpenCallback *OpenCallback; 423370b324cSopenharmony_ci HRESULT Res; 424370b324cSopenharmony_ci 425370b324cSopenharmony_ci // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() 426370b324cSopenharmony_ci void Init(IArchiveOpenCallback *progress); 427370b324cSopenharmony_ci}; 428370b324cSopenharmony_ci 429370b324cSopenharmony_cistatic SRes OpenCallbackProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 /* outSize */) 430370b324cSopenharmony_ci{ 431370b324cSopenharmony_ci Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(COpenCallbackWrap) 432370b324cSopenharmony_ci if (p->OpenCallback) 433370b324cSopenharmony_ci p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); 434370b324cSopenharmony_ci return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); 435370b324cSopenharmony_ci} 436370b324cSopenharmony_ci 437370b324cSopenharmony_civoid COpenCallbackWrap::Init(IArchiveOpenCallback *callback) 438370b324cSopenharmony_ci{ 439370b324cSopenharmony_ci vt.Progress = OpenCallbackProgress; 440370b324cSopenharmony_ci OpenCallback = callback; 441370b324cSopenharmony_ci Res = SZ_OK; 442370b324cSopenharmony_ci} 443370b324cSopenharmony_ci 444370b324cSopenharmony_ci 445370b324cSopenharmony_cistruct CXzsCPP 446370b324cSopenharmony_ci{ 447370b324cSopenharmony_ci CXzs p; 448370b324cSopenharmony_ci CXzsCPP() { Xzs_Construct(&p); } 449370b324cSopenharmony_ci ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } 450370b324cSopenharmony_ci}; 451370b324cSopenharmony_ci 452370b324cSopenharmony_ci#define kInputBufSize ((size_t)1 << 10) 453370b324cSopenharmony_ci 454370b324cSopenharmony_cistruct CLookToRead2_CPP: public CLookToRead2 455370b324cSopenharmony_ci{ 456370b324cSopenharmony_ci CLookToRead2_CPP() 457370b324cSopenharmony_ci { 458370b324cSopenharmony_ci buf = NULL; 459370b324cSopenharmony_ci LookToRead2_CreateVTable(this, 460370b324cSopenharmony_ci True // Lookahead ? 461370b324cSopenharmony_ci ); 462370b324cSopenharmony_ci } 463370b324cSopenharmony_ci void Alloc(size_t allocSize) 464370b324cSopenharmony_ci { 465370b324cSopenharmony_ci buf = (Byte *)MyAlloc(allocSize); 466370b324cSopenharmony_ci if (buf) 467370b324cSopenharmony_ci this->bufSize = allocSize; 468370b324cSopenharmony_ci } 469370b324cSopenharmony_ci ~CLookToRead2_CPP() 470370b324cSopenharmony_ci { 471370b324cSopenharmony_ci MyFree(buf); 472370b324cSopenharmony_ci } 473370b324cSopenharmony_ci}; 474370b324cSopenharmony_ci 475370b324cSopenharmony_ci 476370b324cSopenharmony_cistatic HRESULT SRes_to_Open_HRESULT(SRes res) 477370b324cSopenharmony_ci{ 478370b324cSopenharmony_ci switch (res) 479370b324cSopenharmony_ci { 480370b324cSopenharmony_ci case SZ_OK: return S_OK; 481370b324cSopenharmony_ci case SZ_ERROR_MEM: return E_OUTOFMEMORY; 482370b324cSopenharmony_ci case SZ_ERROR_PROGRESS: return E_ABORT; 483370b324cSopenharmony_ci /* 484370b324cSopenharmony_ci case SZ_ERROR_UNSUPPORTED: 485370b324cSopenharmony_ci case SZ_ERROR_CRC: 486370b324cSopenharmony_ci case SZ_ERROR_DATA: 487370b324cSopenharmony_ci case SZ_ERROR_ARCHIVE: 488370b324cSopenharmony_ci case SZ_ERROR_NO_ARCHIVE: 489370b324cSopenharmony_ci return S_FALSE; 490370b324cSopenharmony_ci */ 491370b324cSopenharmony_ci } 492370b324cSopenharmony_ci return S_FALSE; 493370b324cSopenharmony_ci} 494370b324cSopenharmony_ci 495370b324cSopenharmony_ci 496370b324cSopenharmony_ci 497370b324cSopenharmony_ciHRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) 498370b324cSopenharmony_ci{ 499370b324cSopenharmony_ci _needSeekToStart = true; 500370b324cSopenharmony_ci 501370b324cSopenharmony_ci { 502370b324cSopenharmony_ci CXzStreamFlags st; 503370b324cSopenharmony_ci CSeqInStreamWrap inStreamWrap; 504370b324cSopenharmony_ci 505370b324cSopenharmony_ci inStreamWrap.Init(inStream); 506370b324cSopenharmony_ci 507370b324cSopenharmony_ci SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); 508370b324cSopenharmony_ci 509370b324cSopenharmony_ci if (inStreamWrap.Res != S_OK) 510370b324cSopenharmony_ci return inStreamWrap.Res; 511370b324cSopenharmony_ci if (res != SZ_OK) 512370b324cSopenharmony_ci return SRes_to_Open_HRESULT(res); 513370b324cSopenharmony_ci 514370b324cSopenharmony_ci { 515370b324cSopenharmony_ci CXzBlock block; 516370b324cSopenharmony_ci BoolInt isIndex; 517370b324cSopenharmony_ci UInt32 headerSizeRes; 518370b324cSopenharmony_ci 519370b324cSopenharmony_ci SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); 520370b324cSopenharmony_ci 521370b324cSopenharmony_ci if (inStreamWrap.Res != S_OK) 522370b324cSopenharmony_ci return inStreamWrap.Res; 523370b324cSopenharmony_ci 524370b324cSopenharmony_ci if (res2 != SZ_OK) 525370b324cSopenharmony_ci { 526370b324cSopenharmony_ci if (res2 == SZ_ERROR_INPUT_EOF) 527370b324cSopenharmony_ci { 528370b324cSopenharmony_ci _stat2_decode_SRes = res2; 529370b324cSopenharmony_ci _stream = inStream; 530370b324cSopenharmony_ci _seqStream = inStream; 531370b324cSopenharmony_ci _isArc = true; 532370b324cSopenharmony_ci return S_OK; 533370b324cSopenharmony_ci } 534370b324cSopenharmony_ci 535370b324cSopenharmony_ci if (res2 == SZ_ERROR_ARCHIVE) 536370b324cSopenharmony_ci return S_FALSE; 537370b324cSopenharmony_ci } 538370b324cSopenharmony_ci else if (!isIndex) 539370b324cSopenharmony_ci { 540370b324cSopenharmony_ci _firstBlockWasRead = true; 541370b324cSopenharmony_ci _firstBlock = block; 542370b324cSopenharmony_ci 543370b324cSopenharmony_ci unsigned numFilters = XzBlock_GetNumFilters(&block); 544370b324cSopenharmony_ci for (unsigned i = 0; i < numFilters; i++) 545370b324cSopenharmony_ci { 546370b324cSopenharmony_ci _methodsString.Add_Space_if_NotEmpty(); 547370b324cSopenharmony_ci AddMethodString(_methodsString, block.filters[i]); 548370b324cSopenharmony_ci } 549370b324cSopenharmony_ci } 550370b324cSopenharmony_ci } 551370b324cSopenharmony_ci } 552370b324cSopenharmony_ci 553370b324cSopenharmony_ci RINOK(InStream_GetSize_SeekToEnd(inStream, _stat.InSize)) 554370b324cSopenharmony_ci if (callback) 555370b324cSopenharmony_ci { 556370b324cSopenharmony_ci RINOK(callback->SetTotal(NULL, &_stat.InSize)) 557370b324cSopenharmony_ci } 558370b324cSopenharmony_ci 559370b324cSopenharmony_ci CSeekInStreamWrap inStreamImp; 560370b324cSopenharmony_ci 561370b324cSopenharmony_ci inStreamImp.Init(inStream); 562370b324cSopenharmony_ci 563370b324cSopenharmony_ci CLookToRead2_CPP lookStream; 564370b324cSopenharmony_ci 565370b324cSopenharmony_ci lookStream.Alloc(kInputBufSize); 566370b324cSopenharmony_ci 567370b324cSopenharmony_ci if (!lookStream.buf) 568370b324cSopenharmony_ci return E_OUTOFMEMORY; 569370b324cSopenharmony_ci 570370b324cSopenharmony_ci lookStream.realStream = &inStreamImp.vt; 571370b324cSopenharmony_ci LookToRead2_INIT(&lookStream) 572370b324cSopenharmony_ci 573370b324cSopenharmony_ci COpenCallbackWrap openWrap; 574370b324cSopenharmony_ci openWrap.Init(callback); 575370b324cSopenharmony_ci 576370b324cSopenharmony_ci CXzsCPP xzs; 577370b324cSopenharmony_ci Int64 startPosition; 578370b324cSopenharmony_ci SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc); 579370b324cSopenharmony_ci if (res == SZ_ERROR_PROGRESS) 580370b324cSopenharmony_ci return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; 581370b324cSopenharmony_ci /* 582370b324cSopenharmony_ci if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) 583370b324cSopenharmony_ci res = SZ_OK; 584370b324cSopenharmony_ci */ 585370b324cSopenharmony_ci if (res == SZ_OK && startPosition == 0) 586370b324cSopenharmony_ci { 587370b324cSopenharmony_ci _stat_defined = true; 588370b324cSopenharmony_ci 589370b324cSopenharmony_ci _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); 590370b324cSopenharmony_ci _stat.UnpackSize_Defined = true; 591370b324cSopenharmony_ci 592370b324cSopenharmony_ci _stat.NumStreams = xzs.p.num; 593370b324cSopenharmony_ci _stat.NumStreams_Defined = true; 594370b324cSopenharmony_ci 595370b324cSopenharmony_ci _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); 596370b324cSopenharmony_ci _stat.NumBlocks_Defined = true; 597370b324cSopenharmony_ci 598370b324cSopenharmony_ci AddCheckString(_methodsString, xzs.p); 599370b324cSopenharmony_ci 600370b324cSopenharmony_ci const size_t numBlocks = (size_t)_stat.NumBlocks + 1; 601370b324cSopenharmony_ci const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo); 602370b324cSopenharmony_ci 603370b324cSopenharmony_ci if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1) 604370b324cSopenharmony_ci { 605370b324cSopenharmony_ci _blocks = (CBlockInfo *)MyAlloc(bytesAlloc); 606370b324cSopenharmony_ci if (_blocks) 607370b324cSopenharmony_ci { 608370b324cSopenharmony_ci unsigned blockIndex = 0; 609370b324cSopenharmony_ci UInt64 unpackPos = 0; 610370b324cSopenharmony_ci 611370b324cSopenharmony_ci for (size_t si = xzs.p.num; si != 0;) 612370b324cSopenharmony_ci { 613370b324cSopenharmony_ci si--; 614370b324cSopenharmony_ci const CXzStream &str = xzs.p.streams[si]; 615370b324cSopenharmony_ci UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE; 616370b324cSopenharmony_ci 617370b324cSopenharmony_ci for (size_t bi = 0; bi < str.numBlocks; bi++) 618370b324cSopenharmony_ci { 619370b324cSopenharmony_ci const CXzBlockSizes &bs = str.blocks[bi]; 620370b324cSopenharmony_ci const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3); 621370b324cSopenharmony_ci 622370b324cSopenharmony_ci if (bs.unpackSize != 0) 623370b324cSopenharmony_ci { 624370b324cSopenharmony_ci if (blockIndex >= _stat.NumBlocks) 625370b324cSopenharmony_ci return E_FAIL; 626370b324cSopenharmony_ci 627370b324cSopenharmony_ci CBlockInfo &block = _blocks[blockIndex++]; 628370b324cSopenharmony_ci block.StreamFlags = str.flags; 629370b324cSopenharmony_ci block.PackSize = bs.totalSize; // packSizeAligned; 630370b324cSopenharmony_ci block.PackPos = packPos; 631370b324cSopenharmony_ci block.UnpackPos = unpackPos; 632370b324cSopenharmony_ci } 633370b324cSopenharmony_ci packPos += packSizeAligned; 634370b324cSopenharmony_ci unpackPos += bs.unpackSize; 635370b324cSopenharmony_ci if (_maxBlocksSize < bs.unpackSize) 636370b324cSopenharmony_ci _maxBlocksSize = bs.unpackSize; 637370b324cSopenharmony_ci } 638370b324cSopenharmony_ci } 639370b324cSopenharmony_ci 640370b324cSopenharmony_ci /* 641370b324cSopenharmony_ci if (blockIndex != _stat.NumBlocks) 642370b324cSopenharmony_ci { 643370b324cSopenharmony_ci // there are Empty blocks; 644370b324cSopenharmony_ci } 645370b324cSopenharmony_ci */ 646370b324cSopenharmony_ci if (_stat.OutSize != unpackPos) 647370b324cSopenharmony_ci return E_FAIL; 648370b324cSopenharmony_ci CBlockInfo &block = _blocks[blockIndex++]; 649370b324cSopenharmony_ci block.StreamFlags = 0; 650370b324cSopenharmony_ci block.PackSize = 0; 651370b324cSopenharmony_ci block.PackPos = 0; 652370b324cSopenharmony_ci block.UnpackPos = unpackPos; 653370b324cSopenharmony_ci _blocksArraySize = blockIndex; 654370b324cSopenharmony_ci } 655370b324cSopenharmony_ci } 656370b324cSopenharmony_ci } 657370b324cSopenharmony_ci else 658370b324cSopenharmony_ci { 659370b324cSopenharmony_ci res = SZ_OK; 660370b324cSopenharmony_ci } 661370b324cSopenharmony_ci 662370b324cSopenharmony_ci RINOK(SRes_to_Open_HRESULT(res)) 663370b324cSopenharmony_ci 664370b324cSopenharmony_ci _stream = inStream; 665370b324cSopenharmony_ci _seqStream = inStream; 666370b324cSopenharmony_ci _isArc = true; 667370b324cSopenharmony_ci return S_OK; 668370b324cSopenharmony_ci} 669370b324cSopenharmony_ci 670370b324cSopenharmony_ci 671370b324cSopenharmony_ci 672370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)) 673370b324cSopenharmony_ci{ 674370b324cSopenharmony_ci COM_TRY_BEGIN 675370b324cSopenharmony_ci { 676370b324cSopenharmony_ci Close(); 677370b324cSopenharmony_ci return Open2(inStream, callback); 678370b324cSopenharmony_ci } 679370b324cSopenharmony_ci COM_TRY_END 680370b324cSopenharmony_ci} 681370b324cSopenharmony_ci 682370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream)) 683370b324cSopenharmony_ci{ 684370b324cSopenharmony_ci Close(); 685370b324cSopenharmony_ci _seqStream = stream; 686370b324cSopenharmony_ci _isArc = true; 687370b324cSopenharmony_ci _needSeekToStart = false; 688370b324cSopenharmony_ci return S_OK; 689370b324cSopenharmony_ci} 690370b324cSopenharmony_ci 691370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Close()) 692370b324cSopenharmony_ci{ 693370b324cSopenharmony_ci XzStatInfo_Clear(&_stat); 694370b324cSopenharmony_ci XzStatInfo_Clear(&_stat2); 695370b324cSopenharmony_ci _stat_defined = false; 696370b324cSopenharmony_ci _stat2_defined = false; 697370b324cSopenharmony_ci _stat2_decode_SRes = SZ_OK; 698370b324cSopenharmony_ci 699370b324cSopenharmony_ci _isArc = false; 700370b324cSopenharmony_ci _needSeekToStart = false; 701370b324cSopenharmony_ci _firstBlockWasRead = false; 702370b324cSopenharmony_ci 703370b324cSopenharmony_ci _methodsString.Empty(); 704370b324cSopenharmony_ci _stream.Release(); 705370b324cSopenharmony_ci _seqStream.Release(); 706370b324cSopenharmony_ci 707370b324cSopenharmony_ci MyFree(_blocks); 708370b324cSopenharmony_ci _blocks = NULL; 709370b324cSopenharmony_ci _blocksArraySize = 0; 710370b324cSopenharmony_ci _maxBlocksSize = 0; 711370b324cSopenharmony_ci 712370b324cSopenharmony_ci return S_OK; 713370b324cSopenharmony_ci} 714370b324cSopenharmony_ci 715370b324cSopenharmony_ci 716370b324cSopenharmony_cistruct CXzUnpackerCPP2 717370b324cSopenharmony_ci{ 718370b324cSopenharmony_ci Byte *InBuf; 719370b324cSopenharmony_ci // Byte *OutBuf; 720370b324cSopenharmony_ci CXzUnpacker p; 721370b324cSopenharmony_ci 722370b324cSopenharmony_ci CXzUnpackerCPP2(); 723370b324cSopenharmony_ci ~CXzUnpackerCPP2(); 724370b324cSopenharmony_ci}; 725370b324cSopenharmony_ci 726370b324cSopenharmony_ciCXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL) 727370b324cSopenharmony_ci // , OutBuf(NULL) 728370b324cSopenharmony_ci{ 729370b324cSopenharmony_ci XzUnpacker_Construct(&p, &g_Alloc); 730370b324cSopenharmony_ci} 731370b324cSopenharmony_ci 732370b324cSopenharmony_ciCXzUnpackerCPP2::~CXzUnpackerCPP2() 733370b324cSopenharmony_ci{ 734370b324cSopenharmony_ci XzUnpacker_Free(&p); 735370b324cSopenharmony_ci MidFree(InBuf); 736370b324cSopenharmony_ci // MidFree(OutBuf); 737370b324cSopenharmony_ci} 738370b324cSopenharmony_ci 739370b324cSopenharmony_ci 740370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1( 741370b324cSopenharmony_ci CInStream 742370b324cSopenharmony_ci , IInStream 743370b324cSopenharmony_ci) 744370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(ISequentialInStream) 745370b324cSopenharmony_ci 746370b324cSopenharmony_ci UInt64 _virtPos; 747370b324cSopenharmony_cipublic: 748370b324cSopenharmony_ci UInt64 Size; 749370b324cSopenharmony_ci UInt64 _cacheStartPos; 750370b324cSopenharmony_ci size_t _cacheSize; 751370b324cSopenharmony_ci CByteBuffer _cache; 752370b324cSopenharmony_ci // UInt64 _startPos; 753370b324cSopenharmony_ci CXzUnpackerCPP2 xz; 754370b324cSopenharmony_ci 755370b324cSopenharmony_ci void InitAndSeek() 756370b324cSopenharmony_ci { 757370b324cSopenharmony_ci _virtPos = 0; 758370b324cSopenharmony_ci _cacheStartPos = 0; 759370b324cSopenharmony_ci _cacheSize = 0; 760370b324cSopenharmony_ci // _startPos = startPos; 761370b324cSopenharmony_ci } 762370b324cSopenharmony_ci 763370b324cSopenharmony_ci CHandler *_handlerSpec; 764370b324cSopenharmony_ci CMyComPtr<IUnknown> _handler; 765370b324cSopenharmony_ci 766370b324cSopenharmony_ci // ~CInStream(); 767370b324cSopenharmony_ci}; 768370b324cSopenharmony_ci 769370b324cSopenharmony_ci/* 770370b324cSopenharmony_ciCInStream::~CInStream() 771370b324cSopenharmony_ci{ 772370b324cSopenharmony_ci // _cache.Free(); 773370b324cSopenharmony_ci} 774370b324cSopenharmony_ci*/ 775370b324cSopenharmony_ci 776370b324cSopenharmony_cistatic size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) 777370b324cSopenharmony_ci{ 778370b324cSopenharmony_ci size_t left = 0, right = numBlocks; 779370b324cSopenharmony_ci for (;;) 780370b324cSopenharmony_ci { 781370b324cSopenharmony_ci size_t mid = (left + right) / 2; 782370b324cSopenharmony_ci if (mid == left) 783370b324cSopenharmony_ci return left; 784370b324cSopenharmony_ci if (pos < blocks[mid].UnpackPos) 785370b324cSopenharmony_ci right = mid; 786370b324cSopenharmony_ci else 787370b324cSopenharmony_ci left = mid; 788370b324cSopenharmony_ci } 789370b324cSopenharmony_ci} 790370b324cSopenharmony_ci 791370b324cSopenharmony_ci 792370b324cSopenharmony_ci 793370b324cSopenharmony_cistatic HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu, 794370b324cSopenharmony_ci ISequentialInStream *seqInStream, 795370b324cSopenharmony_ci unsigned streamFlags, 796370b324cSopenharmony_ci UInt64 packSize, // pure size from Index record, it doesn't include pad zeros 797370b324cSopenharmony_ci size_t unpackSize, Byte *dest 798370b324cSopenharmony_ci // , ICompressProgressInfo *progress 799370b324cSopenharmony_ci ) 800370b324cSopenharmony_ci{ 801370b324cSopenharmony_ci const size_t kInBufSize = (size_t)1 << 16; 802370b324cSopenharmony_ci 803370b324cSopenharmony_ci XzUnpacker_Init(&xzu.p); 804370b324cSopenharmony_ci 805370b324cSopenharmony_ci if (!xzu.InBuf) 806370b324cSopenharmony_ci { 807370b324cSopenharmony_ci xzu.InBuf = (Byte *)MidAlloc(kInBufSize); 808370b324cSopenharmony_ci if (!xzu.InBuf) 809370b324cSopenharmony_ci return E_OUTOFMEMORY; 810370b324cSopenharmony_ci } 811370b324cSopenharmony_ci 812370b324cSopenharmony_ci xzu.p.streamFlags = (UInt16)streamFlags; 813370b324cSopenharmony_ci XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p); 814370b324cSopenharmony_ci 815370b324cSopenharmony_ci XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize); 816370b324cSopenharmony_ci 817370b324cSopenharmony_ci const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); 818370b324cSopenharmony_ci UInt64 packRem = packSizeAligned; 819370b324cSopenharmony_ci 820370b324cSopenharmony_ci UInt32 inSize = 0; 821370b324cSopenharmony_ci SizeT inPos = 0; 822370b324cSopenharmony_ci SizeT outPos = 0; 823370b324cSopenharmony_ci 824370b324cSopenharmony_ci HRESULT readRes = S_OK; 825370b324cSopenharmony_ci 826370b324cSopenharmony_ci for (;;) 827370b324cSopenharmony_ci { 828370b324cSopenharmony_ci if (inPos == inSize && readRes == S_OK) 829370b324cSopenharmony_ci { 830370b324cSopenharmony_ci inPos = 0; 831370b324cSopenharmony_ci inSize = 0; 832370b324cSopenharmony_ci UInt32 rem = kInBufSize; 833370b324cSopenharmony_ci if (rem > packRem) 834370b324cSopenharmony_ci rem = (UInt32)packRem; 835370b324cSopenharmony_ci if (rem != 0) 836370b324cSopenharmony_ci readRes = seqInStream->Read(xzu.InBuf, rem, &inSize); 837370b324cSopenharmony_ci } 838370b324cSopenharmony_ci 839370b324cSopenharmony_ci SizeT inLen = inSize - inPos; 840370b324cSopenharmony_ci SizeT outLen = unpackSize - outPos; 841370b324cSopenharmony_ci 842370b324cSopenharmony_ci ECoderStatus status; 843370b324cSopenharmony_ci 844370b324cSopenharmony_ci const SRes res = XzUnpacker_Code(&xzu.p, 845370b324cSopenharmony_ci // dest + outPos, 846370b324cSopenharmony_ci NULL, 847370b324cSopenharmony_ci &outLen, 848370b324cSopenharmony_ci xzu.InBuf + inPos, &inLen, 849370b324cSopenharmony_ci (inLen == 0), // srcFinished 850370b324cSopenharmony_ci CODER_FINISH_END, &status); 851370b324cSopenharmony_ci 852370b324cSopenharmony_ci // return E_OUTOFMEMORY; 853370b324cSopenharmony_ci // res = SZ_ERROR_CRC; 854370b324cSopenharmony_ci 855370b324cSopenharmony_ci if (res != SZ_OK) 856370b324cSopenharmony_ci { 857370b324cSopenharmony_ci if (res == SZ_ERROR_CRC) 858370b324cSopenharmony_ci return S_FALSE; 859370b324cSopenharmony_ci return SResToHRESULT(res); 860370b324cSopenharmony_ci } 861370b324cSopenharmony_ci 862370b324cSopenharmony_ci inPos += inLen; 863370b324cSopenharmony_ci outPos += outLen; 864370b324cSopenharmony_ci 865370b324cSopenharmony_ci packRem -= inLen; 866370b324cSopenharmony_ci 867370b324cSopenharmony_ci const BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p); 868370b324cSopenharmony_ci 869370b324cSopenharmony_ci if ((inLen == 0 && outLen == 0) || blockFinished) 870370b324cSopenharmony_ci { 871370b324cSopenharmony_ci if (packRem != 0 || !blockFinished || unpackSize != outPos) 872370b324cSopenharmony_ci return S_FALSE; 873370b324cSopenharmony_ci if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize) 874370b324cSopenharmony_ci return S_FALSE; 875370b324cSopenharmony_ci return S_OK; 876370b324cSopenharmony_ci } 877370b324cSopenharmony_ci } 878370b324cSopenharmony_ci} 879370b324cSopenharmony_ci 880370b324cSopenharmony_ci 881370b324cSopenharmony_ciZ7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 882370b324cSopenharmony_ci{ 883370b324cSopenharmony_ci COM_TRY_BEGIN 884370b324cSopenharmony_ci 885370b324cSopenharmony_ci if (processedSize) 886370b324cSopenharmony_ci *processedSize = 0; 887370b324cSopenharmony_ci if (size == 0) 888370b324cSopenharmony_ci return S_OK; 889370b324cSopenharmony_ci 890370b324cSopenharmony_ci { 891370b324cSopenharmony_ci if (_virtPos >= Size) 892370b324cSopenharmony_ci return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; 893370b324cSopenharmony_ci { 894370b324cSopenharmony_ci UInt64 rem = Size - _virtPos; 895370b324cSopenharmony_ci if (size > rem) 896370b324cSopenharmony_ci size = (UInt32)rem; 897370b324cSopenharmony_ci } 898370b324cSopenharmony_ci } 899370b324cSopenharmony_ci 900370b324cSopenharmony_ci if (size == 0) 901370b324cSopenharmony_ci return S_OK; 902370b324cSopenharmony_ci 903370b324cSopenharmony_ci if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize) 904370b324cSopenharmony_ci { 905370b324cSopenharmony_ci const size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos); 906370b324cSopenharmony_ci const CBlockInfo &block = _handlerSpec->_blocks[bi]; 907370b324cSopenharmony_ci const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos; 908370b324cSopenharmony_ci if (_cache.Size() < unpackSize) 909370b324cSopenharmony_ci return E_FAIL; 910370b324cSopenharmony_ci 911370b324cSopenharmony_ci _cacheSize = 0; 912370b324cSopenharmony_ci 913370b324cSopenharmony_ci RINOK(_handlerSpec->SeekToPackPos(block.PackPos)) 914370b324cSopenharmony_ci RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize, 915370b324cSopenharmony_ci (size_t)unpackSize, _cache)) 916370b324cSopenharmony_ci _cacheStartPos = block.UnpackPos; 917370b324cSopenharmony_ci _cacheSize = (size_t)unpackSize; 918370b324cSopenharmony_ci } 919370b324cSopenharmony_ci 920370b324cSopenharmony_ci { 921370b324cSopenharmony_ci const size_t offset = (size_t)(_virtPos - _cacheStartPos); 922370b324cSopenharmony_ci const size_t rem = _cacheSize - offset; 923370b324cSopenharmony_ci if (size > rem) 924370b324cSopenharmony_ci size = (UInt32)rem; 925370b324cSopenharmony_ci memcpy(data, _cache + offset, size); 926370b324cSopenharmony_ci _virtPos += size; 927370b324cSopenharmony_ci if (processedSize) 928370b324cSopenharmony_ci *processedSize = size; 929370b324cSopenharmony_ci return S_OK; 930370b324cSopenharmony_ci } 931370b324cSopenharmony_ci 932370b324cSopenharmony_ci COM_TRY_END 933370b324cSopenharmony_ci} 934370b324cSopenharmony_ci 935370b324cSopenharmony_ci 936370b324cSopenharmony_ciZ7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 937370b324cSopenharmony_ci{ 938370b324cSopenharmony_ci switch (seekOrigin) 939370b324cSopenharmony_ci { 940370b324cSopenharmony_ci case STREAM_SEEK_SET: break; 941370b324cSopenharmony_ci case STREAM_SEEK_CUR: offset += _virtPos; break; 942370b324cSopenharmony_ci case STREAM_SEEK_END: offset += Size; break; 943370b324cSopenharmony_ci default: return STG_E_INVALIDFUNCTION; 944370b324cSopenharmony_ci } 945370b324cSopenharmony_ci if (offset < 0) 946370b324cSopenharmony_ci return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; 947370b324cSopenharmony_ci _virtPos = (UInt64)offset; 948370b324cSopenharmony_ci if (newPosition) 949370b324cSopenharmony_ci *newPosition = (UInt64)offset; 950370b324cSopenharmony_ci return S_OK; 951370b324cSopenharmony_ci} 952370b324cSopenharmony_ci 953370b324cSopenharmony_ci 954370b324cSopenharmony_ci 955370b324cSopenharmony_cistatic const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40; 956370b324cSopenharmony_ci 957370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) 958370b324cSopenharmony_ci{ 959370b324cSopenharmony_ci COM_TRY_BEGIN 960370b324cSopenharmony_ci 961370b324cSopenharmony_ci *stream = NULL; 962370b324cSopenharmony_ci 963370b324cSopenharmony_ci if (index != 0) 964370b324cSopenharmony_ci return E_INVALIDARG; 965370b324cSopenharmony_ci 966370b324cSopenharmony_ci if (!_stat.UnpackSize_Defined 967370b324cSopenharmony_ci || _maxBlocksSize == 0 // 18.02 968370b324cSopenharmony_ci || _maxBlocksSize > kMaxBlockSize_for_GetStream 969370b324cSopenharmony_ci || _maxBlocksSize != (size_t)_maxBlocksSize) 970370b324cSopenharmony_ci return S_FALSE; 971370b324cSopenharmony_ci 972370b324cSopenharmony_ci UInt64 memSize; 973370b324cSopenharmony_ci if (!NSystem::GetRamSize(memSize)) 974370b324cSopenharmony_ci memSize = (UInt64)(sizeof(size_t)) << 28; 975370b324cSopenharmony_ci { 976370b324cSopenharmony_ci if (_maxBlocksSize > memSize / 4) 977370b324cSopenharmony_ci return S_FALSE; 978370b324cSopenharmony_ci } 979370b324cSopenharmony_ci 980370b324cSopenharmony_ci CInStream *spec = new CInStream; 981370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> specStream = spec; 982370b324cSopenharmony_ci spec->_cache.Alloc((size_t)_maxBlocksSize); 983370b324cSopenharmony_ci spec->_handlerSpec = this; 984370b324cSopenharmony_ci spec->_handler = (IInArchive *)this; 985370b324cSopenharmony_ci spec->Size = _stat.OutSize; 986370b324cSopenharmony_ci spec->InitAndSeek(); 987370b324cSopenharmony_ci 988370b324cSopenharmony_ci *stream = specStream.Detach(); 989370b324cSopenharmony_ci return S_OK; 990370b324cSopenharmony_ci 991370b324cSopenharmony_ci COM_TRY_END 992370b324cSopenharmony_ci} 993370b324cSopenharmony_ci 994370b324cSopenharmony_ci 995370b324cSopenharmony_cistatic Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) 996370b324cSopenharmony_ci{ 997370b324cSopenharmony_ci Int32 opRes; 998370b324cSopenharmony_ci SRes sres = decoder.MainDecodeSRes; 999370b324cSopenharmony_ci if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) 1000370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kIsNotArc; 1001370b324cSopenharmony_ci else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) 1002370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kUnexpectedEnd; 1003370b324cSopenharmony_ci else if (decoder.Stat.DataAfterEnd) 1004370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kDataAfterEnd; 1005370b324cSopenharmony_ci else if (sres == SZ_ERROR_CRC) // (CrcError) 1006370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kCRCError; 1007370b324cSopenharmony_ci else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported) 1008370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kUnsupportedMethod; 1009370b324cSopenharmony_ci else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError) 1010370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kDataError; 1011370b324cSopenharmony_ci else if (sres == SZ_ERROR_DATA) // (DataError) 1012370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kDataError; 1013370b324cSopenharmony_ci else if (sres != SZ_OK) 1014370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kDataError; 1015370b324cSopenharmony_ci else 1016370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kOK; 1017370b324cSopenharmony_ci return opRes; 1018370b324cSopenharmony_ci} 1019370b324cSopenharmony_ci 1020370b324cSopenharmony_ci 1021370b324cSopenharmony_ci 1022370b324cSopenharmony_ci 1023370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1024370b324cSopenharmony_ci Int32 testMode, IArchiveExtractCallback *extractCallback)) 1025370b324cSopenharmony_ci{ 1026370b324cSopenharmony_ci COM_TRY_BEGIN 1027370b324cSopenharmony_ci if (numItems == 0) 1028370b324cSopenharmony_ci return S_OK; 1029370b324cSopenharmony_ci if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 1030370b324cSopenharmony_ci return E_INVALIDARG; 1031370b324cSopenharmony_ci 1032370b324cSopenharmony_ci const CXzStatInfo *stat = GetStat(); 1033370b324cSopenharmony_ci 1034370b324cSopenharmony_ci if (stat) 1035370b324cSopenharmony_ci extractCallback->SetTotal(stat->InSize); 1036370b324cSopenharmony_ci 1037370b324cSopenharmony_ci UInt64 currentTotalPacked = 0; 1038370b324cSopenharmony_ci RINOK(extractCallback->SetCompleted(¤tTotalPacked)) 1039370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> realOutStream; 1040370b324cSopenharmony_ci const Int32 askMode = testMode ? 1041370b324cSopenharmony_ci NExtract::NAskMode::kTest : 1042370b324cSopenharmony_ci NExtract::NAskMode::kExtract; 1043370b324cSopenharmony_ci 1044370b324cSopenharmony_ci RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) 1045370b324cSopenharmony_ci 1046370b324cSopenharmony_ci if (!testMode && !realOutStream) 1047370b324cSopenharmony_ci return S_OK; 1048370b324cSopenharmony_ci 1049370b324cSopenharmony_ci extractCallback->PrepareOperation(askMode); 1050370b324cSopenharmony_ci 1051370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 1052370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> lpsRef = lps; 1053370b324cSopenharmony_ci lps->Init(extractCallback, true); 1054370b324cSopenharmony_ci 1055370b324cSopenharmony_ci if (_needSeekToStart) 1056370b324cSopenharmony_ci { 1057370b324cSopenharmony_ci if (!_stream) 1058370b324cSopenharmony_ci return E_FAIL; 1059370b324cSopenharmony_ci RINOK(InStream_SeekToBegin(_stream)) 1060370b324cSopenharmony_ci } 1061370b324cSopenharmony_ci else 1062370b324cSopenharmony_ci _needSeekToStart = true; 1063370b324cSopenharmony_ci 1064370b324cSopenharmony_ci 1065370b324cSopenharmony_ci NCompress::NXz::CDecoder decoder; 1066370b324cSopenharmony_ci 1067370b324cSopenharmony_ci HRESULT hres = Decode(decoder, _seqStream, realOutStream, lpsRef); 1068370b324cSopenharmony_ci 1069370b324cSopenharmony_ci if (!decoder.MainDecodeSRes_wasUsed) 1070370b324cSopenharmony_ci return hres == S_OK ? E_FAIL : hres; 1071370b324cSopenharmony_ci 1072370b324cSopenharmony_ci Int32 opRes = Get_Extract_OperationResult(decoder); 1073370b324cSopenharmony_ci if (opRes == NExtract::NOperationResult::kOK 1074370b324cSopenharmony_ci && hres != S_OK) 1075370b324cSopenharmony_ci opRes = NExtract::NOperationResult::kDataError; 1076370b324cSopenharmony_ci 1077370b324cSopenharmony_ci realOutStream.Release(); 1078370b324cSopenharmony_ci return extractCallback->SetOperationResult(opRes); 1079370b324cSopenharmony_ci COM_TRY_END 1080370b324cSopenharmony_ci} 1081370b324cSopenharmony_ci 1082370b324cSopenharmony_ci 1083370b324cSopenharmony_ci 1084370b324cSopenharmony_ci#ifndef Z7_EXTRACT_ONLY 1085370b324cSopenharmony_ci 1086370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType)) 1087370b324cSopenharmony_ci{ 1088370b324cSopenharmony_ci *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType; 1089370b324cSopenharmony_ci // *timeType = NFileTimeType::kUnix; 1090370b324cSopenharmony_ci return S_OK; 1091370b324cSopenharmony_ci} 1092370b324cSopenharmony_ci 1093370b324cSopenharmony_ci 1094370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, 1095370b324cSopenharmony_ci IArchiveUpdateCallback *updateCallback)) 1096370b324cSopenharmony_ci{ 1097370b324cSopenharmony_ci COM_TRY_BEGIN 1098370b324cSopenharmony_ci 1099370b324cSopenharmony_ci if (numItems == 0) 1100370b324cSopenharmony_ci { 1101370b324cSopenharmony_ci CSeqOutStreamWrap seqOutStream; 1102370b324cSopenharmony_ci seqOutStream.Init(outStream); 1103370b324cSopenharmony_ci SRes res = Xz_EncodeEmpty(&seqOutStream.vt); 1104370b324cSopenharmony_ci return SResToHRESULT(res); 1105370b324cSopenharmony_ci } 1106370b324cSopenharmony_ci 1107370b324cSopenharmony_ci if (numItems != 1) 1108370b324cSopenharmony_ci return E_INVALIDARG; 1109370b324cSopenharmony_ci 1110370b324cSopenharmony_ci { 1111370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1112370b324cSopenharmony_ci IStreamSetRestriction, 1113370b324cSopenharmony_ci setRestriction, outStream) 1114370b324cSopenharmony_ci if (setRestriction) 1115370b324cSopenharmony_ci RINOK(setRestriction->SetRestriction(0, 0)) 1116370b324cSopenharmony_ci } 1117370b324cSopenharmony_ci 1118370b324cSopenharmony_ci Int32 newData, newProps; 1119370b324cSopenharmony_ci UInt32 indexInArchive; 1120370b324cSopenharmony_ci if (!updateCallback) 1121370b324cSopenharmony_ci return E_FAIL; 1122370b324cSopenharmony_ci RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)) 1123370b324cSopenharmony_ci 1124370b324cSopenharmony_ci if (IntToBool(newProps)) 1125370b324cSopenharmony_ci { 1126370b324cSopenharmony_ci { 1127370b324cSopenharmony_ci NCOM::CPropVariant prop; 1128370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)) 1129370b324cSopenharmony_ci if (prop.vt != VT_EMPTY) 1130370b324cSopenharmony_ci if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) 1131370b324cSopenharmony_ci return E_INVALIDARG; 1132370b324cSopenharmony_ci } 1133370b324cSopenharmony_ci } 1134370b324cSopenharmony_ci 1135370b324cSopenharmony_ci if (IntToBool(newData)) 1136370b324cSopenharmony_ci { 1137370b324cSopenharmony_ci UInt64 dataSize; 1138370b324cSopenharmony_ci { 1139370b324cSopenharmony_ci NCOM::CPropVariant prop; 1140370b324cSopenharmony_ci RINOK(updateCallback->GetProperty(0, kpidSize, &prop)) 1141370b324cSopenharmony_ci if (prop.vt != VT_UI8) 1142370b324cSopenharmony_ci return E_INVALIDARG; 1143370b324cSopenharmony_ci dataSize = prop.uhVal.QuadPart; 1144370b324cSopenharmony_ci } 1145370b324cSopenharmony_ci 1146370b324cSopenharmony_ci NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder; 1147370b324cSopenharmony_ci CMyComPtr<ICompressCoder> encoder = encoderSpec; 1148370b324cSopenharmony_ci 1149370b324cSopenharmony_ci CXzProps &xzProps = encoderSpec->xzProps; 1150370b324cSopenharmony_ci CLzma2EncProps &lzma2Props = xzProps.lzma2Props; 1151370b324cSopenharmony_ci 1152370b324cSopenharmony_ci lzma2Props.lzmaProps.level = GetLevel(); 1153370b324cSopenharmony_ci 1154370b324cSopenharmony_ci xzProps.reduceSize = dataSize; 1155370b324cSopenharmony_ci /* 1156370b324cSopenharmony_ci { 1157370b324cSopenharmony_ci NCOM::CPropVariant prop = (UInt64)dataSize; 1158370b324cSopenharmony_ci RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop)) 1159370b324cSopenharmony_ci } 1160370b324cSopenharmony_ci */ 1161370b324cSopenharmony_ci 1162370b324cSopenharmony_ci #ifndef Z7_ST 1163370b324cSopenharmony_ci 1164370b324cSopenharmony_ci UInt32 numThreads = _numThreads; 1165370b324cSopenharmony_ci 1166370b324cSopenharmony_ci const UInt32 kNumThreads_Max = 1024; 1167370b324cSopenharmony_ci if (numThreads > kNumThreads_Max) 1168370b324cSopenharmony_ci numThreads = kNumThreads_Max; 1169370b324cSopenharmony_ci 1170370b324cSopenharmony_ci if (!_numThreads_WasForced 1171370b324cSopenharmony_ci && _numThreads >= 1 1172370b324cSopenharmony_ci && _memUsage_WasSet) 1173370b324cSopenharmony_ci { 1174370b324cSopenharmony_ci COneMethodInfo oneMethodInfo; 1175370b324cSopenharmony_ci if (!_methods.IsEmpty()) 1176370b324cSopenharmony_ci oneMethodInfo = _methods[0]; 1177370b324cSopenharmony_ci 1178370b324cSopenharmony_ci SetGlobalLevelTo(oneMethodInfo); 1179370b324cSopenharmony_ci 1180370b324cSopenharmony_ci const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); 1181370b324cSopenharmony_ci if (!numThreads_WasSpecifiedInMethod) 1182370b324cSopenharmony_ci { 1183370b324cSopenharmony_ci // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already 1184370b324cSopenharmony_ci CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads); 1185370b324cSopenharmony_ci } 1186370b324cSopenharmony_ci 1187370b324cSopenharmony_ci UInt64 cs = _numSolidBytes; 1188370b324cSopenharmony_ci if (cs != XZ_PROPS_BLOCK_SIZE_AUTO) 1189370b324cSopenharmony_ci oneMethodInfo.AddProp_BlockSize2(cs); 1190370b324cSopenharmony_ci cs = oneMethodInfo.Get_Xz_BlockSize(); 1191370b324cSopenharmony_ci 1192370b324cSopenharmony_ci if (cs != XZ_PROPS_BLOCK_SIZE_AUTO && 1193370b324cSopenharmony_ci cs != XZ_PROPS_BLOCK_SIZE_SOLID) 1194370b324cSopenharmony_ci { 1195370b324cSopenharmony_ci const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); 1196370b324cSopenharmony_ci const UInt32 numBlockThreads_Original = numThreads / lzmaThreads; 1197370b324cSopenharmony_ci 1198370b324cSopenharmony_ci if (numBlockThreads_Original > 1) 1199370b324cSopenharmony_ci { 1200370b324cSopenharmony_ci UInt32 numBlockThreads = numBlockThreads_Original; 1201370b324cSopenharmony_ci { 1202370b324cSopenharmony_ci const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); 1203370b324cSopenharmony_ci for (; numBlockThreads > 1; numBlockThreads--) 1204370b324cSopenharmony_ci { 1205370b324cSopenharmony_ci UInt64 size = numBlockThreads * (lzmaMemUsage + cs); 1206370b324cSopenharmony_ci UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; 1207370b324cSopenharmony_ci if (cs < ((UInt32)1 << 26)) numPackChunks++; 1208370b324cSopenharmony_ci if (cs < ((UInt32)1 << 24)) numPackChunks++; 1209370b324cSopenharmony_ci if (cs < ((UInt32)1 << 22)) numPackChunks++; 1210370b324cSopenharmony_ci size += numPackChunks * cs; 1211370b324cSopenharmony_ci // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20)); 1212370b324cSopenharmony_ci if (size <= _memUsage_Compress) 1213370b324cSopenharmony_ci break; 1214370b324cSopenharmony_ci } 1215370b324cSopenharmony_ci } 1216370b324cSopenharmony_ci if (numBlockThreads == 0) 1217370b324cSopenharmony_ci numBlockThreads = 1; 1218370b324cSopenharmony_ci if (numBlockThreads != numBlockThreads_Original) 1219370b324cSopenharmony_ci numThreads = numBlockThreads * lzmaThreads; 1220370b324cSopenharmony_ci } 1221370b324cSopenharmony_ci } 1222370b324cSopenharmony_ci } 1223370b324cSopenharmony_ci xzProps.numTotalThreads = (int)numThreads; 1224370b324cSopenharmony_ci 1225370b324cSopenharmony_ci #endif // Z7_ST 1226370b324cSopenharmony_ci 1227370b324cSopenharmony_ci 1228370b324cSopenharmony_ci xzProps.blockSize = _numSolidBytes; 1229370b324cSopenharmony_ci if (_numSolidBytes == XZ_PROPS_BLOCK_SIZE_SOLID) 1230370b324cSopenharmony_ci { 1231370b324cSopenharmony_ci xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; 1232370b324cSopenharmony_ci } 1233370b324cSopenharmony_ci 1234370b324cSopenharmony_ci RINOK(encoderSpec->SetCheckSize(_crcSize)) 1235370b324cSopenharmony_ci 1236370b324cSopenharmony_ci { 1237370b324cSopenharmony_ci CXzFilterProps &filter = xzProps.filterProps; 1238370b324cSopenharmony_ci 1239370b324cSopenharmony_ci if (_filterId == XZ_ID_Delta) 1240370b324cSopenharmony_ci { 1241370b324cSopenharmony_ci bool deltaDefined = false; 1242370b324cSopenharmony_ci FOR_VECTOR (j, _filterMethod.Props) 1243370b324cSopenharmony_ci { 1244370b324cSopenharmony_ci const CProp &prop = _filterMethod.Props[j]; 1245370b324cSopenharmony_ci if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) 1246370b324cSopenharmony_ci { 1247370b324cSopenharmony_ci UInt32 delta = (UInt32)prop.Value.ulVal; 1248370b324cSopenharmony_ci if (delta < 1 || delta > 256) 1249370b324cSopenharmony_ci return E_INVALIDARG; 1250370b324cSopenharmony_ci filter.delta = delta; 1251370b324cSopenharmony_ci deltaDefined = true; 1252370b324cSopenharmony_ci } 1253370b324cSopenharmony_ci else 1254370b324cSopenharmony_ci return E_INVALIDARG; 1255370b324cSopenharmony_ci } 1256370b324cSopenharmony_ci if (!deltaDefined) 1257370b324cSopenharmony_ci return E_INVALIDARG; 1258370b324cSopenharmony_ci } 1259370b324cSopenharmony_ci filter.id = _filterId; 1260370b324cSopenharmony_ci } 1261370b324cSopenharmony_ci 1262370b324cSopenharmony_ci FOR_VECTOR (i, _methods) 1263370b324cSopenharmony_ci { 1264370b324cSopenharmony_ci COneMethodInfo &m = _methods[i]; 1265370b324cSopenharmony_ci 1266370b324cSopenharmony_ci FOR_VECTOR (j, m.Props) 1267370b324cSopenharmony_ci { 1268370b324cSopenharmony_ci const CProp &prop = m.Props[j]; 1269370b324cSopenharmony_ci RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value)) 1270370b324cSopenharmony_ci } 1271370b324cSopenharmony_ci } 1272370b324cSopenharmony_ci 1273370b324cSopenharmony_ci { 1274370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> fileInStream; 1275370b324cSopenharmony_ci RINOK(updateCallback->GetStream(0, &fileInStream)) 1276370b324cSopenharmony_ci if (!fileInStream) 1277370b324cSopenharmony_ci return S_FALSE; 1278370b324cSopenharmony_ci { 1279370b324cSopenharmony_ci CMyComPtr<IStreamGetSize> streamGetSize; 1280370b324cSopenharmony_ci fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize); 1281370b324cSopenharmony_ci if (streamGetSize) 1282370b324cSopenharmony_ci { 1283370b324cSopenharmony_ci UInt64 size; 1284370b324cSopenharmony_ci if (streamGetSize->GetSize(&size) == S_OK) 1285370b324cSopenharmony_ci dataSize = size; 1286370b324cSopenharmony_ci } 1287370b324cSopenharmony_ci } 1288370b324cSopenharmony_ci RINOK(updateCallback->SetTotal(dataSize)) 1289370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 1290370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 1291370b324cSopenharmony_ci lps->Init(updateCallback, true); 1292370b324cSopenharmony_ci RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)) 1293370b324cSopenharmony_ci } 1294370b324cSopenharmony_ci 1295370b324cSopenharmony_ci return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); 1296370b324cSopenharmony_ci } 1297370b324cSopenharmony_ci 1298370b324cSopenharmony_ci if (indexInArchive != 0) 1299370b324cSopenharmony_ci return E_INVALIDARG; 1300370b324cSopenharmony_ci 1301370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 1302370b324cSopenharmony_ci IArchiveUpdateCallbackFile, 1303370b324cSopenharmony_ci opCallback, updateCallback) 1304370b324cSopenharmony_ci if (opCallback) 1305370b324cSopenharmony_ci { 1306370b324cSopenharmony_ci RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) 1307370b324cSopenharmony_ci } 1308370b324cSopenharmony_ci 1309370b324cSopenharmony_ci if (_stream) 1310370b324cSopenharmony_ci { 1311370b324cSopenharmony_ci const CXzStatInfo *stat = GetStat(); 1312370b324cSopenharmony_ci if (stat) 1313370b324cSopenharmony_ci { 1314370b324cSopenharmony_ci RINOK(updateCallback->SetTotal(stat->InSize)) 1315370b324cSopenharmony_ci } 1316370b324cSopenharmony_ci RINOK(InStream_SeekToBegin(_stream)) 1317370b324cSopenharmony_ci } 1318370b324cSopenharmony_ci 1319370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 1320370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 1321370b324cSopenharmony_ci lps->Init(updateCallback, true); 1322370b324cSopenharmony_ci 1323370b324cSopenharmony_ci return NCompress::CopyStream(_stream, outStream, progress); 1324370b324cSopenharmony_ci 1325370b324cSopenharmony_ci COM_TRY_END 1326370b324cSopenharmony_ci} 1327370b324cSopenharmony_ci 1328370b324cSopenharmony_ci#endif 1329370b324cSopenharmony_ci 1330370b324cSopenharmony_ci 1331370b324cSopenharmony_ciHRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) 1332370b324cSopenharmony_ci{ 1333370b324cSopenharmony_ci UString name = nameSpec; 1334370b324cSopenharmony_ci name.MakeLower_Ascii(); 1335370b324cSopenharmony_ci if (name.IsEmpty()) 1336370b324cSopenharmony_ci return E_INVALIDARG; 1337370b324cSopenharmony_ci 1338370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 1339370b324cSopenharmony_ci 1340370b324cSopenharmony_ci if (name[0] == L's') 1341370b324cSopenharmony_ci { 1342370b324cSopenharmony_ci const wchar_t *s = name.Ptr(1); 1343370b324cSopenharmony_ci if (*s == 0) 1344370b324cSopenharmony_ci { 1345370b324cSopenharmony_ci bool useStr = false; 1346370b324cSopenharmony_ci bool isSolid; 1347370b324cSopenharmony_ci switch (value.vt) 1348370b324cSopenharmony_ci { 1349370b324cSopenharmony_ci case VT_EMPTY: isSolid = true; break; 1350370b324cSopenharmony_ci case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; 1351370b324cSopenharmony_ci case VT_BSTR: 1352370b324cSopenharmony_ci if (!StringToBool(value.bstrVal, isSolid)) 1353370b324cSopenharmony_ci useStr = true; 1354370b324cSopenharmony_ci break; 1355370b324cSopenharmony_ci default: return E_INVALIDARG; 1356370b324cSopenharmony_ci } 1357370b324cSopenharmony_ci if (!useStr) 1358370b324cSopenharmony_ci { 1359370b324cSopenharmony_ci _numSolidBytes = (isSolid ? XZ_PROPS_BLOCK_SIZE_SOLID : XZ_PROPS_BLOCK_SIZE_AUTO); 1360370b324cSopenharmony_ci return S_OK; 1361370b324cSopenharmony_ci } 1362370b324cSopenharmony_ci } 1363370b324cSopenharmony_ci return ParseSizeString(s, value, 1364370b324cSopenharmony_ci 0, // percentsBase 1365370b324cSopenharmony_ci _numSolidBytes) ? S_OK: E_INVALIDARG; 1366370b324cSopenharmony_ci } 1367370b324cSopenharmony_ci 1368370b324cSopenharmony_ci return CMultiMethodProps::SetProperty(name, value); 1369370b324cSopenharmony_ci 1370370b324cSopenharmony_ci #else 1371370b324cSopenharmony_ci 1372370b324cSopenharmony_ci { 1373370b324cSopenharmony_ci HRESULT hres; 1374370b324cSopenharmony_ci if (SetCommonProperty(name, value, hres)) 1375370b324cSopenharmony_ci return hres; 1376370b324cSopenharmony_ci } 1377370b324cSopenharmony_ci 1378370b324cSopenharmony_ci return E_INVALIDARG; 1379370b324cSopenharmony_ci 1380370b324cSopenharmony_ci #endif 1381370b324cSopenharmony_ci} 1382370b324cSopenharmony_ci 1383370b324cSopenharmony_ci 1384370b324cSopenharmony_ci 1385370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) 1386370b324cSopenharmony_ci{ 1387370b324cSopenharmony_ci COM_TRY_BEGIN 1388370b324cSopenharmony_ci 1389370b324cSopenharmony_ci Init(); 1390370b324cSopenharmony_ci 1391370b324cSopenharmony_ci for (UInt32 i = 0; i < numProps; i++) 1392370b324cSopenharmony_ci { 1393370b324cSopenharmony_ci RINOK(SetProperty(names[i], values[i])) 1394370b324cSopenharmony_ci } 1395370b324cSopenharmony_ci 1396370b324cSopenharmony_ci #ifndef Z7_EXTRACT_ONLY 1397370b324cSopenharmony_ci 1398370b324cSopenharmony_ci if (!_filterMethod.MethodName.IsEmpty()) 1399370b324cSopenharmony_ci { 1400370b324cSopenharmony_ci unsigned k; 1401370b324cSopenharmony_ci for (k = 0; k < Z7_ARRAY_SIZE(g_NamePairs); k++) 1402370b324cSopenharmony_ci { 1403370b324cSopenharmony_ci const CMethodNamePair &pair = g_NamePairs[k]; 1404370b324cSopenharmony_ci if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) 1405370b324cSopenharmony_ci { 1406370b324cSopenharmony_ci _filterId = pair.Id; 1407370b324cSopenharmony_ci break; 1408370b324cSopenharmony_ci } 1409370b324cSopenharmony_ci } 1410370b324cSopenharmony_ci if (k == Z7_ARRAY_SIZE(g_NamePairs)) 1411370b324cSopenharmony_ci return E_INVALIDARG; 1412370b324cSopenharmony_ci } 1413370b324cSopenharmony_ci 1414370b324cSopenharmony_ci _methods.DeleteFrontal(GetNumEmptyMethods()); 1415370b324cSopenharmony_ci if (_methods.Size() > 1) 1416370b324cSopenharmony_ci return E_INVALIDARG; 1417370b324cSopenharmony_ci if (_methods.Size() == 1) 1418370b324cSopenharmony_ci { 1419370b324cSopenharmony_ci AString &methodName = _methods[0].MethodName; 1420370b324cSopenharmony_ci if (methodName.IsEmpty()) 1421370b324cSopenharmony_ci methodName = k_LZMA2_Name; 1422370b324cSopenharmony_ci else if ( 1423370b324cSopenharmony_ci !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name) 1424370b324cSopenharmony_ci && !methodName.IsEqualTo_Ascii_NoCase("xz")) 1425370b324cSopenharmony_ci return E_INVALIDARG; 1426370b324cSopenharmony_ci } 1427370b324cSopenharmony_ci 1428370b324cSopenharmony_ci #endif 1429370b324cSopenharmony_ci 1430370b324cSopenharmony_ci return S_OK; 1431370b324cSopenharmony_ci 1432370b324cSopenharmony_ci COM_TRY_END 1433370b324cSopenharmony_ci} 1434370b324cSopenharmony_ci 1435370b324cSopenharmony_ci 1436370b324cSopenharmony_ciREGISTER_ARC_IO( 1437370b324cSopenharmony_ci "xz", "xz txz", "* .tar", 0xC, 1438370b324cSopenharmony_ci XZ_SIG, 0 1439370b324cSopenharmony_ci , NArcInfoFlags::kKeepName 1440370b324cSopenharmony_ci , 0 1441370b324cSopenharmony_ci , NULL) 1442370b324cSopenharmony_ci 1443370b324cSopenharmony_ci}} 1444