home *** CD-ROM | disk | FTP | other *** search
- /*\
- * $Id: bitio.c,v 1.5 1992/11/24 19:36:46 dws Exp dws $
- *
- * bitio.c - bitstream I/O
- *
- * Works for (sizeof(unsigned long)-1)*8 bits.
- *
- * Copyright (C) 1992 by David W. Sanderson.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation. This software is provided "as is"
- * without express or implied warranty.
- *
- * $Log: bitio.c,v $
- * Revision 1.5 1992/11/24 19:36:46 dws
- * Added copyright.
- *
- * Revision 1.4 1992/11/17 03:37:50 dws
- * updated comment
- *
- * Revision 1.3 1992/11/10 23:15:16 dws
- * Removed superfluous code.
- *
- * Revision 1.2 1992/11/10 23:11:22 dws
- * Generalized to handle more than one bitstream at once.
- *
- * Revision 1.1 1992/11/10 18:33:21 dws
- * Initial revision
- *
- \*/
-
- #include "bitio.h"
-
- struct bitstream
- {
- FILE *
- f; /* bytestream */
- unsigned long
- bitbuf; /* bit buffer */
- int
- nbitbuf; /* number of bits in 'bitbuf' */
- char
- mode;
- };
-
- #define Mask(n) ((1<<(n))-1)
-
- #define BitPut(b,ul,n) ((b)->bitbuf = (((b)->bitbuf<<(n)) \
- |((ul)&Mask(n))), \
- (b)->nbitbuf += (n))
-
- #define BitGet(b,n) (((b)->bitbuf>>((b)->nbitbuf-=(n))) & Mask(n))
-
- /*
- * pm_bitinit() - allocate and return a struct bitstream * for the
- * given FILE*.
- *
- * mode must be one of "r" or "w", according to whether you will be
- * reading from or writing to the struct bitstream *.
- *
- * Returns 0 on error.
- */
-
- struct bitstream *
- pm_bitinit(f, mode)
- FILE *f;
- char *mode;
- {
- struct bitstream *ans = (struct bitstream *)0;
-
- if(!f || !mode || !*mode)
- return ans;
- if(strcmp(mode, "r") && strcmp(mode, "w"))
- return ans;
-
- ans = (struct bitstream *)calloc(1, sizeof(struct bitstream));
- if(ans)
- {
- ans->f = f;
- ans->mode = *mode;
- }
-
- return ans;
- }
-
- /*
- * pm_bitfini() - deallocate the given struct bitstream *.
- *
- * You must call this after you are done with the struct bitstream *.
- *
- * It may flush some bits left in the buffer.
- *
- * Returns the number of bytes written, -1 on error.
- */
-
- int
- pm_bitfini(b)
- struct bitstream *b;
- {
- int nbyte = 0;
-
- if(!b)
- return -1;
-
- /* flush the output */
- if(b->mode == 'w')
- {
- /* flush the bits */
- if (b->nbitbuf < 0 || b->nbitbuf >= 8)
- {
- /* pm_bitwrite() didn't work */
- return -1;
- }
-
- /*
- * If we get to here, nbitbuf is 0..7
- */
- if(b->nbitbuf)
- {
- char c;
-
- BitPut(b, 0, (long)8-(b->nbitbuf));
- c = (char) BitGet(b, (long)8);
- if(putc(c, b->f) == EOF)
- {
- return -1;
- }
- nbyte++;
- }
- }
-
- free(b);
- return nbyte;
- }
-
- /*
- * pm_bitread() - read the next nbits into *val from the given file.
- *
- * The last pm_bitread() must be followed by a call to pm_bitfini().
- *
- * Returns the number of bytes read, -1 on error.
- */
-
- int
- pm_bitread(b, nbits, val)
- struct bitstream *b;
- unsigned long nbits;
- unsigned long *val;
- {
- int nbyte = 0;
- int c;
-
- if(!b)
- return -1;
-
- while (b->nbitbuf < nbits)
- {
- if((c = getc(b->f)) == EOF)
- {
- return -1;
- }
- nbyte++;
-
- BitPut(b, c, (long) 8);
- }
-
- *val = BitGet(b, nbits);
- return nbyte;
- }
-
- /*
- * pm_bitwrite() - write the low nbits of val to the given file.
- *
- * The last pm_bitwrite() must be followed by a call to pm_bitfini().
- *
- * Returns the number of bytes written, -1 on error.
- */
-
- int
- pm_bitwrite(b, nbits, val)
- struct bitstream *b;
- unsigned long nbits;
- unsigned long val;
- {
- int nbyte = 0;
- char c;
-
- if(!b)
- return -1;
-
- BitPut(b, val, nbits);
-
- while (b->nbitbuf >= 8)
- {
- c = (char) BitGet(b, (long)8);
-
- if(putc(c, b->f) == EOF)
- {
- return -1;
- }
- nbyte++;
- }
-
- return nbyte;
- }
-