InBuffer.cpp (3029B)
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 size_t num = 0; 101 for (;;) 102 { 103 const size_t rem = _bufLim - _buf; 104 if (size <= rem) 105 { 106 if (size != 0) 107 { 108 memcpy(buf, _buf, size); 109 _buf += size; 110 num += size; 111 } 112 return num; 113 } 114 if (rem != 0) 115 { 116 memcpy(buf, _buf, rem); 117 _buf += rem; 118 buf += rem; 119 num += rem; 120 size -= rem; 121 } 122 if (!ReadBlock()) 123 return num; 124 } 125 126 /* 127 if ((size_t)(_bufLim - _buf) >= size) 128 { 129 const Byte *src = _buf; 130 for (size_t i = 0; i < size; i++) 131 buf[i] = src[i]; 132 _buf += size; 133 return size; 134 } 135 for (size_t i = 0; i < size; i++) 136 { 137 if (_buf >= _bufLim) 138 if (!ReadBlock()) 139 return i; 140 buf[i] = *_buf++; 141 } 142 return size; 143 */ 144 } 145 146 size_t CInBufferBase::Skip(size_t size) 147 { 148 size_t processed = 0; 149 for (;;) 150 { 151 size_t rem = (_bufLim - _buf); 152 if (rem >= size) 153 { 154 _buf += size; 155 return processed + size; 156 } 157 _buf += rem; 158 processed += rem; 159 size -= rem; 160 if (!ReadBlock()) 161 return processed; 162 } 163 }