Annotation of researchv10no/cmd/bcp/bitio.h, revision 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.