Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2009-06-02 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:59 +0300
commit829409452d85cd6dd9dfc9151f109d6e13a2bb1c (patch)
treee0acaea47044d167f35fa197584dee1bde41c329 /CPP/7zip/Common/LimitedStreams.cpp
parent8874e4fbc9faabdcff719b9b2ac8ebad4f282bbe (diff)
9.04 beta
Diffstat (limited to 'CPP/7zip/Common/LimitedStreams.cpp')
-rwxr-xr-xCPP/7zip/Common/LimitedStreams.cpp117
1 files changed, 113 insertions, 4 deletions
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp
index 490aa37b..1837e320 100755
--- a/CPP/7zip/Common/LimitedStreams.cpp
+++ b/CPP/7zip/Common/LimitedStreams.cpp
@@ -17,11 +17,116 @@ STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *p
if (realProcessedSize == 0)
_wasFinished = true;
}
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = realProcessedSize;
return result;
}
+STDMETHODIMP CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize != NULL)
+ *processedSize = 0;
+ if (_virtPos >= _size)
+ return (_virtPos == _size) ? S_OK: E_FAIL;
+ UInt64 rem = _size - _virtPos;
+ if (rem < size)
+ size = (UInt32)rem;
+ UInt64 newPos = _startOffset + _virtPos;
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+ HRESULT res = _stream->Read(data, size, &size);
+ if (processedSize != NULL)
+ *processedSize = size;
+ _physPos += size;
+ _virtPos += size;
+ return res;
+}
+
+STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET: _virtPos = offset; break;
+ case STREAM_SEEK_CUR: _virtPos += offset; break;
+ case STREAM_SEEK_END: _virtPos = _size + offset; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (newPosition)
+ *newPosition = _virtPos;
+ return S_OK;
+}
+
+STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize != NULL)
+ *processedSize = 0;
+ if (_virtPos >= Size)
+ return (_virtPos == Size) ? S_OK: E_FAIL;
+
+ if (_curRem == 0)
+ {
+ UInt32 blockSize = (UInt32)1 << BlockSizeLog;
+ UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);
+ UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
+ UInt32 phyBlock = Vector[virtBlock];
+ UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;
+ if (newPos != _physPos)
+ {
+ _physPos = newPos;
+ RINOK(SeekToPhys());
+ }
+ _curRem = blockSize - offsetInBlock;
+ for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)
+ _curRem += (UInt32)1 << BlockSizeLog;
+ UInt64 rem = Size - _virtPos;
+ if (_curRem > rem)
+ _curRem = (UInt32)rem;
+ }
+ if (size > _curRem)
+ size = _curRem;
+ HRESULT res = Stream->Read(data, size, &size);
+ if (processedSize != NULL)
+ *processedSize = size;
+ _physPos += size;
+ _virtPos += size;
+ _curRem -= size;
+ return res;
+}
+
+STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ UInt64 newVirtPos = offset;
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;
+ case STREAM_SEEK_END: newVirtPos += Size; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ if (_virtPos != newVirtPos)
+ _curRem = 0;
+ _virtPos = newVirtPos;
+ if (newPosition)
+ *newPosition = newVirtPos;
+ return S_OK;
+}
+
+
+HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)
+{
+ *resStream = 0;
+ CLimitedInStream *streamSpec = new CLimitedInStream;
+ CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+ streamSpec->SetStream(inStream);
+ RINOK(streamSpec->InitAndSeek(pos, size));
+ streamSpec->SeekToStart();
+ *resStream = streamTemp.Detach();
+ return S_OK;
+}
+
STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
HRESULT result = S_OK;
@@ -29,12 +134,16 @@ STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, U
*processedSize = 0;
if (size > _size)
{
- size = (UInt32)_size;
- if (size == 0)
+ if (_size == 0)
{
_overflow = true;
- return E_FAIL;
+ if (!_overflowIsAllowed)
+ return E_FAIL;
+ if (processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
}
+ size = (UInt32)_size;
}
if (_stream)
result = _stream->Write(data, size, &size);