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