1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
// BitlDecoder.h -- the Least Significant Bit of byte is First
#ifndef __BITL_DECODER_H
#define __BITL_DECODER_H
#include "../IStream.h"
namespace NBitl {
const unsigned kNumBigValueBits = 8 * 4;
const unsigned kNumValueBytes = 3;
const unsigned kNumValueBits = 8 * kNumValueBytes;
const UInt32 kMask = (1 << kNumValueBits) - 1;
extern Byte kInvertTable[256];
/* TInByte must support "Extra Bytes" (bytes that can be read after the end of stream
TInByte::ReadByte() returns 0xFF after the end of stream
TInByte::NumExtraBytes contains the number "Extra Bytes"
Bitl decoder can read up to 4 bytes ahead to internal buffer. */
template<class TInByte>
class CBaseDecoder
{
protected:
unsigned _bitPos;
UInt32 _value;
TInByte _stream;
public:
bool Create(UInt32 bufSize) { return _stream.Create(bufSize); }
void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); }
void Init()
{
_stream.Init();
_bitPos = kNumBigValueBits;
_value = 0;
}
UInt64 GetStreamSize() const { return _stream.GetStreamSize(); }
UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); }
bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; }
void Normalize()
{
for (; _bitPos >= 8; _bitPos -= 8)
_value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value;
}
UInt32 ReadBits(unsigned numBits)
{
Normalize();
UInt32 res = _value & ((1 << numBits) - 1);
_bitPos += numBits;
_value >>= numBits;
return res;
}
bool ExtraBitsWereRead() const
{
return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3));
}
bool ExtraBitsWereRead_Fast() const
{
// full version is not inlined in vc6.
// return _stream.NumExtraBytes != 0 && (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3));
// (_stream.NumExtraBytes > 4) is fast overread detection. It's possible that
// it doesn't return true, if small number of extra bits were read.
return (_stream.NumExtraBytes > 4);
}
// it must be fixed !!! with extra bits
// UInt32 GetNumExtraBytes() const { return _stream.NumExtraBytes; }
};
template<class TInByte>
class CDecoder: public CBaseDecoder<TInByte>
{
UInt32 _normalValue;
public:
void Init()
{
CBaseDecoder<TInByte>::Init();
_normalValue = 0;
}
void Normalize()
{
for (; this->_bitPos >= 8; this->_bitPos -= 8)
{
Byte b = this->_stream.ReadByte();
_normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue;
this->_value = (this->_value << 8) | kInvertTable[b];
}
}
UInt32 GetValue(unsigned numBits)
{
Normalize();
return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits);
}
void MovePos(unsigned numBits)
{
this->_bitPos += numBits;
_normalValue >>= numBits;
}
UInt32 ReadBits(unsigned numBits)
{
Normalize();
UInt32 res = _normalValue & ((1 << numBits) - 1);
MovePos(numBits);
return res;
}
void AlignToByte() { MovePos((32 - this->_bitPos) & 7); }
Byte ReadDirectByte() { return this->_stream.ReadByte(); }
Byte ReadAlignedByte()
{
if (this->_bitPos == kNumBigValueBits)
return this->_stream.ReadByte();
Byte b = (Byte)(_normalValue & 0xFF);
MovePos(8);
return b;
}
};
}
#endif
|