1*f6dc9357SAndroid Build Coastguard Worker // BitlDecoder.h -- the Least Significant Bit of byte is First 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_BITL_DECODER_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_BITL_DECODER_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h" 7*f6dc9357SAndroid Build Coastguard Worker 8*f6dc9357SAndroid Build Coastguard Worker #include "../IStream.h" 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker namespace NBitl { 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumBigValueBits = 8 * 4; 13*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumValueBytes = 3; 14*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumValueBits = 8 * kNumValueBytes; 15*f6dc9357SAndroid Build Coastguard Worker const UInt32 kMask = (1 << kNumValueBits) - 1; 16*f6dc9357SAndroid Build Coastguard Worker 17*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_BITL_USE_REVERSE_BITS_TABLE) 18*f6dc9357SAndroid Build Coastguard Worker #if 1 && defined(MY_CPU_ARM_OR_ARM64) \ 19*f6dc9357SAndroid Build Coastguard Worker && (defined(MY_CPU_ARM64) || defined(__ARM_ARCH_6T2__) \ 20*f6dc9357SAndroid Build Coastguard Worker || defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \ 21*f6dc9357SAndroid Build Coastguard Worker && (defined(__GNUC__) && (__GNUC__ >= 4) \ 22*f6dc9357SAndroid Build Coastguard Worker || defined(__clang__) && (__clang_major__ >= 4)) 23*f6dc9357SAndroid Build Coastguard Worker #define Z7_BITL_USE_REVERSE_BITS_INSTRUCTION 24*f6dc9357SAndroid Build Coastguard Worker #elif 1 25*f6dc9357SAndroid Build Coastguard Worker #define Z7_BITL_USE_REVERSE_BITS_TABLE 26*f6dc9357SAndroid Build Coastguard Worker #endif 27*f6dc9357SAndroid Build Coastguard Worker #endif 28*f6dc9357SAndroid Build Coastguard Worker 29*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_BITL_USE_REVERSE_BITS_TABLE) 30*f6dc9357SAndroid Build Coastguard Worker extern Byte kReverseTable[256]; 31*f6dc9357SAndroid Build Coastguard Worker #endif 32*f6dc9357SAndroid Build Coastguard Worker ReverseBits8(unsigned i)33*f6dc9357SAndroid Build Coastguard Workerinline unsigned ReverseBits8(unsigned i) 34*f6dc9357SAndroid Build Coastguard Worker { 35*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_BITL_USE_REVERSE_BITS_TABLE) 36*f6dc9357SAndroid Build Coastguard Worker return kReverseTable[i]; 37*f6dc9357SAndroid Build Coastguard Worker #elif defined(Z7_BITL_USE_REVERSE_BITS_INSTRUCTION) 38*f6dc9357SAndroid Build Coastguard Worker // rbit is available in ARMv6T2 and above 39*f6dc9357SAndroid Build Coastguard Worker asm ("rbit " 40*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_ARM) 41*f6dc9357SAndroid Build Coastguard Worker "%0,%0" // it uses default register size, 42*f6dc9357SAndroid Build Coastguard Worker // but we need 32-bit register here. 43*f6dc9357SAndroid Build Coastguard Worker // we must use it only if default register size is 32-bit. 44*f6dc9357SAndroid Build Coastguard Worker // it will work incorrectly for ARM64. 45*f6dc9357SAndroid Build Coastguard Worker #else 46*f6dc9357SAndroid Build Coastguard Worker "%w0,%w0" // it uses 32-bit registers in ARM64. 47*f6dc9357SAndroid Build Coastguard Worker // compiler for (MY_CPU_ARM) can't compile it. 48*f6dc9357SAndroid Build Coastguard Worker #endif 49*f6dc9357SAndroid Build Coastguard Worker : "+r" (i)); 50*f6dc9357SAndroid Build Coastguard Worker return i >> 24; 51*f6dc9357SAndroid Build Coastguard Worker #else 52*f6dc9357SAndroid Build Coastguard Worker unsigned 53*f6dc9357SAndroid Build Coastguard Worker x = ((i & 0x55) << 1) | ((i >> 1) & 0x55); 54*f6dc9357SAndroid Build Coastguard Worker x = ((x & 0x33) << 2) | ((x >> 2) & 0x33); 55*f6dc9357SAndroid Build Coastguard Worker return ((x & 0x0f) << 4) | (x >> 4); 56*f6dc9357SAndroid Build Coastguard Worker #endif 57*f6dc9357SAndroid Build Coastguard Worker } 58*f6dc9357SAndroid Build Coastguard Worker 59*f6dc9357SAndroid Build Coastguard Worker 60*f6dc9357SAndroid Build Coastguard Worker /* TInByte must support "Extra Bytes" (bytes that can be read after the end of stream 61*f6dc9357SAndroid Build Coastguard Worker TInByte::ReadByte() returns 0xFF after the end of stream 62*f6dc9357SAndroid Build Coastguard Worker TInByte::NumExtraBytes contains the number "Extra Bytes" 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker Bitl decoder can read up to 4 bytes ahead to internal buffer. */ 65*f6dc9357SAndroid Build Coastguard Worker 66*f6dc9357SAndroid Build Coastguard Worker template<class TInByte> 67*f6dc9357SAndroid Build Coastguard Worker class CBaseDecoder 68*f6dc9357SAndroid Build Coastguard Worker { 69*f6dc9357SAndroid Build Coastguard Worker protected: 70*f6dc9357SAndroid Build Coastguard Worker unsigned _bitPos; 71*f6dc9357SAndroid Build Coastguard Worker UInt32 _value; 72*f6dc9357SAndroid Build Coastguard Worker TInByte _stream; 73*f6dc9357SAndroid Build Coastguard Worker public: Create(UInt32 bufSize)74*f6dc9357SAndroid Build Coastguard Worker bool Create(UInt32 bufSize) { return _stream.Create(bufSize); } SetStream(ISequentialInStream * inStream)75*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); } ClearStreamPtr()76*f6dc9357SAndroid Build Coastguard Worker void ClearStreamPtr() { _stream.ClearStreamPtr(); } Init()77*f6dc9357SAndroid Build Coastguard Worker void Init() 78*f6dc9357SAndroid Build Coastguard Worker { 79*f6dc9357SAndroid Build Coastguard Worker _stream.Init(); 80*f6dc9357SAndroid Build Coastguard Worker _bitPos = kNumBigValueBits; 81*f6dc9357SAndroid Build Coastguard Worker _value = 0; 82*f6dc9357SAndroid Build Coastguard Worker } 83*f6dc9357SAndroid Build Coastguard Worker 84*f6dc9357SAndroid Build Coastguard Worker // the size of portion data in real stream that was already read from this object. 85*f6dc9357SAndroid Build Coastguard Worker // it doesn't include unused data in BitStream object buffer (up to 4 bytes) 86*f6dc9357SAndroid Build Coastguard Worker // it doesn't include unused data in TInByte buffers 87*f6dc9357SAndroid Build Coastguard Worker // it doesn't include virtual Extra bytes after the end of real stream data GetStreamSize()88*f6dc9357SAndroid Build Coastguard Worker UInt64 GetStreamSize() const 89*f6dc9357SAndroid Build Coastguard Worker { 90*f6dc9357SAndroid Build Coastguard Worker return ExtraBitsWereRead() ? 91*f6dc9357SAndroid Build Coastguard Worker _stream.GetStreamSize(): 92*f6dc9357SAndroid Build Coastguard Worker GetProcessedSize(); 93*f6dc9357SAndroid Build Coastguard Worker } 94*f6dc9357SAndroid Build Coastguard Worker 95*f6dc9357SAndroid Build Coastguard Worker // the size of virtual data that was read from this object. GetProcessedSize()96*f6dc9357SAndroid Build Coastguard Worker UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); } 97*f6dc9357SAndroid Build Coastguard Worker ThereAreDataInBitsBuffer()98*f6dc9357SAndroid Build Coastguard Worker bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; } 99*f6dc9357SAndroid Build Coastguard Worker 100*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE Normalize()101*f6dc9357SAndroid Build Coastguard Worker void Normalize() 102*f6dc9357SAndroid Build Coastguard Worker { 103*f6dc9357SAndroid Build Coastguard Worker for (; _bitPos >= 8; _bitPos -= 8) 104*f6dc9357SAndroid Build Coastguard Worker _value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value; 105*f6dc9357SAndroid Build Coastguard Worker } 106*f6dc9357SAndroid Build Coastguard Worker 107*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadBits(unsigned numBits)108*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(unsigned numBits) 109*f6dc9357SAndroid Build Coastguard Worker { 110*f6dc9357SAndroid Build Coastguard Worker Normalize(); 111*f6dc9357SAndroid Build Coastguard Worker UInt32 res = _value & ((1 << numBits) - 1); 112*f6dc9357SAndroid Build Coastguard Worker _bitPos += numBits; 113*f6dc9357SAndroid Build Coastguard Worker _value >>= numBits; 114*f6dc9357SAndroid Build Coastguard Worker return res; 115*f6dc9357SAndroid Build Coastguard Worker } 116*f6dc9357SAndroid Build Coastguard Worker ExtraBitsWereRead()117*f6dc9357SAndroid Build Coastguard Worker bool ExtraBitsWereRead() const 118*f6dc9357SAndroid Build Coastguard Worker { 119*f6dc9357SAndroid Build Coastguard Worker return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); 120*f6dc9357SAndroid Build Coastguard Worker } 121*f6dc9357SAndroid Build Coastguard Worker ExtraBitsWereRead_Fast()122*f6dc9357SAndroid Build Coastguard Worker bool ExtraBitsWereRead_Fast() const 123*f6dc9357SAndroid Build Coastguard Worker { 124*f6dc9357SAndroid Build Coastguard Worker // full version is not inlined in vc6. 125*f6dc9357SAndroid Build Coastguard Worker // return _stream.NumExtraBytes != 0 && (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3)); 126*f6dc9357SAndroid Build Coastguard Worker 127*f6dc9357SAndroid Build Coastguard Worker // (_stream.NumExtraBytes > 4) is fast overread detection. It's possible that 128*f6dc9357SAndroid Build Coastguard Worker // it doesn't return true, if small number of extra bits were read. 129*f6dc9357SAndroid Build Coastguard Worker return (_stream.NumExtraBytes > 4); 130*f6dc9357SAndroid Build Coastguard Worker } 131*f6dc9357SAndroid Build Coastguard Worker 132*f6dc9357SAndroid Build Coastguard Worker // it must be fixed !!! with extra bits 133*f6dc9357SAndroid Build Coastguard Worker // UInt32 GetNumExtraBytes() const { return _stream.NumExtraBytes; } 134*f6dc9357SAndroid Build Coastguard Worker }; 135*f6dc9357SAndroid Build Coastguard Worker 136*f6dc9357SAndroid Build Coastguard Worker template<class TInByte> 137*f6dc9357SAndroid Build Coastguard Worker class CDecoder: public CBaseDecoder<TInByte> 138*f6dc9357SAndroid Build Coastguard Worker { 139*f6dc9357SAndroid Build Coastguard Worker UInt32 _normalValue; 140*f6dc9357SAndroid Build Coastguard Worker 141*f6dc9357SAndroid Build Coastguard Worker public: Init()142*f6dc9357SAndroid Build Coastguard Worker void Init() 143*f6dc9357SAndroid Build Coastguard Worker { 144*f6dc9357SAndroid Build Coastguard Worker CBaseDecoder<TInByte>::Init(); 145*f6dc9357SAndroid Build Coastguard Worker _normalValue = 0; 146*f6dc9357SAndroid Build Coastguard Worker } 147*f6dc9357SAndroid Build Coastguard Worker 148*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE Normalize()149*f6dc9357SAndroid Build Coastguard Worker void Normalize() 150*f6dc9357SAndroid Build Coastguard Worker { 151*f6dc9357SAndroid Build Coastguard Worker for (; this->_bitPos >= 8; this->_bitPos -= 8) 152*f6dc9357SAndroid Build Coastguard Worker { 153*f6dc9357SAndroid Build Coastguard Worker const unsigned b = this->_stream.ReadByte(); 154*f6dc9357SAndroid Build Coastguard Worker _normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue; 155*f6dc9357SAndroid Build Coastguard Worker this->_value = (this->_value << 8) | ReverseBits8(b); 156*f6dc9357SAndroid Build Coastguard Worker } 157*f6dc9357SAndroid Build Coastguard Worker } 158*f6dc9357SAndroid Build Coastguard Worker 159*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue(unsigned numBits)160*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue(unsigned numBits) 161*f6dc9357SAndroid Build Coastguard Worker { 162*f6dc9357SAndroid Build Coastguard Worker Normalize(); 163*f6dc9357SAndroid Build Coastguard Worker return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits); 164*f6dc9357SAndroid Build Coastguard Worker } 165*f6dc9357SAndroid Build Coastguard Worker 166*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetValue_InHigh32bits()167*f6dc9357SAndroid Build Coastguard Worker UInt32 GetValue_InHigh32bits() 168*f6dc9357SAndroid Build Coastguard Worker { 169*f6dc9357SAndroid Build Coastguard Worker Normalize(); 170*f6dc9357SAndroid Build Coastguard Worker return this->_value << this->_bitPos; 171*f6dc9357SAndroid Build Coastguard Worker } 172*f6dc9357SAndroid Build Coastguard Worker 173*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE MovePos(size_t numBits)174*f6dc9357SAndroid Build Coastguard Worker void MovePos(size_t numBits) 175*f6dc9357SAndroid Build Coastguard Worker { 176*f6dc9357SAndroid Build Coastguard Worker this->_bitPos += (unsigned)numBits; 177*f6dc9357SAndroid Build Coastguard Worker _normalValue >>= numBits; 178*f6dc9357SAndroid Build Coastguard Worker } 179*f6dc9357SAndroid Build Coastguard Worker 180*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadBits(unsigned numBits)181*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(unsigned numBits) 182*f6dc9357SAndroid Build Coastguard Worker { 183*f6dc9357SAndroid Build Coastguard Worker Normalize(); 184*f6dc9357SAndroid Build Coastguard Worker UInt32 res = _normalValue & ((1 << numBits) - 1); 185*f6dc9357SAndroid Build Coastguard Worker MovePos(numBits); 186*f6dc9357SAndroid Build Coastguard Worker return res; 187*f6dc9357SAndroid Build Coastguard Worker } 188*f6dc9357SAndroid Build Coastguard Worker AlignToByte()189*f6dc9357SAndroid Build Coastguard Worker void AlignToByte() { MovePos((32 - this->_bitPos) & 7); } 190*f6dc9357SAndroid Build Coastguard Worker 191*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadDirectByte()192*f6dc9357SAndroid Build Coastguard Worker Byte ReadDirectByte() { return this->_stream.ReadByte(); } 193*f6dc9357SAndroid Build Coastguard Worker 194*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadDirectBytesPart(Byte * buf,size_t size)195*f6dc9357SAndroid Build Coastguard Worker size_t ReadDirectBytesPart(Byte *buf, size_t size) { return this->_stream.ReadBytesPart(buf, size); } 196*f6dc9357SAndroid Build Coastguard Worker 197*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadAlignedByte()198*f6dc9357SAndroid Build Coastguard Worker Byte ReadAlignedByte() 199*f6dc9357SAndroid Build Coastguard Worker { 200*f6dc9357SAndroid Build Coastguard Worker if (this->_bitPos == kNumBigValueBits) 201*f6dc9357SAndroid Build Coastguard Worker return this->_stream.ReadByte(); 202*f6dc9357SAndroid Build Coastguard Worker Byte b = (Byte)(_normalValue & 0xFF); 203*f6dc9357SAndroid Build Coastguard Worker MovePos(8); 204*f6dc9357SAndroid Build Coastguard Worker return b; 205*f6dc9357SAndroid Build Coastguard Worker } 206*f6dc9357SAndroid Build Coastguard Worker 207*f6dc9357SAndroid Build Coastguard Worker // call it only if the object is aligned for byte. 208*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE ReadAlignedByte_FromBuf(Byte & b)209*f6dc9357SAndroid Build Coastguard Worker bool ReadAlignedByte_FromBuf(Byte &b) 210*f6dc9357SAndroid Build Coastguard Worker { 211*f6dc9357SAndroid Build Coastguard Worker if (this->_stream.NumExtraBytes != 0) 212*f6dc9357SAndroid Build Coastguard Worker if (this->_stream.NumExtraBytes >= 4 213*f6dc9357SAndroid Build Coastguard Worker || kNumBigValueBits - this->_bitPos <= (this->_stream.NumExtraBytes << 3)) 214*f6dc9357SAndroid Build Coastguard Worker return false; 215*f6dc9357SAndroid Build Coastguard Worker if (this->_bitPos == kNumBigValueBits) 216*f6dc9357SAndroid Build Coastguard Worker return this->_stream.ReadByte_FromBuf(b); 217*f6dc9357SAndroid Build Coastguard Worker b = (Byte)(_normalValue & 0xFF); 218*f6dc9357SAndroid Build Coastguard Worker MovePos(8); 219*f6dc9357SAndroid Build Coastguard Worker return true; 220*f6dc9357SAndroid Build Coastguard Worker } 221*f6dc9357SAndroid Build Coastguard Worker }; 222*f6dc9357SAndroid Build Coastguard Worker 223*f6dc9357SAndroid Build Coastguard Worker } 224*f6dc9357SAndroid Build Coastguard Worker 225*f6dc9357SAndroid Build Coastguard Worker #endif 226