1// LimitedStreams.h
2
3#ifndef __LIMITED_STREAMS_H
4#define __LIMITED_STREAMS_H
5
6#include "../../Common/MyBuffer.h"
7#include "../../Common/MyCom.h"
8#include "../../Common/MyVector.h"
9#include "../IStream.h"
10
11class CLimitedSequentialInStream:
12  public ISequentialInStream,
13  public CMyUnknownImp
14{
15  CMyComPtr<ISequentialInStream> _stream;
16  UInt64 _size;
17  UInt64 _pos;
18  bool _wasFinished;
19public:
20  void SetStream(ISequentialInStream *stream) { _stream = stream; }
21  void ReleaseStream() { _stream.Release(); }
22  void Init(UInt64 streamSize)
23  {
24    _size = streamSize;
25    _pos = 0;
26    _wasFinished = false;
27  }
28
29  MY_UNKNOWN_IMP1(ISequentialInStream)
30
31  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
32  UInt64 GetSize() const { return _pos; }
33  UInt64 GetRem() const { return _size - _pos; }
34  bool WasFinished() const { return _wasFinished; }
35};
36
37class CLimitedInStream:
38  public IInStream,
39  public CMyUnknownImp
40{
41  CMyComPtr<IInStream> _stream;
42  UInt64 _virtPos;
43  UInt64 _physPos;
44  UInt64 _size;
45  UInt64 _startOffset;
46
47  HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
48public:
49  void SetStream(IInStream *stream) { _stream = stream; }
50  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
51  {
52    _startOffset = startOffset;
53    _physPos = startOffset;
54    _virtPos = 0;
55    _size = size;
56    return SeekToPhys();
57  }
58
59  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
60
61  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
62  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
63
64  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
65};
66
67HRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);
68
69class CClusterInStream:
70  public IInStream,
71  public CMyUnknownImp
72{
73  UInt64 _virtPos;
74  UInt64 _physPos;
75  UInt32 _curRem;
76public:
77  unsigned BlockSizeLog;
78  UInt64 Size;
79  CMyComPtr<IInStream> Stream;
80  CRecordVector<UInt32> Vector;
81  UInt64 StartOffset;
82
83  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
84
85  HRESULT InitAndSeek()
86  {
87    _curRem = 0;
88    _virtPos = 0;
89    _physPos = StartOffset;
90    if (Vector.Size() > 0)
91    {
92      _physPos = StartOffset + (Vector[0] << BlockSizeLog);
93      return SeekToPhys();
94    }
95    return S_OK;
96  }
97
98  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
99
100  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
101  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
102};
103
104struct CSeekExtent
105{
106  UInt64 Phy;
107  UInt64 Virt;
108};
109
110class CExtentsStream:
111  public IInStream,
112  public CMyUnknownImp
113{
114  UInt64 _phyPos;
115  UInt64 _virtPos;
116  bool _needStartSeek;
117
118  HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }
119
120public:
121  CMyComPtr<IInStream> Stream;
122  CRecordVector<CSeekExtent> Extents;
123
124  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
125  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
126  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
127  void ReleaseStream() { Stream.Release(); }
128
129  void Init()
130  {
131    _virtPos = 0;
132    _phyPos = 0;
133    _needStartSeek = true;
134  }
135};
136
137class CLimitedSequentialOutStream:
138  public ISequentialOutStream,
139  public CMyUnknownImp
140{
141  CMyComPtr<ISequentialOutStream> _stream;
142  UInt64 _size;
143  bool _overflow;
144  bool _overflowIsAllowed;
145public:
146  MY_UNKNOWN_IMP1(ISequentialOutStream)
147  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
148  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
149  void ReleaseStream() { _stream.Release(); }
150  void Init(UInt64 size, bool overflowIsAllowed = false)
151  {
152    _size = size;
153    _overflow = false;
154    _overflowIsAllowed = overflowIsAllowed;
155  }
156  bool IsFinishedOK() const { return (_size == 0 && !_overflow); }
157  UInt64 GetRem() const { return _size; }
158};
159
160
161class CTailInStream:
162  public IInStream,
163  public CMyUnknownImp
164{
165  UInt64 _virtPos;
166public:
167  CMyComPtr<IInStream> Stream;
168  UInt64 Offset;
169
170  void Init()
171  {
172    _virtPos = 0;
173  }
174
175  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
176
177  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
178  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
179
180  HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); }
181};
182
183class CLimitedCachedInStream:
184  public IInStream,
185  public CMyUnknownImp
186{
187  CMyComPtr<IInStream> _stream;
188  UInt64 _virtPos;
189  UInt64 _physPos;
190  UInt64 _size;
191  UInt64 _startOffset;
192
193  const Byte *_cache;
194  size_t _cacheSize;
195  size_t _cachePhyPos;
196
197
198  HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
199public:
200  CByteBuffer Buffer;
201
202  void SetStream(IInStream *stream) { _stream = stream; }
203  void SetCache(size_t cacheSize, size_t cachePos)
204  {
205    _cache = Buffer;
206    _cacheSize = cacheSize;
207    _cachePhyPos = cachePos;
208  }
209
210  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)
211  {
212    _startOffset = startOffset;
213    _physPos = startOffset;
214    _virtPos = 0;
215    _size = size;
216    return SeekToPhys();
217  }
218
219  MY_UNKNOWN_IMP2(ISequentialInStream, IInStream)
220
221  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
222  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
223
224  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }
225};
226
227class CTailOutStream:
228  public IOutStream,
229  public CMyUnknownImp
230{
231  UInt64 _virtPos;
232  UInt64 _virtSize;
233public:
234  CMyComPtr<IOutStream> Stream;
235  UInt64 Offset;
236
237  virtual ~CTailOutStream() {}
238
239  MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStream)
240
241  void Init()
242  {
243    _virtPos = 0;
244    _virtSize = 0;
245  }
246
247  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
248  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
249  STDMETHOD(SetSize)(UInt64 newSize);
250};
251
252#endif
253