blob: a0f791173a7ce82440fdf82841622c5007e9707a [file] [log] [blame]
// LZInWindow.cpp
#include "StdAfx.h"
#include "LZInWindow.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/Alloc.h"
void CLZInWindow::Free()
{
::BigFree(_bufferBase);
_bufferBase = 0;
}
bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
{
_keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == 0 || _blockSize != blockSize)
{
Free();
_blockSize = blockSize;
if (_blockSize != 0)
_bufferBase = (Byte *)::BigAlloc(_blockSize);
}
_pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter;
if (_blockSize == 0)
return true;
return (_bufferBase != 0);
}
void CLZInWindow::SetStream(ISequentialInStream *stream)
{
_stream = stream;
}
HRESULT CLZInWindow::Init()
{
_buffer = _bufferBase;
_pos = 0;
_streamPos = 0;
_streamEndWasReached = false;
return ReadBlock();
}
/*
void CLZInWindow::ReleaseStream()
{
_stream.Release();
}
*/
///////////////////////////////////////////
// ReadBlock
// In State:
// (_buffer + _streamPos) <= (_bufferBase + _blockSize)
// Out State:
// _posLimit <= _blockSize - _keepSizeAfter;
// if(_streamEndWasReached == false):
// _streamPos >= _pos + _keepSizeAfter
// _posLimit = _streamPos - _keepSizeAfter;
// else
//
HRESULT CLZInWindow::ReadBlock()
{
if(_streamEndWasReached)
return S_OK;
while(true)
{
UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos;
if(size == 0)
return S_OK;
UInt32 numReadBytes;
RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes));
if(numReadBytes == 0)
{
_posLimit = _streamPos;
const Byte *pointerToPostion = _buffer + _posLimit;
if(pointerToPostion > _pointerToLastSafePosition)
_posLimit = (UInt32)(_pointerToLastSafePosition - _buffer);
_streamEndWasReached = true;
return S_OK;
}
_streamPos += numReadBytes;
if(_streamPos >= _pos + _keepSizeAfter)
{
_posLimit = _streamPos - _keepSizeAfter;
return S_OK;
}
}
}
void CLZInWindow::MoveBlock()
{
UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0)
offset--;
UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset;
memmove(_bufferBase, _bufferBase + offset, numBytes);
_buffer -= offset;
}