1// InBuffer.cpp 2 3#include "StdAfx.h" 4 5#include "../../../C/Alloc.h" 6 7#include "InBuffer.h" 8 9CInBufferBase::CInBufferBase() throw(): 10 _buf(NULL), 11 _bufLim(NULL), 12 _bufBase(NULL), 13 _stream(NULL), 14 _processedSize(0), 15 _bufSize(0), 16 _wasFinished(false), 17 NumExtraBytes(0) 18{} 19 20bool CInBuffer::Create(size_t bufSize) throw() 21{ 22 const unsigned kMinBlockSize = 1; 23 if (bufSize < kMinBlockSize) 24 bufSize = kMinBlockSize; 25 if (_bufBase != NULL && _bufSize == bufSize) 26 return true; 27 Free(); 28 _bufSize = bufSize; 29 _bufBase = (Byte *)::MidAlloc(bufSize); 30 return (_bufBase != NULL); 31} 32 33void CInBuffer::Free() throw() 34{ 35 ::MidFree(_bufBase); 36 _bufBase = NULL; 37} 38 39void CInBufferBase::Init() throw() 40{ 41 _processedSize = 0; 42 _buf = _bufBase; 43 _bufLim = _buf; 44 _wasFinished = false; 45 #ifdef Z7_NO_EXCEPTIONS 46 ErrorCode = S_OK; 47 #endif 48 NumExtraBytes = 0; 49} 50 51bool CInBufferBase::ReadBlock() 52{ 53 #ifdef Z7_NO_EXCEPTIONS 54 if (ErrorCode != S_OK) 55 return false; 56 #endif 57 if (_wasFinished) 58 return false; 59 _processedSize += (size_t)(_buf - _bufBase); 60 _buf = _bufBase; 61 _bufLim = _bufBase; 62 UInt32 processed; 63 // FIX_ME: we can improve it to support (_bufSize >= (1 << 32)) 64 const HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed); 65 #ifdef Z7_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 76bool CInBufferBase::ReadByte_FromNewBlock(Byte &b) 77{ 78 if (!ReadBlock()) 79 { 80 // 22.00: we don't increment (NumExtraBytes) here 81 // NumExtraBytes++; 82 b = 0xFF; 83 return false; 84 } 85 b = *_buf++; 86 return true; 87} 88 89Byte CInBufferBase::ReadByte_FromNewBlock() 90{ 91 if (!ReadBlock()) 92 { 93 NumExtraBytes++; 94 return 0xFF; 95 } 96 return *_buf++; 97} 98 99size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) 100{ 101 size_t num = 0; 102 for (;;) 103 { 104 const size_t rem = (size_t)(_bufLim - _buf); 105 if (size <= rem) 106 { 107 if (size != 0) 108 { 109 memcpy(buf, _buf, size); 110 _buf += size; 111 num += size; 112 } 113 return num; 114 } 115 if (rem != 0) 116 { 117 memcpy(buf, _buf, rem); 118 _buf += rem; 119 buf += rem; 120 num += rem; 121 size -= rem; 122 } 123 if (!ReadBlock()) 124 return num; 125 } 126 127 /* 128 if ((size_t)(_bufLim - _buf) >= size) 129 { 130 const Byte *src = _buf; 131 for (size_t i = 0; i < size; i++) 132 buf[i] = src[i]; 133 _buf += size; 134 return size; 135 } 136 for (size_t i = 0; i < size; i++) 137 { 138 if (_buf >= _bufLim) 139 if (!ReadBlock()) 140 return i; 141 buf[i] = *_buf++; 142 } 143 return size; 144 */ 145} 146 147size_t CInBufferBase::Skip(size_t size) 148{ 149 size_t processed = 0; 150 for (;;) 151 { 152 const size_t rem = (size_t)(_bufLim - _buf); 153 if (rem >= size) 154 { 155 _buf += size; 156 return processed + size; 157 } 158 _buf += rem; 159 processed += rem; 160 size -= rem; 161 if (!ReadBlock()) 162 return processed; 163 } 164} 165