Mercurial > vba-linux
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Split/SplitHandler.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,357 @@ 1.4 +// SplitHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/ComTry.h" 1.9 +#include "Common/Defs.h" 1.10 +#include "Common/NewHandler.h" 1.11 +#include "Common/StringConvert.h" 1.12 + 1.13 +#include "Windows/PropVariant.h" 1.14 +#include "Windows/Time.h" 1.15 + 1.16 +#include "../../Common/ProgressUtils.h" 1.17 + 1.18 +#include "../../Compress/CopyCoder.h" 1.19 + 1.20 +#include "../Common/ItemNameUtils.h" 1.21 +#include "../Common/MultiStream.h" 1.22 + 1.23 +#include "SplitHandler.h" 1.24 + 1.25 +using namespace NWindows; 1.26 +using namespace NTime; 1.27 + 1.28 +namespace NArchive { 1.29 +namespace NSplit { 1.30 + 1.31 +STATPROPSTG kProps[] = 1.32 +{ 1.33 + { NULL, kpidPath, VT_BSTR}, 1.34 + { NULL, kpidSize, VT_UI8}, 1.35 + { NULL, kpidPackSize, VT_UI8}, 1.36 +}; 1.37 + 1.38 +IMP_IInArchive_Props 1.39 +IMP_IInArchive_ArcProps_NO 1.40 + 1.41 +class CSeqName 1.42 +{ 1.43 +public: 1.44 + UString _unchangedPart; 1.45 + UString _changedPart; 1.46 + bool _splitStyle; 1.47 + UString GetNextName() 1.48 + { 1.49 + UString newName; 1.50 + if (_splitStyle) 1.51 + { 1.52 + int i; 1.53 + int numLetters = _changedPart.Length(); 1.54 + for (i = numLetters - 1; i >= 0; i--) 1.55 + { 1.56 + wchar_t c = _changedPart[i]; 1.57 + if (c == 'z') 1.58 + { 1.59 + c = 'a'; 1.60 + newName = c + newName; 1.61 + continue; 1.62 + } 1.63 + else if (c == 'Z') 1.64 + { 1.65 + c = 'A'; 1.66 + newName = c + newName; 1.67 + continue; 1.68 + } 1.69 + c++; 1.70 + if ((c == 'z' || c == 'Z') && i == 0) 1.71 + { 1.72 + _unchangedPart += c; 1.73 + wchar_t newChar = (c == 'z') ? L'a' : L'A'; 1.74 + newName.Empty(); 1.75 + numLetters++; 1.76 + for (int k = 0; k < numLetters; k++) 1.77 + newName += newChar; 1.78 + break; 1.79 + } 1.80 + newName = c + newName; 1.81 + i--; 1.82 + for (; i >= 0; i--) 1.83 + newName = _changedPart[i] + newName; 1.84 + break; 1.85 + } 1.86 + } 1.87 + else 1.88 + { 1.89 + int i; 1.90 + int numLetters = _changedPart.Length(); 1.91 + for (i = numLetters - 1; i >= 0; i--) 1.92 + { 1.93 + wchar_t c = _changedPart[i]; 1.94 + if (c == L'9') 1.95 + { 1.96 + c = L'0'; 1.97 + newName = c + newName; 1.98 + if (i == 0) 1.99 + newName = UString(L'1') + newName; 1.100 + continue; 1.101 + } 1.102 + c++; 1.103 + newName = c + newName; 1.104 + i--; 1.105 + for (; i >= 0; i--) 1.106 + newName = _changedPart[i] + newName; 1.107 + break; 1.108 + } 1.109 + } 1.110 + _changedPart = newName; 1.111 + return _unchangedPart + _changedPart; 1.112 + } 1.113 +}; 1.114 + 1.115 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.116 + const UInt64 * /* maxCheckStartPosition */, 1.117 + IArchiveOpenCallback *openArchiveCallback) 1.118 +{ 1.119 + COM_TRY_BEGIN 1.120 + Close(); 1.121 + if (openArchiveCallback == 0) 1.122 + return S_FALSE; 1.123 + // try 1.124 + { 1.125 + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; 1.126 + CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; 1.127 + if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, 1.128 + &openVolumeCallback) != S_OK) 1.129 + return S_FALSE; 1.130 + 1.131 + { 1.132 + NCOM::CPropVariant prop; 1.133 + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); 1.134 + if (prop.vt != VT_BSTR) 1.135 + return S_FALSE; 1.136 + _name = prop.bstrVal; 1.137 + } 1.138 + 1.139 + int dotPos = _name.ReverseFind('.'); 1.140 + UString prefix, ext; 1.141 + if (dotPos >= 0) 1.142 + { 1.143 + prefix = _name.Left(dotPos + 1); 1.144 + ext = _name.Mid(dotPos + 1); 1.145 + } 1.146 + else 1.147 + ext = _name; 1.148 + UString extBig = ext; 1.149 + extBig.MakeUpper(); 1.150 + 1.151 + CSeqName seqName; 1.152 + 1.153 + int numLetters = 2; 1.154 + bool splitStyle = false; 1.155 + if (extBig.Right(2) == L"AA") 1.156 + { 1.157 + splitStyle = true; 1.158 + while (numLetters < extBig.Length()) 1.159 + { 1.160 + if (extBig[extBig.Length() - numLetters - 1] != 'A') 1.161 + break; 1.162 + numLetters++; 1.163 + } 1.164 + } 1.165 + else if (ext.Right(2) == L"01") 1.166 + { 1.167 + while (numLetters < extBig.Length()) 1.168 + { 1.169 + if (extBig[extBig.Length() - numLetters - 1] != '0') 1.170 + break; 1.171 + numLetters++; 1.172 + } 1.173 + if (numLetters != ext.Length()) 1.174 + return S_FALSE; 1.175 + } 1.176 + else 1.177 + return S_FALSE; 1.178 + 1.179 + _streams.Add(stream); 1.180 + 1.181 + seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); 1.182 + seqName._changedPart = ext.Right(numLetters); 1.183 + seqName._splitStyle = splitStyle; 1.184 + 1.185 + if (prefix.Length() < 1) 1.186 + _subName = L"file"; 1.187 + else 1.188 + _subName = prefix.Left(prefix.Length() - 1); 1.189 + 1.190 + _totalSize = 0; 1.191 + UInt64 size; 1.192 + { 1.193 + NCOM::CPropVariant prop; 1.194 + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); 1.195 + if (prop.vt != VT_UI8) 1.196 + return E_INVALIDARG; 1.197 + size = prop.uhVal.QuadPart; 1.198 + } 1.199 + _totalSize += size; 1.200 + _sizes.Add(size); 1.201 + 1.202 + if (openArchiveCallback != NULL) 1.203 + { 1.204 + UInt64 numFiles = _streams.Size(); 1.205 + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); 1.206 + } 1.207 + 1.208 + for (;;) 1.209 + { 1.210 + UString fullName = seqName.GetNextName(); 1.211 + CMyComPtr<IInStream> nextStream; 1.212 + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); 1.213 + if (result == S_FALSE) 1.214 + break; 1.215 + if (result != S_OK) 1.216 + return result; 1.217 + if (!stream) 1.218 + break; 1.219 + { 1.220 + NCOM::CPropVariant prop; 1.221 + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); 1.222 + if (prop.vt != VT_UI8) 1.223 + return E_INVALIDARG; 1.224 + size = prop.uhVal.QuadPart; 1.225 + } 1.226 + _totalSize += size; 1.227 + _sizes.Add(size); 1.228 + _streams.Add(nextStream); 1.229 + if (openArchiveCallback != NULL) 1.230 + { 1.231 + UInt64 numFiles = _streams.Size(); 1.232 + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); 1.233 + } 1.234 + } 1.235 + } 1.236 + /* 1.237 + catch(...) 1.238 + { 1.239 + return S_FALSE; 1.240 + } 1.241 + */ 1.242 + return S_OK; 1.243 + COM_TRY_END 1.244 +} 1.245 + 1.246 +STDMETHODIMP CHandler::Close() 1.247 +{ 1.248 + _sizes.Clear(); 1.249 + _streams.Clear(); 1.250 + return S_OK; 1.251 +} 1.252 + 1.253 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.254 +{ 1.255 + *numItems = _streams.IsEmpty() ? 0 : 1; 1.256 + return S_OK; 1.257 +} 1.258 + 1.259 +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) 1.260 +{ 1.261 + NWindows::NCOM::CPropVariant prop; 1.262 + switch(propID) 1.263 + { 1.264 + case kpidPath: 1.265 + prop = _subName; 1.266 + break; 1.267 + case kpidSize: 1.268 + case kpidPackSize: 1.269 + prop = _totalSize; 1.270 + break; 1.271 + } 1.272 + prop.Detach(value); 1.273 + return S_OK; 1.274 +} 1.275 + 1.276 +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, 1.277 + Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) 1.278 +{ 1.279 + COM_TRY_BEGIN 1.280 + 1.281 + if (numItems != UInt32(-1)) 1.282 + { 1.283 + if (numItems != 1) 1.284 + return E_INVALIDARG; 1.285 + if (indices[0] != 0) 1.286 + return E_INVALIDARG; 1.287 + } 1.288 + bool testMode = (_aTestMode != 0); 1.289 + CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; 1.290 + extractCallback->SetTotal(_totalSize); 1.291 + 1.292 + /* 1.293 + CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; 1.294 + if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) 1.295 + return E_FAIL; 1.296 + */ 1.297 + 1.298 + UInt64 currentTotalSize = 0; 1.299 + UInt64 currentItemSize; 1.300 + 1.301 + RINOK(extractCallback->SetCompleted(¤tTotalSize)); 1.302 + CMyComPtr<ISequentialOutStream> realOutStream; 1.303 + Int32 askMode; 1.304 + askMode = testMode ? NArchive::NExtract::NAskMode::kTest : 1.305 + NArchive::NExtract::NAskMode::kExtract; 1.306 + Int32 index = 0; 1.307 + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); 1.308 + 1.309 + RINOK(extractCallback->PrepareOperation(askMode)); 1.310 + if (testMode) 1.311 + { 1.312 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); 1.313 + return S_OK; 1.314 + } 1.315 + 1.316 + if (!testMode && (!realOutStream)) 1.317 + return S_OK; 1.318 + 1.319 + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 1.320 + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1.321 + 1.322 + CLocalProgress *lps = new CLocalProgress; 1.323 + CMyComPtr<ICompressProgressInfo> progress = lps; 1.324 + lps->Init(extractCallback, false); 1.325 + 1.326 + for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) 1.327 + { 1.328 + lps->InSize = lps->OutSize = currentTotalSize; 1.329 + RINOK(lps->SetCur()); 1.330 + IInStream *inStream = _streams[i]; 1.331 + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); 1.332 + RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); 1.333 + currentItemSize = copyCoderSpec->TotalSize; 1.334 + } 1.335 + realOutStream.Release(); 1.336 + return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); 1.337 + COM_TRY_END 1.338 +} 1.339 + 1.340 +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) 1.341 +{ 1.342 + if (index != 0) 1.343 + return E_INVALIDARG; 1.344 + *stream = 0; 1.345 + CMultiStream *streamSpec = new CMultiStream; 1.346 + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; 1.347 + for (int i = 0; i < _streams.Size(); i++) 1.348 + { 1.349 + CMultiStream::CSubStreamInfo subStreamInfo; 1.350 + subStreamInfo.Stream = _streams[i]; 1.351 + subStreamInfo.Pos = 0; 1.352 + subStreamInfo.Size = _sizes[i]; 1.353 + streamSpec->Streams.Add(subStreamInfo); 1.354 + } 1.355 + streamSpec->Init(); 1.356 + *stream = streamTemp.Detach(); 1.357 + return S_OK; 1.358 +} 1.359 + 1.360 +}}