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