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