// InBuffer.cpp
#include "StdAfx.h"
#include "../../../C/Alloc.h"
#include "InBuffer.h"
CInBufferBase::CInBufferBase() throw():
_buf(0),
_bufLim(0),
_bufBase(0),
_stream(0),
_processedSize(0),
_bufSize(0),
_wasFinished(false),
NumExtraBytes(0)
{}
bool CInBuffer::Create(size_t bufSize) throw()
{
const unsigned kMinBlockSize = 1;
if (bufSize < kMinBlockSize)
bufSize = kMinBlockSize;
if (_bufBase != 0 && _bufSize == bufSize)
return true;
Free();
_bufSize = bufSize;
_bufBase = (Byte *)::MidAlloc(bufSize);
return (_bufBase != 0);
}
void CInBuffer::Free() throw()
{
::MidFree(_bufBase);
_bufBase = 0;
}
void CInBufferBase::Init() throw()
{
_processedSize = 0;
_buf = _bufBase;
_bufLim = _buf;
_wasFinished = false;
#ifdef _NO_EXCEPTIONS
ErrorCode = S_OK;
#endif
NumExtraBytes = 0;
}
bool CInBufferBase::ReadBlock()
{
#ifdef _NO_EXCEPTIONS
if (ErrorCode != S_OK)
return false;
#endif
if (_wasFinished)
return false;
_processedSize += (_buf - _bufBase);
_buf = _bufBase;
_bufLim = _bufBase;
UInt32 processed;
// FIX_ME: we can improve it to support (_bufSize >= (1 << 32))
HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);
#ifdef _NO_EXCEPTIONS
ErrorCode = result;
#else
if (result != S_OK)
throw CInBufferException(result);
#endif
_bufLim = _buf + processed;
_wasFinished = (processed == 0);
return !_wasFinished;
}
bool CInBufferBase::ReadByte_FromNewBlock(Byte &b)
{
if (!ReadBlock())
{
NumExtraBytes++;
b = 0xFF;
return false;
}
b = *_buf++;
return true;
}
Byte CInBufferBase::ReadByte_FromNewBlock()
{
if (!ReadBlock())
{
NumExtraBytes++;
return 0xFF;
}
return *_buf++;
}
size_t CInBufferBase::ReadBytes(Byte *buf, size_t size)
{
if ((size_t)(_bufLim - _buf) >= size)
{
const Byte *src = _buf;
for (size_t i = 0; i < size; i++)
buf[i] = src[i];
_buf += size;
return size;
}
for (size_t i = 0; i < size; i++)
{
if (_buf >= _bufLim)
if (!ReadBlock())
return i;
buf[i] = *_buf++;
}
return size;
}
size_t CInBufferBase::Skip(size_t size)
{
size_t processed = 0;
for (;;)
{
size_t rem = (_bufLim - _buf);
if (rem >= size)
{
_buf += size;
return processed + size;
}
_buf += rem;
processed += rem;
size -= rem;
if (!ReadBlock())
return processed;
}
}