/**************************************************************************** * 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 : BitArrayDuplicate * Description: This function duplicates (creates and copies) the bit array * passed as a parameter and returns a pointer to the * duplicate. * Parameters : src - pointer to bit array to be duplicated * Effects : A duplicate of the source bit array is created. * Returned : Pointer to duplicate of source or NULL on failure. ***************************************************************************/ bit_array_t *BitArrayDuplicate(const bit_array_t *src) { bit_array_t *ba; if (src == NULL) { return NULL; /* no source array */ } ba = BitArrayCreate(src->numBits); if (ba != NULL) { ba->numBits = src->numBits; BitArrayCopy(ba, src); } return ba; }
/**************************************************************************** * 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 CHuffmanInit(struct CHuffman *ch) { int i; /* initialize canonical list */ for (i = 0; i < NUM_CHARS; i++) { ch->canonicalList[i].codeLen = 0; ch->canonicalList[i].code = NULL; } if (!ReadHeader(ch->canonicalList)) { return FALSE; } /* sort the header by code length */ qsort(ch->canonicalList, NUM_CHARS, sizeof(canonical_list_t), CompareByCodeLen); if (AssignCanonicalCodes(ch->canonicalList) == 0) { /* failed to assign codes */ for (i = 0; i < NUM_CHARS; i++) { if(ch->canonicalList[i].code != NULL) { BitArrayDestroy(ch->canonicalList[i].code); } } return FALSE; } if (ch->for_encode) { /* re-sort list in lexical order for use by encode algorithm */ qsort(ch->canonicalList, NUM_CHARS, sizeof(canonical_list_t), CompareBySymbolValue); } else { /* decoding */ /* allocate canonical code list */ ch->code = BitArrayCreate(256); if (ch->code == NULL) { perror("Bit array allocation"); return FALSE; } ch->resume = 0; /* create an index of first code at each possible length */ for (i = 0; i < NUM_CHARS; i++) { ch->lenIndex[i] = NUM_CHARS; } for (i = 0; i < NUM_CHARS; i++) { if (ch->lenIndex[ch->canonicalList[i].codeLen] > i) { /* first occurance of this code length */ ch->lenIndex[ch->canonicalList[i].codeLen] = i; } } } return TRUE; }