Panda3D
|
00001 /* 00002 * bitio.c - bitstream I/O 00003 * 00004 * Works for (sizeof(unsigned long)-1)*8 bits. 00005 * 00006 * Copyright (C) 1992 by David W. Sanderson. 00007 * 00008 * Permission to use, copy, modify, and distribute this software and its 00009 * documentation for any purpose and without fee is hereby granted, 00010 * provided that the above copyright notice appear in all copies and 00011 * that both that copyright notice and this permission notice appear 00012 * in supporting documentation. This software is provided "as is" 00013 * without express or implied warranty. 00014 */ 00015 00016 #include "pnmbitio.h" 00017 #include <assert.h> 00018 struct bitstream 00019 { 00020 istream *inf; 00021 ostream *outf; 00022 unsigned long 00023 bitbuf; /* bit buffer */ 00024 int 00025 nbitbuf; /* number of bits in 'bitbuf' */ 00026 char 00027 mode; 00028 }; 00029 00030 #define Mask(n) ((1<<(n))-1) 00031 00032 #define BitPut(b,ul,n) ((b)->bitbuf = (((b)->bitbuf<<(n)) \ 00033 |((ul)&Mask(n))), \ 00034 (b)->nbitbuf += (n)) 00035 00036 #define BitGet(b,n) (((b)->bitbuf>>((b)->nbitbuf-=(n))) & Mask(n)) 00037 00038 /* 00039 * pm_bitinit() - allocate and return a struct bitstream * for the 00040 * given FILE*. 00041 * 00042 * mode must be one of "r" or "w", according to whether you will be 00043 * reading from or writing to the struct bitstream *. 00044 * 00045 * Returns 0 on error. 00046 */ 00047 00048 EXPCL_PANDA_PNMIMAGE struct bitstream * 00049 pm_bitinit(istream *f, const char *mode) 00050 { 00051 struct bitstream *ans = (struct bitstream *)0; 00052 00053 if(!f || !mode || !*mode) 00054 return ans; 00055 if(strcmp(mode, "r")) 00056 return ans; 00057 00058 ans = (struct bitstream *)calloc(1, sizeof(struct bitstream)); 00059 if(ans) 00060 { 00061 ans->inf = f; 00062 ans->mode = *mode; 00063 } 00064 00065 return ans; 00066 } 00067 00068 EXPCL_PANDA_PNMIMAGE struct bitstream * 00069 pm_bitinit(ostream *f, const char *mode) 00070 { 00071 struct bitstream *ans = (struct bitstream *)0; 00072 00073 if(!f || !mode || !*mode) 00074 return ans; 00075 if(strcmp(mode, "w")) 00076 return ans; 00077 00078 ans = (struct bitstream *)calloc(1, sizeof(struct bitstream)); 00079 if(ans) 00080 { 00081 ans->outf = f; 00082 ans->mode = *mode; 00083 } 00084 00085 return ans; 00086 } 00087 00088 /* 00089 * pm_bitfini() - deallocate the given struct bitstream *. 00090 * 00091 * You must call this after you are done with the struct bitstream *. 00092 * 00093 * It may flush some bits left in the buffer. 00094 * 00095 * Returns the number of bytes written, -1 on error. 00096 */ 00097 00098 EXPCL_PANDA_PNMIMAGE int 00099 pm_bitfini(struct bitstream *b) 00100 { 00101 int nbyte = 0; 00102 00103 if(!b) 00104 return -1; 00105 00106 /* flush the output */ 00107 if(b->mode == 'w') 00108 { 00109 /* flush the bits */ 00110 if (b->nbitbuf < 0 || b->nbitbuf >= 8) 00111 { 00112 /* pm_bitwrite() didn't work */ 00113 return -1; 00114 } 00115 00116 /* 00117 * If we get to here, nbitbuf is 0..7 00118 */ 00119 if(b->nbitbuf) 00120 { 00121 char c; 00122 00123 BitPut(b, 0, (long)8-(b->nbitbuf)); 00124 c = (char) BitGet(b, (long)8); 00125 if(!b->outf->put(c)) 00126 { 00127 return -1; 00128 } 00129 nbyte++; 00130 } 00131 } 00132 00133 free(b); 00134 return nbyte; 00135 } 00136 00137 /* 00138 * pm_bitread() - read the next nbits into *val from the given file. 00139 * 00140 * The last pm_bitread() must be followed by a call to pm_bitfini(). 00141 * 00142 * Returns the number of bytes read, -1 on error. 00143 */ 00144 00145 EXPCL_PANDA_PNMIMAGE int 00146 pm_bitread(struct bitstream *b, unsigned long nbits, unsigned long *val) 00147 { 00148 int nbyte = 0; 00149 int c; 00150 00151 if(!b) 00152 return -1; 00153 00154 #ifdef _DEBUG 00155 assert(((signed long)nbits) > 0); 00156 #endif 00157 00158 while (b->nbitbuf < (signed long)nbits) 00159 { 00160 if((c = b->inf->get()) == EOF) 00161 { 00162 return -1; 00163 } 00164 nbyte++; 00165 00166 BitPut(b, c, (long) 8); 00167 } 00168 00169 *val = BitGet(b, nbits); 00170 return nbyte; 00171 } 00172 00173 /* 00174 * pm_bitwrite() - write the low nbits of val to the given file. 00175 * 00176 * The last pm_bitwrite() must be followed by a call to pm_bitfini(). 00177 * 00178 * Returns the number of bytes written, -1 on error. 00179 */ 00180 00181 EXPCL_PANDA_PNMIMAGE int 00182 pm_bitwrite(struct bitstream *b, unsigned long nbits, unsigned long val) 00183 { 00184 int nbyte = 0; 00185 char c; 00186 00187 if(!b) 00188 return -1; 00189 00190 BitPut(b, val, nbits); 00191 00192 while (b->nbitbuf >= 8) 00193 { 00194 c = (char) BitGet(b, (long)8); 00195 00196 if(!b->outf->put(c)) 00197 { 00198 return -1; 00199 } 00200 nbyte++; 00201 } 00202 00203 return nbyte; 00204 }