// BitmEncoder.h -- the Most Significant Bit of byte is First #ifndef ZIP7_INC_BITM_ENCODER_H #define ZIP7_INC_BITM_ENCODER_H #include "../IStream.h" template class CBitmEncoder { unsigned _bitPos; // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte unsigned _curByte; // low (_bitPos) bits are zeros // high (8 - _bitPos) bits are filled TOutByte _stream; public: bool Create(UInt32 bufferSize) { return _stream.Create(bufferSize); } void SetStream(ISequentialOutStream *outStream) { _stream.SetStream(outStream);} UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() + ((8 - _bitPos + 7) >> 3); } void Init() { _stream.Init(); _bitPos = 8; _curByte = 0; } HRESULT Flush() { if (_bitPos < 8) { _stream.WriteByte((Byte)_curByte); _bitPos = 8; _curByte = 0; } return _stream.Flush(); } // required condition: (value >> numBits) == 0 // numBits == 0 is allowed void WriteBits(UInt32 value, unsigned numBits) { do { unsigned bp = _bitPos; unsigned curByte = _curByte; if (numBits < bp) { bp -= numBits; _curByte = curByte | (value << bp); _bitPos = bp; return; } numBits -= bp; const UInt32 hi = (value >> numBits); value -= (hi << numBits); _stream.WriteByte((Byte)(curByte | hi)); _bitPos = 8; _curByte = 0; } while (numBits); } void WriteByte(unsigned b) { const unsigned bp = _bitPos; const unsigned a = _curByte | (b >> (8 - bp)); _curByte = b << bp; _stream.WriteByte((Byte)a); } void WriteBytes(const Byte *data, size_t num) { const unsigned bp = _bitPos; #if 1 // 1 for optional speed-optimized code branch if (bp == 8) { _stream.WriteBytes(data, num); return; } #endif unsigned c = _curByte; const unsigned bp_rev = 8 - bp; for (size_t i = 0; i < num; i++) { const unsigned b = data[i]; _stream.WriteByte((Byte)(c | (b >> bp_rev))); c = b << bp; } _curByte = c; } }; #endif