/**************************************************************************** * 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; }
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; }