Home | History | Annotate | Download | only in Common
      1 // InBuffer.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../C/Alloc.h"
      6 
      7 #include "InBuffer.h"
      8 
      9 CInBufferBase::CInBufferBase() throw():
     10   _buf(0),
     11   _bufLim(0),
     12   _bufBase(0),
     13   _stream(0),
     14   _processedSize(0),
     15   _bufSize(0),
     16   _wasFinished(false),
     17   NumExtraBytes(0)
     18 {}
     19 
     20 bool CInBuffer::Create(size_t bufSize) throw()
     21 {
     22   const unsigned kMinBlockSize = 1;
     23   if (bufSize < kMinBlockSize)
     24     bufSize = kMinBlockSize;
     25   if (_bufBase != 0 && _bufSize == bufSize)
     26     return true;
     27   Free();
     28   _bufSize = bufSize;
     29   _bufBase = (Byte *)::MidAlloc(bufSize);
     30   return (_bufBase != 0);
     31 }
     32 
     33 void CInBuffer::Free() throw()
     34 {
     35   ::MidFree(_bufBase);
     36   _bufBase = 0;
     37 }
     38 
     39 void CInBufferBase::Init() throw()
     40 {
     41   _processedSize = 0;
     42   _buf = _bufBase;
     43   _bufLim = _buf;
     44   _wasFinished = false;
     45   #ifdef _NO_EXCEPTIONS
     46   ErrorCode = S_OK;
     47   #endif
     48   NumExtraBytes = 0;
     49 }
     50 
     51 bool CInBufferBase::ReadBlock()
     52 {
     53   #ifdef _NO_EXCEPTIONS
     54   if (ErrorCode != S_OK)
     55     return false;
     56   #endif
     57   if (_wasFinished)
     58     return false;
     59   _processedSize += (_buf - _bufBase);
     60   _buf = _bufBase;
     61   _bufLim = _bufBase;
     62   UInt32 processed;
     63   // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
     64   HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
     65   #ifdef _NO_EXCEPTIONS
     66   ErrorCode = result;
     67   #else
     68   if (result != S_OK)
     69     throw CInBufferException(result);
     70   #endif
     71   _bufLim = _buf + processed;
     72   _wasFinished = (processed == 0);
     73   return !_wasFinished;
     74 }
     75 
     76 bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
     77 {
     78   if (!ReadBlock())
     79   {
     80     NumExtraBytes++;
     81     b = 0xFF;
     82     return false;
     83   }
     84   b = *_buf++;
     85   return true;
     86 }
     87 
     88 Byte CInBufferBase::ReadByte_FromNewBlock()
     89 {
     90   if (!ReadBlock())
     91   {
     92     NumExtraBytes++;
     93     return 0xFF;
     94   }
     95   return *_buf++;
     96 }
     97 
     98 size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
     99 {
    100   if ((size_t)(_bufLim - _buf) >= size)
    101   {
    102     const Byte *src = _buf;
    103     for (size_t i = 0; i < size; i++)
    104       buf[i] = src[i];
    105     _buf += size;
    106     return size;
    107   }
    108   for (size_t i = 0; i < size; i++)
    109   {
    110     if (_buf >= _bufLim)
    111       if (!ReadBlock())
    112         return i;
    113     buf[i] = *_buf++;
    114   }
    115   return size;
    116 }
    117 
    118 size_t CInBufferBase::Skip(size_t size)
    119 {
    120   size_t processed = 0;
    121   for (;;)
    122   {
    123     size_t rem = (_bufLim - _buf);
    124     if (rem >= size)
    125     {
    126       _buf += size;
    127       return processed + size;
    128     }
    129     _buf += rem;
    130     processed += rem;
    131     size -= rem;
    132     if (!ReadBlock())
    133       return processed;
    134   }
    135 }
    136