view src/win32/7zip/7z/CPP/7zip/Compress/Rar3Decoder.h @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 // Rar3Decoder.h
2 // According to unRAR license, this code may not be used to develop
3 // a program that creates RAR archives
5 #ifndef __COMPRESS_RAR3_DECODER_H
6 #define __COMPRESS_RAR3_DECODER_H
8 #include "../../Common/MyCom.h"
10 #include "../ICoder.h"
12 #include "../Common/InBuffer.h"
14 #include "BitmDecoder.h"
15 #include "HuffmanDecoder.h"
16 #include "PpmdDecode.h"
17 #include "Rar3Vm.h"
19 namespace NCompress {
20 namespace NRar3 {
22 const UInt32 kWindowSize = 1 << 22;
23 const UInt32 kWindowMask = (kWindowSize - 1);
25 const UInt32 kNumReps = 4;
26 const UInt32 kNumLen2Symbols = 8;
27 const UInt32 kLenTableSize = 28;
28 const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize;
29 const UInt32 kDistTableSize = 60;
31 const int kNumAlignBits = 4;
32 const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1;
34 const UInt32 kLevelTableSize = 20;
36 const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
38 class CBitDecoder
39 {
40 UInt32 m_Value;
41 public:
42 UInt32 m_BitPos;
43 CInBuffer m_Stream;
44 bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
45 void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}
46 void ReleaseStream() { m_Stream.ReleaseStream();}
48 void Init()
49 {
50 m_Stream.Init();
51 m_BitPos = 0;
52 m_Value = 0;
53 // m_BitPos = kNumBigValueBits;
54 // Normalize();
55 }
57 UInt64 GetProcessedSize() const
58 { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }
59 UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); }
61 /*
62 void Normalize()
63 {
64 for (;m_BitPos >= 8; m_BitPos -= 8)
65 m_Value = (m_Value << 8) | m_Stream.ReadByte();
66 }
67 */
69 UInt32 GetValue(UInt32 numBits)
70 {
71 // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits);
72 // return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits);
73 if (m_BitPos < numBits)
74 {
75 m_BitPos += 8;
76 m_Value = (m_Value << 8) | m_Stream.ReadByte();
77 if (m_BitPos < numBits)
78 {
79 m_BitPos += 8;
80 m_Value = (m_Value << 8) | m_Stream.ReadByte();
81 }
82 }
83 return m_Value >> (m_BitPos - numBits);
84 }
86 void MovePos(UInt32 numBits)
87 {
88 m_BitPos -= numBits;
89 m_Value = m_Value & ((1 << m_BitPos) - 1);
90 }
92 UInt32 ReadBits(UInt32 numBits)
93 {
94 UInt32 res = GetValue(numBits);
95 MovePos(numBits);
96 return res;
97 }
98 };
100 const int kNumTopBits = 24;
101 const UInt32 kTopValue = (1 << kNumTopBits);
102 const UInt32 kBot = (1 << 15);
104 class CRangeDecoder:public NPpmd::CRangeDecoderVirt, public CBitDecoder
105 {
106 public:
107 UInt32 Range;
108 UInt32 Low;
109 UInt32 Code;
111 void Normalize()
112 {
113 while ((Low ^ (Low + Range)) < kTopValue ||
114 Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
115 {
116 Code = (Code << 8) | m_Stream.ReadByte();
117 Range <<= 8;
118 Low <<= 8;
119 }
120 }
122 void InitRangeCoder()
123 {
124 Code = 0;
125 Low = 0;
126 Range = 0xFFFFFFFF;
127 for(int i = 0; i < 4; i++)
128 Code = (Code << 8) | ReadBits(8);
129 }
131 virtual UInt32 GetThreshold(UInt32 total)
132 {
133 return (Code - Low) / ( Range /= total);
134 }
136 virtual void Decode(UInt32 start, UInt32 size)
137 {
138 Low += start * Range;
139 Range *= size;
140 Normalize();
141 }
143 virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
144 {
145 if (((Code - Low) / (Range >>= numTotalBits)) < size0)
146 {
147 Decode(0, size0);
148 return 0;
149 }
150 else
151 {
152 Decode(size0, (1 << numTotalBits) - size0);
153 return 1;
154 }
155 }
157 // UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); }
158 };
161 struct CFilter: public NVm::CProgram
162 {
163 CRecordVector<Byte> GlobalData;
164 UInt32 BlockStart;
165 UInt32 BlockSize;
166 UInt32 ExecCount;
167 CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}
168 };
170 struct CTempFilter: public NVm::CProgramInitState
171 {
172 UInt32 BlockStart;
173 UInt32 BlockSize;
174 UInt32 ExecCount;
175 bool NextWindow;
177 UInt32 FilterIndex;
178 };
180 const int kNumHuffmanBits = 15;
182 class CDecoder:
183 public ICompressCoder,
184 public ICompressSetDecoderProperties2,
185 public CMyUnknownImp
186 {
187 CRangeDecoder m_InBitStream;
188 Byte *_window;
189 UInt32 _winPos;
190 UInt32 _wrPtr;
191 UInt64 _lzSize;
192 UInt64 _unpackSize;
193 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
194 CMyComPtr<ISequentialOutStream> _outStream;
195 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
196 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
197 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
198 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
199 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
201 UInt32 _reps[kNumReps];
202 UInt32 _lastLength;
204 Byte m_LastLevels[kTablesSizesSum];
206 Byte *_vmData;
207 Byte *_vmCode;
208 NVm::CVm _vm;
209 CRecordVector<CFilter *> _filters;
210 CRecordVector<CTempFilter *> _tempFilters;
211 UInt32 _lastFilter;
213 bool m_IsSolid;
215 bool _lzMode;
217 UInt32 PrevAlignBits;
218 UInt32 PrevAlignCount;
220 bool TablesRead;
222 NPpmd::CDecodeInfo _ppm;
223 int PpmEscChar;
225 HRESULT WriteDataToStream(const Byte *data, UInt32 size);
226 HRESULT WriteData(const Byte *data, UInt32 size);
227 HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
228 void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef);
229 HRESULT WriteBuf();
231 void InitFilters();
232 bool AddVmCode(UInt32 firstByte, UInt32 codeSize);
233 bool ReadVmCodeLZ();
234 bool ReadVmCodePPM();
236 UInt32 ReadBits(int numBits);
238 HRESULT InitPPM();
239 int DecodePpmSymbol();
240 HRESULT DecodePPM(Int32 num, bool &keepDecompressing);
242 HRESULT ReadTables(bool &keepDecompressing);
243 HRESULT ReadEndOfBlock(bool &keepDecompressing);
244 HRESULT DecodeLZ(bool &keepDecompressing);
245 HRESULT CodeReal(ICompressProgressInfo *progress);
246 public:
247 CDecoder();
248 ~CDecoder();
250 MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
252 void ReleaseStreams()
253 {
254 _outStream.Release();
255 m_InBitStream.ReleaseStream();
256 }
258 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
259 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
261 STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
263 void CopyBlock(UInt32 distance, UInt32 len)
264 {
265 _lzSize += len;
266 UInt32 pos = (_winPos - distance - 1) & kWindowMask;
267 Byte *window = _window;
268 UInt32 winPos = _winPos;
269 if (kWindowSize - winPos > len && kWindowSize - pos > len)
270 {
271 const Byte *src = window + pos;
272 Byte *dest = window + winPos;
273 _winPos += len;
274 do
275 *dest++ = *src++;
276 while(--len != 0);
277 return;
278 }
279 do
280 {
281 window[winPos] = window[pos];
282 winPos = (winPos + 1) & kWindowMask;
283 pos = (pos + 1) & kWindowMask;
284 }
285 while(--len != 0);
286 _winPos = winPos;
287 }
289 void PutByte(Byte b)
290 {
291 _window[_winPos] = b;
292 _winPos = (_winPos + 1) & kWindowMask;
293 _lzSize++;
294 }
297 };
299 }}
301 #endif