1370b324cSopenharmony_ci// StreamObjects.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../C/Alloc.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "StreamObjects.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ciZ7_COM7F_IMF(CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
10370b324cSopenharmony_ci{
11370b324cSopenharmony_ci  if (processedSize)
12370b324cSopenharmony_ci    *processedSize = 0;
13370b324cSopenharmony_ci  if (size == 0)
14370b324cSopenharmony_ci    return S_OK;
15370b324cSopenharmony_ci  if (_pos >= Buf.Size())
16370b324cSopenharmony_ci    return S_OK;
17370b324cSopenharmony_ci  size_t rem = Buf.Size() - (size_t)_pos;
18370b324cSopenharmony_ci  if (rem > size)
19370b324cSopenharmony_ci    rem = (size_t)size;
20370b324cSopenharmony_ci  memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);
21370b324cSopenharmony_ci  _pos += rem;
22370b324cSopenharmony_ci  if (processedSize)
23370b324cSopenharmony_ci    *processedSize = (UInt32)rem;
24370b324cSopenharmony_ci  return S_OK;
25370b324cSopenharmony_ci}
26370b324cSopenharmony_ci
27370b324cSopenharmony_ciZ7_COM7F_IMF(CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
28370b324cSopenharmony_ci{
29370b324cSopenharmony_ci  switch (seekOrigin)
30370b324cSopenharmony_ci  {
31370b324cSopenharmony_ci    case STREAM_SEEK_SET: break;
32370b324cSopenharmony_ci    case STREAM_SEEK_CUR: offset += _pos; break;
33370b324cSopenharmony_ci    case STREAM_SEEK_END: offset += Buf.Size(); break;
34370b324cSopenharmony_ci    default: return STG_E_INVALIDFUNCTION;
35370b324cSopenharmony_ci  }
36370b324cSopenharmony_ci  if (offset < 0)
37370b324cSopenharmony_ci    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
38370b324cSopenharmony_ci  _pos = (UInt64)offset;
39370b324cSopenharmony_ci  if (newPosition)
40370b324cSopenharmony_ci    *newPosition = (UInt64)offset;
41370b324cSopenharmony_ci  return S_OK;
42370b324cSopenharmony_ci}
43370b324cSopenharmony_ci
44370b324cSopenharmony_ciZ7_COM7F_IMF(CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
45370b324cSopenharmony_ci{
46370b324cSopenharmony_ci  if (processedSize)
47370b324cSopenharmony_ci    *processedSize = 0;
48370b324cSopenharmony_ci  if (size == 0)
49370b324cSopenharmony_ci    return S_OK;
50370b324cSopenharmony_ci  if (_pos >= _size)
51370b324cSopenharmony_ci    return S_OK;
52370b324cSopenharmony_ci  size_t rem = _size - (size_t)_pos;
53370b324cSopenharmony_ci  if (rem > size)
54370b324cSopenharmony_ci    rem = (size_t)size;
55370b324cSopenharmony_ci  memcpy(data, _data + (size_t)_pos, rem);
56370b324cSopenharmony_ci  _pos += rem;
57370b324cSopenharmony_ci  if (processedSize)
58370b324cSopenharmony_ci    *processedSize = (UInt32)rem;
59370b324cSopenharmony_ci  return S_OK;
60370b324cSopenharmony_ci}
61370b324cSopenharmony_ci
62370b324cSopenharmony_ciZ7_COM7F_IMF(CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
63370b324cSopenharmony_ci{
64370b324cSopenharmony_ci  switch (seekOrigin)
65370b324cSopenharmony_ci  {
66370b324cSopenharmony_ci    case STREAM_SEEK_SET: break;
67370b324cSopenharmony_ci    case STREAM_SEEK_CUR: offset += _pos; break;
68370b324cSopenharmony_ci    case STREAM_SEEK_END: offset += _size; break;
69370b324cSopenharmony_ci    default: return STG_E_INVALIDFUNCTION;
70370b324cSopenharmony_ci  }
71370b324cSopenharmony_ci  if (offset < 0)
72370b324cSopenharmony_ci    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
73370b324cSopenharmony_ci  _pos = (UInt64)offset;
74370b324cSopenharmony_ci  if (newPosition)
75370b324cSopenharmony_ci    *newPosition = (UInt64)offset;
76370b324cSopenharmony_ci  return S_OK;
77370b324cSopenharmony_ci}
78370b324cSopenharmony_ci
79370b324cSopenharmony_civoid Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)
80370b324cSopenharmony_ci{
81370b324cSopenharmony_ci  *stream = NULL;
82370b324cSopenharmony_ci  CBufInStream *inStreamSpec = new CBufInStream;
83370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
84370b324cSopenharmony_ci  inStreamSpec->Init((const Byte *)data, size, ref);
85370b324cSopenharmony_ci  *stream = streamTemp.Detach();
86370b324cSopenharmony_ci}
87370b324cSopenharmony_ci
88370b324cSopenharmony_civoid Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
89370b324cSopenharmony_ci{
90370b324cSopenharmony_ci  *stream = NULL;
91370b324cSopenharmony_ci  CBufferInStream *inStreamSpec = new CBufferInStream;
92370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
93370b324cSopenharmony_ci  inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
94370b324cSopenharmony_ci  inStreamSpec->Init();
95370b324cSopenharmony_ci  *stream = streamTemp.Detach();
96370b324cSopenharmony_ci}
97370b324cSopenharmony_ci
98370b324cSopenharmony_civoid CByteDynBuffer::Free() throw()
99370b324cSopenharmony_ci{
100370b324cSopenharmony_ci  MyFree(_buf);
101370b324cSopenharmony_ci  _buf = NULL;
102370b324cSopenharmony_ci  _capacity = 0;
103370b324cSopenharmony_ci}
104370b324cSopenharmony_ci
105370b324cSopenharmony_cibool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
106370b324cSopenharmony_ci{
107370b324cSopenharmony_ci  if (cap <= _capacity)
108370b324cSopenharmony_ci    return true;
109370b324cSopenharmony_ci  const size_t cap2 = _capacity + _capacity / 4;
110370b324cSopenharmony_ci  if (cap < cap2)
111370b324cSopenharmony_ci    cap = cap2;
112370b324cSopenharmony_ci  Byte *buf = (Byte *)MyRealloc(_buf, cap);
113370b324cSopenharmony_ci  if (!buf)
114370b324cSopenharmony_ci    return false;
115370b324cSopenharmony_ci  _buf = buf;
116370b324cSopenharmony_ci  _capacity = cap;
117370b324cSopenharmony_ci  return true;
118370b324cSopenharmony_ci}
119370b324cSopenharmony_ci
120370b324cSopenharmony_ciByte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
121370b324cSopenharmony_ci{
122370b324cSopenharmony_ci  addSize += _size;
123370b324cSopenharmony_ci  if (addSize < _size)
124370b324cSopenharmony_ci    return NULL;
125370b324cSopenharmony_ci  if (!_buffer.EnsureCapacity(addSize))
126370b324cSopenharmony_ci    return NULL;
127370b324cSopenharmony_ci  return (Byte *)_buffer + _size;
128370b324cSopenharmony_ci}
129370b324cSopenharmony_ci
130370b324cSopenharmony_civoid CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
131370b324cSopenharmony_ci{
132370b324cSopenharmony_ci  dest.CopyFrom((const Byte *)_buffer, _size);
133370b324cSopenharmony_ci}
134370b324cSopenharmony_ci
135370b324cSopenharmony_ciZ7_COM7F_IMF(CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
136370b324cSopenharmony_ci{
137370b324cSopenharmony_ci  if (processedSize)
138370b324cSopenharmony_ci    *processedSize = 0;
139370b324cSopenharmony_ci  if (size == 0)
140370b324cSopenharmony_ci    return S_OK;
141370b324cSopenharmony_ci  Byte *buf = GetBufPtrForWriting(size);
142370b324cSopenharmony_ci  if (!buf)
143370b324cSopenharmony_ci    return E_OUTOFMEMORY;
144370b324cSopenharmony_ci  memcpy(buf, data, size);
145370b324cSopenharmony_ci  UpdateSize(size);
146370b324cSopenharmony_ci  if (processedSize)
147370b324cSopenharmony_ci    *processedSize = size;
148370b324cSopenharmony_ci  return S_OK;
149370b324cSopenharmony_ci}
150370b324cSopenharmony_ci
151370b324cSopenharmony_ciZ7_COM7F_IMF(CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
152370b324cSopenharmony_ci{
153370b324cSopenharmony_ci  size_t rem = _size - _pos;
154370b324cSopenharmony_ci  if (rem > size)
155370b324cSopenharmony_ci    rem = (size_t)size;
156370b324cSopenharmony_ci  if (rem != 0)
157370b324cSopenharmony_ci  {
158370b324cSopenharmony_ci    memcpy(_buffer + _pos, data, rem);
159370b324cSopenharmony_ci    _pos += rem;
160370b324cSopenharmony_ci  }
161370b324cSopenharmony_ci  if (processedSize)
162370b324cSopenharmony_ci    *processedSize = (UInt32)rem;
163370b324cSopenharmony_ci  return (rem != 0 || size == 0) ? S_OK : E_FAIL;
164370b324cSopenharmony_ci}
165370b324cSopenharmony_ci
166370b324cSopenharmony_ciZ7_COM7F_IMF(CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize))
167370b324cSopenharmony_ci{
168370b324cSopenharmony_ci  UInt32 realProcessedSize;
169370b324cSopenharmony_ci  HRESULT result = _stream->Write(data, size, &realProcessedSize);
170370b324cSopenharmony_ci  _size += realProcessedSize;
171370b324cSopenharmony_ci  if (processedSize)
172370b324cSopenharmony_ci    *processedSize = realProcessedSize;
173370b324cSopenharmony_ci  return result;
174370b324cSopenharmony_ci}
175370b324cSopenharmony_ci
176370b324cSopenharmony_cistatic const UInt64 kEmptyTag = (UInt64)(Int64)-1;
177370b324cSopenharmony_ci
178370b324cSopenharmony_civoid CCachedInStream::Free() throw()
179370b324cSopenharmony_ci{
180370b324cSopenharmony_ci  MyFree(_tags);
181370b324cSopenharmony_ci  _tags = NULL;
182370b324cSopenharmony_ci  MidFree(_data);
183370b324cSopenharmony_ci  _data = NULL;
184370b324cSopenharmony_ci}
185370b324cSopenharmony_ci
186370b324cSopenharmony_cibool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()
187370b324cSopenharmony_ci{
188370b324cSopenharmony_ci  unsigned sizeLog = blockSizeLog + numBlocksLog;
189370b324cSopenharmony_ci  if (sizeLog >= sizeof(size_t) * 8)
190370b324cSopenharmony_ci    return false;
191370b324cSopenharmony_ci  size_t dataSize = (size_t)1 << sizeLog;
192370b324cSopenharmony_ci  if (!_data || dataSize != _dataSize)
193370b324cSopenharmony_ci  {
194370b324cSopenharmony_ci    MidFree(_data);
195370b324cSopenharmony_ci    _data = (Byte *)MidAlloc(dataSize);
196370b324cSopenharmony_ci    if (!_data)
197370b324cSopenharmony_ci      return false;
198370b324cSopenharmony_ci    _dataSize = dataSize;
199370b324cSopenharmony_ci  }
200370b324cSopenharmony_ci  if (!_tags || numBlocksLog != _numBlocksLog)
201370b324cSopenharmony_ci  {
202370b324cSopenharmony_ci    MyFree(_tags);
203370b324cSopenharmony_ci    _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
204370b324cSopenharmony_ci    if (!_tags)
205370b324cSopenharmony_ci      return false;
206370b324cSopenharmony_ci    _numBlocksLog = numBlocksLog;
207370b324cSopenharmony_ci  }
208370b324cSopenharmony_ci  _blockSizeLog = blockSizeLog;
209370b324cSopenharmony_ci  return true;
210370b324cSopenharmony_ci}
211370b324cSopenharmony_ci
212370b324cSopenharmony_civoid CCachedInStream::Init(UInt64 size) throw()
213370b324cSopenharmony_ci{
214370b324cSopenharmony_ci  _size = size;
215370b324cSopenharmony_ci  _pos = 0;
216370b324cSopenharmony_ci  const size_t numBlocks = (size_t)1 << _numBlocksLog;
217370b324cSopenharmony_ci  for (size_t i = 0; i < numBlocks; i++)
218370b324cSopenharmony_ci    _tags[i] = kEmptyTag;
219370b324cSopenharmony_ci}
220370b324cSopenharmony_ci
221370b324cSopenharmony_ciZ7_COM7F_IMF(CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
222370b324cSopenharmony_ci{
223370b324cSopenharmony_ci  if (processedSize)
224370b324cSopenharmony_ci    *processedSize = 0;
225370b324cSopenharmony_ci  if (size == 0)
226370b324cSopenharmony_ci    return S_OK;
227370b324cSopenharmony_ci  if (_pos >= _size)
228370b324cSopenharmony_ci    return S_OK;
229370b324cSopenharmony_ci
230370b324cSopenharmony_ci  {
231370b324cSopenharmony_ci    const UInt64 rem = _size - _pos;
232370b324cSopenharmony_ci    if (size > rem)
233370b324cSopenharmony_ci      size = (UInt32)rem;
234370b324cSopenharmony_ci  }
235370b324cSopenharmony_ci
236370b324cSopenharmony_ci  while (size != 0)
237370b324cSopenharmony_ci  {
238370b324cSopenharmony_ci    const UInt64 cacheTag = _pos >> _blockSizeLog;
239370b324cSopenharmony_ci    const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
240370b324cSopenharmony_ci    Byte *p = _data + (cacheIndex << _blockSizeLog);
241370b324cSopenharmony_ci
242370b324cSopenharmony_ci    if (_tags[cacheIndex] != cacheTag)
243370b324cSopenharmony_ci    {
244370b324cSopenharmony_ci      _tags[cacheIndex] = kEmptyTag;
245370b324cSopenharmony_ci      const UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
246370b324cSopenharmony_ci      size_t blockSize = (size_t)1 << _blockSizeLog;
247370b324cSopenharmony_ci      if (blockSize > remInBlock)
248370b324cSopenharmony_ci        blockSize = (size_t)remInBlock;
249370b324cSopenharmony_ci
250370b324cSopenharmony_ci      RINOK(ReadBlock(cacheTag, p, blockSize))
251370b324cSopenharmony_ci
252370b324cSopenharmony_ci      _tags[cacheIndex] = cacheTag;
253370b324cSopenharmony_ci    }
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci    const size_t kBlockSize = (size_t)1 << _blockSizeLog;
256370b324cSopenharmony_ci    const size_t offset = (size_t)_pos & (kBlockSize - 1);
257370b324cSopenharmony_ci    UInt32 cur = size;
258370b324cSopenharmony_ci    const size_t rem = kBlockSize - offset;
259370b324cSopenharmony_ci    if (cur > rem)
260370b324cSopenharmony_ci      cur = (UInt32)rem;
261370b324cSopenharmony_ci
262370b324cSopenharmony_ci    memcpy(data, p + offset, cur);
263370b324cSopenharmony_ci
264370b324cSopenharmony_ci    if (processedSize)
265370b324cSopenharmony_ci      *processedSize += cur;
266370b324cSopenharmony_ci    data = (void *)((const Byte *)data + cur);
267370b324cSopenharmony_ci    _pos += cur;
268370b324cSopenharmony_ci    size -= cur;
269370b324cSopenharmony_ci  }
270370b324cSopenharmony_ci
271370b324cSopenharmony_ci  return S_OK;
272370b324cSopenharmony_ci}
273370b324cSopenharmony_ci
274370b324cSopenharmony_ci
275370b324cSopenharmony_ciZ7_COM7F_IMF(CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
276370b324cSopenharmony_ci{
277370b324cSopenharmony_ci  switch (seekOrigin)
278370b324cSopenharmony_ci  {
279370b324cSopenharmony_ci    case STREAM_SEEK_SET: break;
280370b324cSopenharmony_ci    case STREAM_SEEK_CUR: offset += _pos; break;
281370b324cSopenharmony_ci    case STREAM_SEEK_END: offset += _size; break;
282370b324cSopenharmony_ci    default: return STG_E_INVALIDFUNCTION;
283370b324cSopenharmony_ci  }
284370b324cSopenharmony_ci  if (offset < 0)
285370b324cSopenharmony_ci    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
286370b324cSopenharmony_ci  _pos = (UInt64)offset;
287370b324cSopenharmony_ci  if (newPosition)
288370b324cSopenharmony_ci    *newPosition = (UInt64)offset;
289370b324cSopenharmony_ci  return S_OK;
290370b324cSopenharmony_ci}
291