Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Archive/Split/SplitHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // SplitHandler.cpp3 #include "StdAfx.h"5 #include "Common/ComTry.h"6 #include "Common/Defs.h"7 #include "Common/NewHandler.h"8 #include "Common/StringConvert.h"10 #include "Windows/PropVariant.h"11 #include "Windows/Time.h"13 #include "../../Common/ProgressUtils.h"15 #include "../../Compress/CopyCoder.h"17 #include "../Common/ItemNameUtils.h"18 #include "../Common/MultiStream.h"20 #include "SplitHandler.h"22 using namespace NWindows;23 using namespace NTime;25 namespace NArchive {26 namespace NSplit {28 STATPROPSTG kProps[] =29 {30 { NULL, kpidPath, VT_BSTR},31 { NULL, kpidSize, VT_UI8},32 { NULL, kpidPackSize, VT_UI8},33 };35 IMP_IInArchive_Props36 IMP_IInArchive_ArcProps_NO38 class CSeqName39 {40 public:41 UString _unchangedPart;42 UString _changedPart;43 bool _splitStyle;44 UString GetNextName()45 {46 UString newName;47 if (_splitStyle)48 {49 int i;50 int numLetters = _changedPart.Length();51 for (i = numLetters - 1; i >= 0; i--)52 {53 wchar_t c = _changedPart[i];54 if (c == 'z')55 {56 c = 'a';57 newName = c + newName;58 continue;59 }60 else if (c == 'Z')61 {62 c = 'A';63 newName = c + newName;64 continue;65 }66 c++;67 if ((c == 'z' || c == 'Z') && i == 0)68 {69 _unchangedPart += c;70 wchar_t newChar = (c == 'z') ? L'a' : L'A';71 newName.Empty();72 numLetters++;73 for (int k = 0; k < numLetters; k++)74 newName += newChar;75 break;76 }77 newName = c + newName;78 i--;79 for (; i >= 0; i--)80 newName = _changedPart[i] + newName;81 break;82 }83 }84 else85 {86 int i;87 int numLetters = _changedPart.Length();88 for (i = numLetters - 1; i >= 0; i--)89 {90 wchar_t c = _changedPart[i];91 if (c == L'9')92 {93 c = L'0';94 newName = c + newName;95 if (i == 0)96 newName = UString(L'1') + newName;97 continue;98 }99 c++;100 newName = c + newName;101 i--;102 for (; i >= 0; i--)103 newName = _changedPart[i] + newName;104 break;105 }106 }107 _changedPart = newName;108 return _unchangedPart + _changedPart;109 }110 };112 STDMETHODIMP CHandler::Open(IInStream *stream,113 const UInt64 * /* maxCheckStartPosition */,114 IArchiveOpenCallback *openArchiveCallback)115 {116 COM_TRY_BEGIN117 Close();118 if (openArchiveCallback == 0)119 return S_FALSE;120 // try121 {122 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;123 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;124 if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,125 &openVolumeCallback) != S_OK)126 return S_FALSE;128 {129 NCOM::CPropVariant prop;130 RINOK(openVolumeCallback->GetProperty(kpidName, &prop));131 if (prop.vt != VT_BSTR)132 return S_FALSE;133 _name = prop.bstrVal;134 }136 int dotPos = _name.ReverseFind('.');137 UString prefix, ext;138 if (dotPos >= 0)139 {140 prefix = _name.Left(dotPos + 1);141 ext = _name.Mid(dotPos + 1);142 }143 else144 ext = _name;145 UString extBig = ext;146 extBig.MakeUpper();148 CSeqName seqName;150 int numLetters = 2;151 bool splitStyle = false;152 if (extBig.Right(2) == L"AA")153 {154 splitStyle = true;155 while (numLetters < extBig.Length())156 {157 if (extBig[extBig.Length() - numLetters - 1] != 'A')158 break;159 numLetters++;160 }161 }162 else if (ext.Right(2) == L"01")163 {164 while (numLetters < extBig.Length())165 {166 if (extBig[extBig.Length() - numLetters - 1] != '0')167 break;168 numLetters++;169 }170 if (numLetters != ext.Length())171 return S_FALSE;172 }173 else174 return S_FALSE;176 _streams.Add(stream);178 seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);179 seqName._changedPart = ext.Right(numLetters);180 seqName._splitStyle = splitStyle;182 if (prefix.Length() < 1)183 _subName = L"file";184 else185 _subName = prefix.Left(prefix.Length() - 1);187 _totalSize = 0;188 UInt64 size;189 {190 NCOM::CPropVariant prop;191 RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));192 if (prop.vt != VT_UI8)193 return E_INVALIDARG;194 size = prop.uhVal.QuadPart;195 }196 _totalSize += size;197 _sizes.Add(size);199 if (openArchiveCallback != NULL)200 {201 UInt64 numFiles = _streams.Size();202 RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));203 }205 for (;;)206 {207 UString fullName = seqName.GetNextName();208 CMyComPtr<IInStream> nextStream;209 HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);210 if (result == S_FALSE)211 break;212 if (result != S_OK)213 return result;214 if (!stream)215 break;216 {217 NCOM::CPropVariant prop;218 RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));219 if (prop.vt != VT_UI8)220 return E_INVALIDARG;221 size = prop.uhVal.QuadPart;222 }223 _totalSize += size;224 _sizes.Add(size);225 _streams.Add(nextStream);226 if (openArchiveCallback != NULL)227 {228 UInt64 numFiles = _streams.Size();229 RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));230 }231 }232 }233 /*234 catch(...)235 {236 return S_FALSE;237 }238 */239 return S_OK;240 COM_TRY_END241 }243 STDMETHODIMP CHandler::Close()244 {245 _sizes.Clear();246 _streams.Clear();247 return S_OK;248 }250 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)251 {252 *numItems = _streams.IsEmpty() ? 0 : 1;253 return S_OK;254 }256 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)257 {258 NWindows::NCOM::CPropVariant prop;259 switch(propID)260 {261 case kpidPath:262 prop = _subName;263 break;264 case kpidSize:265 case kpidPackSize:266 prop = _totalSize;267 break;268 }269 prop.Detach(value);270 return S_OK;271 }273 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,274 Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)275 {276 COM_TRY_BEGIN278 if (numItems != UInt32(-1))279 {280 if (numItems != 1)281 return E_INVALIDARG;282 if (indices[0] != 0)283 return E_INVALIDARG;284 }285 bool testMode = (_aTestMode != 0);286 CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;287 extractCallback->SetTotal(_totalSize);289 /*290 CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback;291 if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK)292 return E_FAIL;293 */295 UInt64 currentTotalSize = 0;296 UInt64 currentItemSize;298 RINOK(extractCallback->SetCompleted(¤tTotalSize));299 CMyComPtr<ISequentialOutStream> realOutStream;300 Int32 askMode;301 askMode = testMode ? NArchive::NExtract::NAskMode::kTest :302 NArchive::NExtract::NAskMode::kExtract;303 Int32 index = 0;304 RINOK(extractCallback->GetStream(index, &realOutStream, askMode));306 RINOK(extractCallback->PrepareOperation(askMode));307 if (testMode)308 {309 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));310 return S_OK;311 }313 if (!testMode && (!realOutStream))314 return S_OK;316 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;317 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;319 CLocalProgress *lps = new CLocalProgress;320 CMyComPtr<ICompressProgressInfo> progress = lps;321 lps->Init(extractCallback, false);323 for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize)324 {325 lps->InSize = lps->OutSize = currentTotalSize;326 RINOK(lps->SetCur());327 IInStream *inStream = _streams[i];328 RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));329 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));330 currentItemSize = copyCoderSpec->TotalSize;331 }332 realOutStream.Release();333 return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK);334 COM_TRY_END335 }337 STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)338 {339 if (index != 0)340 return E_INVALIDARG;341 *stream = 0;342 CMultiStream *streamSpec = new CMultiStream;343 CMyComPtr<ISequentialInStream> streamTemp = streamSpec;344 for (int i = 0; i < _streams.Size(); i++)345 {346 CMultiStream::CSubStreamInfo subStreamInfo;347 subStreamInfo.Stream = _streams[i];348 subStreamInfo.Pos = 0;349 subStreamInfo.Size = _sizes[i];350 streamSpec->Streams.Add(subStreamInfo);351 }352 streamSpec->Init();353 *stream = streamTemp.Detach();354 return S_OK;355 }357 }}