ShrinkDecoder.cpp (p7zip_15.14.1_src_all) | : | ShrinkDecoder.cpp (p7zip_16.02_src_all) | ||
---|---|---|---|---|
// ShrinkDecoder.cpp | // ShrinkDecoder.cpp | |||
#include "StdAfx.h" | #include "StdAfx.h" | |||
#include <stdio.h> | ||||
#include "../../../C/Alloc.h" | #include "../../../C/Alloc.h" | |||
#include "../Common/InBuffer.h" | #include "../Common/InBuffer.h" | |||
#include "../Common/OutBuffer.h" | #include "../Common/OutBuffer.h" | |||
#include "BitlDecoder.h" | #include "BitlDecoder.h" | |||
#include "ShrinkDecoder.h" | #include "ShrinkDecoder.h" | |||
namespace NCompress { | namespace NCompress { | |||
namespace NShrink { | namespace NShrink { | |||
static const UInt32 kBufferSize = (1 << 20); | static const UInt32 kBufferSize = (1 << 18); | |||
static const int kNumMinBits = 9; | static const unsigned kNumMinBits = 9; | |||
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * outStream, | HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream * outStream, | |||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgress Info *progress) | const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgress Info *progress) | |||
{ | { | |||
NBitl::CBaseDecoder<CInBuffer> inBuffer; | NBitl::CBaseDecoder<CInBuffer> inBuffer; | |||
COutBuffer outBuffer; | COutBuffer outBuffer; | |||
if (!inBuffer.Create(kBufferSize)) | if (!inBuffer.Create(kBufferSize)) | |||
return E_OUTOFMEMORY; | return E_OUTOFMEMORY; | |||
inBuffer.SetStream(inStream); | inBuffer.SetStream(inStream); | |||
inBuffer.Init(); | inBuffer.Init(); | |||
if (!outBuffer.Create(kBufferSize)) | if (!outBuffer.Create(kBufferSize)) | |||
return E_OUTOFMEMORY; | return E_OUTOFMEMORY; | |||
outBuffer.SetStream(outStream); | outBuffer.SetStream(outStream); | |||
outBuffer.Init(); | outBuffer.Init(); | |||
{ | ||||
unsigned i; | ||||
for (i = 0; i < 257; i++) | ||||
_parents[i] = (UInt16)i; | ||||
for (; i < kNumItems; i++) | ||||
_parents[i] = kNumItems; | ||||
for (i = 0; i < kNumItems; i++) | ||||
_suffixes[i] = 0; | ||||
} | ||||
UInt64 prevPos = 0; | UInt64 prevPos = 0; | |||
int numBits = kNumMinBits; | unsigned numBits = kNumMinBits; | |||
UInt32 head = 257; | unsigned head = 257; | |||
bool needPrev = false; | int lastSym = -1; | |||
UInt32 lastSymbol = 0; | Byte lastChar2 = 0; | |||
int i; | ||||
for (i = 0; i < kNumItems; i++) | ||||
_parents[i] = 0; | ||||
for (i = 0; i < kNumItems; i++) | ||||
_suffixes[i] = 0; | ||||
for (i = 0; i < 257; i++) | ||||
_isFree[i] = false; | ||||
for (; i < kNumItems; i++) | ||||
_isFree[i] = true; | ||||
for (;;) | for (;;) | |||
{ | { | |||
UInt32 symbol = inBuffer.ReadBits(numBits); | UInt32 sym = inBuffer.ReadBits(numBits); | |||
if (inBuffer.ExtraBitsWereRead()) | if (inBuffer.ExtraBitsWereRead()) | |||
break; | break; | |||
if (_isFree[symbol]) | ||||
return S_FALSE; | if (sym == 256) | |||
if (symbol == 256) | ||||
{ | { | |||
UInt32 symbol = inBuffer.ReadBits(numBits); | sym = inBuffer.ReadBits(numBits); | |||
if (symbol == 1) | if (sym == 1) | |||
{ | { | |||
if (numBits < kNumMaxBits) | if (numBits >= kNumMaxBits) | |||
numBits++; | return S_FALSE; | |||
numBits++; | ||||
continue; | ||||
} | } | |||
else if (symbol == 2) | if (sym != 2) | |||
return S_FALSE; | ||||
{ | { | |||
if (needPrev) | unsigned i; | |||
_isFree[head - 1] = true; | ||||
for (i = 257; i < kNumItems; i++) | for (i = 257; i < kNumItems; i++) | |||
_isParent[i] = false; | _stack[i] = 0; | |||
for (i = 257; i < kNumItems; i++) | for (i = 257; i < kNumItems; i++) | |||
if (!_isFree[i]) | { | |||
_isParent[_parents[i]] = true; | unsigned par = _parents[i]; | |||
if (par != kNumItems) | ||||
_stack[par] = 1; | ||||
} | ||||
for (i = 257; i < kNumItems; i++) | for (i = 257; i < kNumItems; i++) | |||
if (!_isParent[i]) | if (_stack[i] == 0) | |||
_isFree[i] = true; | _parents[i] = kNumItems; | |||
head = 257; | head = 257; | |||
while (head < kNumItems && !_isFree[head]) | ||||
head++; | continue; | |||
if (head < kNumItems) | } | |||
} | ||||
bool needPrev = false; | ||||
if (head < kNumItems && lastSym >= 0) | ||||
{ | ||||
while (head < kNumItems && _parents[head] != kNumItems) | ||||
head++; | ||||
if (head < kNumItems) | ||||
{ | ||||
if (head == (unsigned)lastSym) | ||||
{ | { | |||
needPrev = true; | // we need to fix the code for that case | |||
_isFree[head] = false; | // _parents[head] is not allowed to link to itself | |||
_parents[head] = (UInt16)lastSymbol; | return E_NOTIMPL; | |||
head++; | ||||
} | } | |||
needPrev = true; | ||||
_parents[head] = (UInt16)lastSym; | ||||
_suffixes[head] = (Byte)lastChar2; | ||||
head++; | ||||
} | } | |||
else | ||||
return S_FALSE; | ||||
continue; | ||||
} | } | |||
UInt32 cur = symbol; | ||||
i = 0; | if (_parents[sym] == kNumItems) | |||
int corectionIndex = -1; | return S_FALSE; | |||
lastSym = sym; | ||||
unsigned cur = sym; | ||||
unsigned i = 0; | ||||
while (cur >= 256) | while (cur >= 256) | |||
{ | { | |||
if (cur == head - 1) | ||||
corectionIndex = i; | ||||
_stack[i++] = _suffixes[cur]; | _stack[i++] = _suffixes[cur]; | |||
cur = _parents[cur]; | cur = _parents[cur]; | |||
} | } | |||
_stack[i++] = (Byte)cur; | _stack[i++] = (Byte)cur; | |||
lastChar2 = (Byte)cur; | ||||
if (needPrev) | if (needPrev) | |||
{ | ||||
_suffixes[head - 1] = (Byte)cur; | _suffixes[head - 1] = (Byte)cur; | |||
if (corectionIndex >= 0) | ||||
_stack[corectionIndex] = (Byte)cur; | ||||
} | ||||
while (i > 0) | ||||
outBuffer.WriteByte((_stack[--i])); | ||||
while (head < kNumItems && !_isFree[head]) | ||||
head++; | ||||
if (head < kNumItems) | ||||
{ | ||||
needPrev = true; | ||||
_isFree[head] = false; | ||||
_parents[head] = (UInt16)symbol; | ||||
head++; | ||||
} | ||||
else | ||||
needPrev = false; | ||||
lastSymbol = symbol; | ||||
UInt64 nowPos = outBuffer.GetProcessedSize(); | do | |||
if (progress != NULL && nowPos - prevPos > (1 << 18)) | outBuffer.WriteByte(_stack[--i]); | |||
while (i); | ||||
if (progress) | ||||
{ | { | |||
prevPos = nowPos; | const UInt64 nowPos = outBuffer.GetProcessedSize(); | |||
UInt64 packSize = inBuffer.GetProcessedSize(); | if (nowPos - prevPos >= (1 << 18)) | |||
RINOK(progress->SetRatioInfo(&packSize, &nowPos)); | { | |||
prevPos = nowPos; | ||||
const UInt64 packSize = inBuffer.GetProcessedSize(); | ||||
RINOK(progress->SetRatioInfo(&packSize, &nowPos)); | ||||
} | ||||
} | } | |||
} | } | |||
return outBuffer.Flush(); | return outBuffer.Flush(); | |||
} | } | |||
STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, | STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, | |||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progr ess) | const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress ) | |||
{ | { | |||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); } | try { return CodeReal(inStream, outStream, inSize, outSize, progress); } | |||
catch(const CInBufferException &e) { return e.ErrorCode; } | catch(const CInBufferException &e) { return e.ErrorCode; } | |||
catch(const COutBufferException &e) { return e.ErrorCode; } | catch(const COutBufferException &e) { return e.ErrorCode; } | |||
catch(...) { return S_FALSE; } | catch(...) { return S_FALSE; } | |||
} | } | |||
}} | }} | |||
End of changes. 27 change blocks. | ||||
71 lines changed or deleted | 85 lines changed or added |