home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 4441 / mpegcode / src / bitio.c < prev    next >
C/C++ Source or Header  |  1993-09-27  |  14KB  |  520 lines

  1. /*===========================================================================*
  2.  * bitio.c                                     *
  3.  *                                         *
  4.  *    Procedures concerned with the bit-wise I/O                 *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    Bitio_New                                 *
  8.  *    Bitio_Free                                 *
  9.  *    Bitio_Write                                 *
  10.  *    Bitio_Flush                                 *
  11.  *    Bitio_WriteToSocket                             *
  12.  *    Bitio_BytePad                                 *
  13.  *                                         *
  14.  *===========================================================================*/
  15.  
  16. /*
  17.  * Copyright (c) 1993 The Regents of the University of California.
  18.  * All rights reserved.
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose, without fee, and without written agreement is
  22.  * hereby granted, provided that the above copyright notice and the following
  23.  * two paragraphs appear in all copies of this software.
  24.  *
  25.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  26.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  27.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  28.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  31.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  32.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  33.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  34.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  35.  */
  36.  
  37. /*
  38.  *  $Header: /n/picasso/users/keving/encode/src/RCS/bitio.c,v 1.9 1993/07/22 22:23:43 keving Exp keving $
  39.  *  $Log: bitio.c,v $
  40.  * Revision 1.9  1993/07/22  22:23:43  keving
  41.  * nothing
  42.  *
  43.  * Revision 1.8  1993/06/30  20:06:09  keving
  44.  * nothing
  45.  *
  46.  * Revision 1.7  1993/06/03  21:08:08  keving
  47.  * nothing
  48.  *
  49.  * Revision 1.6  1993/02/17  23:21:41  dwallach
  50.  * checkin prior to keving's joining the project
  51.  *
  52.  * Revision 1.5  1993/01/18  10:20:02  dwallach
  53.  * *** empty log message ***
  54.  *
  55.  * Revision 1.4  1993/01/18  10:17:29  dwallach
  56.  * RCS headers installed, code indented uniformly
  57.  *
  58.  * Revision 1.4  1993/01/18  10:17:29  dwallach
  59.  * RCS headers installed, code indented uniformly
  60.  *
  61.  */
  62.  
  63. /*==============*
  64.  * HEADER FILES *
  65.  *==============*/
  66.  
  67. #include <assert.h>
  68. #include "all.h"
  69. #include "byteorder.h"
  70. #include "bitio.h"
  71. #include "mtypes.h"
  72.  
  73.  
  74. /*===============================*
  75.  * INTERNAL PROCEDURE prototypes *
  76.  *===============================*/
  77.  
  78. static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
  79.  
  80.  
  81. /*==================*
  82.  * STATIC VARIABLES *
  83.  *==================*/
  84.  
  85. static uint32 lower_mask[33] = {
  86.     0,
  87.     0x1, 0x3, 0x7, 0xf,
  88.     0x1f, 0x3f, 0x7f, 0xff,
  89.     0x1ff, 0x3ff, 0x7ff, 0xfff,
  90.     0x1fff, 0x3fff, 0x7fff, 0xffff,
  91.     0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
  92.     0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
  93.     0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
  94.     0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
  95. };
  96.  
  97.  
  98. /*=====================*
  99.  * EXPORTED PROCEDURES *
  100.  *=====================*/
  101.  
  102.  
  103. /*===========================================================================*
  104.  *
  105.  * Bitio_New
  106.  *
  107.  *    Create a new bit bucket; filePtr is a pointer to the open file the
  108.  *    bits should ultimately be written to.
  109.  *
  110.  * RETURNS:    pointer to the resulting bit bucket
  111.  *
  112.  * SIDE EFFECTS:    none
  113.  *
  114.  *===========================================================================*/
  115. BitBucket *
  116. Bitio_New(filePtr)
  117.     FILE *filePtr;
  118. {
  119.     BitBucket *bbPtr;
  120.  
  121.     bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
  122.     ERRCHK(bbPtr, "malloc");
  123.  
  124.     bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
  125.     ERRCHK(bbPtr->firstPtr, "malloc");
  126.  
  127.     bbPtr->totalbits = 0;
  128.     bbPtr->cumulativeBits = 0;
  129.     bbPtr->bitsWritten = 0;
  130.     bbPtr->filePtr = filePtr;
  131.  
  132.     bbPtr->firstPtr->nextPtr = NULL;
  133.     bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
  134.     bbPtr->firstPtr->bitsleftcur = 32;
  135.     bbPtr->firstPtr->currword = 0;
  136.     bzero((char *)bbPtr->firstPtr->bits, sizeof(uint32) * WORDS_PER_BUCKET);
  137.  
  138.     return bbPtr;
  139. }
  140.  
  141.  
  142. /*===========================================================================*
  143.  *
  144.  * Bitio_Free
  145.  *
  146.  *    Frees the memory associated with the given bit bucket
  147.  *
  148.  * RETURNS:    nothing
  149.  *
  150.  * SIDE EFFECTS:    none
  151.  *
  152.  *===========================================================================*/
  153. void
  154. Bitio_Free(bbPtr)
  155.     BitBucket *bbPtr;
  156. {
  157.     struct bitBucket *tmpPtr, *nextPtr;
  158.  
  159.     for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
  160.     nextPtr = tmpPtr->nextPtr;
  161.     free(tmpPtr);
  162.     }
  163.     free(bbPtr);
  164. }
  165.  
  166.  
  167. /*===========================================================================*
  168.  *
  169.  * Bitio_Write
  170.  *
  171.  *    Writes 'nbits' bits from 'bits' into the given bit bucket
  172.  *    'nbits' must be between 0 and 32
  173.  *
  174.  * RETURNS:    nothing
  175.  *
  176.  * SIDE EFFECTS:    if the number of bits in the bit bucket surpasses
  177.  *            MAX_BITS, then that many bits are flushed to the
  178.  *            appropriate output file
  179.  *
  180.  *===========================================================================*/
  181. void
  182. Bitio_Write(bbPtr, bits, nbits)
  183.     BitBucket *bbPtr;
  184.     uint32 bits;
  185.     int nbits;
  186. {
  187.     register struct bitBucket *lastPtr, *newPtr;
  188.     register int delta;
  189.  
  190.     assert(nbits <= 32 && nbits >= 0);
  191.  
  192.     /*
  193.      * Clear top bits if not part of data, necessary due to down and
  194.      * dirty calls of Bitio_Write with unecessary top bits set.
  195.      */
  196.  
  197.     bits = bits & lower_mask[nbits];
  198.  
  199.     bbPtr->totalbits += nbits;
  200.     bbPtr->cumulativeBits += nbits;
  201.     lastPtr = bbPtr->lastPtr;
  202.  
  203.     delta = nbits - lastPtr->bitsleft;
  204.     if (delta >= 0) {
  205.     /*
  206.          * there's not enough room in the current bucket, so we're
  207.          * going to have to allocate another bucket
  208.          */
  209.     newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
  210.     ERRCHK(newPtr, "malloc");
  211.     newPtr->nextPtr = NULL;
  212.     newPtr->bitsleft = MAXBITS_PER_BUCKET;
  213.     newPtr->bitsleftcur = 32;
  214.     newPtr->currword = 0;
  215.     bzero(newPtr->bits, sizeof(uint32) * WORDS_PER_BUCKET);
  216.     bbPtr->lastPtr = newPtr;
  217.  
  218.     assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
  219.     lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
  220.     lastPtr->bitsleft = 0;
  221.     lastPtr->bitsleftcur = 0;
  222.     /* lastPtr->currword++; */
  223.  
  224.     if (!delta) {
  225.         if ( bbPtr->totalbits > MAX_BITS ) {
  226.         Dump(bbPtr);
  227.         }
  228.     }
  229.  
  230.     assert(delta <= 32);
  231.     newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
  232.     newPtr->bitsleft -= delta;
  233.     newPtr->bitsleftcur -= delta;
  234.     } else {
  235.     /*
  236.          * the current bucket will be sufficient
  237.      */
  238.     delta = nbits - lastPtr->bitsleftcur;
  239.     lastPtr->bitsleftcur -= nbits;
  240.     lastPtr->bitsleft -= nbits;
  241.  
  242.     if (delta >= 0)
  243.     {
  244.         /*
  245.          * these bits will span more than one word
  246.          */
  247.         lastPtr->bits[lastPtr->currword] |= (bits >> delta);
  248.         lastPtr->currword++;
  249.         lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
  250.         lastPtr->bitsleftcur = 32 - delta;
  251.     } else {
  252.         /*
  253.          * these bits will fit, whole
  254.          */
  255.         lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
  256.     }
  257.     }
  258.  
  259.     if ( bbPtr->totalbits > MAX_BITS )    /* flush bits */
  260.     Dump(bbPtr);
  261. }
  262.  
  263.  
  264. /*===========================================================================*
  265.  *
  266.  * Bitio_Flush
  267.  *
  268.  *    Flushes all of the remaining bits in the given bit bucket to the
  269.  *    appropriate output file.  It will generate up to the nearest 8-bit
  270.  *    unit of bits, which means that up to 7 extra 0 bits will be appended
  271.  *    to the end of the file.
  272.  *
  273.  * RETURNS:    nothing
  274.  *
  275.  * SIDE EFFECTS:    frees the bit bucket
  276.  *
  277.  *===========================================================================*/
  278. void
  279. Bitio_Flush(bbPtr)
  280.     BitBucket *bbPtr;
  281. {
  282.     struct bitBucket *ptr, *tempPtr;
  283.     uint32 buffer[WORDS_PER_BUCKET];
  284.     uint32  lastWord;
  285.     int i, nitems;
  286.     int        bitsWritten = 0;
  287.     int        bitsLeft;
  288.     int        numWords;
  289.     uint8   charBuf[4];
  290.     boolean    flushHere = FALSE;
  291.  
  292.     bitsLeft = bbPtr->totalbits;
  293.  
  294.     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
  295.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  296.         continue;        /* empty */
  297.     }
  298.  
  299.     if ( bitsLeft >= 32 ) {
  300.         if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
  301.         numWords = ptr->currword;
  302.         flushHere = TRUE;
  303.         } else {
  304.         numWords = ptr->currword+1;
  305.         }
  306.  
  307.         for (i = 0; i < numWords; i++) {
  308.         buffer[i] = htonl(ptr->bits[i]);
  309.         }
  310.  
  311.         nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
  312.         if (nitems != numWords) {
  313.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
  314.             (int)(numWords), nitems);
  315.         exit(1);
  316.         }
  317.  
  318.         bitsWritten += (numWords * 32);
  319.         bitsLeft -= (numWords * 32);
  320.     } else {
  321.         flushHere = TRUE;
  322.     }
  323.  
  324.     if ( (bitsLeft < 32) && flushHere ) {
  325.         lastWord = ptr->bits[ptr->currword];
  326.  
  327.         /* output the lastPtr word in big-endian order (network) */
  328.  
  329.         /* now write out lastPtr bits */
  330.         while ( bitsLeft > 0 ) {
  331.         charBuf[0] = (lastWord >> 24);
  332.         charBuf[0] &= lower_mask[8];
  333.         fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
  334.         lastWord = (lastWord << 8);
  335.         bitsLeft -= 8;
  336.         bitsWritten += 8;
  337.         }
  338.     }
  339.     }
  340.  
  341.     while ( bbPtr->firstPtr != ptr ) {
  342.     tempPtr = bbPtr->firstPtr;
  343.     bbPtr->firstPtr = tempPtr->nextPtr;
  344.     free(tempPtr);
  345.     }
  346.  
  347.     free(bbPtr);
  348. }
  349.  
  350.  
  351. /*===========================================================================*
  352.  *
  353.  * Bitio_WriteToSocket
  354.  *
  355.  *    Writes all of the remaining bits in the given bit bucket to the
  356.  *    given socket.  May pad the end of the socket stream with extra 0
  357.  *    bits as does Bitio_Flush.
  358.  *
  359.  * RETURNS:    nothing
  360.  *
  361.  * SIDE EFFECTS:    frees the bit bucket
  362.  *
  363.  *===========================================================================*/
  364. void
  365. Bitio_WriteToSocket(bbPtr, socket)
  366.     BitBucket *bbPtr;
  367.     int socket;
  368. {
  369.     struct bitBucket *ptr, *tempPtr;
  370.     uint32 buffer[WORDS_PER_BUCKET];
  371.     uint32  lastWord;
  372.     int i, nitems;
  373.     int        bitsWritten = 0;
  374.     int        bitsLeft;
  375.     int        numWords;
  376.     uint8   charBuf[4];
  377.     boolean    flushHere = FALSE;
  378.  
  379.     bitsLeft = bbPtr->totalbits;
  380.  
  381.     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
  382.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  383.         continue;        /* empty */
  384.     }
  385.  
  386.     if ( bitsLeft >= 32 ) {
  387.         if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
  388.         numWords = ptr->currword;
  389.         flushHere = TRUE;
  390.         } else {
  391.         numWords = ptr->currword+1;
  392.         }
  393.  
  394.         for (i = 0; i < numWords; i++) {
  395.         buffer[i] = htonl(ptr->bits[i]);
  396.         }
  397.  
  398.         nitems = write(socket, buffer, numWords * sizeof(uint32));
  399.         if (nitems != numWords*sizeof(uint32)) {
  400.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d bytes)!  Game over, dude!\n",
  401.             (int)(numWords*sizeof(uint32)), nitems);
  402.         exit(1);
  403.         }
  404.  
  405.         bitsWritten += (numWords * 32);
  406.         bitsLeft -= (numWords * 32);
  407.     } else {
  408.         flushHere = TRUE;
  409.     }
  410.  
  411.     if ( (bitsLeft < 32) && flushHere ) {
  412.         lastWord = ptr->bits[ptr->currword];
  413.  
  414.         /* output the lastPtr word in big-endian order (network) */
  415.  
  416.         /* now write out lastPtr bits */
  417.         while ( bitsLeft > 0 ) {
  418.         charBuf[0] = (lastWord >> 24);
  419.         charBuf[0] &= lower_mask[8];
  420.         if ( write(socket, charBuf, 1) != 1 ) {
  421.             fprintf(stderr, "ERROR:  write of lastPtr bits\n");
  422.             exit(1);
  423.         }
  424.         lastWord = (lastWord << 8);
  425.         bitsLeft -= 8;
  426.         bitsWritten += 8;
  427.         }
  428.     }
  429.     }
  430.  
  431.     while ( bbPtr->firstPtr != ptr ) {
  432.     tempPtr = bbPtr->firstPtr;
  433.     bbPtr->firstPtr = tempPtr->nextPtr;
  434.     free(tempPtr);
  435.     }
  436.  
  437.     free(bbPtr);
  438. }
  439.  
  440.  
  441. /*===========================================================================*
  442.  *
  443.  * Bitio_BytePad
  444.  *
  445.  *    Pads the end of the bit bucket to the nearest byte with 0 bits
  446.  *
  447.  * RETURNS:    nothing
  448.  *
  449.  *===========================================================================*/
  450. void
  451. Bitio_BytePad(bbPtr)
  452.     BitBucket *bbPtr;
  453. {
  454.     struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
  455.  
  456.     if (lastPtrPtr->bitsleftcur % 8) {
  457.     Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
  458.     }
  459. }
  460.  
  461.  
  462. /*=====================*
  463.  * INTERNAL PROCEDURES *
  464.  *=====================*/
  465.  
  466.  
  467. /*===========================================================================*
  468.  *
  469.  * Dump
  470.  *
  471.  *    Writes out the first MAX_BITS bits of the bit bucket to the
  472.  *    appropriate output file
  473.  *
  474.  * RETURNS:    nothing
  475.  *
  476.  * SIDE EFFECTS:  none
  477.  *
  478.  *===========================================================================*/
  479. static void
  480. Dump(bbPtr)
  481.     BitBucket *bbPtr;
  482. {
  483.     struct bitBucket *ptr, *tempPtr;
  484.     uint32 buffer[WORDS_PER_BUCKET];
  485.     int i, nitems;
  486.     int        bitsWritten = 0;
  487.  
  488.     for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
  489.      ptr = ptr->nextPtr) {
  490.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  491.         continue;        /* empty */
  492.     }
  493.  
  494.     for (i = 0; i <= ptr->currword; i++) {
  495.         buffer[i] = htonl(ptr->bits[i]);
  496.     }
  497.  
  498.     nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
  499.     if (nitems != (ptr->currword+1)) {
  500.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
  501.             (int)((ptr->currword+1)), nitems);
  502.         assert(0);
  503.         exit(1);
  504.     }
  505.  
  506.     bitsWritten += ((ptr->currword + 1) * 32);
  507.     }
  508.  
  509.     while ( bbPtr->firstPtr != ptr ) {
  510.     tempPtr = bbPtr->firstPtr;
  511.     bbPtr->firstPtr = tempPtr->nextPtr;
  512.     free(tempPtr);
  513.     }
  514.  
  515.     bbPtr->totalbits -= bitsWritten;
  516.     bbPtr->bitsWritten += bitsWritten;
  517. }
  518.  
  519.  
  520.