// LimitedStreams.h #ifndef __LIMITED_STREAMS_H #define __LIMITED_STREAMS_H #include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" #include "../../Common/MyVector.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedInStream: public IInStream, public CMyUnknownImp { CMyComPtr<IInStream> _stream; UInt64 _virtPos; UInt64 _physPos; UInt64 _size; UInt64 _startOffset; HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } public: void SetStream(IInStream *stream) { _stream = stream; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) { _startOffset = startOffset; _physPos = startOffset; _virtPos = 0; _size = size; return SeekToPhys(); } MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream); class CClusterInStream: public IInStream, public CMyUnknownImp { UInt64 _virtPos; UInt64 _physPos; UInt32 _curRem; public: CMyComPtr<IInStream> Stream; UInt64 StartOffset; UInt64 Size; unsigned BlockSizeLog; CRecordVector<UInt32> Vector; HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } HRESULT InitAndSeek() { _curRem = 0; _virtPos = 0; _physPos = StartOffset; if (Vector.Size() > 0) { _physPos = StartOffset + (Vector[0] << BlockSizeLog); return SeekToPhys(); } return S_OK; } MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; struct CSeekExtent { UInt64 Phy; UInt64 Virt; }; class CExtentsStream: public IInStream, public CMyUnknownImp { UInt64 _phyPos; UInt64 _virtPos; bool _needStartSeek; HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } public: CMyComPtr<IInStream> Stream; CRecordVector<CSeekExtent> Extents; MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); void ReleaseStream() { Stream.Release(); } void Init() { _virtPos = 0; _phyPos = 0; _needStartSeek = true; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; bool _overflowIsAllowed; public: MY_UNKNOWN_IMP1(ISequentialOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size, bool overflowIsAllowed = false) { _size = size; _overflow = false; _overflowIsAllowed = overflowIsAllowed; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; class CTailInStream: public IInStream, public CMyUnknownImp { UInt64 _virtPos; public: CMyComPtr<IInStream> Stream; UInt64 Offset; void Init() { _virtPos = 0; } MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); } }; class CLimitedCachedInStream: public IInStream, public CMyUnknownImp { CMyComPtr<IInStream> _stream; UInt64 _virtPos; UInt64 _physPos; UInt64 _size; UInt64 _startOffset; const Byte *_cache; size_t _cacheSize; size_t _cachePhyPos; HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } public: CByteBuffer Buffer; void SetStream(IInStream *stream) { _stream = stream; } void SetCache(size_t cacheSize, size_t cachePos) { _cache = Buffer; _cacheSize = cacheSize; _cachePhyPos = cachePos; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) { _startOffset = startOffset; _physPos = startOffset; _virtPos = 0; _size = size; return SeekToPhys(); } MY_UNKNOWN_IMP2(ISequentialInStream, IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); } }; class CTailOutStream: public IOutStream, public CMyUnknownImp { UInt64 _virtPos; UInt64 _virtSize; public: CMyComPtr<IOutStream> Stream; UInt64 Offset; virtual ~CTailOutStream() {} MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream) void Init() { _virtPos = 0; _virtSize = 0; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(UInt64 newSize); }; #endif