1370b324cSopenharmony_ci// SplitHandler.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../Common/ComTry.h" 6370b324cSopenharmony_ci#include "../../Common/MyString.h" 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci#include "../../Windows/PropVariant.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#include "../Common/ProgressUtils.h" 11370b324cSopenharmony_ci#include "../Common/RegisterArc.h" 12370b324cSopenharmony_ci#include "../Common/StreamUtils.h" 13370b324cSopenharmony_ci 14370b324cSopenharmony_ci#include "../Compress/CopyCoder.h" 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci#include "Common/MultiStream.h" 17370b324cSopenharmony_ci 18370b324cSopenharmony_ciusing namespace NWindows; 19370b324cSopenharmony_ci 20370b324cSopenharmony_cinamespace NArchive { 21370b324cSopenharmony_cinamespace NSplit { 22370b324cSopenharmony_ci 23370b324cSopenharmony_cistatic const Byte kProps[] = 24370b324cSopenharmony_ci{ 25370b324cSopenharmony_ci kpidPath, 26370b324cSopenharmony_ci kpidSize 27370b324cSopenharmony_ci}; 28370b324cSopenharmony_ci 29370b324cSopenharmony_cistatic const Byte kArcProps[] = 30370b324cSopenharmony_ci{ 31370b324cSopenharmony_ci kpidNumVolumes, 32370b324cSopenharmony_ci kpidTotalPhySize 33370b324cSopenharmony_ci}; 34370b324cSopenharmony_ci 35370b324cSopenharmony_ci 36370b324cSopenharmony_ciZ7_CLASS_IMP_CHandler_IInArchive_1( 37370b324cSopenharmony_ci IInArchiveGetStream 38370b324cSopenharmony_ci) 39370b324cSopenharmony_ci CObjectVector<CMyComPtr<IInStream> > _streams; 40370b324cSopenharmony_ci CRecordVector<UInt64> _sizes; 41370b324cSopenharmony_ci UString _subName; 42370b324cSopenharmony_ci UInt64 _totalSize; 43370b324cSopenharmony_ci 44370b324cSopenharmony_ci HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); 45370b324cSopenharmony_ci}; 46370b324cSopenharmony_ci 47370b324cSopenharmony_ciIMP_IInArchive_Props 48370b324cSopenharmony_ciIMP_IInArchive_ArcProps 49370b324cSopenharmony_ci 50370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 51370b324cSopenharmony_ci{ 52370b324cSopenharmony_ci NCOM::CPropVariant prop; 53370b324cSopenharmony_ci switch (propID) 54370b324cSopenharmony_ci { 55370b324cSopenharmony_ci case kpidMainSubfile: prop = (UInt32)0; break; 56370b324cSopenharmony_ci case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break; 57370b324cSopenharmony_ci case kpidTotalPhySize: prop = _totalSize; break; 58370b324cSopenharmony_ci case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; 59370b324cSopenharmony_ci } 60370b324cSopenharmony_ci prop.Detach(value); 61370b324cSopenharmony_ci return S_OK; 62370b324cSopenharmony_ci} 63370b324cSopenharmony_ci 64370b324cSopenharmony_cistruct CSeqName 65370b324cSopenharmony_ci{ 66370b324cSopenharmony_ci UString _unchangedPart; 67370b324cSopenharmony_ci UString _changedPart; 68370b324cSopenharmony_ci bool _splitStyle; 69370b324cSopenharmony_ci 70370b324cSopenharmony_ci bool GetNextName(UString &s) 71370b324cSopenharmony_ci { 72370b324cSopenharmony_ci { 73370b324cSopenharmony_ci unsigned i = _changedPart.Len(); 74370b324cSopenharmony_ci for (;;) 75370b324cSopenharmony_ci { 76370b324cSopenharmony_ci wchar_t c = _changedPart[--i]; 77370b324cSopenharmony_ci 78370b324cSopenharmony_ci if (_splitStyle) 79370b324cSopenharmony_ci { 80370b324cSopenharmony_ci if (c == 'z') 81370b324cSopenharmony_ci { 82370b324cSopenharmony_ci _changedPart.ReplaceOneCharAtPos(i, L'a'); 83370b324cSopenharmony_ci if (i == 0) 84370b324cSopenharmony_ci return false; 85370b324cSopenharmony_ci continue; 86370b324cSopenharmony_ci } 87370b324cSopenharmony_ci else if (c == 'Z') 88370b324cSopenharmony_ci { 89370b324cSopenharmony_ci _changedPart.ReplaceOneCharAtPos(i, L'A'); 90370b324cSopenharmony_ci if (i == 0) 91370b324cSopenharmony_ci return false; 92370b324cSopenharmony_ci continue; 93370b324cSopenharmony_ci } 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci else 96370b324cSopenharmony_ci { 97370b324cSopenharmony_ci if (c == '9') 98370b324cSopenharmony_ci { 99370b324cSopenharmony_ci _changedPart.ReplaceOneCharAtPos(i, L'0'); 100370b324cSopenharmony_ci if (i == 0) 101370b324cSopenharmony_ci { 102370b324cSopenharmony_ci _changedPart.InsertAtFront(L'1'); 103370b324cSopenharmony_ci break; 104370b324cSopenharmony_ci } 105370b324cSopenharmony_ci continue; 106370b324cSopenharmony_ci } 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci 109370b324cSopenharmony_ci c++; 110370b324cSopenharmony_ci _changedPart.ReplaceOneCharAtPos(i, c); 111370b324cSopenharmony_ci break; 112370b324cSopenharmony_ci } 113370b324cSopenharmony_ci } 114370b324cSopenharmony_ci 115370b324cSopenharmony_ci s = _unchangedPart + _changedPart; 116370b324cSopenharmony_ci return true; 117370b324cSopenharmony_ci } 118370b324cSopenharmony_ci}; 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci 121370b324cSopenharmony_ciHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) 122370b324cSopenharmony_ci{ 123370b324cSopenharmony_ci Close(); 124370b324cSopenharmony_ci if (!callback) 125370b324cSopenharmony_ci return S_FALSE; 126370b324cSopenharmony_ci 127370b324cSopenharmony_ci Z7_DECL_CMyComPtr_QI_FROM( 128370b324cSopenharmony_ci IArchiveOpenVolumeCallback, 129370b324cSopenharmony_ci volumeCallback, callback) 130370b324cSopenharmony_ci if (!volumeCallback) 131370b324cSopenharmony_ci return S_FALSE; 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci UString name; 134370b324cSopenharmony_ci { 135370b324cSopenharmony_ci NCOM::CPropVariant prop; 136370b324cSopenharmony_ci RINOK(volumeCallback->GetProperty(kpidName, &prop)) 137370b324cSopenharmony_ci if (prop.vt != VT_BSTR) 138370b324cSopenharmony_ci return S_FALSE; 139370b324cSopenharmony_ci name = prop.bstrVal; 140370b324cSopenharmony_ci } 141370b324cSopenharmony_ci 142370b324cSopenharmony_ci const int dotPos = name.ReverseFind_Dot(); 143370b324cSopenharmony_ci const UString prefix = name.Left((unsigned)(dotPos + 1)); 144370b324cSopenharmony_ci const UString ext = name.Ptr((unsigned)(dotPos + 1)); 145370b324cSopenharmony_ci UString ext2 = ext; 146370b324cSopenharmony_ci ext2.MakeLower_Ascii(); 147370b324cSopenharmony_ci 148370b324cSopenharmony_ci CSeqName seqName; 149370b324cSopenharmony_ci 150370b324cSopenharmony_ci unsigned numLetters = 2; 151370b324cSopenharmony_ci bool splitStyle = false; 152370b324cSopenharmony_ci 153370b324cSopenharmony_ci if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), "aa")) 154370b324cSopenharmony_ci { 155370b324cSopenharmony_ci splitStyle = true; 156370b324cSopenharmony_ci while (numLetters < ext2.Len()) 157370b324cSopenharmony_ci { 158370b324cSopenharmony_ci if (ext2[ext2.Len() - numLetters - 1] != 'a') 159370b324cSopenharmony_ci break; 160370b324cSopenharmony_ci numLetters++; 161370b324cSopenharmony_ci } 162370b324cSopenharmony_ci } 163370b324cSopenharmony_ci else if (ext2.Len() >= 2 && ( 164370b324cSopenharmony_ci StringsAreEqual_Ascii(ext2.RightPtr(2), "01") 165370b324cSopenharmony_ci || StringsAreEqual_Ascii(ext2.RightPtr(2), "00") 166370b324cSopenharmony_ci )) 167370b324cSopenharmony_ci { 168370b324cSopenharmony_ci while (numLetters < ext2.Len()) 169370b324cSopenharmony_ci { 170370b324cSopenharmony_ci if (ext2[ext2.Len() - numLetters - 1] != '0') 171370b324cSopenharmony_ci break; 172370b324cSopenharmony_ci numLetters++; 173370b324cSopenharmony_ci } 174370b324cSopenharmony_ci if (numLetters != ext2.Len()) 175370b324cSopenharmony_ci return S_FALSE; 176370b324cSopenharmony_ci } 177370b324cSopenharmony_ci else 178370b324cSopenharmony_ci return S_FALSE; 179370b324cSopenharmony_ci 180370b324cSopenharmony_ci seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters); 181370b324cSopenharmony_ci seqName._changedPart = ext.RightPtr(numLetters); 182370b324cSopenharmony_ci seqName._splitStyle = splitStyle; 183370b324cSopenharmony_ci 184370b324cSopenharmony_ci if (prefix.Len() < 1) 185370b324cSopenharmony_ci _subName = "file"; 186370b324cSopenharmony_ci else 187370b324cSopenharmony_ci _subName.SetFrom(prefix, prefix.Len() - 1); 188370b324cSopenharmony_ci 189370b324cSopenharmony_ci UInt64 size; 190370b324cSopenharmony_ci { 191370b324cSopenharmony_ci /* 192370b324cSopenharmony_ci NCOM::CPropVariant prop; 193370b324cSopenharmony_ci RINOK(volumeCallback->GetProperty(kpidSize, &prop)) 194370b324cSopenharmony_ci if (prop.vt != VT_UI8) 195370b324cSopenharmony_ci return E_INVALIDARG; 196370b324cSopenharmony_ci size = prop.uhVal.QuadPart; 197370b324cSopenharmony_ci */ 198370b324cSopenharmony_ci } 199370b324cSopenharmony_ci RINOK(InStream_AtBegin_GetSize(stream, size)) 200370b324cSopenharmony_ci 201370b324cSopenharmony_ci _totalSize += size; 202370b324cSopenharmony_ci _sizes.Add(size); 203370b324cSopenharmony_ci _streams.Add(stream); 204370b324cSopenharmony_ci 205370b324cSopenharmony_ci { 206370b324cSopenharmony_ci const UInt64 numFiles = _streams.Size(); 207370b324cSopenharmony_ci RINOK(callback->SetCompleted(&numFiles, NULL)) 208370b324cSopenharmony_ci } 209370b324cSopenharmony_ci 210370b324cSopenharmony_ci for (;;) 211370b324cSopenharmony_ci { 212370b324cSopenharmony_ci UString fullName; 213370b324cSopenharmony_ci if (!seqName.GetNextName(fullName)) 214370b324cSopenharmony_ci break; 215370b324cSopenharmony_ci CMyComPtr<IInStream> nextStream; 216370b324cSopenharmony_ci const HRESULT result = volumeCallback->GetStream(fullName, &nextStream); 217370b324cSopenharmony_ci if (result == S_FALSE) 218370b324cSopenharmony_ci break; 219370b324cSopenharmony_ci if (result != S_OK) 220370b324cSopenharmony_ci return result; 221370b324cSopenharmony_ci if (!nextStream) 222370b324cSopenharmony_ci break; 223370b324cSopenharmony_ci RINOK(InStream_AtBegin_GetSize(nextStream, size)) 224370b324cSopenharmony_ci _totalSize += size; 225370b324cSopenharmony_ci _sizes.Add(size); 226370b324cSopenharmony_ci _streams.Add(nextStream); 227370b324cSopenharmony_ci { 228370b324cSopenharmony_ci const UInt64 numFiles = _streams.Size(); 229370b324cSopenharmony_ci RINOK(callback->SetCompleted(&numFiles, NULL)) 230370b324cSopenharmony_ci } 231370b324cSopenharmony_ci } 232370b324cSopenharmony_ci 233370b324cSopenharmony_ci if (_streams.Size() == 1) 234370b324cSopenharmony_ci { 235370b324cSopenharmony_ci if (splitStyle) 236370b324cSopenharmony_ci return S_FALSE; 237370b324cSopenharmony_ci } 238370b324cSopenharmony_ci return S_OK; 239370b324cSopenharmony_ci} 240370b324cSopenharmony_ci 241370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)) 242370b324cSopenharmony_ci{ 243370b324cSopenharmony_ci COM_TRY_BEGIN 244370b324cSopenharmony_ci const HRESULT res = Open2(stream, callback); 245370b324cSopenharmony_ci if (res != S_OK) 246370b324cSopenharmony_ci Close(); 247370b324cSopenharmony_ci return res; 248370b324cSopenharmony_ci COM_TRY_END 249370b324cSopenharmony_ci} 250370b324cSopenharmony_ci 251370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Close()) 252370b324cSopenharmony_ci{ 253370b324cSopenharmony_ci _totalSize = 0; 254370b324cSopenharmony_ci _subName.Empty(); 255370b324cSopenharmony_ci _streams.Clear(); 256370b324cSopenharmony_ci _sizes.Clear(); 257370b324cSopenharmony_ci return S_OK; 258370b324cSopenharmony_ci} 259370b324cSopenharmony_ci 260370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 261370b324cSopenharmony_ci{ 262370b324cSopenharmony_ci *numItems = _streams.IsEmpty() ? 0 : 1; 263370b324cSopenharmony_ci return S_OK; 264370b324cSopenharmony_ci} 265370b324cSopenharmony_ci 266370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)) 267370b324cSopenharmony_ci{ 268370b324cSopenharmony_ci NCOM::CPropVariant prop; 269370b324cSopenharmony_ci switch (propID) 270370b324cSopenharmony_ci { 271370b324cSopenharmony_ci case kpidPath: prop = _subName; break; 272370b324cSopenharmony_ci case kpidSize: 273370b324cSopenharmony_ci case kpidPackSize: 274370b324cSopenharmony_ci prop = _totalSize; 275370b324cSopenharmony_ci break; 276370b324cSopenharmony_ci } 277370b324cSopenharmony_ci prop.Detach(value); 278370b324cSopenharmony_ci return S_OK; 279370b324cSopenharmony_ci} 280370b324cSopenharmony_ci 281370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 282370b324cSopenharmony_ci Int32 testMode, IArchiveExtractCallback *extractCallback)) 283370b324cSopenharmony_ci{ 284370b324cSopenharmony_ci COM_TRY_BEGIN 285370b324cSopenharmony_ci if (numItems == 0) 286370b324cSopenharmony_ci return S_OK; 287370b324cSopenharmony_ci if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 288370b324cSopenharmony_ci return E_INVALIDARG; 289370b324cSopenharmony_ci 290370b324cSopenharmony_ci UInt64 currentTotalSize = 0; 291370b324cSopenharmony_ci RINOK(extractCallback->SetTotal(_totalSize)) 292370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> outStream; 293370b324cSopenharmony_ci const Int32 askMode = testMode ? 294370b324cSopenharmony_ci NExtract::NAskMode::kTest : 295370b324cSopenharmony_ci NExtract::NAskMode::kExtract; 296370b324cSopenharmony_ci RINOK(extractCallback->GetStream(0, &outStream, askMode)) 297370b324cSopenharmony_ci if (!testMode && !outStream) 298370b324cSopenharmony_ci return S_OK; 299370b324cSopenharmony_ci RINOK(extractCallback->PrepareOperation(askMode)) 300370b324cSopenharmony_ci 301370b324cSopenharmony_ci NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 302370b324cSopenharmony_ci CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 303370b324cSopenharmony_ci 304370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 305370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 306370b324cSopenharmony_ci lps->Init(extractCallback, false); 307370b324cSopenharmony_ci 308370b324cSopenharmony_ci for (unsigned i = 0;; i++) 309370b324cSopenharmony_ci { 310370b324cSopenharmony_ci lps->InSize = lps->OutSize = currentTotalSize; 311370b324cSopenharmony_ci RINOK(lps->SetCur()) 312370b324cSopenharmony_ci if (i == _streams.Size()) 313370b324cSopenharmony_ci break; 314370b324cSopenharmony_ci IInStream *inStream = _streams[i]; 315370b324cSopenharmony_ci RINOK(InStream_SeekToBegin(inStream)) 316370b324cSopenharmony_ci RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) 317370b324cSopenharmony_ci currentTotalSize += copyCoderSpec->TotalSize; 318370b324cSopenharmony_ci } 319370b324cSopenharmony_ci outStream.Release(); 320370b324cSopenharmony_ci return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); 321370b324cSopenharmony_ci COM_TRY_END 322370b324cSopenharmony_ci} 323370b324cSopenharmony_ci 324370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) 325370b324cSopenharmony_ci{ 326370b324cSopenharmony_ci COM_TRY_BEGIN 327370b324cSopenharmony_ci if (index != 0) 328370b324cSopenharmony_ci return E_INVALIDARG; 329370b324cSopenharmony_ci *stream = NULL; 330370b324cSopenharmony_ci CMultiStream *streamSpec = new CMultiStream; 331370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 332370b324cSopenharmony_ci FOR_VECTOR (i, _streams) 333370b324cSopenharmony_ci { 334370b324cSopenharmony_ci CMultiStream::CSubStreamInfo subStreamInfo; 335370b324cSopenharmony_ci subStreamInfo.Stream = _streams[i]; 336370b324cSopenharmony_ci subStreamInfo.Size = _sizes[i]; 337370b324cSopenharmony_ci streamSpec->Streams.Add(subStreamInfo); 338370b324cSopenharmony_ci } 339370b324cSopenharmony_ci streamSpec->Init(); 340370b324cSopenharmony_ci *stream = streamTemp.Detach(); 341370b324cSopenharmony_ci return S_OK; 342370b324cSopenharmony_ci COM_TRY_END 343370b324cSopenharmony_ci} 344370b324cSopenharmony_ci 345370b324cSopenharmony_ciREGISTER_ARC_I_NO_SIG( 346370b324cSopenharmony_ci "Split", "001", NULL, 0xEA, 347370b324cSopenharmony_ci 0, 348370b324cSopenharmony_ci 0, 349370b324cSopenharmony_ci NULL) 350370b324cSopenharmony_ci 351370b324cSopenharmony_ci}} 352