diff options
Diffstat (limited to 'lib/bitio.c')
-rw-r--r-- | lib/bitio.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/bitio.c b/lib/bitio.c new file mode 100644 index 00000000..ca1b55f9 --- /dev/null +++ b/lib/bitio.c @@ -0,0 +1,207 @@ +/*\ + * $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 <string.h> + +#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(FILE * const f, const char * const mode) { + + struct bitstream * ans; + + if (!f || !mode) + ans = NULL; + else if (strcmp(mode, "r") != 0 && strcmp(mode, "w") != 0) + ans = NULL; + else { + ans = (struct bitstream *)calloc(1, sizeof(struct bitstream)); + if (ans != NULL) { + 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; +} |