1// StreamObjects.cpp 2 3#include "StdAfx.h" 4 5#include "../../../C/Alloc.h" 6 7#include "StreamObjects.h" 8 9Z7_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 27Z7_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 44Z7_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 62Z7_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 79void 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 88void 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 98void CByteDynBuffer::Free() throw() 99{ 100 MyFree(_buf); 101 _buf = NULL; 102 _capacity = 0; 103} 104 105bool 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 120Byte *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 130void CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const 131{ 132 dest.CopyFrom((const Byte *)_buffer, _size); 133} 134 135Z7_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 151Z7_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 166Z7_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 176static const UInt64 kEmptyTag = (UInt64)(Int64)-1; 177 178void CCachedInStream::Free() throw() 179{ 180 MyFree(_tags); 181 _tags = NULL; 182 MidFree(_data); 183 _data = NULL; 184} 185 186bool 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 212void 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 221Z7_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 275Z7_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