diff options
author | 2015-01-11 08:10:25 +0100 | |
---|---|---|
committer | 2015-01-11 08:10:25 +0100 | |
commit | 6a23c2f3b766cf4fc7028628f76b5ff9396383f0 (patch) | |
tree | a01e16637118ae0c80f337119898bdf18f081e24 /3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp | |
parent | 45ac9b351e0076c371de4c7453f59567b27b1cb6 (diff) |
Added full lzma sdk source (nw)
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp b/3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp new file mode 100644 index 00000000000..5d84de4ed9a --- /dev/null +++ b/3rdparty/lzma/CPP/7zip/Archive/SplitHandler.cpp @@ -0,0 +1,366 @@ +// SplitHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Common/MyString.h" + +#include "Windows/PropVariant.h" + +#include "../Common/ProgressUtils.h" +#include "../Common/RegisterArc.h" + +#include "../Compress/CopyCoder.h" + +#include "Common/MultiStream.h" + +using namespace NWindows; + +namespace NArchive { +namespace NSplit { + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidSize, VT_UI8} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidNumVolumes, VT_UI4} +}; + +class CHandler: + public IInArchive, + public IInArchiveGetStream, + public CMyUnknownImp +{ + UString _subName; + CObjectVector<CMyComPtr<IInStream> > _streams; + CRecordVector<UInt64> _sizes; + UInt64 _totalSize; +public: + MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) + INTERFACE_IInArchive(;) + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + NCOM::CPropVariant prop; + switch(propID) + { + case kpidMainSubfile: prop = (UInt32)0; break; + case kpidNumVolumes: prop = (UInt32)_streams.Size(); break; + } + prop.Detach(value); + return S_OK; +} + +struct CSeqName +{ + UString _unchangedPart; + UString _changedPart; + bool _splitStyle; + + UString GetNextName() + { + UString newName; + if (_splitStyle) + { + int i; + int numLetters = _changedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = _changedPart[i]; + if (c == 'z') + { + c = 'a'; + newName = c + newName; + continue; + } + else if (c == 'Z') + { + c = 'A'; + newName = c + newName; + continue; + } + c++; + if ((c == 'z' || c == 'Z') && i == 0) + { + _unchangedPart += c; + wchar_t newChar = (c == 'z') ? L'a' : L'A'; + newName.Empty(); + numLetters++; + for (int k = 0; k < numLetters; k++) + newName += newChar; + break; + } + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = _changedPart[i] + newName; + break; + } + } + else + { + int i; + int numLetters = _changedPart.Length(); + for (i = numLetters - 1; i >= 0; i--) + { + wchar_t c = _changedPart[i]; + if (c == L'9') + { + c = L'0'; + newName = c + newName; + if (i == 0) + newName = UString(L'1') + newName; + continue; + } + c++; + newName = c + newName; + i--; + for (; i >= 0; i--) + newName = _changedPart[i] + newName; + break; + } + } + _changedPart = newName; + return _unchangedPart + _changedPart; + } +}; + +STDMETHODIMP CHandler::Open(IInStream *stream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + Close(); + if (openArchiveCallback == 0) + return S_FALSE; + // try + { + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; + CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; + if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, + &openVolumeCallback) != S_OK) + return S_FALSE; + + UString name; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); + if (prop.vt != VT_BSTR) + return S_FALSE; + name = prop.bstrVal; + } + + int dotPos = name.ReverseFind('.'); + UString prefix, ext; + if (dotPos >= 0) + { + prefix = name.Left(dotPos + 1); + ext = name.Mid(dotPos + 1); + } + else + ext = name; + UString extBig = ext; + extBig.MakeUpper(); + + CSeqName seqName; + + int numLetters = 2; + bool splitStyle = false; + if (extBig.Right(2) == L"AA") + { + splitStyle = true; + while (numLetters < extBig.Length()) + { + if (extBig[extBig.Length() - numLetters - 1] != 'A') + break; + numLetters++; + } + } + else if (ext.Right(2) == L"01") + { + while (numLetters < extBig.Length()) + { + if (extBig[extBig.Length() - numLetters - 1] != '0') + break; + numLetters++; + } + if (numLetters != ext.Length()) + return S_FALSE; + } + else + return S_FALSE; + + _streams.Add(stream); + + seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); + seqName._changedPart = ext.Right(numLetters); + seqName._splitStyle = splitStyle; + + if (prefix.Length() < 1) + _subName = L"file"; + else + _subName = prefix.Left(prefix.Length() - 1); + + _totalSize = 0; + UInt64 size; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + _totalSize += size; + _sizes.Add(size); + + if (openArchiveCallback != NULL) + { + UInt64 numFiles = _streams.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + + for (;;) + { + UString fullName = seqName.GetNextName(); + CMyComPtr<IInStream> nextStream; + HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); + if (result == S_FALSE) + break; + if (result != S_OK) + return result; + if (!stream) + break; + { + NCOM::CPropVariant prop; + RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); + if (prop.vt != VT_UI8) + return E_INVALIDARG; + size = prop.uhVal.QuadPart; + } + _totalSize += size; + _sizes.Add(size); + _streams.Add(nextStream); + if (openArchiveCallback != NULL) + { + UInt64 numFiles = _streams.Size(); + RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); + } + } + } + /* + catch(...) + { + return S_FALSE; + } + */ + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _sizes.Clear(); + _streams.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _streams.IsEmpty() ? 0 : 1; + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidPath: prop = _subName; break; + case kpidSize: + case kpidPackSize: + prop = _totalSize; + break; + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + if (numItems == 0) + return S_OK; + if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + return E_INVALIDARG; + + UInt64 currentTotalSize = 0; + RINOK(extractCallback->SetTotal(_totalSize)); + CMyComPtr<ISequentialOutStream> outStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(0, &outStream, askMode)); + if (!testMode && !outStream) + return S_OK; + RINOK(extractCallback->PrepareOperation(askMode)); + + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, false); + + for (int i = 0; i < _streams.Size(); i++) + { + lps->InSize = lps->OutSize = currentTotalSize; + RINOK(lps->SetCur()); + IInStream *inStream = _streams[i]; + RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); + currentTotalSize += copyCoderSpec->TotalSize; + } + outStream.Release(); + return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK); + COM_TRY_END +} + +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) +{ + COM_TRY_BEGIN + if (index != 0) + return E_INVALIDARG; + *stream = 0; + CMultiStream *streamSpec = new CMultiStream; + CMyComPtr<ISequentialInStream> streamTemp = streamSpec; + for (int i = 0; i < _streams.Size(); i++) + { + CMultiStream::CSubStreamInfo subStreamInfo; + subStreamInfo.Stream = _streams[i]; + subStreamInfo.Size = _sizes[i]; + streamSpec->Streams.Add(subStreamInfo); + } + streamSpec->Init(); + *stream = streamTemp.Detach(); + return S_OK; + COM_TRY_END +} + +static IInArchive *CreateArc() { return new CHandler; } + +static CArcInfo g_ArcInfo = +{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; + +REGISTER_ARC(Split) + +}} |