huff_code_t *
huff_code_read(FILE *infh)
{
    huff_code_t *hc;
    uint32 i, j;

    hc = (huff_code_t*)ckd_calloc(1, sizeof(*hc));
    hc->refcount = 1;

    hc->maxbits = fgetc(infh);
    hc->type = fgetc(infh);

    /* Two bytes of padding. */
    fgetc(infh);
    fgetc(infh);

    /* Allocate stuff. */
    hc->firstcode = (uint32*)ckd_calloc(hc->maxbits + 1, sizeof(*hc->firstcode));
    hc->numl = (uint32*)ckd_calloc(hc->maxbits + 1, sizeof(*hc->numl));
    hc->syms = (huff_codeword_t**)ckd_calloc(hc->maxbits + 1, sizeof(*hc->syms));

    /* Read the symbol tables. */
    hc->codewords = hash_table_new(hc->maxbits, HASH_CASE_YES);
    for (i = 1; i <= hc->maxbits; ++i) {
        if (fread(&hc->firstcode[i], 4, 1, infh) != 1)
            goto error_out;
        SWAP_BE_32(&hc->firstcode[i]);
        if (fread(&hc->numl[i], 4, 1, infh) != 1)
            goto error_out;
        SWAP_BE_32(&hc->numl[i]);
        hc->syms[i] =(huff_codeword_t*) ckd_calloc(hc->numl[i], sizeof(**hc->syms));
        for (j = 0; j < hc->numl[i]; ++j) {
            huff_codeword_t *cw = &hc->syms[i][j];
            cw->nbits = i;
            cw->codeword = hc->firstcode[i] + j;
            if (hc->type == HUFF_CODE_INT) {
                if (fread(&cw->r.ival, 4, 1, infh) != 1)
                    goto error_out;
                SWAP_BE_32(&cw->r.ival);
                hash_table_enter_bkey(hc->codewords,
                                      (char const *)&cw->r.ival,
                                      sizeof(cw->r.ival),
                                      (void *)cw);
            }
            else {
                size_t len;
                cw->r.sval = fread_line(infh, &len);
                cw->r.sval[len-1] = '\0';
                hash_table_enter(hc->codewords, cw->r.sval, (void *)cw);
            }
        }
    }

    return hc;
error_out:
    huff_code_free(hc);
    return 0;
}
huff_code_t *
huff_code_build_str(char * const *values, int32 const *frequencies, int nvals)
{
    huff_code_t *hc;
    huff_node_t *root;
    heap_t *q;
    int i;

    hc = (huff_code_t*)ckd_calloc(1, sizeof(*hc));
    hc->refcount = 1;
    hc->type = HUFF_CODE_STR;

    /* Initialize the heap with nodes for each symbol. */
    q = heap_new();
    for (i = 0; i < nvals; ++i) {
        heap_insert(q,
                    huff_node_new_str(values[i]),
                    frequencies[i]);
    }

    /* Now build the tree, which gives us codeword lengths. */
    root = huff_code_build_tree(q);
    heap_destroy(q);
    if (root == 0 || root->nbits > 32) {
        E_ERROR("Huffman trees currently limited to 32 bits\n");
        huff_node_free_str(root, TRUE);
        huff_code_free(hc);
        return 0;
    }

    /* Build a canonical codebook. */
    hc->maxbits = root->nbits;
    huff_code_canonicalize(hc, root);

    /* Tree no longer needed (note we retain pointers to its strings). */
    huff_node_free_str(root, FALSE);

    return hc;
}
Exemple #3
0
huff_code_t *
huff_code_build_int(int32 const *values, int32 const *frequencies, int nvals)
{
    huff_code_t *hc;
    huff_node_t *root;
    heap_t *q;
    int i;

    hc = ckd_calloc(1, sizeof(*hc));
    hc->refcount = 1;
    hc->type = HUFF_CODE_INT;

    /* Initialize the heap with nodes for each symbol. */
    q = heap_new();
    for (i = 0; i < nvals; ++i) {
        heap_insert(q,
                    huff_node_new_int(values[i]),
                    frequencies[i]);
    }

    /* Now build the tree, which gives us codeword lengths. */
    root = huff_code_build_tree(q);
    heap_destroy(q);
    if (root == NULL || root->nbits > 64) {
        E_ERROR("Huffman trees currently limited to 32 bits\n");
        huff_node_free_int(root);
        huff_code_free(hc);
        return NULL;
    }

    /* Build a canonical codebook. */
    hc->maxbits = root->nbits;
    huff_code_canonicalize(hc, root);

    /* Tree no longer needed. */
    huff_node_free_int(root);

    return hc;
}