home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / bitio.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  4KB  |  209 lines

  1. /*\
  2.  * $Id: bitio.c,v 1.5 1992/11/24 19:36:46 dws Exp dws $
  3.  *
  4.  * bitio.c - bitstream I/O
  5.  *
  6.  * Works for (sizeof(unsigned long)-1)*8 bits.
  7.  *
  8.  * Copyright (C) 1992 by David W. Sanderson.
  9.  * 
  10.  * Permission to use, copy, modify, and distribute this software and its
  11.  * documentation for any purpose and without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and
  13.  * that both that copyright notice and this permission notice appear
  14.  * in supporting documentation.  This software is provided "as is"
  15.  * without express or implied warranty.
  16.  *
  17.  * $Log: bitio.c,v $
  18.  * Revision 1.5  1992/11/24  19:36:46  dws
  19.  * Added copyright.
  20.  *
  21.  * Revision 1.4  1992/11/17  03:37:50  dws
  22.  * updated comment
  23.  *
  24.  * Revision 1.3  1992/11/10  23:15:16  dws
  25.  * Removed superfluous code.
  26.  *
  27.  * Revision 1.2  1992/11/10  23:11:22  dws
  28.  * Generalized to handle more than one bitstream at once.
  29.  *
  30.  * Revision 1.1  1992/11/10  18:33:21  dws
  31.  * Initial revision
  32.  *
  33. \*/
  34.  
  35. #include "bitio.h"
  36.  
  37. struct bitstream
  38. {
  39.     FILE *
  40.         f;        /* bytestream */
  41.     unsigned long
  42.         bitbuf;        /* bit buffer */
  43.     int
  44.         nbitbuf;    /* number of bits in 'bitbuf' */
  45.     char
  46.         mode;
  47. };
  48.  
  49. #define Mask(n)        ((1<<(n))-1)
  50.  
  51. #define BitPut(b,ul,n)    ((b)->bitbuf = (((b)->bitbuf<<(n))    \
  52.                     |((ul)&Mask(n))),    \
  53.             (b)->nbitbuf += (n))
  54.  
  55. #define BitGet(b,n)    (((b)->bitbuf>>((b)->nbitbuf-=(n))) & Mask(n))
  56.  
  57. /*
  58.  * pm_bitinit() - allocate and return a struct bitstream * for the
  59.  * given FILE*.
  60.  *
  61.  * mode must be one of "r" or "w", according to whether you will be
  62.  * reading from or writing to the struct bitstream *.
  63.  *
  64.  * Returns 0 on error.
  65.  */
  66.  
  67. struct bitstream *
  68. pm_bitinit(f, mode)
  69.     FILE           *f;
  70.     char           *mode;
  71. {
  72.     struct bitstream *ans = (struct bitstream *)0;
  73.  
  74.     if(!f || !mode || !*mode)
  75.         return ans;
  76.     if(strcmp(mode, "r") && strcmp(mode, "w"))
  77.         return ans;
  78.  
  79.     ans = (struct bitstream *)calloc(1, sizeof(struct bitstream));
  80.     if(ans)
  81.     {
  82.         ans->f = f;
  83.         ans->mode = *mode;
  84.     }
  85.  
  86.     return ans;
  87. }
  88.  
  89. /*
  90.  * pm_bitfini() - deallocate the given struct bitstream *.
  91.  *
  92.  * You must call this after you are done with the struct bitstream *.
  93.  * 
  94.  * It may flush some bits left in the buffer.
  95.  *
  96.  * Returns the number of bytes written, -1 on error.
  97.  */
  98.  
  99. int
  100. pm_bitfini(b)
  101.     struct bitstream *b;
  102. {
  103.     int        nbyte = 0;
  104.  
  105.     if(!b)
  106.         return -1;
  107.  
  108.     /* flush the output */
  109.     if(b->mode == 'w')
  110.     {
  111.         /* flush the bits */
  112.         if (b->nbitbuf < 0 || b->nbitbuf >= 8)
  113.         {
  114.             /* pm_bitwrite() didn't work */
  115.             return -1;
  116.         }
  117.  
  118.         /*
  119.          * If we get to here, nbitbuf is 0..7
  120.          */
  121.         if(b->nbitbuf)
  122.         {
  123.             char    c;
  124.  
  125.             BitPut(b, 0, (long)8-(b->nbitbuf));
  126.             c = (char) BitGet(b, (long)8);
  127.             if(putc(c, b->f) == EOF)
  128.             {
  129.                 return -1;
  130.             }
  131.             nbyte++;
  132.         }
  133.     }
  134.  
  135.     free(b);
  136.     return nbyte;
  137. }
  138.  
  139. /*
  140.  * pm_bitread() - read the next nbits into *val from the given file.
  141.  * 
  142.  * The last pm_bitread() must be followed by a call to pm_bitfini().
  143.  * 
  144.  * Returns the number of bytes read, -1 on error.
  145.  */
  146.  
  147. int 
  148. pm_bitread(b, nbits, val)
  149.     struct bitstream *b;
  150.     unsigned long   nbits;
  151.     unsigned long  *val;
  152. {
  153.     int        nbyte = 0;
  154.     int        c;
  155.  
  156.     if(!b)
  157.         return -1;
  158.  
  159.     while (b->nbitbuf < nbits)
  160.     {
  161.         if((c = getc(b->f)) == EOF)
  162.         {
  163.             return -1;
  164.         }
  165.         nbyte++;
  166.  
  167.         BitPut(b, c, (long) 8);
  168.     }
  169.  
  170.     *val = BitGet(b, nbits);
  171.     return nbyte;
  172. }
  173.  
  174. /*
  175.  * pm_bitwrite() - write the low nbits of val to the given file.
  176.  * 
  177.  * The last pm_bitwrite() must be followed by a call to pm_bitfini().
  178.  * 
  179.  * Returns the number of bytes written, -1 on error.
  180.  */
  181.  
  182. int
  183. pm_bitwrite(b, nbits, val)
  184.     struct bitstream *b;
  185.     unsigned long   nbits;
  186.     unsigned long   val;
  187. {
  188.     int        nbyte = 0;
  189.     char        c;
  190.  
  191.     if(!b)
  192.         return -1;
  193.  
  194.     BitPut(b, val, nbits);
  195.  
  196.     while (b->nbitbuf >= 8)
  197.     {
  198.         c = (char) BitGet(b, (long)8);
  199.  
  200.         if(putc(c, b->f) == EOF)
  201.         {
  202.             return -1;
  203.         }
  204.         nbyte++;
  205.     }
  206.  
  207.     return nbyte;
  208. }
  209.