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