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