int QccBitBufferInitialize(QccBitBuffer *bit_buffer);
int QccBitBufferStart(QccBitBuffer *bit_buffer);
int QccBitBufferEnd(QccBitBuffer
*bit_buffer);
int QccBitBufferFlush(QccBitBuffer *bit_buffer);
int QccBitBufferCopy(QccBitBuffer
*output_buffer, QccBitBuffer *input_buffer, int num_bits);
int QccBitBufferPutBit(QccBitBuffer
*bit_buffer, int bit_value);
int QccBitBufferGetBit(QccBitBuffer *bit_buffer,
int *bit_value);
int QccBitBufferPutBits(QccBitBuffer *bit_buffer, int
val, int num_bits);
int QccBitBufferGetBits(QccBitBuffer *bit_buffer,
int *val, int num_bits);
int QccBitBufferPutChar(QccBitBuffer *bit_buffer,
unsigned char val);
int QccBitBufferGetChar(QccBitBuffer *bit_buffer,
unsigned char *val);
int QccBitBufferPutInt(QccBitBuffer *bit_buffer,
int val);
int QccBitBufferGetInt(QccBitBuffer *bit_buffer, int *val);
int QccBitBufferPutDouble(QccBitBuffer *bit_buffer, double val);
int
QccBitBufferGetDouble(QccBitBuffer *bit_buffer, double *val);
typedef unsigned char QccBitBufferChar;
typedef struct
{
QccString filename;
FILE *fileptr;
int type;
int bit_cnt;
int byte_cnt;
int bits_to_go;
QccBitBufferChar buffer;
} QccBitBuffer;
The fields of QccBitBuffer are as follows:
filename: NULL string
fileptr: NULL
type: QCCBITBUFFER_OUTPUT
bit_cnt: 0
bits_to_go: 8
buffer: 0
QccBitBufferStart() starts a read or write on bit_buffer. bit_buffer->type must be set to indicate whether bit_buffer will read a file (QCCBITBUFFER_INPUT) or write a file (QCCBITBUFFER_OUTPUT). If bit_buffer->fileptr is NULL, the file indicated by bit_buffer->filename is opened and the resulting FILE pointer is returned in bit_buffer->fileptr. Otherwise, it is assumed that the file is already opened properly for reading or writing as appropriate, and is properly positioned to the start of binary data in the file (thus, QccBitBufferStart() permits the reading of, say, an ASCII header by some external procedure before the reading of binary data commences). In either case, if bit_buffer is being started for reading, bit_buffer->buffer is primed by reading the first character of the file.
QccBitBufferEnd() should be called after all accesses (read or write) to bit_buffer are complete. QccBitBufferEnd() closes bit_buffer->fileptr.
QccBitBufferFlush() should be called at the end of writing a bitstream after all bits have been written but before QccBitBufferEnd() is called. QccBitBufferFlush() ensures that the last byte being packed with bits, which may not be full, is output to the file. If any bits are output after a call to QccBitBufferFlush(), they will be written to the next byte of the file; i.e., QccBitBufferFlush() can be used to align output to byte boundaries in the file. QccBitBufferFlush() is usually called only for buffers opened for output. In the case of an input buffer, QccBitBufferFlush() will cause the next bit read to come from the next byte of the file; i.e., on input, QccBitBufferFlush() can be used to enforce alignment to byte boundaries during reading the file. On output, QccBitBufferFlush() calls QccFileFlush(3) to ensure that all stream buffers are flushed.
QccBitBufferCopy() copies num_bits from input_buffer to output_buffer by calling QccBitBufferGetBit() on input_buffer and QccBitBufferPutBit() on output_buffer num_bits times.
QccBitBufferPutBit() outputs a bit, bit_value, to output buffer bit_buffer. The bit is packed into the current byte, and, if this byte is full, it is written to the file. bit_value gives the value of the bit; bit_value should be zero to denote a 0 bit and nonzero to denote a 1 bit.
QccBitBufferGetBit() inputs a bit, bit_value, from an input buffer bit_buffer. If the current byte is empty, the next byte is read from the file. Then, a bit is unpacked from the byte. The bit is returned in bit_value; a 0 is returned for a 0 bit, a 1 is returned for a 1 bit. If the bit_value pointer is NULL, then the bit is read from input_buffer but not returned.
QccBitBufferPutBits() outputs the least-significant num_bits bits of val to bit_buffer via num_bits consecutive calls to QccBitBufferPutBit(). The bits are output starting with the least-significant bit of val.
QccBitBufferGetBits() inputs num_bits bits from bit_buffer to the least-significant bits of val via num_bits consecutive calls to QccBitBufferGetBit(). The bits are placed into val starting with the least-significant bit first. If the val pointer is NULL, then the bits are read from input_buffer but not returned.
QccBitBufferPutChar() and QccBitBufferGetChar() write or read, respectively, an unsigned char to or from the file. That is, these two routines effectuate 8 consecutive bit writes or reads via QccBitBufferPutBit() or QccBitBufferGetBit(). If the val pointer is NULL, then QccBitBufferGetBit() reads the character from input_buffer, but it is not returned.
QccBitBufferPutInt() and QccBitBufferGetInt() use QccBinaryIntToChar(3) and QccBinaryChartoInt(3) to convert between an int and four characters. These four characters are read from or written to the file via four calls to QccBitBufferPutChar() or QccBitBufferGetChar(). If the val pointer is NULL, then QccBitBufferGetInt() reads the integer from input_buffer, but it is not returned.
QccBitBufferPutDouble() and QccBitBufferGetDouble() use QccBinaryFloatToChar(3) and QccBinaryChartoFloat(3) to convert between a double and four characters. These four characters are read from or written to the file via four calls to QccBitBufferPutChar() or QccBitBufferGetChar(). QccBitBufferPutDouble() and QccBitBufferGetDouble() actually read and write double as float; consequently, these routines may incur a loss of precision. If the val pointer is NULL, then QccBitBufferGetDouble() reads the value from input_buffer, but it is not returned.
On a related note, bit_buffer->bit_cnt stores the number of bits actually put into or got out of the buffer. On the other hand, bit_buffer->byte_cnt stores the number of bytes that have been read from or written to the file associated to the buffer. Calls to QccBitBufferFlush() may cause these two to appear to be "out of sync." For example, when the last byte of a file is written, if this last byte is not completely full, bit_buffer->bit_cnt is incremented by only the number of bits actually put into the buffer (something less than 8), while bit_buffer->byte_cnt is incremented once indicating that a byte (8 bits) was written to the file. In this case, bit_buffer->bit_cnt will not be equal to 8 times bit_buffer->byte_cnt as might have been expected. This issue is important to keep in mind should QccBitBufferFlush() be called multiple times during reading or writing in order to align to byte boundaries; in this case, the bits in the file that are "skipped" to get to the start of the next byte are not included in the bit_buffer->bit_cnt count.