1// LZMA/Decoder.h
2
3#ifndef __LZMA_DECODER_H
4#define __LZMA_DECODER_H
5
6#include "../../../Common/MyCom.h"
7#include "../../ICoder.h"
8#include "../LZ/LZOutWindow.h"
9#include "../RangeCoder/RangeCoderBitTree.h"
10
11extern "C"
12{
13  #include "../../../../C/Alloc.h"
14}
15
16#include "LZMA.h"
17
18namespace NCompress {
19namespace NLZMA {
20
21typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder;
22
23class CLiteralDecoder2
24{
25  CMyBitDecoder _decoders[0x300];
26public:
27  void Init()
28  {
29    for (int i = 0; i < 0x300; i++)
30      _decoders[i].Init();
31  }
32  Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder)
33  {
34    UInt32 symbol = 1;
35    RC_INIT_VAR
36    do
37    {
38      // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
39      RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
40    }
41    while (symbol < 0x100);
42    RC_FLUSH_VAR
43    return (Byte)symbol;
44  }
45  Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte)
46  {
47    UInt32 symbol = 1;
48    RC_INIT_VAR
49    do
50    {
51      UInt32 matchBit = (matchByte >> 7) & 1;
52      matchByte <<= 1;
53      // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder);
54      // symbol = (symbol << 1) | bit;
55      UInt32 bit;
56      RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol,
57          bit = 0, bit = 1)
58      if (matchBit != bit)
59      {
60        while (symbol < 0x100)
61        {
62          // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
63          RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
64        }
65        break;
66      }
67    }
68    while (symbol < 0x100);
69    RC_FLUSH_VAR
70    return (Byte)symbol;
71  }
72};
73
74class CLiteralDecoder
75{
76  CLiteralDecoder2 *_coders;
77  int _numPrevBits;
78  int _numPosBits;
79  UInt32 _posMask;
80public:
81  CLiteralDecoder(): _coders(0) {}
82  ~CLiteralDecoder()  { Free(); }
83  void Free()
84  {
85    MyFree(_coders);
86    _coders = 0;
87  }
88  bool Create(int numPosBits, int numPrevBits)
89  {
90    if (_coders == 0 || (numPosBits + numPrevBits) !=
91        (_numPrevBits + _numPosBits) )
92    {
93      Free();
94      UInt32 numStates = 1 << (numPosBits + numPrevBits);
95      _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2));
96    }
97    _numPosBits = numPosBits;
98    _posMask = (1 << numPosBits) - 1;
99    _numPrevBits = numPrevBits;
100    return (_coders != 0);
101  }
102  void Init()
103  {
104    UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
105    for (UInt32 i = 0; i < numStates; i++)
106      _coders[i].Init();
107  }
108  UInt32 GetState(UInt32 pos, Byte prevByte) const
109    { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
110  Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte)
111    { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
112  Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte)
113    { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
114};
115
116namespace NLength {
117
118class CDecoder
119{
120  CMyBitDecoder _choice;
121  CMyBitDecoder _choice2;
122  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits>  _lowCoder[kNumPosStatesMax];
123  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits>  _midCoder[kNumPosStatesMax];
124  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder;
125public:
126  void Init(UInt32 numPosStates)
127  {
128    _choice.Init();
129    _choice2.Init();
130    for (UInt32 posState = 0; posState < numPosStates; posState++)
131    {
132      _lowCoder[posState].Init();
133      _midCoder[posState].Init();
134    }
135    _highCoder.Init();
136  }
137  UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState)
138  {
139    if(_choice.Decode(rangeDecoder) == 0)
140      return _lowCoder[posState].Decode(rangeDecoder);
141    if(_choice2.Decode(rangeDecoder) == 0)
142      return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder);
143    return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder);
144  }
145};
146
147}
148
149class CDecoder:
150  public ICompressCoder,
151  public ICompressSetDecoderProperties2,
152  public ICompressGetInStreamProcessedSize,
153  #ifndef NO_READ_FROM_CODER
154  public ICompressSetInStream,
155  public ICompressSetOutStreamSize,
156  public ISequentialInStream,
157  #endif
158  public CMyUnknownImp
159{
160  CLZOutWindow _outWindowStream;
161  NRangeCoder::CDecoder _rangeDecoder;
162
163  CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax];
164  CMyBitDecoder _isRep[kNumStates];
165  CMyBitDecoder _isRepG0[kNumStates];
166  CMyBitDecoder _isRepG1[kNumStates];
167  CMyBitDecoder _isRepG2[kNumStates];
168  CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax];
169
170  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
171
172  CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex];
173  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder;
174
175  NLength::CDecoder _lenDecoder;
176  NLength::CDecoder _repMatchLenDecoder;
177
178  CLiteralDecoder _literalDecoder;
179
180  UInt32 _posStateMask;
181
182  ///////////////////
183  // State
184  UInt32 _reps[4];
185  CState _state;
186  Int32 _remainLen; // -1 means end of stream. // -2 means need Init
187  UInt64 _outSize;
188  bool _outSizeDefined;
189
190  void Init();
191  HRESULT CodeSpec(UInt32 size);
192public:
193
194  #ifndef NO_READ_FROM_CODER
195  MY_UNKNOWN_IMP5(
196      ICompressSetDecoderProperties2,
197      ICompressGetInStreamProcessedSize,
198      ICompressSetInStream,
199      ICompressSetOutStreamSize,
200      ISequentialInStream)
201  #else
202  MY_UNKNOWN_IMP2(
203      ICompressSetDecoderProperties2,
204      ICompressGetInStreamProcessedSize)
205  #endif
206
207  void ReleaseStreams()
208  {
209    _outWindowStream.ReleaseStream();
210    ReleaseInStream();
211  }
212
213  class CDecoderFlusher
214  {
215    CDecoder *_decoder;
216  public:
217    bool NeedFlush;
218    CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
219    ~CDecoderFlusher()
220    {
221      if (NeedFlush)
222        _decoder->Flush();
223      _decoder->ReleaseStreams();
224    }
225  };
226
227  HRESULT Flush() {  return _outWindowStream.Flush(); }
228
229  STDMETHOD(CodeReal)(ISequentialInStream *inStream,
230      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
231      ICompressProgressInfo *progress);
232
233  STDMETHOD(Code)(ISequentialInStream *inStream,
234      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
235      ICompressProgressInfo *progress);
236
237  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
238  STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize);
239
240  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
241
242  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
243  STDMETHOD(ReleaseInStream)();
244  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
245
246  #ifndef NO_READ_FROM_CODER
247  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
248  #endif
249
250  CDecoder(): _outSizeDefined(false) {}
251  virtual ~CDecoder() {}
252};
253
254}}
255
256#endif
257