xref: /aosp_15_r20/external/lzma/CPP/7zip/Common/StreamObjects.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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