Annotation of researchv10no/cmd/bcp/bitio.h, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.