1*f6dc9357SAndroid Build Coastguard Worker // BitmDecoder.h -- the Most Significant Bit of byte is First 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_BITM_DECODER_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_BITM_DECODER_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../IStream.h" 7*f6dc9357SAndroid Build Coastguard Worker 8*f6dc9357SAndroid Build Coastguard Worker namespace NBitm { 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumBigValueBits = 8 * 4; 11*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumValueBytes = 3; 12*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumValueBits = 8 * kNumValueBytes; 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker const UInt32 kMask = (1 << kNumValueBits) - 1; 15*f6dc9357SAndroid Build Coastguard Worker 16*f6dc9357SAndroid Build Coastguard Worker // _bitPos - the number of free bits (high bits in _value) 17*f6dc9357SAndroid Build Coastguard Worker // (kNumBigValueBits - _bitPos) = (32 - _bitPos) == the number of ready to read bits (low bits of _value) 18*f6dc9357SAndroid Build Coastguard Worker 19*f6dc9357SAndroid Build Coastguard Worker template<class TInByte> 20*f6dc9357SAndroid Build Coastguard Worker class CDecoder 21*f6dc9357SAndroid Build Coastguard Worker { 22*f6dc9357SAndroid Build Coastguard Worker unsigned _bitPos; 23*f6dc9357SAndroid Build Coastguard Worker UInt32 _value; 24*f6dc9357SAndroid Build Coastguard Worker TInByte _stream; 25*f6dc9357SAndroid Build Coastguard Worker public: Create(UInt32 bufSize)26*f6dc9357SAndroid Build Coastguard Worker bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } SetStream(ISequentialInStream * inStream)27*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream);} 28*f6dc9357SAndroid Build Coastguard Worker Init()29*f6dc9357SAndroid Build Coastguard Worker void Init() 30*f6dc9357SAndroid Build Coastguard Worker { 31*f6dc9357SAndroid Build Coastguard Worker _stream.Init(); 32*f6dc9357SAndroid Build Coastguard Worker _bitPos = kNumBigValueBits; 33*f6dc9357SAndroid Build Coastguard Worker _value = 0; 34*f6dc9357SAndroid Build Coastguard Worker Normalize(); 35*f6dc9357SAndroid Build Coastguard Worker } 36*f6dc9357SAndroid Build Coastguard Worker GetStreamSize()37*f6dc9357SAndroid Build Coastguard Worker UInt64 GetStreamSize() const { return _stream.GetStreamSize(); } GetProcessedSize()38*f6dc9357SAndroid Build Coastguard Worker UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } 39*f6dc9357SAndroid Build Coastguard Worker ExtraBitsWereRead()40*f6dc9357SAndroid Build Coastguard Worker bool ExtraBitsWereRead() const 41*f6dc9357SAndroid Build Coastguard Worker { 42*f6dc9357SAndroid Build Coastguard Worker return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); 43*f6dc9357SAndroid Build Coastguard Worker } 44*f6dc9357SAndroid Build Coastguard Worker ExtraBitsWereRead_Fast()45*f6dc9357SAndroid Build Coastguard Worker bool ExtraBitsWereRead_Fast() const 46*f6dc9357SAndroid Build Coastguard Worker { 47*f6dc9357SAndroid Build Coastguard Worker return (_stream.NumExtraBytes > 4); 48*f6dc9357SAndroid Build Coastguard Worker } 49*f6dc9357SAndroid Build Coastguard Worker 50*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE Normalize()51*f6dc9357SAndroid Build Coastguard Worker void Normalize() 52*f6dc9357SAndroid Build Coastguard Worker { 53*f6dc9357SAndroid Build Coastguard Worker for (; _bitPos >= 8; _bitPos -= 8) 54*f6dc9357SAndroid Build Coastguard Worker _value = (_value << 8) | _stream.ReadByte(); 55*f6dc9357SAndroid Build Coastguard Worker } 56*f6dc9357SAndroid Build Coastguard Worker 57*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue(unsigned numBits)58*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue(unsigned numBits) const 59*f6dc9357SAndroid Build Coastguard Worker { 60*f6dc9357SAndroid Build Coastguard Worker // return (_value << _bitPos) >> (kNumBigValueBits - numBits); 61*f6dc9357SAndroid Build Coastguard Worker return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits); 62*f6dc9357SAndroid Build Coastguard Worker } 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue_InHigh32bits()65*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue_InHigh32bits() const 66*f6dc9357SAndroid Build Coastguard Worker { 67*f6dc9357SAndroid Build Coastguard Worker return this->_value << this->_bitPos; 68*f6dc9357SAndroid Build Coastguard Worker } 69*f6dc9357SAndroid Build Coastguard Worker 70*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE MovePos(unsigned numBits)71*f6dc9357SAndroid Build Coastguard Worker void MovePos(unsigned numBits) 72*f6dc9357SAndroid Build Coastguard Worker { 73*f6dc9357SAndroid Build Coastguard Worker _bitPos += numBits; 74*f6dc9357SAndroid Build Coastguard Worker Normalize(); 75*f6dc9357SAndroid Build Coastguard Worker } 76*f6dc9357SAndroid Build Coastguard Worker 77*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadBits(unsigned numBits)78*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(unsigned numBits) 79*f6dc9357SAndroid Build Coastguard Worker { 80*f6dc9357SAndroid Build Coastguard Worker UInt32 res = GetValue(numBits); 81*f6dc9357SAndroid Build Coastguard Worker MovePos(numBits); 82*f6dc9357SAndroid Build Coastguard Worker return res; 83*f6dc9357SAndroid Build Coastguard Worker } 84*f6dc9357SAndroid Build Coastguard Worker 85*f6dc9357SAndroid Build Coastguard Worker /* 86*f6dc9357SAndroid Build Coastguard Worker unsigned ReadBit() 87*f6dc9357SAndroid Build Coastguard Worker { 88*f6dc9357SAndroid Build Coastguard Worker UInt32 res = ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - 1); 89*f6dc9357SAndroid Build Coastguard Worker if (++_bitPos >= 8) 90*f6dc9357SAndroid Build Coastguard Worker { 91*f6dc9357SAndroid Build Coastguard Worker _value = (_value << 8) | _stream.ReadByte(); 92*f6dc9357SAndroid Build Coastguard Worker _bitPos -= 8; 93*f6dc9357SAndroid Build Coastguard Worker } 94*f6dc9357SAndroid Build Coastguard Worker return (unsigned)res; 95*f6dc9357SAndroid Build Coastguard Worker } 96*f6dc9357SAndroid Build Coastguard Worker */ 97*f6dc9357SAndroid Build Coastguard Worker AlignToByte()98*f6dc9357SAndroid Build Coastguard Worker void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); } 99*f6dc9357SAndroid Build Coastguard Worker 100*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadAlignBits()101*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); } 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 #endif 107