This commit is contained in:
Igor Pavlov
2017-04-30 00:00:00 +00:00
committed by Kornel
parent 603abd5528
commit 2efa10565a
442 changed files with 15479 additions and 8525 deletions

View File

@@ -1,10 +1,7 @@
// ShrinkDecoder.cpp
#include "StdAfx.h"
#include <stdio.h>
#include "../../../C/Alloc.h"
#include "../Common/InBuffer.h"
@@ -20,18 +17,19 @@ static const UInt32 kBufferSize = (1 << 18);
static const unsigned kNumMinBits = 9;
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
NBitl::CBaseDecoder<CInBuffer> inBuffer;
COutBuffer outBuffer;
if (!inBuffer.Create(kBufferSize))
return E_OUTOFMEMORY;
if (!outBuffer.Create(kBufferSize))
return E_OUTOFMEMORY;
inBuffer.SetStream(inStream);
inBuffer.Init();
if (!outBuffer.Create(kBufferSize))
return E_OUTOFMEMORY;
outBuffer.SetStream(outStream);
outBuffer.Init();
@@ -45,31 +43,69 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
_suffixes[i] = 0;
}
UInt64 prevPos = 0;
UInt64 prevPos = 0, inPrev = 0;
unsigned numBits = kNumMinBits;
unsigned head = 257;
int lastSym = -1;
Byte lastChar2 = 0;
bool moreOut = false;
HRESULT res = S_FALSE;
for (;;)
{
_inProcessed = inBuffer.GetProcessedSize();
const UInt64 nowPos = outBuffer.GetProcessedSize();
bool eofCheck = false;
if (outSize && nowPos >= *outSize)
{
if (!_fullStreamMode || moreOut)
{
res = S_OK;
break;
}
eofCheck = true;
// Is specSym(=256) allowed after end of stream
// Do we need to read it here
}
if (progress)
{
if (nowPos - prevPos >= (1 << 18)
|| _inProcessed - inPrev >= (1 << 20))
{
prevPos = nowPos;
inPrev = _inProcessed;
RINOK(progress->SetRatioInfo(&_inProcessed, &nowPos));
}
}
UInt32 sym = inBuffer.ReadBits(numBits);
if (inBuffer.ExtraBitsWereRead())
{
res = S_OK;
break;
}
if (sym == 256)
{
sym = inBuffer.ReadBits(numBits);
if (inBuffer.ExtraBitsWereRead())
break;
if (sym == 1)
{
if (numBits >= kNumMaxBits)
return S_FALSE;
break;
numBits++;
continue;
}
if (sym != 2)
return S_FALSE;
break;
{
unsigned i;
for (i = 257; i < kNumItems; i++)
@@ -90,6 +126,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
}
}
if (eofCheck)
{
// It's can be error case.
// That error can be detected later in (*inSize != _inProcessed) check.
res = S_OK;
break;
}
bool needPrev = false;
if (head < kNumItems && lastSym >= 0)
{
@@ -101,7 +145,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
{
// we need to fix the code for that case
// _parents[head] is not allowed to link to itself
return E_NOTIMPL;
res = E_NOTIMPL;
break;
}
needPrev = true;
_parents[head] = (UInt16)lastSym;
@@ -111,7 +156,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
}
if (_parents[sym] == kNumItems)
return S_FALSE;
break;
lastSym = sym;
unsigned cur = sym;
@@ -127,34 +172,64 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
lastChar2 = (Byte)cur;
if (needPrev)
_suffixes[head - 1] = (Byte)cur;
_suffixes[(size_t)head - 1] = (Byte)cur;
if (outSize)
{
const UInt64 limit = *outSize - nowPos;
if (i > limit)
{
moreOut = true;
i = (unsigned)limit;
}
}
do
outBuffer.WriteByte(_stack[--i]);
while (i);
if (progress)
{
const UInt64 nowPos = outBuffer.GetProcessedSize();
if (nowPos - prevPos >= (1 << 18))
{
prevPos = nowPos;
const UInt64 packSize = inBuffer.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
}
}
}
return outBuffer.Flush();
RINOK(outBuffer.Flush());
if (res == S_OK)
if (_fullStreamMode)
{
if (moreOut)
res = S_FALSE;
const UInt64 nowPos = outBuffer.GetProcessedSize();
if (outSize && *outSize != nowPos)
res = S_FALSE;
if (inSize && *inSize != _inProcessed)
res = S_FALSE;
}
return res;
}
STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
catch(const CInBufferException &e) { return e.ErrorCode; }
catch(const COutBufferException &e) { return e.ErrorCode; }
// catch(const CInBufferException &e) { return e.ErrorCode; }
// catch(const COutBufferException &e) { return e.ErrorCode; }
catch(const CSystemException &e) { return e.ErrorCode; }
catch(...) { return S_FALSE; }
}
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
{
_fullStreamMode = (finishMode != 0);
return S_OK;
}
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
{
*value = _inProcessed;
return S_OK;
}
}}