Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

bitio.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * bitio.c                                                                   *
00003  *                                                                           *
00004  *      Procedures concerned with the bit-wise I/O                           *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      Bitio_New                                                            *
00008  *      Bitio_Free                                                           *
00009  *      Bitio_Write                                                          *
00010  *      Bitio_Flush                                                          *
00011  *      Bitio_WriteToSocket                                                  *
00012  *      Bitio_BytePad                                                        *
00013  *                                                                           *
00014  *===========================================================================*/
00015 
00016 /*
00017  * Copyright (c) 1995 The Regents of the University of California.
00018  * All rights reserved.
00019  *
00020  * Permission to use, copy, modify, and distribute this software and its
00021  * documentation for any purpose, without fee, and without written agreement is
00022  * hereby granted, provided that the above copyright notice and the following
00023  * two paragraphs appear in all copies of this software.
00024  *
00025  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00026  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00027  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00028  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00031  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00032  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00033  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00034  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00035  */
00036 
00037 /*
00038  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/bitio.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00039  *  $Log: bitio.c,v $
00040  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00041  *  Cput
00042  *
00043  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00044  *  Cput
00045  *
00046  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00047  *  Cput
00048  *
00049  *  Revision 1.1  2001/12/17 16:11:53  rwcox
00050  *  Cadd
00051  *
00052  * Revision 1.13  1995/06/21  18:36:06  smoot
00053  * added a flush when done with file
00054  *
00055  * Revision 1.12  1995/01/19  23:07:15  eyhung
00056  * Changed copyrights
00057  *
00058  * Revision 1.11  1994/11/12  02:11:43  keving
00059  * nothing
00060  *
00061  * Revision 1.10  1993/12/22  19:19:01  keving
00062  * nothing
00063  *
00064  * Revision 1.10  1993/12/22  19:19:01  keving
00065  * nothing
00066  *
00067  * Revision 1.9  1993/07/22  22:23:43  keving
00068  * nothing
00069  *
00070  * Revision 1.8  1993/06/30  20:06:09  keving
00071  * nothing
00072  *
00073  * Revision 1.7  1993/06/03  21:08:08  keving
00074  * nothing
00075  *
00076  * Revision 1.6  1993/02/17  23:21:41  dwallach
00077  * checkin prior to keving's joining the project
00078  *
00079  * Revision 1.5  1993/01/18  10:20:02  dwallach
00080  * *** empty log message ***
00081  *
00082  * Revision 1.4  1993/01/18  10:17:29  dwallach
00083  * RCS headers installed, code indented uniformly
00084  *
00085  * Revision 1.4  1993/01/18  10:17:29  dwallach
00086  * RCS headers installed, code indented uniformly
00087  *
00088  */
00089 
00090 /*==============*
00091  * HEADER FILES *
00092  *==============*/
00093 
00094 #include <assert.h>
00095 #include "all.h"
00096 #include "byteorder.h"
00097 #include "bitio.h"
00098 #include "mtypes.h"
00099 
00100 
00101 /*===============================*
00102  * INTERNAL PROCEDURE prototypes *
00103  *===============================*/
00104  
00105 static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
00106 
00107 
00108 /*==================*
00109  * STATIC VARIABLES *
00110  *==================*/
00111 
00112 static uint32 lower_mask[33] = {
00113     0,
00114     0x1, 0x3, 0x7, 0xf,
00115     0x1f, 0x3f, 0x7f, 0xff,
00116     0x1ff, 0x3ff, 0x7ff, 0xfff,
00117     0x1fff, 0x3fff, 0x7fff, 0xffff,
00118     0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
00119     0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
00120     0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
00121     0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
00122 };
00123 
00124 
00125 extern time_t IOtime;
00126 
00127 
00128 /*=====================*
00129  * EXPORTED PROCEDURES *
00130  *=====================*/
00131 
00132 
00133 /*===========================================================================*
00134  *
00135  * Bitio_New
00136  *
00137  *      Create a new bit bucket; filePtr is a pointer to the open file the
00138  *      bits should ultimately be written to.
00139  *
00140  * RETURNS:     pointer to the resulting bit bucket
00141  *
00142  * SIDE EFFECTS:    none
00143  *
00144  *===========================================================================*/
00145 BitBucket *
00146 Bitio_New(filePtr)
00147     FILE *filePtr;
00148 {
00149     BitBucket *bbPtr;
00150 
00151     bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
00152     ERRCHK(bbPtr, "malloc");
00153 
00154     bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
00155     ERRCHK(bbPtr->firstPtr, "malloc");
00156 
00157     bbPtr->totalbits = 0;
00158     bbPtr->cumulativeBits = 0;
00159     bbPtr->bitsWritten = 0;
00160     bbPtr->filePtr = filePtr;
00161 
00162     bbPtr->firstPtr->nextPtr = NULL;
00163     bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
00164     bbPtr->firstPtr->bitsleftcur = 32;
00165     bbPtr->firstPtr->currword = 0;
00166     memset((char *)bbPtr->firstPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
00167 
00168     return bbPtr;
00169 }
00170 
00171 
00172 /*===========================================================================*
00173  *
00174  * Bitio_Free
00175  *
00176  *      Frees the memory associated with the given bit bucket
00177  *
00178  * RETURNS:     nothing
00179  *
00180  * SIDE EFFECTS:    none
00181  *
00182  *===========================================================================*/
00183 void
00184 Bitio_Free(bbPtr)
00185     BitBucket *bbPtr;
00186 {
00187     struct bitBucket *tmpPtr, *nextPtr;
00188 
00189     for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
00190         nextPtr = tmpPtr->nextPtr;
00191         free(tmpPtr);
00192     }
00193     free(bbPtr);
00194 }
00195 
00196 
00197 /*===========================================================================*
00198  *
00199  * Bitio_Write
00200  *
00201  *      Writes 'nbits' bits from 'bits' into the given bit bucket
00202  *      'nbits' must be between 0 and 32
00203  *
00204  * RETURNS:     nothing
00205  *
00206  * SIDE EFFECTS:    if the number of bits in the bit bucket surpasses
00207  *                  MAX_BITS, then that many bits are flushed to the
00208  *                  appropriate output file
00209  *
00210  *===========================================================================*/
00211 void
00212 Bitio_Write(bbPtr, bits, nbits)
00213     BitBucket *bbPtr;
00214     uint32 bits;
00215     int nbits;
00216 {
00217     register struct bitBucket *lastPtr, *newPtr;
00218     register int delta;
00219 
00220     assert(nbits <= 32 && nbits >= 0);
00221 
00222     /*
00223      * Clear top bits if not part of data, necessary due to down and
00224      * dirty calls of Bitio_Write with unecessary top bits set.
00225      */
00226 
00227     bits = bits & lower_mask[nbits];
00228 
00229     bbPtr->totalbits += nbits;
00230     bbPtr->cumulativeBits += nbits;
00231     lastPtr = bbPtr->lastPtr;
00232 
00233     delta = nbits - lastPtr->bitsleft;
00234     if (delta >= 0) {
00235         /*
00236          * there's not enough room in the current bucket, so we're
00237          * going to have to allocate another bucket
00238          */
00239         newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
00240         ERRCHK(newPtr, "malloc");
00241         newPtr->nextPtr = NULL;
00242         newPtr->bitsleft = MAXBITS_PER_BUCKET;
00243         newPtr->bitsleftcur = 32;
00244         newPtr->currword = 0;
00245         memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
00246         bbPtr->lastPtr = newPtr;
00247 
00248         assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
00249         lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
00250         lastPtr->bitsleft = 0;
00251         lastPtr->bitsleftcur = 0;
00252         /* lastPtr->currword++; */
00253 
00254         if (!delta) {
00255             if ( bbPtr->totalbits > MAX_BITS ) {
00256                 Dump(bbPtr);
00257             }
00258         }
00259 
00260         assert(delta <= 32);
00261         newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
00262         newPtr->bitsleft -= delta;
00263         newPtr->bitsleftcur -= delta;
00264     } else {
00265         /*
00266          * the current bucket will be sufficient
00267          */
00268         delta = nbits - lastPtr->bitsleftcur;
00269         lastPtr->bitsleftcur -= nbits;
00270         lastPtr->bitsleft -= nbits;
00271 
00272         if (delta >= 0)
00273         {
00274             /*
00275              * these bits will span more than one word
00276              */
00277             lastPtr->bits[lastPtr->currword] |= (bits >> delta);
00278             lastPtr->currword++;
00279             lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
00280             lastPtr->bitsleftcur = 32 - delta;
00281         } else {
00282             /*
00283              * these bits will fit, whole
00284              */
00285             lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
00286         }
00287     }
00288 
00289     if ( bbPtr->totalbits > MAX_BITS )  /* flush bits */
00290         Dump(bbPtr);
00291 }
00292 
00293 
00294 /*===========================================================================*
00295  *
00296  * Bitio_Flush
00297  *
00298  *      Flushes all of the remaining bits in the given bit bucket to the
00299  *      appropriate output file.  It will generate up to the nearest 8-bit
00300  *      unit of bits, which means that up to 7 extra 0 bits will be appended
00301  *      to the end of the file.
00302  *
00303  * RETURNS:     nothing
00304  *
00305  * SIDE EFFECTS:    frees the bit bucket
00306  *
00307  *===========================================================================*/
00308 void
00309 Bitio_Flush(bbPtr)
00310     BitBucket *bbPtr;
00311 {
00312     struct bitBucket *ptr, *tempPtr;
00313     uint32 buffer[WORDS_PER_BUCKET];
00314     uint32  lastWord;
00315     int i, nitems;
00316     int     bitsWritten = 0;
00317     int     bitsLeft;
00318     int     numWords;
00319     uint8   charBuf[4];
00320     boolean    flushHere = FALSE;
00321     time_t  tempTimeStart, tempTimeEnd;
00322 
00323     time(&tempTimeStart);
00324 
00325     bitsLeft = bbPtr->totalbits;
00326 
00327     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
00328         if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00329             continue;           /* empty */
00330         }
00331 
00332         if ( bitsLeft >= 32 ) {
00333             if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
00334                 numWords = ptr->currword;
00335                 flushHere = TRUE;
00336             } else {
00337                 numWords = ptr->currword+1;
00338             }
00339 
00340             for (i = 0; i < numWords; i++) {
00341                 buffer[i] = htonl(ptr->bits[i]);
00342             }
00343 
00344             nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
00345             if (nitems != numWords) {
00346                 fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
00347                         (int)(numWords), nitems);
00348                 exit(1);
00349             }
00350 
00351             bitsWritten += (numWords * 32);
00352             bitsLeft -= (numWords * 32);
00353         } else {
00354             flushHere = TRUE;
00355         }
00356 
00357         if ( (bitsLeft < 32) && flushHere ) {
00358             lastWord = ptr->bits[ptr->currword];
00359 
00360             /* output the lastPtr word in big-endian order (network) */
00361 
00362             /* now write out lastPtr bits */
00363             while ( bitsLeft > 0 ) {
00364                 charBuf[0] = (lastWord >> 24);
00365                 charBuf[0] &= lower_mask[8];
00366                 fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
00367                 lastWord = (lastWord << 8);
00368                 bitsLeft -= 8;
00369                 bitsWritten += 8;
00370             }
00371         }
00372     }
00373     fflush(bbPtr->filePtr);
00374     while ( bbPtr->firstPtr != ptr ) {
00375         tempPtr = bbPtr->firstPtr;
00376         bbPtr->firstPtr = tempPtr->nextPtr;
00377         free(tempPtr);
00378     }
00379 
00380     free(bbPtr);
00381 
00382     time(&tempTimeEnd);
00383     IOtime += (tempTimeEnd-tempTimeStart);
00384 }
00385 
00386 
00387 /*===========================================================================*
00388  *
00389  * Bitio_WriteToSocket
00390  *
00391  *      Writes all of the remaining bits in the given bit bucket to the
00392  *      given socket.  May pad the end of the socket stream with extra 0
00393  *      bits as does Bitio_Flush.
00394  *
00395  * RETURNS:     nothing
00396  *
00397  * SIDE EFFECTS:    frees the bit bucket
00398  *
00399  *===========================================================================*/
00400 void
00401 Bitio_WriteToSocket(bbPtr, socket)
00402     BitBucket *bbPtr;
00403     int socket;
00404 {
00405     struct bitBucket *ptr, *tempPtr;
00406     uint32 buffer[WORDS_PER_BUCKET];
00407     uint32  lastWord;
00408     int i, nitems;
00409     int     bitsWritten = 0;
00410     int     bitsLeft;
00411     int     numWords;
00412     uint8   charBuf[4];
00413     boolean    flushHere = FALSE;
00414 
00415     bitsLeft = bbPtr->totalbits;
00416 
00417     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
00418         if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00419             continue;           /* empty */
00420         }
00421 
00422         if ( bitsLeft >= 32 ) {
00423             if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
00424                 numWords = ptr->currword;
00425                 flushHere = TRUE;
00426             } else {
00427                 numWords = ptr->currword+1;
00428             }
00429 
00430             for (i = 0; i < numWords; i++) {
00431                 buffer[i] = htonl(ptr->bits[i]);
00432             }
00433 
00434             nitems = write(socket, buffer, numWords * sizeof(uint32));
00435             if (nitems != numWords*sizeof(uint32)) {
00436                 fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d bytes)!  Game over, dude!\n",
00437                         (int)(numWords*sizeof(uint32)), nitems);
00438                 exit(1);
00439             }
00440 
00441             bitsWritten += (numWords * 32);
00442             bitsLeft -= (numWords * 32);
00443         } else {
00444             flushHere = TRUE;
00445         }
00446 
00447         if ( (bitsLeft < 32) && flushHere ) {
00448             lastWord = ptr->bits[ptr->currword];
00449 
00450             /* output the lastPtr word in big-endian order (network) */
00451 
00452             /* now write out lastPtr bits */
00453             while ( bitsLeft > 0 ) {
00454                 charBuf[0] = (lastWord >> 24);
00455                 charBuf[0] &= lower_mask[8];
00456                 if ( write(socket, charBuf, 1) != 1 ) {
00457                     fprintf(stderr, "ERROR:  write of lastPtr bits\n");
00458                     exit(1);
00459                 }
00460                 lastWord = (lastWord << 8);
00461                 bitsLeft -= 8;
00462                 bitsWritten += 8;
00463             }
00464         }
00465     }
00466 
00467     while ( bbPtr->firstPtr != ptr ) {
00468         tempPtr = bbPtr->firstPtr;
00469         bbPtr->firstPtr = tempPtr->nextPtr;
00470         free(tempPtr);
00471     }
00472 
00473     free(bbPtr);
00474 }
00475 
00476 
00477 /*===========================================================================*
00478  *
00479  * Bitio_BytePad
00480  *
00481  *      Pads the end of the bit bucket to the nearest byte with 0 bits
00482  *
00483  * RETURNS:     nothing
00484  *
00485  *===========================================================================*/
00486 void
00487 Bitio_BytePad(bbPtr)
00488     BitBucket *bbPtr;
00489 {
00490     struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
00491 
00492     if (lastPtrPtr->bitsleftcur % 8) {
00493         Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
00494     }
00495 }
00496 
00497 
00498 /*=====================*
00499  * INTERNAL PROCEDURES *
00500  *=====================*/
00501 
00502 
00503 /*===========================================================================*
00504  *
00505  * Dump
00506  *
00507  *      Writes out the first MAX_BITS bits of the bit bucket to the
00508  *      appropriate output file
00509  *
00510  * RETURNS:     nothing
00511  *
00512  * SIDE EFFECTS:  none
00513  *
00514  *===========================================================================*/
00515 static void
00516 Dump(bbPtr)
00517     BitBucket *bbPtr;
00518 {
00519     struct bitBucket *ptr, *tempPtr;
00520     uint32 buffer[WORDS_PER_BUCKET];
00521     int i, nitems;
00522     int     bitsWritten = 0;
00523     time_t  tempTimeStart, tempTimeEnd;
00524 
00525     time(&tempTimeStart);
00526 
00527     for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
00528          ptr = ptr->nextPtr) {
00529         if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00530             continue;           /* empty */
00531         }
00532 
00533         for (i = 0; i <= ptr->currword; i++) {
00534             buffer[i] = htonl(ptr->bits[i]);
00535         }
00536 
00537         nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
00538         if (nitems != (ptr->currword+1)) {
00539             fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
00540                     (int)((ptr->currword+1)), nitems);
00541             assert(0);
00542             exit(1);
00543         }
00544 
00545         bitsWritten += ((ptr->currword + 1) * 32);
00546     }
00547 
00548     while ( bbPtr->firstPtr != ptr ) {
00549         tempPtr = bbPtr->firstPtr;
00550         bbPtr->firstPtr = tempPtr->nextPtr;
00551         free(tempPtr);
00552     }
00553 
00554     bbPtr->totalbits -= bitsWritten;
00555     bbPtr->bitsWritten += bitsWritten;
00556 
00557     time(&tempTimeEnd);
00558     IOtime += (tempTimeEnd-tempTimeStart);
00559 }
00560 
00561 
 

Powered by Plone

This site conforms to the following standards: