/*===========================================================================* * bitio.c * * * * Procedures concerned with the bit-wise I/O * * * * EXPORTED PROCEDURES: * * Bitio_New * * Bitio_Free * * Bitio_Write * * Bitio_BytePad * * * *===========================================================================*/ /* * Copyright (c) 1993 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ /*==============* * HEADER FILES * *==============*/ #include #include "all.h" #include "byteorder.h" #include "bitio.h" #include "mtypes.h" #include "string.h" /*==================* * STATIC VARIABLES * *==================*/ uint32 lower_mask[33] = { 0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff }; /*=====================* * EXPORTED PROCEDURES * *=====================*/ /*===========================================================================* * * Bitio_New * * Create a new bit bucket; filePtr is a pointer to the open file the * bits should ultimately be written to. * * RETURNS: pointer to the resulting bit bucket * * SIDE EFFECTS: none * *===========================================================================*/ BitBucket *Bitio_New(void) { BitBucket *bbPtr; bbPtr = (BitBucket *) malloc(sizeof(BitBucket)); ERRCHK(bbPtr, "malloc"); bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket)); ERRCHK(bbPtr->firstPtr, "malloc"); bbPtr->totalbits = 0; bbPtr->cumulativeBits = 0; bbPtr->bitsWritten = 0; bbPtr->firstPtr->nextPtr = NULL; bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET; bbPtr->firstPtr->bitsleftcur = 32; bbPtr->firstPtr->currword = 0; memset((char *)bbPtr->firstPtr->bits,0,sizeof(uint32) * WORDS_PER_BUCKET); return bbPtr; } /*===========================================================================* * * Bitio_Free * * Frees the memory associated with the given bit bucket * * RETURNS: nothing * * SIDE EFFECTS: none * *===========================================================================*/ void Bitio_Free(bbPtr) BitBucket *bbPtr; { struct bitBucket *tmpPtr, *nextPtr; for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) { nextPtr = tmpPtr->nextPtr; free(tmpPtr); } free(bbPtr); } /*===========================================================================* * * Bitio_Write * * Writes 'nbits' bits from 'bits' into the given bit bucket * 'nbits' must be between 0 and 32 * * RETURNS: nothing * * SIDE EFFECTS: if the number of bits in the bit bucket surpasses * MAX_BITS, then that many bits are flushed to the * appropriate output file * *===========================================================================*/ void Bitio_Write(bbPtr, bits, nbits) BitBucket *bbPtr; uint32 bits; int nbits; { register struct bitBucket *lastPtr, *newPtr; register int delta; assert(nbits <= 32 && nbits >= 0); /* * Clear top bits if not part of data, necessary due to down and * dirty calls of Bitio_Write with unecessary top bits set. */ bits = bits & lower_mask[nbits]; bbPtr->totalbits += nbits; bbPtr->cumulativeBits += nbits; lastPtr = bbPtr->lastPtr; delta = nbits - lastPtr->bitsleft; if (delta >= 0) { /* * there's not enough room in the current bucket, so we're * going to have to allocate another bucket */ newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket)); ERRCHK(newPtr, "malloc"); newPtr->nextPtr = NULL; newPtr->bitsleft = MAXBITS_PER_BUCKET; newPtr->bitsleftcur = 32; newPtr->currword = 0; memset(newPtr->bits,0, sizeof(uint32) * WORDS_PER_BUCKET); bbPtr->lastPtr = newPtr; assert(lastPtr->currword == WORDS_PER_BUCKET - 1); lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta); lastPtr->bitsleft = 0; lastPtr->bitsleftcur = 0; /* lastPtr->currword++; */ if (!delta) { if ( bbPtr->totalbits > MAX_BITS ) { fprintf(stderr,"OH NO! The bit buffer in bitio.c has overflowed!\n"); } } assert(delta <= 32); newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta); newPtr->bitsleft -= delta; newPtr->bitsleftcur -= delta; } else { /* * the current bucket will be sufficient */ delta = nbits - lastPtr->bitsleftcur; lastPtr->bitsleftcur -= nbits; lastPtr->bitsleft -= nbits; if (delta >= 0) { /* * these bits will span more than one word */ lastPtr->bits[lastPtr->currword] |= (bits >> delta); lastPtr->currword++; lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta); lastPtr->bitsleftcur = 32 - delta; } else { /* * these bits will fit, whole */ lastPtr->bits[lastPtr->currword] |= (bits << (-delta)); } } if ( bbPtr->totalbits > MAX_BITS ) /* flush bits */ fprintf(stderr,"OH NO! The bit buffer in bitio.c has overflowed!\n"); } /*===========================================================================* * * Bitio_BytePad * * Pads the end of the bit bucket to the nearest byte with 0 bits * * RETURNS: nothing * *===========================================================================*/ void Bitio_BytePad(bbPtr) BitBucket *bbPtr; { struct bitBucket *lastPtrPtr = bbPtr->lastPtr; if (lastPtrPtr->bitsleftcur % 8) { Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8); } }