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