1 // StreamObjects.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../C/Alloc.h"
6
7 #include "StreamObjects.h"
8
Z7_COM7F_IMF(CBufferInStream::Read (void * data,UInt32 size,UInt32 * processedSize))9 Z7_COM7F_IMF(CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
10 {
11 if (processedSize)
12 *processedSize = 0;
13 if (size == 0)
14 return S_OK;
15 if (_pos >= Buf.Size())
16 return S_OK;
17 size_t rem = Buf.Size() - (size_t)_pos;
18 if (rem > size)
19 rem = (size_t)size;
20 memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);
21 _pos += rem;
22 if (processedSize)
23 *processedSize = (UInt32)rem;
24 return S_OK;
25 }
26
Z7_COM7F_IMF(CBufferInStream::Seek (Int64 offset,UInt32 seekOrigin,UInt64 * newPosition))27 Z7_COM7F_IMF(CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
28 {
29 switch (seekOrigin)
30 {
31 case STREAM_SEEK_SET: break;
32 case STREAM_SEEK_CUR: offset += _pos; break;
33 case STREAM_SEEK_END: offset += Buf.Size(); break;
34 default: return STG_E_INVALIDFUNCTION;
35 }
36 if (offset < 0)
37 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
38 _pos = (UInt64)offset;
39 if (newPosition)
40 *newPosition = (UInt64)offset;
41 return S_OK;
42 }
43
Z7_COM7F_IMF(CBufInStream::Read (void * data,UInt32 size,UInt32 * processedSize))44 Z7_COM7F_IMF(CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
45 {
46 if (processedSize)
47 *processedSize = 0;
48 if (size == 0)
49 return S_OK;
50 if (_pos >= _size)
51 return S_OK;
52 size_t rem = _size - (size_t)_pos;
53 if (rem > size)
54 rem = (size_t)size;
55 memcpy(data, _data + (size_t)_pos, rem);
56 _pos += rem;
57 if (processedSize)
58 *processedSize = (UInt32)rem;
59 return S_OK;
60 }
61
Z7_COM7F_IMF(CBufInStream::Seek (Int64 offset,UInt32 seekOrigin,UInt64 * newPosition))62 Z7_COM7F_IMF(CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
63 {
64 switch (seekOrigin)
65 {
66 case STREAM_SEEK_SET: break;
67 case STREAM_SEEK_CUR: offset += _pos; break;
68 case STREAM_SEEK_END: offset += _size; break;
69 default: return STG_E_INVALIDFUNCTION;
70 }
71 if (offset < 0)
72 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
73 _pos = (UInt64)offset;
74 if (newPosition)
75 *newPosition = (UInt64)offset;
76 return S_OK;
77 }
78
Create_BufInStream_WithReference(const void * data,size_t size,IUnknown * ref,ISequentialInStream ** stream)79 void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)
80 {
81 *stream = NULL;
82 CBufInStream *inStreamSpec = new CBufInStream;
83 CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
84 inStreamSpec->Init((const Byte *)data, size, ref);
85 *stream = streamTemp.Detach();
86 }
87
Create_BufInStream_WithNewBuffer(const void * data,size_t size,ISequentialInStream ** stream)88 void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)
89 {
90 *stream = NULL;
91 CBufferInStream *inStreamSpec = new CBufferInStream;
92 CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
93 inStreamSpec->Buf.CopyFrom((const Byte *)data, size);
94 inStreamSpec->Init();
95 *stream = streamTemp.Detach();
96 }
97
Free()98 void CByteDynBuffer::Free() throw()
99 {
100 MyFree(_buf);
101 _buf = NULL;
102 _capacity = 0;
103 }
104
EnsureCapacity(size_t cap)105 bool CByteDynBuffer::EnsureCapacity(size_t cap) throw()
106 {
107 if (cap <= _capacity)
108 return true;
109 const size_t cap2 = _capacity + _capacity / 4;
110 if (cap < cap2)
111 cap = cap2;
112 Byte *buf = (Byte *)MyRealloc(_buf, cap);
113 if (!buf)
114 return false;
115 _buf = buf;
116 _capacity = cap;
117 return true;
118 }
119
GetBufPtrForWriting(size_t addSize)120 Byte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)
121 {
122 addSize += _size;
123 if (addSize < _size)
124 return NULL;
125 if (!_buffer.EnsureCapacity(addSize))
126 return NULL;
127 return (Byte *)_buffer + _size;
128 }
129
CopyToBuffer(CByteBuffer & dest) const130 void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const
131 {
132 dest.CopyFrom((const Byte *)_buffer, _size);
133 }
134
Z7_COM7F_IMF(CDynBufSeqOutStream::Write (const void * data,UInt32 size,UInt32 * processedSize))135 Z7_COM7F_IMF(CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
136 {
137 if (processedSize)
138 *processedSize = 0;
139 if (size == 0)
140 return S_OK;
141 Byte *buf = GetBufPtrForWriting(size);
142 if (!buf)
143 return E_OUTOFMEMORY;
144 memcpy(buf, data, size);
145 UpdateSize(size);
146 if (processedSize)
147 *processedSize = size;
148 return S_OK;
149 }
150
Z7_COM7F_IMF(CBufPtrSeqOutStream::Write (const void * data,UInt32 size,UInt32 * processedSize))151 Z7_COM7F_IMF(CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
152 {
153 size_t rem = _size - _pos;
154 if (rem > size)
155 rem = (size_t)size;
156 if (rem != 0)
157 {
158 memcpy(_buffer + _pos, data, rem);
159 _pos += rem;
160 }
161 if (processedSize)
162 *processedSize = (UInt32)rem;
163 return (rem != 0 || size == 0) ? S_OK : E_FAIL;
164 }
165
Z7_COM7F_IMF(CSequentialOutStreamSizeCount::Write (const void * data,UInt32 size,UInt32 * processedSize))166 Z7_COM7F_IMF(CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize))
167 {
168 UInt32 realProcessedSize;
169 HRESULT result = _stream->Write(data, size, &realProcessedSize);
170 _size += realProcessedSize;
171 if (processedSize)
172 *processedSize = realProcessedSize;
173 return result;
174 }
175
176 static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
177
Free()178 void CCachedInStream::Free() throw()
179 {
180 MyFree(_tags);
181 _tags = NULL;
182 MidFree(_data);
183 _data = NULL;
184 }
185
Alloc(unsigned blockSizeLog,unsigned numBlocksLog)186 bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()
187 {
188 unsigned sizeLog = blockSizeLog + numBlocksLog;
189 if (sizeLog >= sizeof(size_t) * 8)
190 return false;
191 size_t dataSize = (size_t)1 << sizeLog;
192 if (!_data || dataSize != _dataSize)
193 {
194 MidFree(_data);
195 _data = (Byte *)MidAlloc(dataSize);
196 if (!_data)
197 return false;
198 _dataSize = dataSize;
199 }
200 if (!_tags || numBlocksLog != _numBlocksLog)
201 {
202 MyFree(_tags);
203 _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);
204 if (!_tags)
205 return false;
206 _numBlocksLog = numBlocksLog;
207 }
208 _blockSizeLog = blockSizeLog;
209 return true;
210 }
211
Init(UInt64 size)212 void CCachedInStream::Init(UInt64 size) throw()
213 {
214 _size = size;
215 _pos = 0;
216 const size_t numBlocks = (size_t)1 << _numBlocksLog;
217 for (size_t i = 0; i < numBlocks; i++)
218 _tags[i] = kEmptyTag;
219 }
220
Z7_COM7F_IMF(CCachedInStream::Read (void * data,UInt32 size,UInt32 * processedSize))221 Z7_COM7F_IMF(CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
222 {
223 if (processedSize)
224 *processedSize = 0;
225 if (size == 0)
226 return S_OK;
227 if (_pos >= _size)
228 return S_OK;
229
230 {
231 const UInt64 rem = _size - _pos;
232 if (size > rem)
233 size = (UInt32)rem;
234 }
235
236 while (size != 0)
237 {
238 const UInt64 cacheTag = _pos >> _blockSizeLog;
239 const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);
240 Byte *p = _data + (cacheIndex << _blockSizeLog);
241
242 if (_tags[cacheIndex] != cacheTag)
243 {
244 _tags[cacheIndex] = kEmptyTag;
245 const UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);
246 size_t blockSize = (size_t)1 << _blockSizeLog;
247 if (blockSize > remInBlock)
248 blockSize = (size_t)remInBlock;
249
250 RINOK(ReadBlock(cacheTag, p, blockSize))
251
252 _tags[cacheIndex] = cacheTag;
253 }
254
255 const size_t kBlockSize = (size_t)1 << _blockSizeLog;
256 const size_t offset = (size_t)_pos & (kBlockSize - 1);
257 UInt32 cur = size;
258 const size_t rem = kBlockSize - offset;
259 if (cur > rem)
260 cur = (UInt32)rem;
261
262 memcpy(data, p + offset, cur);
263
264 if (processedSize)
265 *processedSize += cur;
266 data = (void *)((const Byte *)data + cur);
267 _pos += cur;
268 size -= cur;
269 }
270
271 return S_OK;
272 }
273
274
Z7_COM7F_IMF(CCachedInStream::Seek (Int64 offset,UInt32 seekOrigin,UInt64 * newPosition))275 Z7_COM7F_IMF(CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
276 {
277 switch (seekOrigin)
278 {
279 case STREAM_SEEK_SET: break;
280 case STREAM_SEEK_CUR: offset += _pos; break;
281 case STREAM_SEEK_END: offset += _size; break;
282 default: return STG_E_INVALIDFUNCTION;
283 }
284 if (offset < 0)
285 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
286 _pos = (UInt64)offset;
287 if (newPosition)
288 *newPosition = (UInt64)offset;
289 return S_OK;
290 }
291