⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitio.c

📁 linux下将各类格式图片转换工具
💻 C
字号:
/*===========================================================================* * bitio.c * *  Procedures concerned with the bit-wise I/O * * EXPORTED PROCEDURES: *  Bitio_New *  Bitio_Free *  Bitio_Write *  Bitio_Flush *  Bitio_WriteToSocket *  Bitio_BytePad * *===========================================================================*//* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//*==============* * HEADER FILES * *==============*/#include <assert.h>#include <time.h>#include <unistd.h>#include <errno.h>#include "pm.h"#include "all.h"#include "byteorder.h"#include "bitio.h"#include "mtypes.h"/*===============================* * INTERNAL PROCEDURE prototypes * *===============================*/ static void Dump _ANSI_ARGS_((BitBucket *bbPtr));/*==================* * STATIC VARIABLES * *==================*/static uint32 lower_mask[33] = {    0,    0x1, 0x3, 0x7, 0xf,    0x1f, 0x3f, 0x7f, 0xff,    0x1ff, 0x3ff, 0x7ff, 0xfff,    0x1fff, 0x3fff, 0x7fff, 0xffff,    0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,    0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,    0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,    0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};extern time_t IOtime;/*=====================* * EXPORTED PROCEDURES * *=====================*//*===========================================================================* * * Bitio_New * *  Create a new bit bucket; filePtr is a pointer to the open file the *  bits should ultimately be written to. * * RETURNS: pointer to the resulting bit bucket * * SIDE EFFECTS:    none * *===========================================================================*/BitBucket *Bitio_New(FILE * const filePtr) {    BitBucket *bbPtr;    bbPtr = (BitBucket *) malloc(sizeof(BitBucket));    ERRCHK(bbPtr, "malloc");    bbPtr->firstPtr = bbPtr->lastPtr = malloc(sizeof(struct bitBucket));    ERRCHK(bbPtr->firstPtr, "malloc");    bbPtr->totalbits = 0;    bbPtr->cumulativeBits = 0;    bbPtr->bitsWritten = 0;    bbPtr->filePtr = filePtr;    bbPtr->firstPtr->nextPtr = NULL;    bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;    bbPtr->firstPtr->bitsleftcur = 32;    bbPtr->firstPtr->currword = 0;    memset((char *)bbPtr->firstPtr->bits, 0,            sizeof(uint32) * WORDS_PER_BUCKET);    return bbPtr;}BitBucket *Bitio_New_Filename(const char * const fileName) {    FILE * outputFile;        outputFile = fopen(fileName, "wb");    if (outputFile == NULL)        pm_error("Could not open output file '%s'.  "                 "Errno=%d (%s)", fileName, errno, strerror(errno));    return Bitio_New(outputFile);}/*===========================================================================* * * Bitio_Free * *  Frees the memory associated with the given bit bucket * * RETURNS: nothing * * SIDE EFFECTS:    none * *===========================================================================*/voidBitio_Free(BitBucket *bbPtr){    struct bitBucket *tmpPtr, *nextPtr;    for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {    nextPtr = tmpPtr->nextPtr;    free(tmpPtr);    }    free(bbPtr);}/*===========================================================================* * * Bitio_Write * *  Writes 'nbits' bits from 'bits' into the given bit bucket *  'nbits' must be between 0 and 32 * * RETURNS: nothing * * SIDE EFFECTS:    if the number of bits in the bit bucket surpasses *          MAX_BITS, then that many bits are flushed to the *          appropriate output file * *===========================================================================*/voidBitio_Write(BitBucket *bbPtr, uint32 bits_arg, int nbits){    register struct bitBucket *lastPtr, *newPtr;    register int delta;    uint32 bits;        bits=bits_arg;    assert(nbits <= 32 && nbits >= 0);    /*     * Clear top bits if not part of data, necessary due to down and     * dirty calls of Bitio_Write with unecessary top bits set.     */    bits &= lower_mask[nbits];    bits = bits & lower_mask[nbits];    bbPtr->totalbits += nbits;    bbPtr->cumulativeBits += nbits;    lastPtr = bbPtr->lastPtr;    delta = nbits - lastPtr->bitsleft;    if (delta >= 0) {    /*         * there's not enough room in the current bucket, so we're         * going to have to allocate another bucket         */    newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));    ERRCHK(newPtr, "malloc");    newPtr->nextPtr = NULL;    newPtr->bitsleft = MAXBITS_PER_BUCKET;    newPtr->bitsleftcur = 32;    newPtr->currword = 0;    memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);    bbPtr->lastPtr = newPtr;    assert(lastPtr->currword == WORDS_PER_BUCKET - 1);    lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);    lastPtr->bitsleft = 0;    lastPtr->bitsleftcur = 0;    /* lastPtr->currword++; */    if (!delta) {        if ( bbPtr->totalbits > MAX_BITS ) {        Dump(bbPtr);        }    }    assert(delta <= 32);    newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);    newPtr->bitsleft -= delta;    newPtr->bitsleftcur -= delta;    } else {    /*         * the current bucket will be sufficient     */    delta = nbits - lastPtr->bitsleftcur;    lastPtr->bitsleftcur -= nbits;    lastPtr->bitsleft -= nbits;    if (delta >= 0)    {        /*         * these bits will span more than one word         */        lastPtr->bits[lastPtr->currword] |= (bits >> delta);        lastPtr->currword++;        lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);        lastPtr->bitsleftcur = 32 - delta;    } else {        /*         * these bits will fit, whole         */        lastPtr->bits[lastPtr->currword] |= (bits << (-delta));    }    }    if ( bbPtr->totalbits > MAX_BITS )  /* flush bits */    Dump(bbPtr);}/*===========================================================================* * * Bitio_Flush * *  Flushes all of the remaining bits in the given bit bucket to the *  appropriate output file.  It will generate up to the nearest 8-bit *  unit of bits, which means that up to 7 extra 0 bits will be appended *  to the end of the file. * * RETURNS: nothing * * SIDE EFFECTS:    frees the bit bucket * *===========================================================================*/voidBitio_Flush(BitBucket *bbPtr){    struct bitBucket *ptr, *tempPtr;    uint32 buffer[WORDS_PER_BUCKET];    uint32  lastWord;    int i, nitems;    int     bitsWritten = 0;    int     bitsLeft;    unsigned int     numWords;    uint8   charBuf[4];    boolean    flushHere = FALSE;    time_t  tempTimeStart, tempTimeEnd;    time(&tempTimeStart);    bitsLeft = bbPtr->totalbits;    for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {        if (ptr->bitsleftcur == 32 && ptr->currword == 0) {            continue;       /* empty */        }        if ( bitsLeft >= 32 ) {            if ( ((ptr->currword + 1) * 32) > bitsLeft ) {                numWords = ptr->currword;                flushHere = TRUE;            } else                numWords = ptr->currword+1;            for (i = 0; i < numWords; i++)                buffer[i] = htonl(ptr->bits[i]);            nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);            if (nitems != numWords) {                if (ferror(bbPtr->filePtr))                    pm_error("Error writing %u words to flush a bit bucket.  "                             "fwrite() gives errno %d (%s)",                              numWords, errno, strerror(errno));                else                    pm_error("Problem writing %u words "                             "to flush a bit bucket.  "                             "Only %d words transferred.",                              numWords, nitems);            }            bitsWritten += (numWords * 32);            bitsLeft -= (numWords * 32);        } else {            flushHere = TRUE;        }        if ( (bitsLeft < 32) && flushHere ) {            lastWord = ptr->bits[ptr->currword];            /* output the lastPtr word in big-endian order (network) */            /* now write out lastPtr bits */            while ( bitsLeft > 0 ) {                charBuf[0] = (lastWord >> 24);                charBuf[0] &= lower_mask[8];                fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);                lastWord = (lastWord << 8);                bitsLeft -= 8;                bitsWritten += 8;            }        }    }    fflush(bbPtr->filePtr);    while ( bbPtr->firstPtr != ptr ) {        tempPtr = bbPtr->firstPtr;        bbPtr->firstPtr = tempPtr->nextPtr;        free(tempPtr);    }    free(bbPtr);    time(&tempTimeEnd);    IOtime += (tempTimeEnd-tempTimeStart);}voidBitio_Close(BitBucket * const bbPtr) {    fclose(bbPtr->filePtr);}/*===========================================================================* * * Bitio_WriteToSocket * *  Writes all of the remaining bits in the given bit bucket to the *  given socket.  May pad the end of the socket stream with extra 0 *  bits as does Bitio_Flush. * * RETURNS: nothing * * SIDE EFFECTS:    frees the bit bucket * *===========================================================================*/voidBitio_WriteToSocket(BitBucket *bbPtr, int socket){    struct bitBucket *ptr, *tempPtr;    uint32 buffer[WORDS_PER_BUCKET];    uint32  lastWord;    int i, nitems;    int     bitsWritten = 0;    int     bitsLeft;    int     numWords;    uint8   charBuf[4];    boolean    flushHere = FALSE;    bitsLeft = bbPtr->totalbits;    for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {    if (ptr->bitsleftcur == 32 && ptr->currword == 0) {        continue;       /* empty */    }    if ( bitsLeft >= 32 ) {        if ( ((ptr->currword + 1) * 32) > bitsLeft ) {        numWords = ptr->currword;        flushHere = TRUE;        } else {        numWords = ptr->currword+1;        }        for (i = 0; i < numWords; i++) {        buffer[i] = htonl(ptr->bits[i]);        }        nitems = write(socket, buffer, numWords * sizeof(uint32));        if (nitems != numWords*sizeof(uint32)) {        fprintf(stderr, "Whoa!  Trouble writing %d bytes (wrote %d bytes)!  "                "Game over, dude!\n",            (int)(numWords*sizeof(uint32)), nitems);        exit(1);        }        bitsWritten += (numWords * 32);        bitsLeft -= (numWords * 32);    } else {        flushHere = TRUE;    }    if ( (bitsLeft < 32) && flushHere ) {        lastWord = ptr->bits[ptr->currword];        /* output the lastPtr word in big-endian order (network) */        /* now write out lastPtr bits */        while ( bitsLeft > 0 ) {        charBuf[0] = (lastWord >> 24);        charBuf[0] &= lower_mask[8];        if ( write(socket, charBuf, 1) != 1 ) {            fprintf(stderr, "ERROR:  write of lastPtr bits\n");            exit(1);        }        lastWord = (lastWord << 8);        bitsLeft -= 8;        bitsWritten += 8;        }    }    }    while ( bbPtr->firstPtr != ptr ) {    tempPtr = bbPtr->firstPtr;    bbPtr->firstPtr = tempPtr->nextPtr;    free(tempPtr);    }    free(bbPtr);}/*===========================================================================* * * Bitio_BytePad * *  Pads the end of the bit bucket to the nearest byte with 0 bits * * RETURNS: nothing * *===========================================================================*/voidBitio_BytePad(BitBucket *bbPtr){    struct bitBucket *lastPtrPtr = bbPtr->lastPtr;    if (lastPtrPtr->bitsleftcur % 8) {    Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);    }}/*=====================* * INTERNAL PROCEDURES * *=====================*//*===========================================================================* * * Dump * *  Writes out the first MAX_BITS bits of the bit bucket to the *  appropriate output file * * RETURNS: nothing * * SIDE EFFECTS:  none * *===========================================================================*/static voidDump(bbPtr)    BitBucket *bbPtr;{    struct bitBucket *ptr, *tempPtr;    uint32 buffer[WORDS_PER_BUCKET];    int i, nitems;    int     bitsWritten = 0;    time_t  tempTimeStart, tempTimeEnd;    time(&tempTimeStart);    for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);     ptr = ptr->nextPtr) {    if (ptr->bitsleftcur == 32 && ptr->currword == 0) {        continue;       /* empty */    }    for (i = 0; i <= ptr->currword; i++) {        buffer[i] = htonl(ptr->bits[i]);    }    nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1),                     bbPtr->filePtr);    if (nitems != (ptr->currword+1)) {        fprintf(stderr, "Whoa!  Trouble writing %d words (wrote %d words)!  "                "Game over, dude!\n",                (int)((ptr->currword+1)), nitems);        assert(0);        exit(1);    }    bitsWritten += ((ptr->currword + 1) * 32);    }    while ( bbPtr->firstPtr != ptr ) {    tempPtr = bbPtr->firstPtr;    bbPtr->firstPtr = tempPtr->nextPtr;    free(tempPtr);    }    bbPtr->totalbits -= bitsWritten;    bbPtr->bitsWritten += bitsWritten;    time(&tempTimeEnd);    IOtime += (tempTimeEnd-tempTimeStart);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -