1*f6dc9357SAndroid Build Coastguard Worker // LzmsDecoder.h 2*f6dc9357SAndroid Build Coastguard Worker // The code is based on LZMS description from wimlib code 3*f6dc9357SAndroid Build Coastguard Worker 4*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_LZMS_DECODER_H 5*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_LZMS_DECODER_H 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h" 8*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/HuffEnc.h" 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker #include "HuffmanDecoder.h" 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker namespace NCompress { 13*f6dc9357SAndroid Build Coastguard Worker namespace NLzms { 14*f6dc9357SAndroid Build Coastguard Worker 15*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumLitSyms = 256; 16*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumLenSyms = 54; 17*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumPosSyms = 799; 18*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumPowerSyms = 8; 19*f6dc9357SAndroid Build Coastguard Worker 20*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumProbBits = 6; 21*f6dc9357SAndroid Build Coastguard Worker const unsigned k_ProbLimit = 1 << k_NumProbBits; 22*f6dc9357SAndroid Build Coastguard Worker const unsigned k_InitialProb = 48; 23*f6dc9357SAndroid Build Coastguard Worker const UInt32 k_InitialHist = 0x55555555; 24*f6dc9357SAndroid Build Coastguard Worker 25*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumReps = 3; 26*f6dc9357SAndroid Build Coastguard Worker 27*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumMainProbs = 16; 28*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumMatchProbs = 32; 29*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumRepProbs = 64; 30*f6dc9357SAndroid Build Coastguard Worker 31*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumHuffmanBits = 15; 32*f6dc9357SAndroid Build Coastguard Worker 33*f6dc9357SAndroid Build Coastguard Worker template <UInt32 m_NumSyms, UInt32 m_RebuildFreq, unsigned numTableBits> 34*f6dc9357SAndroid Build Coastguard Worker class CHuffDecoder: public NCompress::NHuffman::CDecoder<k_NumHuffmanBits, m_NumSyms, numTableBits> 35*f6dc9357SAndroid Build Coastguard Worker { 36*f6dc9357SAndroid Build Coastguard Worker public: 37*f6dc9357SAndroid Build Coastguard Worker UInt32 RebuildRem; 38*f6dc9357SAndroid Build Coastguard Worker UInt32 NumSyms; 39*f6dc9357SAndroid Build Coastguard Worker UInt32 Freqs[m_NumSyms]; 40*f6dc9357SAndroid Build Coastguard Worker Generate()41*f6dc9357SAndroid Build Coastguard Worker void Generate() throw() 42*f6dc9357SAndroid Build Coastguard Worker { 43*f6dc9357SAndroid Build Coastguard Worker UInt32 vals[m_NumSyms]; 44*f6dc9357SAndroid Build Coastguard Worker Byte levels[m_NumSyms]; 45*f6dc9357SAndroid Build Coastguard Worker 46*f6dc9357SAndroid Build Coastguard Worker // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!! 47*f6dc9357SAndroid Build Coastguard Worker Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits); 48*f6dc9357SAndroid Build Coastguard Worker 49*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = NumSyms; i < m_NumSyms; i++) 50*f6dc9357SAndroid Build Coastguard Worker levels[i] = 0; 51*f6dc9357SAndroid Build Coastguard Worker 52*f6dc9357SAndroid Build Coastguard Worker this->Build(levels, /* NumSyms, */ NHuffman::k_BuildMode_Full); 53*f6dc9357SAndroid Build Coastguard Worker } 54*f6dc9357SAndroid Build Coastguard Worker Rebuild()55*f6dc9357SAndroid Build Coastguard Worker void Rebuild() throw() 56*f6dc9357SAndroid Build Coastguard Worker { 57*f6dc9357SAndroid Build Coastguard Worker Generate(); 58*f6dc9357SAndroid Build Coastguard Worker RebuildRem = m_RebuildFreq; 59*f6dc9357SAndroid Build Coastguard Worker const UInt32 num = NumSyms; 60*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < num; i++) 61*f6dc9357SAndroid Build Coastguard Worker Freqs[i] = (Freqs[i] >> 1) + 1; 62*f6dc9357SAndroid Build Coastguard Worker } 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker public: throw()65*f6dc9357SAndroid Build Coastguard Worker void Init(UInt32 numSyms = m_NumSyms) throw() 66*f6dc9357SAndroid Build Coastguard Worker { 67*f6dc9357SAndroid Build Coastguard Worker RebuildRem = m_RebuildFreq; 68*f6dc9357SAndroid Build Coastguard Worker NumSyms = numSyms; 69*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numSyms; i++) 70*f6dc9357SAndroid Build Coastguard Worker Freqs[i] = 1; 71*f6dc9357SAndroid Build Coastguard Worker // for (; i < m_NumSyms; i++) Freqs[i] = 0; 72*f6dc9357SAndroid Build Coastguard Worker Generate(); 73*f6dc9357SAndroid Build Coastguard Worker } 74*f6dc9357SAndroid Build Coastguard Worker }; 75*f6dc9357SAndroid Build Coastguard Worker 76*f6dc9357SAndroid Build Coastguard Worker 77*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry 78*f6dc9357SAndroid Build Coastguard Worker { 79*f6dc9357SAndroid Build Coastguard Worker UInt32 Prob; 80*f6dc9357SAndroid Build Coastguard Worker UInt64 Hist; 81*f6dc9357SAndroid Build Coastguard Worker InitCProbEntry82*f6dc9357SAndroid Build Coastguard Worker void Init() 83*f6dc9357SAndroid Build Coastguard Worker { 84*f6dc9357SAndroid Build Coastguard Worker Prob = k_InitialProb; 85*f6dc9357SAndroid Build Coastguard Worker Hist = k_InitialHist; 86*f6dc9357SAndroid Build Coastguard Worker } 87*f6dc9357SAndroid Build Coastguard Worker GetProbCProbEntry88*f6dc9357SAndroid Build Coastguard Worker UInt32 GetProb() const throw() 89*f6dc9357SAndroid Build Coastguard Worker { 90*f6dc9357SAndroid Build Coastguard Worker UInt32 prob = Prob; 91*f6dc9357SAndroid Build Coastguard Worker if (prob == 0) 92*f6dc9357SAndroid Build Coastguard Worker prob = 1; 93*f6dc9357SAndroid Build Coastguard Worker else if (prob == k_ProbLimit) 94*f6dc9357SAndroid Build Coastguard Worker prob = k_ProbLimit - 1; 95*f6dc9357SAndroid Build Coastguard Worker return prob; 96*f6dc9357SAndroid Build Coastguard Worker } 97*f6dc9357SAndroid Build Coastguard Worker UpdateCProbEntry98*f6dc9357SAndroid Build Coastguard Worker void Update(unsigned bit) throw() 99*f6dc9357SAndroid Build Coastguard Worker { 100*f6dc9357SAndroid Build Coastguard Worker Prob += (UInt32)((Int32)(Hist >> (k_ProbLimit - 1)) - (Int32)bit); 101*f6dc9357SAndroid Build Coastguard Worker Hist = (Hist << 1) | bit; 102*f6dc9357SAndroid Build Coastguard Worker } 103*f6dc9357SAndroid Build Coastguard Worker }; 104*f6dc9357SAndroid Build Coastguard Worker 105*f6dc9357SAndroid Build Coastguard Worker 106*f6dc9357SAndroid Build Coastguard Worker struct CRangeDecoder 107*f6dc9357SAndroid Build Coastguard Worker { 108*f6dc9357SAndroid Build Coastguard Worker UInt32 range; 109*f6dc9357SAndroid Build Coastguard Worker UInt32 code; 110*f6dc9357SAndroid Build Coastguard Worker const Byte *cur; 111*f6dc9357SAndroid Build Coastguard Worker // const Byte *end; 112*f6dc9357SAndroid Build Coastguard Worker InitCRangeDecoder113*f6dc9357SAndroid Build Coastguard Worker void Init(const Byte *data, size_t /* size */) throw() 114*f6dc9357SAndroid Build Coastguard Worker { 115*f6dc9357SAndroid Build Coastguard Worker range = 0xFFFFFFFF; 116*f6dc9357SAndroid Build Coastguard Worker code = (((UInt32)GetUi16(data)) << 16) | GetUi16(data + 2); 117*f6dc9357SAndroid Build Coastguard Worker cur = data + 4; 118*f6dc9357SAndroid Build Coastguard Worker // end = data + size; 119*f6dc9357SAndroid Build Coastguard Worker } 120*f6dc9357SAndroid Build Coastguard Worker NormalizeCRangeDecoder121*f6dc9357SAndroid Build Coastguard Worker void Normalize() 122*f6dc9357SAndroid Build Coastguard Worker { 123*f6dc9357SAndroid Build Coastguard Worker if (range <= 0xFFFF) 124*f6dc9357SAndroid Build Coastguard Worker { 125*f6dc9357SAndroid Build Coastguard Worker range <<= 16; 126*f6dc9357SAndroid Build Coastguard Worker code <<= 16; 127*f6dc9357SAndroid Build Coastguard Worker // if (cur >= end) throw 1; 128*f6dc9357SAndroid Build Coastguard Worker code |= GetUi16(cur); 129*f6dc9357SAndroid Build Coastguard Worker cur += 2; 130*f6dc9357SAndroid Build Coastguard Worker } 131*f6dc9357SAndroid Build Coastguard Worker } 132*f6dc9357SAndroid Build Coastguard Worker DecodeCRangeDecoder133*f6dc9357SAndroid Build Coastguard Worker unsigned Decode(UInt32 *state, UInt32 numStates, struct CProbEntry *probs) 134*f6dc9357SAndroid Build Coastguard Worker { 135*f6dc9357SAndroid Build Coastguard Worker UInt32 st = *state; 136*f6dc9357SAndroid Build Coastguard Worker CProbEntry *entry = &probs[st]; 137*f6dc9357SAndroid Build Coastguard Worker st = (st << 1) & (numStates - 1); 138*f6dc9357SAndroid Build Coastguard Worker 139*f6dc9357SAndroid Build Coastguard Worker const UInt32 prob = entry->GetProb(); 140*f6dc9357SAndroid Build Coastguard Worker 141*f6dc9357SAndroid Build Coastguard Worker if (range <= 0xFFFF) 142*f6dc9357SAndroid Build Coastguard Worker { 143*f6dc9357SAndroid Build Coastguard Worker range <<= 16; 144*f6dc9357SAndroid Build Coastguard Worker code <<= 16; 145*f6dc9357SAndroid Build Coastguard Worker // if (cur >= end) throw 1; 146*f6dc9357SAndroid Build Coastguard Worker code |= GetUi16(cur); 147*f6dc9357SAndroid Build Coastguard Worker cur += 2; 148*f6dc9357SAndroid Build Coastguard Worker } 149*f6dc9357SAndroid Build Coastguard Worker 150*f6dc9357SAndroid Build Coastguard Worker const UInt32 bound = (range >> k_NumProbBits) * prob; 151*f6dc9357SAndroid Build Coastguard Worker 152*f6dc9357SAndroid Build Coastguard Worker if (code < bound) 153*f6dc9357SAndroid Build Coastguard Worker { 154*f6dc9357SAndroid Build Coastguard Worker range = bound; 155*f6dc9357SAndroid Build Coastguard Worker *state = st; 156*f6dc9357SAndroid Build Coastguard Worker entry->Update(0); 157*f6dc9357SAndroid Build Coastguard Worker return 0; 158*f6dc9357SAndroid Build Coastguard Worker } 159*f6dc9357SAndroid Build Coastguard Worker else 160*f6dc9357SAndroid Build Coastguard Worker { 161*f6dc9357SAndroid Build Coastguard Worker range -= bound; 162*f6dc9357SAndroid Build Coastguard Worker code -= bound; 163*f6dc9357SAndroid Build Coastguard Worker *state = st | 1; 164*f6dc9357SAndroid Build Coastguard Worker entry->Update(1); 165*f6dc9357SAndroid Build Coastguard Worker return 1; 166*f6dc9357SAndroid Build Coastguard Worker } 167*f6dc9357SAndroid Build Coastguard Worker } 168*f6dc9357SAndroid Build Coastguard Worker }; 169*f6dc9357SAndroid Build Coastguard Worker 170*f6dc9357SAndroid Build Coastguard Worker 171*f6dc9357SAndroid Build Coastguard Worker class CDecoder 172*f6dc9357SAndroid Build Coastguard Worker { 173*f6dc9357SAndroid Build Coastguard Worker // CRangeDecoder _rc; 174*f6dc9357SAndroid Build Coastguard Worker size_t _pos; 175*f6dc9357SAndroid Build Coastguard Worker 176*f6dc9357SAndroid Build Coastguard Worker UInt32 _reps[k_NumReps + 1]; 177*f6dc9357SAndroid Build Coastguard Worker UInt64 _deltaReps[k_NumReps + 1]; 178*f6dc9357SAndroid Build Coastguard Worker 179*f6dc9357SAndroid Build Coastguard Worker UInt32 mainState; 180*f6dc9357SAndroid Build Coastguard Worker UInt32 matchState; 181*f6dc9357SAndroid Build Coastguard Worker UInt32 lzRepStates[k_NumReps]; 182*f6dc9357SAndroid Build Coastguard Worker UInt32 deltaRepStates[k_NumReps]; 183*f6dc9357SAndroid Build Coastguard Worker 184*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry mainProbs[k_NumMainProbs]; 185*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry matchProbs[k_NumMatchProbs]; 186*f6dc9357SAndroid Build Coastguard Worker 187*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry lzRepProbs[k_NumReps][k_NumRepProbs]; 188*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry deltaRepProbs[k_NumReps][k_NumRepProbs]; 189*f6dc9357SAndroid Build Coastguard Worker 190*f6dc9357SAndroid Build Coastguard Worker CHuffDecoder<k_NumLitSyms, 1024, 9> m_LitDecoder; 191*f6dc9357SAndroid Build Coastguard Worker CHuffDecoder<k_NumPosSyms, 1024, 9> m_PosDecoder; 192*f6dc9357SAndroid Build Coastguard Worker CHuffDecoder<k_NumLenSyms, 512, 8> m_LenDecoder; 193*f6dc9357SAndroid Build Coastguard Worker CHuffDecoder<k_NumPowerSyms, 512, 6> m_PowerDecoder; 194*f6dc9357SAndroid Build Coastguard Worker CHuffDecoder<k_NumPosSyms, 1024, 9> m_DeltaDecoder; 195*f6dc9357SAndroid Build Coastguard Worker 196*f6dc9357SAndroid Build Coastguard Worker Int32 *_x86_history; 197*f6dc9357SAndroid Build Coastguard Worker 198*f6dc9357SAndroid Build Coastguard Worker HRESULT CodeReal(const Byte *in, size_t inSize, Byte *out, size_t outSize); 199*f6dc9357SAndroid Build Coastguard Worker public: 200*f6dc9357SAndroid Build Coastguard Worker CDecoder(); 201*f6dc9357SAndroid Build Coastguard Worker ~CDecoder(); 202*f6dc9357SAndroid Build Coastguard Worker 203*f6dc9357SAndroid Build Coastguard Worker HRESULT Code(const Byte *in, size_t inSize, Byte *out, size_t outSize); GetUnpackSize()204*f6dc9357SAndroid Build Coastguard Worker size_t GetUnpackSize() const { return _pos; } 205*f6dc9357SAndroid Build Coastguard Worker }; 206*f6dc9357SAndroid Build Coastguard Worker 207*f6dc9357SAndroid Build Coastguard Worker }} 208*f6dc9357SAndroid Build Coastguard Worker 209*f6dc9357SAndroid Build Coastguard Worker #endif 210