7
#include "../../../C/Alloc.h"
10
#include "../Common/InBuffer.h"
11
#include "../Common/OutBuffer.h"
18
static const UInt32 kBufferSize = (1 << 20);
19
static const Byte kNumBitsMask = 0x1F;
20
static const Byte kBlockModeMask = 0x80;
21
static const int kNumMinBits = 9;
22
static const int kNumMaxBits = 16;
26
MyFree(_parents); _parents = 0;
27
MyFree(_suffixes); _suffixes = 0;
28
MyFree(_stack); _stack = 0;
31
CDecoder::~CDecoder() { Free(); }
33
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
34
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
39
if (!inBuffer.Create(kBufferSize))
41
inBuffer.SetStream(inStream);
44
if (!outBuffer.Create(kBufferSize))
46
outBuffer.SetStream(outStream);
49
int maxbits = _properties & kNumBitsMask;
50
if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
52
UInt32 numItems = 1 << maxbits;
53
bool blockMode = ((_properties & kBlockModeMask) != 0);
55
if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)
58
_parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (_parents == 0) return E_OUTOFMEMORY;
59
_suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_suffixes == 0) return E_OUTOFMEMORY;
60
_stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (_stack == 0) return E_OUTOFMEMORY;
61
_numMaxBits = maxbits;
65
int numBits = kNumMinBits;
66
UInt32 head = blockMode ? 257 : 256;
68
bool needPrev = false;
71
unsigned numBufBits = 0;
73
Byte buf[kNumMaxBits + 4];
75
_parents[256] = 0; // virus protection
80
if (numBufBits == bitPos)
82
numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8;
84
UInt64 nowPos = outBuffer.GetProcessedSize();
85
if (progress != NULL && nowPos - prevPos >= (1 << 18))
88
UInt64 packSize = inBuffer.GetProcessedSize();
89
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
92
unsigned bytePos = bitPos >> 3;
93
UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);
94
symbol >>= (bitPos & 7);
95
symbol &= (1 << numBits) - 1;
97
if (bitPos > numBufBits)
101
if (blockMode && symbol == 256)
103
numBufBits = bitPos = 0;
104
numBits = kNumMinBits;
113
_stack[i++] = _suffixes[cur];
116
_stack[i++] = (Byte)cur;
119
_suffixes[head - 1] = (Byte)cur;
120
if (symbol == head - 1)
121
_stack[0] = (Byte)cur;
124
outBuffer.WriteByte((_stack[--i]));
129
_parents[head++] = (UInt16)symbol;
130
if (head > ((UInt32)1 << numBits))
132
if (numBits < maxbits)
134
numBufBits = bitPos = 0;
142
return outBuffer.Flush();
145
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
146
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
148
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
149
catch(const CInBufferException &e) { return e.ErrorCode; }
150
catch(const COutBufferException &e) { return e.ErrorCode; }
151
catch(...) { return S_FALSE; }
154
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
158
_properties = data[0];