9
#include "../../../../C/Alloc.h"
12
#include "../../Common/InBuffer.h"
13
#include "../../Common/OutBuffer.h"
14
#include "../../Common/LSBFDecoder.h"
19
static const UInt32 kBufferSize = (1 << 20);
20
static const Byte kNumBitsMask = 0x1F;
21
static const Byte kBlockModeMask = 0x80;
22
static const int kNumMinBits = 9;
23
static const int kNumMaxBits = 16;
35
bool CDecoder::Alloc(size_t numItems)
38
_parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16));
41
_suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte));
44
_stack = (Byte *)MyAlloc(numItems * sizeof(Byte));
53
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
54
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
55
ICompressProgressInfo *progress)
57
NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer;
60
if (!inBuffer.Create(kBufferSize))
62
inBuffer.SetStream(inStream);
65
if (!outBuffer.Create(kBufferSize))
67
outBuffer.SetStream(outStream);
70
int maxbits = _properties & kNumBitsMask;
71
if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
73
UInt32 numItems = 1 << maxbits;
74
bool blockMode = ((_properties & kBlockModeMask) != 0);
78
if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)
82
_numMaxBits = maxbits;
86
int numBits = kNumMinBits;
87
UInt32 head = blockMode ? 257 : 256;
89
bool needPrev = false;
93
_parents[256] = 0; // virus protection
98
if (keepBits < numBits)
99
keepBits = numBits * 8;
100
UInt32 symbol = inBuffer.ReadBits(numBits);
101
if (inBuffer.ExtraBitsWereRead())
106
if (blockMode && symbol == 256)
108
for (;keepBits > 0; keepBits--)
109
inBuffer.ReadBits(1);
110
numBits = kNumMinBits;
119
_stack[i++] = _suffixes[cur];
122
_stack[i++] = (Byte)cur;
125
_suffixes[head - 1] = (Byte)cur;
126
if (symbol == head - 1)
127
_stack[0] = (Byte)cur;
130
outBuffer.WriteByte((_stack[--i]));
134
_parents[head++] = (UInt16)symbol;
135
if (head > ((UInt32)1 << numBits))
137
if (numBits < maxbits)
140
keepBits = numBits * 8;
147
UInt64 nowPos = outBuffer.GetProcessedSize();
148
if (progress != NULL && nowPos - prevPos > (1 << 18))
151
UInt64 packSize = inBuffer.GetProcessedSize();
152
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
155
return outBuffer.Flush();
158
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
159
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
160
ICompressProgressInfo *progress)
162
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
163
catch(const CInBufferException &e) { return e.ErrorCode; }
164
catch(const COutBufferException &e) { return e.ErrorCode; }
165
catch(...) { return S_FALSE; }
168
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
172
_properties = data[0];