You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
3.0 KiB
164 lines
3.0 KiB
// 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)
|
|
{
|
|
size_t num = 0;
|
|
for (;;)
|
|
{
|
|
const size_t rem = _bufLim - _buf;
|
|
if (size <= rem)
|
|
{
|
|
if (size != 0)
|
|
{
|
|
memcpy(buf, _buf, size);
|
|
_buf += size;
|
|
num += size;
|
|
}
|
|
return num;
|
|
}
|
|
if (rem != 0)
|
|
{
|
|
memcpy(buf, _buf, rem);
|
|
_buf += rem;
|
|
buf += rem;
|
|
num += rem;
|
|
size -= rem;
|
|
}
|
|
if (!ReadBlock())
|
|
return num;
|
|
}
|
|
|
|
/*
|
|
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;
|
|
}
|
|
}
|