tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StreamObjects.cpp (7288B)


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