Beispiel #1
0
/***************************************************************************
*   Function   : BitArrayShiftLeft
*   Description: This function shifts the bits in a bit array to the left
*                by the amount of positions specified.
*   Parameters : ba - pointer to the bit array 0 is the msb of the first
*                     unsigned char in the bit array.
*                shifts - number of bits to shift by.
*   Effects    : The bit array data pointed to by ba is shifted to the left.
*                New bits shifted in will be set to 0.
*   Returned   : None
***************************************************************************/
void BitArrayShiftLeft(bit_array_t *ba, unsigned int shifts)
{
    int i, j;
    int chars = shifts / CHAR_BIT;  /* number of whole byte shifts */
    shifts = shifts % CHAR_BIT;     /* number of bit shifts remaining */

    if (ba == NULL)
    {
        return;         /* nothing to shift */
    }

    if (shifts >= ba->numBits)
    {
        /* all bits have been shifted off */
        BitArrayClearAll(ba);
        return;
    }

    /* first handle big jumps of bytes */
    if (chars > 0)
    {
        for (i = 0; (i + chars) <  BITS_TO_CHARS(ba->numBits); i++)
        {
            ba->array[i] = ba->array[i + chars];
        }

        /* now zero out new bytes on the right */
        for (i = BITS_TO_CHARS(ba->numBits); chars > 0; chars--)
        {
            ba->array[i - chars] = 0;
        }
    }

    /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */
    for (i = 0; i < shifts; i++)
    {
        for (j = 0; j < BIT_CHAR(ba->numBits - 1); j++)
        {
            ba->array[j] <<= 1;

            /* handle shifts across byte bounds */
            if (ba->array[j + 1] & MS_BIT)
            {
                ba->array[j] |= 0x01;
            }
        }

        ba->array[BIT_CHAR(ba->numBits - 1)] <<= 1;
    }
}
Beispiel #2
0
/****************************************************************************
*   Function   : AssignCanonicalCode
*   Description: This function accepts a list of symbols sorted by their
*                code lengths, and assigns a canonical Huffman code to each
*                symbol.
*   Parameters : cl - sorted list of symbols to have code values assigned
*   Effects    : cl stores a list of canonical codes sorted by the length
*                of the code used to encode the symbol.
*   Returned   : TRUE for success, FALSE for failure
****************************************************************************/
static int AssignCanonicalCodes(canonical_list_t *cl)
{
    int i;
    byte_t length;
    bit_array_t *code;

    /* assign the new codes */
    code = BitArrayCreate(256);
    BitArrayClearAll(code);

    length = cl[(NUM_CHARS - 1)].codeLen;

    for(i = (NUM_CHARS - 1); i >= 0; i--)
    {
        /* bail if we hit a zero len code */
        if (cl[i].codeLen == 0)
        {
            break;
        }

        /* adjust code if this length is shorter than the previous */
        if (cl[i].codeLen < length)
        {
            BitArrayShiftRight(code, (length - cl[i].codeLen));
            length = cl[i].codeLen;
        }

        /* assign left justified code */
        if ((cl[i].code = BitArrayDuplicate(code)) == NULL)
        {
            perror("Duplicating code");
            BitArrayDestroy(code);
            return FALSE;
        }

        BitArrayShiftLeft(cl[i].code, 256 - length);

        BitArrayIncrement(code);
    }

    BitArrayDestroy(code);
    return TRUE;
}
Beispiel #3
0
/****************************************************************************
*   Function   : MakeCodeList
*   Description: This function uses a huffman tree to build a list of codes
*                and their length for each encoded symbol.  This simplifies
*                the encoding process.  Instead of traversing a tree in
*                search of the code for any symbol, the code maybe found
*                by accessing codeList[symbol].code.
*   Parameters : ht - pointer to root of huffman tree
*                codeList - code list to populate.
*   Effects    : Code values are filled in for symbols in a code list.
*   Returned   : 0 for success, -1 for failure.  errno will be set in the
*                event of a failure.
****************************************************************************/
static int MakeCodeList(huffman_node_t *ht, code_list_t *codeList)
{
    bit_array_t *code;
    byte_t depth = 0;

    if((code = BitArrayCreate(EOF_CHAR)) == NULL)
    {
        perror("Unable to allocate bit array");
        return -1;
    }

    BitArrayClearAll(code);

    for(;;)
    {
        /* follow this branch all the way left */
        while (ht->left != NULL)
        {
            BitArrayShiftLeft(code, 1);
            ht = ht->left;
            depth++;
        }

        if (ht->value != COMPOSITE_NODE)
        {
            /* enter results in list */
            codeList[ht->value].codeLen = depth;
            codeList[ht->value].code = BitArrayDuplicate(code);
            if (codeList[ht->value].code == NULL)
            {
                perror("Unable to allocate bit array");
                BitArrayDestroy(code);
                return -1;
            }

            /* now left justify code */
            BitArrayShiftLeft(codeList[ht->value].code, EOF_CHAR - depth);
        }

        while (ht->parent != NULL)
        {
            if (ht != ht->parent->right)
            {
                /* try the parent's right */
                BitArraySetBit(code, (EOF_CHAR - 1));
                ht = ht->parent->right;
                break;
            }
            else
            {
                /* parent's right tried, go up one level yet */
                depth--;
                BitArrayShiftRight(code, 1);
                ht = ht->parent;
            }
        }

        if (ht->parent == NULL)
        {
            /* we're at the top with nowhere to go */
            break;
        }
    }

    BitArrayDestroy(code);
    return 0;
}
Beispiel #4
0
/***************************************************************************
*   Function   : BitArrayShiftRight
*   Description: This function shifts the bits in a bit array to the right
*                by the amount of positions specified.
*   Parameters : ba - pointer to the bit array 0 is the msb of the first
*                     unsigned char in the bit array.
*                shifts - number of bits to shift by.
*   Effects    : The bit array data pointed to by ba is shifted to the
*                right.  New bits shifted in will be set to 0.
*   Returned   : None
***************************************************************************/
void BitArrayShiftRight(bit_array_t *ba, unsigned int shifts)
{
    int i, j;
    unsigned char mask;
    int chars = shifts / CHAR_BIT;  /* number of whole byte shifts */
    shifts = shifts % CHAR_BIT;     /* number of bit shifts remaining */

    if (ba == NULL)
    {
        return;         /* nothing to shift */
    }

    if (shifts >= ba->numBits)
    {
        /* all bits have been shifted off */
        BitArrayClearAll(ba);
        return;
    }

    /* first handle big jumps of bytes */
    if (chars > 0)
    {
        for (i = BIT_CHAR(ba->numBits - 1); (i - chars) >= 0; i--)
        {
            ba->array[i] = ba->array[i - chars];
        }

        /* now zero out new bytes on the right */
        for (; chars > 0; chars--)
        {
            ba->array[chars - 1] = 0;
        }
    }

    /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */
    for (i = 0; i < shifts; i++)
    {
        for (j = BIT_CHAR(ba->numBits - 1); j > 0; j--)
        {
            ba->array[j] >>= 1;

            /* handle shifts across byte bounds */
            if (ba->array[j - 1] & 0x01)
            {
                ba->array[j] |= MS_BIT;
            }
        }

        ba->array[0] >>= 1;
    }

    /***********************************************************************
    * zero any spare bits that are beyond the end of the bit array so
    * increment and decrement are consistent.
    ***********************************************************************/
    i = ba->numBits % CHAR_BIT;
    if (i != 0)
    {
        mask = UCHAR_MAX << (CHAR_BIT - i);
        ba->array[BIT_CHAR(ba->numBits - 1)] &= mask;
    }
}
Beispiel #5
0
int CHuffmanDecode(struct CHuffman *ch)
{
	bit_file_t bfpIn;
	int i, newBit;
    
	bfpIn.mode = BF_READ;
    	bfpIn.buf = ch->inBuf;
    	bfpIn.bufLen = ch->inLen;
    	BitFileInit(&bfpIn);

	/* open binary output file and bitfile input file */
	/* decode input file */

	ch->outIndex = 0;
	if (!ch->resume) {
		BitArrayClearAll(ch->code);
		ch->decode_length = 0;
	}

    while (1) {
	newBit = BitFileGetBit(&bfpIn);
	if (newBit == EOF) {
		fprintf(stderr, "error reading bitfile\n");
		exit(1);
	}
        if (newBit == BUFFER_EMPTY) {
	    ch->resume = 1;
            return BUFFER_EMPTY;
        }
        if (newBit != 0)
        {
            BitArraySetBit(ch->code, ch->decode_length);
        }

        ch->decode_length++;

        if (ch->lenIndex[ch->decode_length] != NUM_CHARS)
        {
            /* there are code of this length */
            for(i = ch->lenIndex[ch->decode_length];
                (i < NUM_CHARS) && (ch->canonicalList[i].codeLen == ch->decode_length);
                i++)
            {
                if (BitArrayCompare(ch->canonicalList[i].code, ch->code) == 0)
		{
			/* we just read a symbol output decoded value */
                    	if (ch->canonicalList[i].value == EOF_CHAR) {
				if (BitFileByteAlign(&bfpIn)) {
					fprintf(stderr, "buffer full\n");
					exit(1);
				}
			}
                    else {
			if (ch->outIndex >= ch->outLen) {
				/* buffer limit reached */
				fprintf(stderr, "buffer full\n");
				exit(1);
			}
			ch->outBuf[ch->outIndex++] = ch->canonicalList[i].value;
                    }

                    BitArrayClearAll(ch->code);
                    ch->decode_length = 0;

                    break;
                }
            }
        }
    }
    ch->resume = 0;

    /* close all files */
    BitFileClose(&bfpIn);

    return 0;
}