1*f6dc9357SAndroid Build Coastguard Worker // Compress/HuffmanDecoder.h 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h" 7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyTypes.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker namespace NCompress { 10*f6dc9357SAndroid Build Coastguard Worker namespace NHuffman { 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker // const unsigned kNumTableBits_Default = 9; 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker #if 0 || 0 && defined(MY_CPU_64BIT) 15*f6dc9357SAndroid Build Coastguard Worker // for debug or optimization: 16*f6dc9357SAndroid Build Coastguard Worker // 64-BIT limit array can be faster for some compilers. 17*f6dc9357SAndroid Build Coastguard Worker // for debug or optimization: 18*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_USE_64BIT_LIMIT 19*f6dc9357SAndroid Build Coastguard Worker #else 20*f6dc9357SAndroid Build Coastguard Worker // sizet value variable allows to eliminate some move operation in some compilers. 21*f6dc9357SAndroid Build Coastguard Worker // for debug or optimization: 22*f6dc9357SAndroid Build Coastguard Worker // #define Z7_HUFF_USE_SIZET_VALUE 23*f6dc9357SAndroid Build Coastguard Worker #endif 24*f6dc9357SAndroid Build Coastguard Worker 25*f6dc9357SAndroid Build Coastguard Worker // v0 must normalized to (32 bits) : (v0 < ((UInt64)1 << 32)) 26*f6dc9357SAndroid Build Coastguard Worker 27*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_HUFF_USE_64BIT_LIMIT 28*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CLimitInt; 29*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CValueInt; 30*f6dc9357SAndroid Build Coastguard Worker // all _limits[*] are normalized and limited by ((UInt64)1 << 32). 31*f6dc9357SAndroid Build Coastguard Worker // we don't use (v1) in this branch 32*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) 32 33*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \ 34*f6dc9357SAndroid Build Coastguard Worker ((NCompress::NHuffman::CLimitInt)v0 >= (huf)->_limits[0]) 35*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits) (v0) 36*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits) ((v0) >> (32 - kNumTableBits)) 37*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1) 38*f6dc9357SAndroid Build Coastguard Worker #else 39*f6dc9357SAndroid Build Coastguard Worker typedef UInt32 CLimitInt; 40*f6dc9357SAndroid Build Coastguard Worker typedef 41*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_HUFF_USE_SIZET_VALUE 42*f6dc9357SAndroid Build Coastguard Worker size_t 43*f6dc9357SAndroid Build Coastguard Worker #else 44*f6dc9357SAndroid Build Coastguard Worker UInt32 45*f6dc9357SAndroid Build Coastguard Worker #endif 46*f6dc9357SAndroid Build Coastguard Worker CValueInt; 47*f6dc9357SAndroid Build Coastguard Worker // v1 must be precalculated from v0 in this branch 48*f6dc9357SAndroid Build Coastguard Worker // _limits[0] and (v1) are normalized and limited by (1 << kNumTableBits). 49*f6dc9357SAndroid Build Coastguard Worker // _limits[non_0] are normalized and limited by (1 << kNumBitsMax). 50*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) (kNumBitsMax) 51*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \ 52*f6dc9357SAndroid Build Coastguard Worker ((NCompress::NHuffman::CLimitInt)v1 >= (huf)->_limits[0]) 53*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits) ((v0) >> (32 - kNumBitsMax)) 54*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits) (v1) 55*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1) const UInt32 v1 = ((v0) >> (32 - kNumTableBits)); 56*f6dc9357SAndroid Build Coastguard Worker #endif 57*f6dc9357SAndroid Build Coastguard Worker 58*f6dc9357SAndroid Build Coastguard Worker 59*f6dc9357SAndroid Build Coastguard Worker enum enum_BuildMode 60*f6dc9357SAndroid Build Coastguard Worker { 61*f6dc9357SAndroid Build Coastguard Worker k_BuildMode_Partial = 0, 62*f6dc9357SAndroid Build Coastguard Worker k_BuildMode_Full = 1, 63*f6dc9357SAndroid Build Coastguard Worker k_BuildMode_Full_or_Empty = 2 64*f6dc9357SAndroid Build Coastguard Worker }; 65*f6dc9357SAndroid Build Coastguard Worker 66*f6dc9357SAndroid Build Coastguard Worker 67*f6dc9357SAndroid Build Coastguard Worker template <class symType, class symType2, class symType4, unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */> 68*f6dc9357SAndroid Build Coastguard Worker struct CDecoderBase 69*f6dc9357SAndroid Build Coastguard Worker { 70*f6dc9357SAndroid Build Coastguard Worker CLimitInt _limits[kNumBitsMax + 2 - kNumTableBits]; 71*f6dc9357SAndroid Build Coastguard Worker UInt32 _poses[kNumBitsMax - kNumTableBits]; // unsigned 72*f6dc9357SAndroid Build Coastguard Worker union 73*f6dc9357SAndroid Build Coastguard Worker { 74*f6dc9357SAndroid Build Coastguard Worker // if defined(MY_CPU_64BIT), we need 64-bit alignment for _symbols. 75*f6dc9357SAndroid Build Coastguard Worker // if !defined(MY_CPU_64BIT), we need 32-bit alignment for _symbols 76*f6dc9357SAndroid Build Coastguard Worker // but we provide alignment for _lens. 77*f6dc9357SAndroid Build Coastguard Worker // _symbols also will be aligned, if _lens are aligned 78*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_64BIT) 79*f6dc9357SAndroid Build Coastguard Worker UInt64 80*f6dc9357SAndroid Build Coastguard Worker #else 81*f6dc9357SAndroid Build Coastguard Worker UInt32 82*f6dc9357SAndroid Build Coastguard Worker #endif 83*f6dc9357SAndroid Build Coastguard Worker _pad_align[m_NumSymbols < (1u << sizeof(symType) * 8) ? 1 : -1]; 84*f6dc9357SAndroid Build Coastguard Worker /* if symType is Byte, we use 16-bytes padding to avoid cache 85*f6dc9357SAndroid Build Coastguard Worker bank conflict between _lens and _symbols: */ 86*f6dc9357SAndroid Build Coastguard Worker Byte _lens[(1 << kNumTableBits) + (sizeof(symType) == 1 ? 16 : 0)]; 87*f6dc9357SAndroid Build Coastguard Worker } _u; 88*f6dc9357SAndroid Build Coastguard Worker symType _symbols[(1 << kNumTableBits) + m_NumSymbols - (kNumTableBits + 1)]; 89*f6dc9357SAndroid Build Coastguard Worker 90*f6dc9357SAndroid Build Coastguard Worker /* 91*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE 92*f6dc9357SAndroid Build Coastguard Worker bool IsFull() const 93*f6dc9357SAndroid Build Coastguard Worker { 94*f6dc9357SAndroid Build Coastguard Worker return _limits[kNumBitsMax - kNumTableBits] == 95*f6dc9357SAndroid Build Coastguard Worker (CLimitInt)1u << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax); 96*f6dc9357SAndroid Build Coastguard Worker } 97*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE 98*f6dc9357SAndroid Build Coastguard Worker bool IsEmpty() const 99*f6dc9357SAndroid Build Coastguard Worker { 100*f6dc9357SAndroid Build Coastguard Worker return _limits[kNumBitsMax - kNumTableBits] == 0; 101*f6dc9357SAndroid Build Coastguard Worker } 102*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE 103*f6dc9357SAndroid Build Coastguard Worker bool Is_Full_or_Empty() const 104*f6dc9357SAndroid Build Coastguard Worker { 105*f6dc9357SAndroid Build Coastguard Worker return 0 == (_limits[kNumBitsMax - kNumTableBits] & 106*f6dc9357SAndroid Build Coastguard Worker ~((CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax))); 107*f6dc9357SAndroid Build Coastguard Worker } 108*f6dc9357SAndroid Build Coastguard Worker */ 109*f6dc9357SAndroid Build Coastguard Worker 110*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE throwCDecoderBase111*f6dc9357SAndroid Build Coastguard Worker bool Build(const Byte *lens, enum_BuildMode buidMode = k_BuildMode_Partial) throw() 112*f6dc9357SAndroid Build Coastguard Worker { 113*f6dc9357SAndroid Build Coastguard Worker unsigned counts[kNumBitsMax + 1]; 114*f6dc9357SAndroid Build Coastguard Worker size_t i; 115*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i <= kNumBitsMax; i++) 116*f6dc9357SAndroid Build Coastguard Worker counts[i] = 0; 117*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < m_NumSymbols; i++) 118*f6dc9357SAndroid Build Coastguard Worker counts[lens[i]]++; 119*f6dc9357SAndroid Build Coastguard Worker 120*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = 0; 121*f6dc9357SAndroid Build Coastguard Worker for (i = 1; i <= kNumTableBits; i++) 122*f6dc9357SAndroid Build Coastguard Worker { 123*f6dc9357SAndroid Build Coastguard Worker sum <<= 1; 124*f6dc9357SAndroid Build Coastguard Worker sum += counts[i]; 125*f6dc9357SAndroid Build Coastguard Worker } 126*f6dc9357SAndroid Build Coastguard Worker 127*f6dc9357SAndroid Build Coastguard Worker CLimitInt startPos = (CLimitInt)sum; 128*f6dc9357SAndroid Build Coastguard Worker _limits[0] = 129*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_HUFF_USE_64BIT_LIMIT 130*f6dc9357SAndroid Build Coastguard Worker startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - kNumTableBits); 131*f6dc9357SAndroid Build Coastguard Worker #else 132*f6dc9357SAndroid Build Coastguard Worker startPos; 133*f6dc9357SAndroid Build Coastguard Worker #endif 134*f6dc9357SAndroid Build Coastguard Worker 135*f6dc9357SAndroid Build Coastguard Worker for (i = kNumTableBits + 1; i <= kNumBitsMax; i++) 136*f6dc9357SAndroid Build Coastguard Worker { 137*f6dc9357SAndroid Build Coastguard Worker startPos <<= 1; 138*f6dc9357SAndroid Build Coastguard Worker _poses[i - (kNumTableBits + 1)] = (UInt32)(startPos - sum); 139*f6dc9357SAndroid Build Coastguard Worker const unsigned cnt = counts[i]; 140*f6dc9357SAndroid Build Coastguard Worker counts[i] = sum; 141*f6dc9357SAndroid Build Coastguard Worker sum += cnt; 142*f6dc9357SAndroid Build Coastguard Worker startPos += cnt; 143*f6dc9357SAndroid Build Coastguard Worker _limits[i - kNumTableBits] = startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - i); 144*f6dc9357SAndroid Build Coastguard Worker } 145*f6dc9357SAndroid Build Coastguard Worker 146*f6dc9357SAndroid Build Coastguard Worker _limits[kNumBitsMax + 1 - kNumTableBits] = 147*f6dc9357SAndroid Build Coastguard Worker (CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax); 148*f6dc9357SAndroid Build Coastguard Worker 149*f6dc9357SAndroid Build Coastguard Worker if (buidMode == k_BuildMode_Partial) 150*f6dc9357SAndroid Build Coastguard Worker { 151*f6dc9357SAndroid Build Coastguard Worker if (startPos > (1u << kNumBitsMax)) return false; 152*f6dc9357SAndroid Build Coastguard Worker } 153*f6dc9357SAndroid Build Coastguard Worker else 154*f6dc9357SAndroid Build Coastguard Worker { 155*f6dc9357SAndroid Build Coastguard Worker if (buidMode != k_BuildMode_Full && startPos == 0) return true; 156*f6dc9357SAndroid Build Coastguard Worker if (startPos != (1u << kNumBitsMax)) return false; 157*f6dc9357SAndroid Build Coastguard Worker } 158*f6dc9357SAndroid Build Coastguard Worker size_t sum2 = 0; 159*f6dc9357SAndroid Build Coastguard Worker for (i = 1; i <= kNumTableBits; i++) 160*f6dc9357SAndroid Build Coastguard Worker { 161*f6dc9357SAndroid Build Coastguard Worker const unsigned cnt = counts[i] << (kNumTableBits - i); 162*f6dc9357SAndroid Build Coastguard Worker counts[i] = (unsigned)sum2 >> (kNumTableBits - i); 163*f6dc9357SAndroid Build Coastguard Worker memset(_u._lens + sum2, (int)i, cnt); 164*f6dc9357SAndroid Build Coastguard Worker sum2 += cnt; 165*f6dc9357SAndroid Build Coastguard Worker } 166*f6dc9357SAndroid Build Coastguard Worker 167*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT 168*f6dc9357SAndroid Build Coastguard Worker symType4 169*f6dc9357SAndroid Build Coastguard Worker // UInt64 // for symType = UInt16 170*f6dc9357SAndroid Build Coastguard Worker // UInt32 // for symType = Byte 171*f6dc9357SAndroid Build Coastguard Worker #else 172*f6dc9357SAndroid Build Coastguard Worker UInt32 173*f6dc9357SAndroid Build Coastguard Worker #endif 174*f6dc9357SAndroid Build Coastguard Worker v = 0; 175*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < m_NumSymbols; i++, 176*f6dc9357SAndroid Build Coastguard Worker v += 177*f6dc9357SAndroid Build Coastguard Worker 1 178*f6dc9357SAndroid Build Coastguard Worker + ( (UInt32)1 << (sizeof(symType) * 8 * 1)) 179*f6dc9357SAndroid Build Coastguard Worker // 0x00010001 // for symType = UInt16 180*f6dc9357SAndroid Build Coastguard Worker // 0x00000101 // for symType = Byte 181*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT 182*f6dc9357SAndroid Build Coastguard Worker + ((symType4)1 << (sizeof(symType) * 8 * 2)) 183*f6dc9357SAndroid Build Coastguard Worker + ((symType4)1 << (sizeof(symType) * 8 * 3)) 184*f6dc9357SAndroid Build Coastguard Worker // 0x0001000100010001 // for symType = UInt16 185*f6dc9357SAndroid Build Coastguard Worker // 0x0000000001010101 // for symType = Byte 186*f6dc9357SAndroid Build Coastguard Worker #endif 187*f6dc9357SAndroid Build Coastguard Worker ) 188*f6dc9357SAndroid Build Coastguard Worker { 189*f6dc9357SAndroid Build Coastguard Worker const unsigned len = lens[i]; 190*f6dc9357SAndroid Build Coastguard Worker if (len == 0) 191*f6dc9357SAndroid Build Coastguard Worker continue; 192*f6dc9357SAndroid Build Coastguard Worker const size_t offset = counts[len]; 193*f6dc9357SAndroid Build Coastguard Worker counts[len] = (unsigned)offset + 1; 194*f6dc9357SAndroid Build Coastguard Worker if (len >= kNumTableBits) 195*f6dc9357SAndroid Build Coastguard Worker _symbols[offset] = (symType)v; 196*f6dc9357SAndroid Build Coastguard Worker else 197*f6dc9357SAndroid Build Coastguard Worker { 198*f6dc9357SAndroid Build Coastguard Worker Byte *s2 = (Byte *)(void *)_symbols + (offset << 199*f6dc9357SAndroid Build Coastguard Worker (kNumTableBits + sizeof(symType) / 2 - len)); 200*f6dc9357SAndroid Build Coastguard Worker Byte *lim = s2 + ((size_t)1 << 201*f6dc9357SAndroid Build Coastguard Worker (kNumTableBits + sizeof(symType) / 2 - len)); 202*f6dc9357SAndroid Build Coastguard Worker if (len >= kNumTableBits - 2) 203*f6dc9357SAndroid Build Coastguard Worker { 204*f6dc9357SAndroid Build Coastguard Worker *(symType2 *)(void *)(s2 ) = (symType2)v; 205*f6dc9357SAndroid Build Coastguard Worker *(symType2 *)(void *)(lim - sizeof(symType) * 2) = (symType2)v; 206*f6dc9357SAndroid Build Coastguard Worker } 207*f6dc9357SAndroid Build Coastguard Worker else 208*f6dc9357SAndroid Build Coastguard Worker { 209*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT 210*f6dc9357SAndroid Build Coastguard Worker symType4 *s = (symType4 *)(void *)s2; 211*f6dc9357SAndroid Build Coastguard Worker do 212*f6dc9357SAndroid Build Coastguard Worker { 213*f6dc9357SAndroid Build Coastguard Worker s[0] = v; s[1] = v; s += 2; 214*f6dc9357SAndroid Build Coastguard Worker } 215*f6dc9357SAndroid Build Coastguard Worker while (s != (const symType4 *)(const void *)lim); 216*f6dc9357SAndroid Build Coastguard Worker #else 217*f6dc9357SAndroid Build Coastguard Worker symType2 *s = (symType2 *)(void *)s2; 218*f6dc9357SAndroid Build Coastguard Worker do 219*f6dc9357SAndroid Build Coastguard Worker { 220*f6dc9357SAndroid Build Coastguard Worker s[0] = (symType2)v; s[1] = (symType2)v; s += 2; 221*f6dc9357SAndroid Build Coastguard Worker s[0] = (symType2)v; s[1] = (symType2)v; s += 2; 222*f6dc9357SAndroid Build Coastguard Worker } 223*f6dc9357SAndroid Build Coastguard Worker while (s != (const symType2 *)(const void *)lim); 224*f6dc9357SAndroid Build Coastguard Worker #endif 225*f6dc9357SAndroid Build Coastguard Worker } 226*f6dc9357SAndroid Build Coastguard Worker } 227*f6dc9357SAndroid Build Coastguard Worker } 228*f6dc9357SAndroid Build Coastguard Worker return true; 229*f6dc9357SAndroid Build Coastguard Worker } 230*f6dc9357SAndroid Build Coastguard Worker 231*f6dc9357SAndroid Build Coastguard Worker 232*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES(_numBits_, kNumBitsMax, error_op) if (_numBits_ > kNumBitsMax) { error_op } 233*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO( _numBits_, kNumBitsMax, error_op) 234*f6dc9357SAndroid Build Coastguard Worker 235*f6dc9357SAndroid Build Coastguard Worker 236*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits, \ 237*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 238*f6dc9357SAndroid Build Coastguard Worker get_val_for_limits, \ 239*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, _numBits_) \ 240*f6dc9357SAndroid Build Coastguard Worker { \ 241*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \ 242*f6dc9357SAndroid Build Coastguard Worker _numBits_ = kNumTableBits + 1; \ 243*f6dc9357SAndroid Build Coastguard Worker if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \ 244*f6dc9357SAndroid Build Coastguard Worker do { _numBits_++; } \ 245*f6dc9357SAndroid Build Coastguard Worker while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \ 246*f6dc9357SAndroid Build Coastguard Worker check_op(_numBits_, kNumBitsMax, error_op) \ 247*f6dc9357SAndroid Build Coastguard Worker sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \ 248*f6dc9357SAndroid Build Coastguard Worker - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \ 249*f6dc9357SAndroid Build Coastguard Worker } 250*f6dc9357SAndroid Build Coastguard Worker 251*f6dc9357SAndroid Build Coastguard Worker /* 252*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits, \ 253*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 254*f6dc9357SAndroid Build Coastguard Worker get_val_for_limits, \ 255*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, _numBits_) \ 256*f6dc9357SAndroid Build Coastguard Worker 257*f6dc9357SAndroid Build Coastguard Worker */ 258*f6dc9357SAndroid Build Coastguard Worker 259*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \ 260*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 261*f6dc9357SAndroid Build Coastguard Worker get_val_for_table, get_val_for_limits, \ 262*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, after_op, bs) \ 263*f6dc9357SAndroid Build Coastguard Worker { \ 264*f6dc9357SAndroid Build Coastguard Worker if (Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1)) \ 265*f6dc9357SAndroid Build Coastguard Worker { \ 266*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \ 267*f6dc9357SAndroid Build Coastguard Worker size_t _numBits_ = kNumTableBits + 1; \ 268*f6dc9357SAndroid Build Coastguard Worker if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \ 269*f6dc9357SAndroid Build Coastguard Worker do { _numBits_++; } \ 270*f6dc9357SAndroid Build Coastguard Worker while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \ 271*f6dc9357SAndroid Build Coastguard Worker check_op(_numBits_, kNumBitsMax, error_op) \ 272*f6dc9357SAndroid Build Coastguard Worker sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \ 273*f6dc9357SAndroid Build Coastguard Worker - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \ 274*f6dc9357SAndroid Build Coastguard Worker move_pos_op(bs, _numBits_); \ 275*f6dc9357SAndroid Build Coastguard Worker } \ 276*f6dc9357SAndroid Build Coastguard Worker else \ 277*f6dc9357SAndroid Build Coastguard Worker { \ 278*f6dc9357SAndroid Build Coastguard Worker const size_t _val = get_val_for_table(v0, v1, kNumBitsMax, kNumTableBits); \ 279*f6dc9357SAndroid Build Coastguard Worker const size_t _numBits_ = (huf)->_u._lens[_val]; \ 280*f6dc9357SAndroid Build Coastguard Worker sym = (huf)->_symbols[_val]; \ 281*f6dc9357SAndroid Build Coastguard Worker move_pos_op(bs, _numBits_); \ 282*f6dc9357SAndroid Build Coastguard Worker } \ 283*f6dc9357SAndroid Build Coastguard Worker after_op \ 284*f6dc9357SAndroid Build Coastguard Worker } 285*f6dc9357SAndroid Build Coastguard Worker 286*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits, \ 287*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 288*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, after_op, bs) \ 289*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \ 290*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 291*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_TABLE, \ 292*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_LIMITS, \ 293*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, after_op, bs) \ 294*f6dc9357SAndroid Build Coastguard Worker 295*f6dc9357SAndroid Build Coastguard Worker 296*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huf, kNumBitsMax, kNumTableBits, \ 297*f6dc9357SAndroid Build Coastguard Worker v0, \ 298*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, after_op, bs) \ 299*f6dc9357SAndroid Build Coastguard Worker { \ 300*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_PRECALC_V1(kNumTableBits, v0, _v1_temp) \ 301*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits, \ 302*f6dc9357SAndroid Build Coastguard Worker v0, _v1_temp, \ 303*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, after_op, bs) \ 304*f6dc9357SAndroid Build Coastguard Worker } 305*f6dc9357SAndroid Build Coastguard Worker 306*f6dc9357SAndroid Build Coastguard Worker #if 0 || defined(Z7_HUFF_USE_64BIT_LIMIT) 307*f6dc9357SAndroid Build Coastguard Worker // this branch uses bitStream->GetValue_InHigh32bits(). 308*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, \ 309*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op) \ 310*f6dc9357SAndroid Build Coastguard Worker { \ 311*f6dc9357SAndroid Build Coastguard Worker const UInt32 v0 = (bitStream)->GetValue_InHigh32bits(); \ 312*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1); \ 313*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \ 314*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 315*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_TABLE, \ 316*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_LIMITS, \ 317*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, {}, bitStream) \ 318*f6dc9357SAndroid Build Coastguard Worker } 319*f6dc9357SAndroid Build Coastguard Worker #else 320*f6dc9357SAndroid Build Coastguard Worker /* 321*f6dc9357SAndroid Build Coastguard Worker this branch uses bitStream->GetValue(). 322*f6dc9357SAndroid Build Coastguard Worker So we use SIMPLE versions for v0, v1 calculation: 323*f6dc9357SAndroid Build Coastguard Worker v0 is normalized for kNumBitsMax 324*f6dc9357SAndroid Build Coastguard Worker v1 is normalized for kNumTableBits 325*f6dc9357SAndroid Build Coastguard Worker */ 326*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE(v0, v1, kNumBitsMax, kNumTableBits) v0 327*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE( v0, v1, kNumBitsMax, kNumTableBits) v1 328*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, move_pos_op) \ 329*f6dc9357SAndroid Build Coastguard Worker { \ 330*f6dc9357SAndroid Build Coastguard Worker const UInt32 v0 = (bitStream)->GetValue(kNumBitsMax); \ 331*f6dc9357SAndroid Build Coastguard Worker const UInt32 v1 = v0 >> (kNumBitsMax - kNumTableBits); \ 332*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \ 333*f6dc9357SAndroid Build Coastguard Worker v0, v1, \ 334*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE, \ 335*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE, \ 336*f6dc9357SAndroid Build Coastguard Worker check_op, error_op, move_pos_op, {}, bitStream) \ 337*f6dc9357SAndroid Build Coastguard Worker } 338*f6dc9357SAndroid Build Coastguard Worker #endif 339*f6dc9357SAndroid Build Coastguard Worker 340*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_bitStream_MovePos(bitStream, numBits) (bitStream)->MovePos((unsigned)(numBits)) 341*f6dc9357SAndroid Build Coastguard Worker 342*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_1(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \ 343*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \ 344*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_bitStream_MovePos) 345*f6dc9357SAndroid Build Coastguard Worker 346*f6dc9357SAndroid Build Coastguard Worker // MovePosCheck 347*f6dc9357SAndroid Build Coastguard Worker 348*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_2(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \ 349*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \ 350*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_bitStream_MovePos) 351*f6dc9357SAndroid Build Coastguard Worker 352*f6dc9357SAndroid Build Coastguard Worker // MovePosCheck 353*f6dc9357SAndroid Build Coastguard Worker 354*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODE_CHECK(sym, huf, kNumBitsMax, kNumTableBits, bitStream, error_op) \ 355*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_1( sym, huf, kNumBitsMax, kNumTableBits, bitStream, \ 356*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, error_op) 357*f6dc9357SAndroid Build Coastguard Worker 358*f6dc9357SAndroid Build Coastguard Worker template <class TBitDecoder> 359*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE Decode2CDecoderBase360*f6dc9357SAndroid Build Coastguard Worker bool Decode2(TBitDecoder *bitStream, unsigned &sym) const 361*f6dc9357SAndroid Build Coastguard Worker { 362*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream, 363*f6dc9357SAndroid Build Coastguard Worker { return false; } 364*f6dc9357SAndroid Build Coastguard Worker ) 365*f6dc9357SAndroid Build Coastguard Worker return true; 366*f6dc9357SAndroid Build Coastguard Worker } 367*f6dc9357SAndroid Build Coastguard Worker 368*f6dc9357SAndroid Build Coastguard Worker template <class TBitDecoder> 369*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE Decode_SymCheck_MovePosCheckCDecoderBase370*f6dc9357SAndroid Build Coastguard Worker bool Decode_SymCheck_MovePosCheck(TBitDecoder *bitStream, unsigned &sym) const 371*f6dc9357SAndroid Build Coastguard Worker { 372*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_0(sym, this, kNumBitsMax, kNumTableBits, bitStream, 373*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, 374*f6dc9357SAndroid Build Coastguard Worker { return false; }, 375*f6dc9357SAndroid Build Coastguard Worker { return (bitStream)->MovePosCheck; } 376*f6dc9357SAndroid Build Coastguard Worker ) 377*f6dc9357SAndroid Build Coastguard Worker } 378*f6dc9357SAndroid Build Coastguard Worker 379*f6dc9357SAndroid Build Coastguard Worker template <class TBitDecoder> 380*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE DecodeCDecoderBase381*f6dc9357SAndroid Build Coastguard Worker unsigned Decode(TBitDecoder *bitStream) const 382*f6dc9357SAndroid Build Coastguard Worker { 383*f6dc9357SAndroid Build Coastguard Worker unsigned sym; 384*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream, 385*f6dc9357SAndroid Build Coastguard Worker { return (unsigned)(int)(Int32)0xffffffff; } 386*f6dc9357SAndroid Build Coastguard Worker ) 387*f6dc9357SAndroid Build Coastguard Worker return sym; 388*f6dc9357SAndroid Build Coastguard Worker } 389*f6dc9357SAndroid Build Coastguard Worker 390*f6dc9357SAndroid Build Coastguard Worker 391*f6dc9357SAndroid Build Coastguard Worker template <class TBitDecoder> 392*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE DecodeFullCDecoderBase393*f6dc9357SAndroid Build Coastguard Worker unsigned DecodeFull(TBitDecoder *bitStream) const 394*f6dc9357SAndroid Build Coastguard Worker { 395*f6dc9357SAndroid Build Coastguard Worker /* 396*f6dc9357SAndroid Build Coastguard Worker const UInt32 val = bitStream->GetValue(kNumBitsMax); 397*f6dc9357SAndroid Build Coastguard Worker if (val < _limits[kNumTableBits]) 398*f6dc9357SAndroid Build Coastguard Worker { 399*f6dc9357SAndroid Build Coastguard Worker const unsigned pair = _u._lens[(size_t)(val >> (kNumBitsMax - kNumTableBits))]; 400*f6dc9357SAndroid Build Coastguard Worker bitStream->MovePos(pair & kPairLenMask); 401*f6dc9357SAndroid Build Coastguard Worker return pair >> kNumPairLenBits; 402*f6dc9357SAndroid Build Coastguard Worker } 403*f6dc9357SAndroid Build Coastguard Worker 404*f6dc9357SAndroid Build Coastguard Worker unsigned numBits; 405*f6dc9357SAndroid Build Coastguard Worker for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++); 406*f6dc9357SAndroid Build Coastguard Worker 407*f6dc9357SAndroid Build Coastguard Worker bitStream->MovePos(numBits); 408*f6dc9357SAndroid Build Coastguard Worker return _symbols[_poses[numBits] + (unsigned) 409*f6dc9357SAndroid Build Coastguard Worker ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits))]; 410*f6dc9357SAndroid Build Coastguard Worker */ 411*f6dc9357SAndroid Build Coastguard Worker unsigned sym; 412*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_2(sym, this, kNumBitsMax, kNumTableBits, bitStream, 413*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {} 414*f6dc9357SAndroid Build Coastguard Worker ) 415*f6dc9357SAndroid Build Coastguard Worker return sym; 416*f6dc9357SAndroid Build Coastguard Worker } 417*f6dc9357SAndroid Build Coastguard Worker }; 418*f6dc9357SAndroid Build Coastguard Worker 419*f6dc9357SAndroid Build Coastguard Worker 420*f6dc9357SAndroid Build Coastguard Worker template <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */> 421*f6dc9357SAndroid Build Coastguard Worker struct CDecoder: public CDecoderBase 422*f6dc9357SAndroid Build Coastguard Worker <UInt16, UInt32, UInt64, kNumBitsMax, m_NumSymbols, kNumTableBits> {}; 423*f6dc9357SAndroid Build Coastguard Worker 424*f6dc9357SAndroid Build Coastguard Worker template <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = 7 */> 425*f6dc9357SAndroid Build Coastguard Worker struct CDecoder256: public CDecoderBase 426*f6dc9357SAndroid Build Coastguard Worker <Byte, UInt16, UInt32, kNumBitsMax, m_NumSymbols, kNumTableBits> {}; 427*f6dc9357SAndroid Build Coastguard Worker 428*f6dc9357SAndroid Build Coastguard Worker 429*f6dc9357SAndroid Build Coastguard Worker template <unsigned numSymbols> 430*f6dc9357SAndroid Build Coastguard Worker class CDecoder7b 431*f6dc9357SAndroid Build Coastguard Worker { 432*f6dc9357SAndroid Build Coastguard Worker public: 433*f6dc9357SAndroid Build Coastguard Worker Byte _lens[1 << 7]; 434*f6dc9357SAndroid Build Coastguard Worker Build(const Byte * lens,bool full)435*f6dc9357SAndroid Build Coastguard Worker bool Build(const Byte *lens, bool full) throw() 436*f6dc9357SAndroid Build Coastguard Worker { 437*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumBitsMax = 7; 438*f6dc9357SAndroid Build Coastguard Worker 439*f6dc9357SAndroid Build Coastguard Worker unsigned counts[kNumBitsMax + 1]; 440*f6dc9357SAndroid Build Coastguard Worker unsigned _poses[kNumBitsMax + 1]; 441*f6dc9357SAndroid Build Coastguard Worker unsigned _limits[kNumBitsMax + 1]; 442*f6dc9357SAndroid Build Coastguard Worker unsigned i; 443*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i <= kNumBitsMax; i++) 444*f6dc9357SAndroid Build Coastguard Worker counts[i] = 0; 445*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numSymbols; i++) 446*f6dc9357SAndroid Build Coastguard Worker counts[lens[i]]++; 447*f6dc9357SAndroid Build Coastguard Worker 448*f6dc9357SAndroid Build Coastguard Worker _limits[0] = 0; 449*f6dc9357SAndroid Build Coastguard Worker const unsigned kMaxValue = 1u << kNumBitsMax; 450*f6dc9357SAndroid Build Coastguard Worker unsigned startPos = 0; 451*f6dc9357SAndroid Build Coastguard Worker unsigned sum = 0; 452*f6dc9357SAndroid Build Coastguard Worker 453*f6dc9357SAndroid Build Coastguard Worker for (i = 1; i <= kNumBitsMax; i++) 454*f6dc9357SAndroid Build Coastguard Worker { 455*f6dc9357SAndroid Build Coastguard Worker const unsigned cnt = counts[i]; 456*f6dc9357SAndroid Build Coastguard Worker startPos += cnt << (kNumBitsMax - i); 457*f6dc9357SAndroid Build Coastguard Worker _limits[i] = startPos; 458*f6dc9357SAndroid Build Coastguard Worker counts[i] = sum; 459*f6dc9357SAndroid Build Coastguard Worker _poses[i] = sum; 460*f6dc9357SAndroid Build Coastguard Worker sum += cnt; 461*f6dc9357SAndroid Build Coastguard Worker } 462*f6dc9357SAndroid Build Coastguard Worker 463*f6dc9357SAndroid Build Coastguard Worker counts[0] = sum; 464*f6dc9357SAndroid Build Coastguard Worker _poses[0] = sum; 465*f6dc9357SAndroid Build Coastguard Worker 466*f6dc9357SAndroid Build Coastguard Worker if (full) 467*f6dc9357SAndroid Build Coastguard Worker { 468*f6dc9357SAndroid Build Coastguard Worker if (startPos != kMaxValue) 469*f6dc9357SAndroid Build Coastguard Worker return false; 470*f6dc9357SAndroid Build Coastguard Worker } 471*f6dc9357SAndroid Build Coastguard Worker else 472*f6dc9357SAndroid Build Coastguard Worker { 473*f6dc9357SAndroid Build Coastguard Worker if (startPos > kMaxValue) 474*f6dc9357SAndroid Build Coastguard Worker return false; 475*f6dc9357SAndroid Build Coastguard Worker } 476*f6dc9357SAndroid Build Coastguard Worker 477*f6dc9357SAndroid Build Coastguard Worker 478*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numSymbols; i++) 479*f6dc9357SAndroid Build Coastguard Worker { 480*f6dc9357SAndroid Build Coastguard Worker const unsigned len = lens[i]; 481*f6dc9357SAndroid Build Coastguard Worker if (len == 0) 482*f6dc9357SAndroid Build Coastguard Worker continue; 483*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = counts[len]++; 484*f6dc9357SAndroid Build Coastguard Worker { 485*f6dc9357SAndroid Build Coastguard Worker Byte *dest = _lens + _limits[(size_t)len - 1] 486*f6dc9357SAndroid Build Coastguard Worker + ((offset - _poses[len]) << (kNumBitsMax - len)); 487*f6dc9357SAndroid Build Coastguard Worker const unsigned num = (unsigned)1 << (kNumBitsMax - len); 488*f6dc9357SAndroid Build Coastguard Worker const unsigned val = (i << 3) + len; 489*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = 0; k < num; k++) 490*f6dc9357SAndroid Build Coastguard Worker dest[k] = (Byte)val; 491*f6dc9357SAndroid Build Coastguard Worker } 492*f6dc9357SAndroid Build Coastguard Worker } 493*f6dc9357SAndroid Build Coastguard Worker 494*f6dc9357SAndroid Build Coastguard Worker if (!full) 495*f6dc9357SAndroid Build Coastguard Worker { 496*f6dc9357SAndroid Build Coastguard Worker const unsigned limit = _limits[kNumBitsMax]; 497*f6dc9357SAndroid Build Coastguard Worker const unsigned num = ((unsigned)1 << kNumBitsMax) - limit; 498*f6dc9357SAndroid Build Coastguard Worker Byte *dest = _lens + limit; 499*f6dc9357SAndroid Build Coastguard Worker for (unsigned k = 0; k < num; k++) 500*f6dc9357SAndroid Build Coastguard Worker dest[k] = (Byte) 501*f6dc9357SAndroid Build Coastguard Worker // (0x1f << 3); 502*f6dc9357SAndroid Build Coastguard Worker ((0x1f << 3) + 0x7); 503*f6dc9357SAndroid Build Coastguard Worker } 504*f6dc9357SAndroid Build Coastguard Worker 505*f6dc9357SAndroid Build Coastguard Worker return true; 506*f6dc9357SAndroid Build Coastguard Worker } 507*f6dc9357SAndroid Build Coastguard Worker 508*f6dc9357SAndroid Build Coastguard Worker #define Z7_HUFF_DECODER_7B_DECODE(dest, huf, get_val, move_pos, bs) \ 509*f6dc9357SAndroid Build Coastguard Worker { \ 510*f6dc9357SAndroid Build Coastguard Worker const unsigned pair = huf->_lens[(size_t)get_val(7)]; \ 511*f6dc9357SAndroid Build Coastguard Worker const unsigned numBits = pair & 0x7; \ 512*f6dc9357SAndroid Build Coastguard Worker move_pos(bs, numBits); \ 513*f6dc9357SAndroid Build Coastguard Worker dest = pair >> 3; \ 514*f6dc9357SAndroid Build Coastguard Worker } 515*f6dc9357SAndroid Build Coastguard Worker 516*f6dc9357SAndroid Build Coastguard Worker template <class TBitDecoder> Decode(TBitDecoder * bitStream)517*f6dc9357SAndroid Build Coastguard Worker unsigned Decode(TBitDecoder *bitStream) const 518*f6dc9357SAndroid Build Coastguard Worker { 519*f6dc9357SAndroid Build Coastguard Worker const unsigned pair = _lens[(size_t)bitStream->GetValue(7)]; 520*f6dc9357SAndroid Build Coastguard Worker bitStream->MovePos(pair & 0x7); 521*f6dc9357SAndroid Build Coastguard Worker return pair >> 3; 522*f6dc9357SAndroid Build Coastguard Worker } 523*f6dc9357SAndroid Build Coastguard Worker }; 524*f6dc9357SAndroid Build Coastguard Worker 525*f6dc9357SAndroid Build Coastguard Worker }} 526*f6dc9357SAndroid Build Coastguard Worker 527*f6dc9357SAndroid Build Coastguard Worker #endif 528