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