|
|
1.1 ! root 1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */ ! 2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */ ! 3: /* The copyright notice does not imply actual or intended publication. */ ! 4: /* AUTHORS: */ ! 5: /* H. S. Baird - ATT-BL MH - first versions */ ! 6: ! 7: /* bitio.h - view a stream file as a sequence of binary values, hiding the ! 8: bit- and byte-packing format of the file. The format of input and output ! 9: files may differ. Reading and writing are performed by macroes for speed; ! 10: the price for this is that the file formats must be fixed at compile time. ! 11: ! 12: SYNOPSIS ! 13: #include <stdio.h> ! 14: #include "bitio.h" ! 15: ! 16: BITFILE *bopen(stream,type); ! 17: FILE *stream; ! 18: char *type; ! 19: ! 20: int getb(bitfile); ! 21: BITFILE *bitfile; ! 22: ! 23: putb(bit,bitfile); ! 24: int bit; ! 25: ! 26: padb(bitfile,bit,bdy,len); ! 27: int bit,bdy,len; ! 28: ! 29: char *bbuffer(bitfile); ! 30: ! 31: unsigned long bsize(bitfile); ! 32: ! 33: unsigned long bflush(bitfile); ! 34: ! 35: unsigned long bclose(bitfile); ! 36: ! 37: COMPILER DEPENDENCIES ! 38: The compiler's data types must include: ! 39: unsigned char: 8 bits each ! 40: unsigned short: 2 unsigned chars each ! 41: unsigned int: 2 unsigned shorts each ! 42: DESCRIPTION ! 43: Bopen views the named stream file as a bit file to be read (if type is "r") ! 44: or written (if type is "w" or "wb"). The stream file must already have been ! 45: fopen(3)ed, and the first bit to be read/written will be the first bit in its ! 46: next byte in getc(3)/putc(3) order. Bopen returns a pointer which identifies ! 47: the bitfile to the other functions. System or stream I/O to/from the ! 48: associated stream should not be used until after bclose is called. ! 49: If bopen's type is "wb", then the entire output stream will be buffered ! 50: in main memory until bflush or bclose are called. At any time, bbuffer ! 51: returns this buffer's address and bsize its length in bytes. ! 52: Getb returns the next bit from the named bitfile. It returns EOF on ! 53: end of file or read error. EOF may occur on a byte, short, or int boundary, ! 54: depending on file format. ! 55: Putb appends the given bit to the named bitfile. ! 56: Padb writes 'bit' enough times (possibly 0) so that if a bitstring ! 57: of length 'len' were written next it would end on a 'bdy'-bit boundary ! 58: (may do the wrong thing if 'bdy' doesn't divide UINT_MAX). ! 59: Bflush ensures that all written bits have been written to the stream ! 60: via putc(3). The output is padded with 0 bits to a byte, short, or int ! 61: boundary, depending on file format. It returns the number of bytes (not bits) ! 62: written since bopen or the last bflush. The bitfile remains open. It does not ! 63: fflush(3) the associated stream. ! 64: Bclose causes a bflush and frees all buffers. It returns the total ! 65: number of bytes (not bits) read/written since bopen. It fflush(3)'es, ! 66: but does not fclose(3) the associated stream. ! 67: ! 68: Bitfile formats are selected at compile time: see `FORMAT:' at the ! 69: end of this file. The formats for input and output may differ. Formats ! 70: include: ! 71: a each bit is an ASCII character: '0' or '1', in putc(3) order; not padded. ! 72: 0 the low-order (0001) bit in each byte is first ("little-endian"), and ! 73: bytes are in putc(3) order; EOF and padding at a byte boundary. ! 74: 1 the high-order (0200) bit in each byte is first ("big-endian"), and ! 75: bytes are in putc(3) order; EOF and padding at a byte boundary. ! 76: 10 the low-order (0001) bit in each byte is first ("little-endian"), but ! 77: bytes are reversed (in each pair) from putc(3) order; EOF and padding ! 78: at a short boundary. ! 79: 11 the high-order (0200) bit in each byte is first ("big-endian"), but ! 80: bytes are reversed (in each pair) from putc(3) order; EOF and padding ! 81: at a short boundary. ! 82: Planned (data structures are in place; code will be implemented if needed): ! 83: 100 the low-order (0001) bit in each byte is first ("little-endian"), and ! 84: bytes (in each pair) are in putc(3) order; but shorts (in each pair) ! 85: are reversed from putc(3) order; EOF and padding at an int boundary. ! 86: 101, 110, 111 - by obvious analogy ! 87: BUGS ! 88: Putting to an input bitfile or getting from an output bitfile is ! 89: erroneous, but is not checked for. ! 90: */ ! 91: ! 92: #define BUFFERED (T) /* enable buffering of output */ ! 93: ! 94: typedef struct BITFILE { ! 95: FILE *fp; /* associated stream */ ! 96: char type; /* one of 'r','w' */ ! 97: int ic; /* byte just read */ ! 98: unsigned long nb; /* no. bytes read/written since bopen */ ! 99: unsigned long alloc; /* no. bytes allocated in buffer */ ! 100: char *buf; /* buffer (in malloc space) */ ! 101: char *cp; /* next char in buffer */ ! 102: unsigned int n; /* no. bits written so far (mod UINT_MAX) */ ! 103: unsigned char cm; /* single-bit mask */ ! 104: unsigned short sm; /* single-bit mask */ ! 105: unsigned int im; /* single-bit mask */ ! 106: union { struct { /* used to reorder char & short order */ ! 107: union { struct { ! 108: unsigned char c0; ! 109: unsigned char c1; ! 110: } cc; ! 111: unsigned short s; ! 112: } s0; ! 113: union { struct { ! 114: unsigned char c0; ! 115: unsigned char c1; ! 116: } cc; ! 117: unsigned short s; ! 118: } s1; ! 119: } ss; ! 120: unsigned int i; ! 121: } i; ! 122: } BITFILE; ! 123: #define Init_BITFILE {NULL,'\0',0,0L,0L,NULL,NULL,0,0,0} ! 124: #if MAIN ! 125: BITFILE empty_BITFILE = Init_BITFILE; ! 126: #else ! 127: extern BITFILE empty_BITFILE; ! 128: #endif ! 129: ! 130: /* Code common to all formats: */ ! 131: #if MAIN ! 132: BITFILE *bopen_rw(s,t) ! 133: FILE *s; ! 134: char *t; ! 135: { BITFILE *f; ! 136: if((f=(BITFILE *)malloc(sizeof(BITFILE)))==NULL) { ! 137: err("bopen: can't alloc"); ! 138: return(NULL); ! 139: }; ! 140: *f = empty_BITFILE; ! 141: f->fp = s; ! 142: f->type = *t; ! 143: return(f); ! 144: } ! 145: #else ! 146: BITFILE *bopen_rw(); ! 147: #endif ! 148: ! 149: #define bbuffer(f) ((f)->buf) ! 150: #define bsize(f) ((bbuffer(f)!=NULL)? ((f)->cp - (f)->buf): 0L) ! 151: ! 152: #if !BUFFERED ! 153: #define bputc(c,f) putc((c),(f)->fp) ! 154: #define bbflush(f) (0L) ! 155: #else ! 156: #define BITFILE_incr (512) /* buffer allocations are in these increments */ ! 157: ! 158: #if MAIN ! 159: brealloc(f) ! 160: BITFILE *f; ! 161: { int nbuf; /* no. bytes in buffer */ ! 162: nbuf = bsize(f); ! 163: f->alloc += BITFILE_incr; ! 164: if((f->buf=(char *)realloc(f->buf,f->alloc))==NULL) ! 165: abort(""); ! 166: f->cp = f->buf + nbuf; ! 167: } ! 168: #endif ! 169: ! 170: #define bputc(c,f) { \ ! 171: if((f)->buf==NULL) putc((c),(f)->fp); \ ! 172: else { if(bsize(f)==(f)->alloc) brealloc(f); \ ! 173: *(++((f)->cp))=(c); \ ! 174: } \ ! 175: } ! 176: ! 177: #if MAIN ! 178: unsigned long bbflush(f) ! 179: BITFILE *f; /* f->buf!=NULL && bsize(f)>0 */ ! 180: { register char *cp,*cq; ! 181: unsigned long nbuf; ! 182: nbuf = bsize(f); ! 183: for(cq=(cp=f->buf)+nbuf; cp<cq; cp++) putc(*cp,f->fp); ! 184: f->cp=f->buf; ! 185: return(nbuf); ! 186: } ! 187: #else ! 188: unsigned long bbflush(); ! 189: #endif ! 190: #endif ! 191: ! 192: /* Code particular to each format: */ ! 193: ! 194: /* Format a: ASCII file, one printable char ('0' or '1') per bit: */ ! 195: #define bopen_r_a(s) bopen_rw((s),"r") ! 196: #define bopen_w_a(s) bopen_rw((s),"w") ! 197: #define getb_a(f) ( (((f)->ic=getc((f)->fp))!=EOF)? \ ! 198: ((f)->nb++, \ ! 199: ((f)->ic=='0')? \ ! 200: 0: \ ! 201: (((f)->ic=='1')? 1: EOF)): \ ! 202: EOF ) ! 203: #define putb_a(b,f) { if((b)) bputc('1',f); else bputc('0',f); (f)->nb++; } ! 204: #define bflush_a(f) ( (bsize(f)>0)? bbflush(f): (0L) ) ! 205: ! 206: /* Format 0: the low-order bit (0001) in each byte is first ("little-endian"), ! 207: and bytes are in putc(3) order; */ ! 208: #if MAIN ! 209: BITFILE *bopen_r_0(s) ! 210: FILE *s; ! 211: { BITFILE *f; ! 212: if((f=bopen_rw(s,"r"))!=NULL) { ! 213: f->cm=0000; ! 214: }; ! 215: return(f); ! 216: } ! 217: #else ! 218: BITFILE *bopen_r_0(); ! 219: #endif ! 220: #if MAIN ! 221: BITFILE *bopen_w_0(s) ! 222: FILE *s; ! 223: { BITFILE *f; ! 224: if((f=bopen_rw(s,"w"))!=NULL) { ! 225: f->i.ss.s0.cc.c0=0000; ! 226: f->cm=0001; ! 227: }; ! 228: return(f); ! 229: } ! 230: #else ! 231: BITFILE *bopen_w_0(); ! 232: #endif ! 233: #define getb_0(f) ( ((f)->cm)? \ ! 234: ( ((f)->cm&(f)->ic)? \ ! 235: ((f)->cm<<=1,1): \ ! 236: ((f)->cm<<=1,0) ): \ ! 237: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 238: EOF: \ ! 239: ( (f)->nb++, \ ! 240: (f)->cm=0001, \ ! 241: ((f)->cm&(f)->ic)? \ ! 242: ((f)->cm<<=1,1): \ ! 243: ((f)->cm<<=1,0) ) ) ) ! 244: #define putb_0(b,f) { \ ! 245: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \ ! 246: if( !((f)->cm<<=1) ) { \ ! 247: bputc((f)->i.ss.s0.cc.c0,f); \ ! 248: (f)->nb++; \ ! 249: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0001; \ ! 250: }; \ ! 251: (f)->n++; \ ! 252: } ! 253: #define bflush_0(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L) ! 254: ! 255: /* Format 1: the high-order bit (0200) in each byte is first ("big-endian"), and ! 256: bytes are in putc(3) order; */ ! 257: #if MAIN ! 258: BITFILE *bopen_r_1(s) ! 259: FILE *s; ! 260: { BITFILE *f; ! 261: if((f=bopen_rw(s,"r"))!=NULL) { ! 262: f->cm=0000; ! 263: }; ! 264: return(f); ! 265: } ! 266: #else ! 267: BITFILE *bopen_r_1(); ! 268: #endif ! 269: #if MAIN ! 270: BITFILE *bopen_w_1(s) ! 271: FILE *s; ! 272: { BITFILE *f; ! 273: if((f=bopen_rw(s,"w"))!=NULL) { ! 274: f->i.ss.s0.cc.c0=0000; ! 275: f->cm=0200; ! 276: }; ! 277: return(f); ! 278: } ! 279: #else ! 280: BITFILE *bopen_w_1(); ! 281: #endif ! 282: #define getb_1(f) ( ((f)->cm)? \ ! 283: ( ((f)->cm&(f)->ic)? \ ! 284: ((f)->cm>>=1,1): \ ! 285: ((f)->cm>>=1,0) ): \ ! 286: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 287: EOF: \ ! 288: ( (f)->nb++, \ ! 289: (f)->cm=0200, \ ! 290: ((f)->cm&(f)->ic)? \ ! 291: ((f)->cm>>=1,1): \ ! 292: ((f)->cm>>=1,0) ) ) ) ! 293: #define putb_1(b,f) { \ ! 294: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \ ! 295: if( !((f)->cm>>=1) ) { \ ! 296: bputc((f)->i.ss.s0.cc.c0,f); \ ! 297: (f)->nb++; \ ! 298: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0200; \ ! 299: }; \ ! 300: (f)->n++; \ ! 301: } ! 302: #define bflush_1(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L) ! 303: ! 304: /* Format 10: the low-order (0001) bit in each byte is first ("little-endian"), and ! 305: bytes are reversed (in each pair) from putc(3) order; ! 306: */ ! 307: #if MAIN ! 308: BITFILE *bopen_r_10(s) ! 309: FILE *s; ! 310: { BITFILE *f; ! 311: if((f=bopen_rw(s,"r"))!=NULL) { ! 312: f->sm=0000000; ! 313: }; ! 314: return(f); ! 315: } ! 316: #else ! 317: BITFILE *bopen_r_10(); ! 318: #endif ! 319: #if MAIN ! 320: BITFILE *bopen_w_10(s) ! 321: FILE *s; ! 322: { BITFILE *f; ! 323: if((f=bopen_rw(s,"w"))!=NULL) { ! 324: f->i.ss.s0.s=0000000; ! 325: f->sm=0000001; ! 326: }; ! 327: return(f); ! 328: } ! 329: #else ! 330: BITFILE *bopen_w_10(); ! 331: #endif ! 332: #define getb_10(f) ( ((f)->sm)? \ ! 333: ( ((f)->sm&(f)->i.ss.s0.s)? \ ! 334: ((f)->sm<<=1,1): \ ! 335: ((f)->sm<<=1,0) ): \ ! 336: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 337: EOF: \ ! 338: ( (f)->nb++, \ ! 339: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \ ! 340: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 341: EOF: \ ! 342: ( (f)->nb++, \ ! 343: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \ ! 344: (f)->sm=0000001, \ ! 345: ((f)->sm&(f)->i.ss.s0.s)? \ ! 346: ((f)->sm<<=1,1): \ ! 347: ((f)->sm<<=1,0) ) ) ) ) ) ! 348: #define putb_10(b,f) { \ ! 349: if((b)) (f)->i.ss.s0.s |= (f)->sm; \ ! 350: if( !((f)->sm<<=1) ) { \ ! 351: bputc((f)->i.ss.s0.cc.c1,f); \ ! 352: (f)->nb++; \ ! 353: bputc((f)->i.ss.s0.cc.c0,f); \ ! 354: (f)->nb++; \ ! 355: (f)->i.ss.s0.s=0000000; (f)->sm=0000001; \ ! 356: }; \ ! 357: (f)->n++; \ ! 358: } ! 359: #define bflush_10(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L) ! 360: ! 361: /* Format 11: the high-order (0200) bit in each byte is first ("little-endian"), ! 362: and bytes are reversed (in each pair) from putc(3) order. ! 363: */ ! 364: #if MAIN ! 365: BITFILE *bopen_r_11(s) ! 366: FILE *s; ! 367: { BITFILE *f; ! 368: if((f=bopen_rw(s,"r"))!=NULL) { ! 369: f->sm=0000000; ! 370: }; ! 371: return(f); ! 372: } ! 373: #else ! 374: BITFILE *bopen_r_11(); ! 375: #endif ! 376: #if MAIN ! 377: BITFILE *bopen_w_11(s) ! 378: FILE *s; ! 379: { BITFILE *f; ! 380: if((f=bopen_rw(s,"w"))!=NULL) { ! 381: f->i.ss.s0.s=0000000; ! 382: f->sm=0100000; ! 383: }; ! 384: return(f); ! 385: } ! 386: #else ! 387: BITFILE *bopen_w_11(); ! 388: #endif ! 389: #define getb_11(f) ( ((f)->sm)? \ ! 390: ( ((f)->sm&(f)->i.ss.s0.s)? \ ! 391: ((f)->sm>>=1,1): \ ! 392: ((f)->sm>>=1,0) ): \ ! 393: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 394: EOF: \ ! 395: ( (f)->nb++, \ ! 396: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \ ! 397: ( (((f)->ic=getc((f)->fp))==EOF)? \ ! 398: EOF: \ ! 399: ( (f)->nb++, \ ! 400: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \ ! 401: (f)->sm=0100000, \ ! 402: ((f)->sm&(f)->i.ss.s0.s)? \ ! 403: ((f)->sm>>=1,1): \ ! 404: ((f)->sm>>=1,0) ) ) ) ) ) ! 405: #define putb_11(b,f) { \ ! 406: if((b)) (f)->i.ss.s0.s |= (f)->sm; \ ! 407: if( !((f)->sm>>=1) ) { \ ! 408: bputc((f)->i.ss.s0.cc.c0,f); \ ! 409: (f)->nb++; \ ! 410: bputc((f)->i.ss.s0.cc.c1,f); \ ! 411: (f)->nb++; \ ! 412: (f)->i.ss.s0.s=0000000; (f)->sm=0100000; \ ! 413: }; \ ! 414: (f)->n++; \ ! 415: } ! 416: #define bflush_11(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L) ! 417: ! 418: /**************************************************************/ ! 419: /* FORMAT: may be selected here (input and output may differ) */ ! 420: ! 421: /* Input: */ ! 422: #define bopen_r(s) bopen_r_0((s)) ! 423: #define getb(f) getb_0(f) ! 424: /* Output: */ ! 425: #define bopen_w(s) bopen_w_0((s)) ! 426: #define putb(b,f) putb_0((b),(f)) ! 427: #define bflush(f) bflush_0(f) ! 428: ! 429: /**************************************************************/ ! 430: ! 431: /* Code common to all formats: */ ! 432: #if MAIN ! 433: BITFILE *bopen(s,t) ! 434: FILE *s; ! 435: char *t; ! 436: { BITFILE *res; ! 437: if(*(t)=='r') res=bopen_r(s); ! 438: else if(*(t)=='w') { ! 439: res=bopen_w(s); ! 440: #if BUFFERED ! 441: if(*(t+1)=='b') { ! 442: res->alloc = BITFILE_incr; ! 443: if((res->buf=(char *)malloc(res->alloc))==NULL) ! 444: abort("bopen: can't alloc buffer"); ! 445: res->cp = res->buf; ! 446: }; ! 447: #endif ! 448: } ! 449: else abort("bopen: bad type: \"%s\"",t); ! 450: return(res); ! 451: } ! 452: #else ! 453: BITFILE *bopen(); ! 454: #endif ! 455: ! 456: #if MAIN ! 457: padb(f,b,B,l) ! 458: BITFILE *f; ! 459: char b; ! 460: int l,B; ! 461: { while(((f)->n+(l))%(B)) putb((b),(f)); ! 462: } ! 463: #endif ! 464: ! 465: #if MAIN ! 466: unsigned long bclose(f) ! 467: BITFILE *f; ! 468: { unsigned long nb,nbuf; ! 469: if(f->type=='w') { ! 470: nbuf=bflush(f); ! 471: fflush(f->fp); ! 472: #if BUFFERED ! 473: if(f->buf!=NULL) { free(f->buf); f->buf=NULL; } ! 474: #endif ! 475: }; ! 476: nb=f->nb; ! 477: free(f); ! 478: return(nb); ! 479: } ! 480: #else ! 481: unsigned long bclose(); ! 482: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.