CBitStream16.h
//-----------------------------------------------------------------------------
// $Header: CBitStream16.h,v 2.2 96/10/17 15:36:53 messer Exp $
//
// COOL Program Library
// Copyright (C) CERES collaboration, 1995, 1996
//
// Declaration and implementation of class CBitStream16.
//
// Extract n bits from a 16 bit aligned buffer of any length,
// where n must be in the range [1...16].
//
//-----------------------------------------------------------------------------
#ifndef CBITSTREAM16_H
#define CBITSTREAM16_H
class CBitStream16 {
#ifdef ARCH_IS_LITTLE_ENDIAN
enum { SHORTHI = 0, SHORTLO = 1 };
#else
enum { SHORTHI = 1, SHORTLO = 0 };
#endif
public:
inline CBitStream16(const unsigned short*, unsigned int);
inline unsigned long peek(unsigned int=1); // tells you what to expect for the next 'next()'
inline unsigned long next(unsigned int=1); // extracts the next bits
inline int eos() const; // returns True if end-of-stream is reached
inline int bad() const; // returns True if error bit is set
inline int count() const; // returns number of bits extracted so far
private:
int maxbits;
int bitpos; // running from 0 to lastbit
unsigned short *buffer;
int error;
private:
CBitStream16();
CBitStream16(const CBitStream16&);
};
int CBitStream16::eos() const {return bitpos >= maxbits;}
int CBitStream16::bad() const {return error != 0;}
int CBitStream16::count() const {return bitpos;}
CBitStream16::CBitStream16() { /* nop */ }
CBitStream16::CBitStream16(const CBitStream16&) { /* nop */ }
CBitStream16::CBitStream16(const unsigned short* chunk, unsigned int chunkbits)
{
maxbits = int(chunkbits);
buffer = (unsigned short*)chunk;
bitpos = 0;
error = 0;
}
unsigned long CBitStream16::peek(unsigned int nbits)
{
const int MaxExtraction = 16;
const int BitsInByte = 8;
const int BitsInShort = 16;
const int BitsInLong = 32;
union {
unsigned long Long; // contains later the requested bits right-adjusted
unsigned short Short[2];
} result;
error = (nbits+bitpos > maxbits); // check if enough bits in buffer to extract nbits
error += (nbits > MaxExtraction); // request exceeds limit
if (nbits && !error) {
int firstShort = bitpos/BitsInShort; // first short where extraction starts
//
// Swap order of shorts to give a continuous stream
//
result.Short[SHORTHI] = buffer[firstShort];
result.Short[SHORTLO] = buffer[firstShort+1];
//
// Right-adjust bits to be extracted and zero the rest
//
result.Long >>= (firstShort > 0 ? bitpos%(firstShort*BitsInShort) : bitpos);
result.Long &= ~(~0L << nbits);
}
return result.Long;
}
unsigned long CBitStream16::next(unsigned int nbits)
{
union {
unsigned long Long; // contains later the requested bits right-adjusted
unsigned short Short[2];
} result;
result.Long = peek(nbits);
if (nbits && !error) {
bitpos += nbits; // next bit in buffer
}
return result.Long;
}
#endif /* CBITSTREAM16_H */