1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// StreamObjects.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../C/Alloc.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StreamObjects.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
9baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size == 0)
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_pos > _size)
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t rem = _size - (size_t)_pos;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (rem > size)
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    rem = (size_t)size;
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(data, _data + (size_t)_pos, rem);
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _pos += rem;
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)rem;
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
27baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(seekOrigin)
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_SET: _pos = offset; break;
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_CUR: _pos += offset; break;
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_END: _pos = _size + offset; break;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    default: return STG_E_INVALIDFUNCTION;
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (newPosition)
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = _pos;
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
41baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CByteDynBuffer::Free()
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  free(_buf);
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _buf = 0;
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _capacity = 0;
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CByteDynBuffer::EnsureCapacity(size_t cap)
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (cap <= _capacity)
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return true;
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t delta;
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_capacity > 64)
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    delta = _capacity / 4;
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else if (_capacity > 8)
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    delta = 16;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    delta = 4;
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  cap = MyMax(_capacity + delta, cap);
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte *buf = (Byte *)realloc(_buf, cap);
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!buf)
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _buf = buf;
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _capacity = cap;
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
68baa3858d3f5d128a5c8466b700098109edcad5f2repo syncByte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  addSize += _size;
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (addSize < _size)
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return NULL;
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_buffer.EnsureCapacity(addSize))
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return NULL;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (Byte *)_buffer + _size;
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
78baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dest.SetCapacity(_size);
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(dest, _buffer, _size);
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
84baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size == 0)
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte *buf = GetBufPtrForWriting(size);
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!buf)
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(buf, data, size);
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UpdateSize(size);
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = size;
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
100baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t rem = _size - _pos;
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (rem > size)
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    rem = (size_t)size;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(_buffer + _pos, data, rem);
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _pos += rem;
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)rem;
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (rem != 0 || size == 0) ? S_OK : E_FAIL;
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
112baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 realProcessedSize;
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT result = _stream->Write(data, size, &realProcessedSize);
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _size += realProcessedSize;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = realProcessedSize;
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return result;
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
122baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt64 kEmptyTag = (UInt64)(Int64)-1;
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
124baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CCachedInStream::Free()
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MyFree(_tags);
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _tags = 0;
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MidFree(_data);
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _data = 0;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
132baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog)
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  unsigned sizeLog = blockSizeLog + numBlocksLog;
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (sizeLog >= sizeof(size_t) * 8)
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t dataSize = (size_t)1 << sizeLog;
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_data == 0 || dataSize != _dataSize)
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MidFree(_data);
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _data = (Byte *)MidAlloc(dataSize);
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_data == 0)
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _dataSize = dataSize;
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_tags == 0 || numBlocksLog != _numBlocksLog)
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    MyFree(_tags);
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_tags == 0)
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _numBlocksLog = numBlocksLog;
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _blockSizeLog = blockSizeLog;
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
158baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid CCachedInStream::Init(UInt64 size)
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _size = size;
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _pos = 0;
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t numBlocks = (size_t)1 << _numBlocksLog;
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (size_t i = 0; i < numBlocks; i++)
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _tags[i] = kEmptyTag;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
167baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize)
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size == 0)
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_pos > _size)
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 rem = _size - _pos;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (size > rem)
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      size = (UInt32)rem;
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (size != 0)
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 cacheTag = _pos >> _blockSizeLog;
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Byte *p = _data + (cacheIndex << _blockSizeLog);
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_tags[cacheIndex] != cacheTag)
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      size_t blockSize = (size_t)1 << _blockSizeLog;
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (blockSize > remInBlock)
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        blockSize = (size_t)remInBlock;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(ReadBlock(cacheTag, p, blockSize));
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _tags[cacheIndex] = cacheTag;
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1);
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size);
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    memcpy(data, p + offset, cur);
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (processedSize)
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      *processedSize += cur;
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    data = (void *)((const Byte *)data + cur);
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _pos += cur;
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size -= cur;
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
209baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(seekOrigin)
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_SET: _pos = offset; break;
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_CUR: _pos = _pos + offset; break;
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case STREAM_SEEK_END: _pos = _size + offset; break;
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    default: return STG_E_INVALIDFUNCTION;
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (newPosition != 0)
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = _pos;
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
222