⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trees.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
📖 第 1 页 / 共 4 页
字号:
     * must be all ones.     */    Assert(code + bl_count[MAX_BITS]-1 == (1<< ((ush) MAX_BITS)) - 1,            "inconsistent bit counts");    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));    for (n = 0;  n <= max_code; n++) {        int len = tree[n].Len;        if (len == 0) continue;        /* Now reverse the bits */        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);        Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));    }}/* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. * Update the total bit length for the current block. * IN assertion: the field freq is set for all tree elements. * OUT assertions: the fields len and code are set to the optimal bit length *     and corresponding code. The length opt_len is updated; static_len is *     also updated if stree is not null. The field max_code is set. */local void build_tree(desc)    tree_desc near *desc; /* the tree descriptor */{    ct_data near *tree   = desc->dyn_tree;    ct_data near *stree  = desc->static_tree;    int elems            = desc->elems;    int n, m;          /* iterate over heap elements */    int max_code = -1; /* largest code with non zero frequency */    int node = elems;  /* next internal node of the tree */    /* Construct the initial heap, with least frequent element in     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].     * heap[0] is not used.     */    heap_len = 0, heap_max = HEAP_SIZE;    for (n = 0; n < elems; n++) {        if (tree[n].Freq != 0) {            heap[++heap_len] = max_code = n;            depth[n] = 0;        } else {            tree[n].Len = 0;        }    }    /* The pkzip format requires that at least one distance code exists,     * and that at least one bit should be sent even if there is only one     * possible code. So to avoid special checks later on we force at least     * two codes of non zero frequency.     */    while (heap_len < 2) {        int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);        tree[new].Freq = 1;        depth[new] = 0;        opt_len--; if (stree) static_len -= stree[new].Len;        /* new is 0 or 1 so it does not have extra bits */    }    desc->max_code = max_code;    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,     * establish sub-heaps of increasing lengths:     */    for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);    /* Construct the Huffman tree by repeatedly combining the least two     * frequent nodes.     */    do {        pqremove(tree, n);   /* n = node of least frequency */        m = heap[SMALLEST];  /* m = node of next least frequency */        heap[--heap_max] = n; /* keep the nodes sorted by frequency */        heap[--heap_max] = m;        /* Create a new node father of n and m */        tree[node].Freq = (ush)(tree[n].Freq + tree[m].Freq);        depth[node] = (uch) (Max(depth[n], depth[m]) + 1);        tree[n].Dad = tree[m].Dad = (ush)node;#ifdef DUMP_BL_TREE        if (tree == bl_tree) {            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);        }#endif        /* and insert the new node in the heap */        heap[SMALLEST] = node++;        pqdownheap(tree, SMALLEST);    } while (heap_len >= 2);    heap[--heap_max] = heap[SMALLEST];    /* At this point, the fields freq and dad are set. We can now     * generate the bit lengths.     */    gen_bitlen((tree_desc near *)desc);    /* The field len is now set, we can generate the bit codes */    gen_codes ((ct_data near *)tree, max_code);}/* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. Updates opt_len to take into account the repeat * counts. (The contribution of the bit length codes will be added later * during the construction of bl_tree.) */local void scan_tree (tree, max_code)    ct_data near *tree; /* the tree to be scanned */    int max_code;       /* and its largest code of non zero frequency */{    int n;                     /* iterates over all tree elements */    int prevlen = -1;          /* last emitted length */    int curlen;                /* length of current code */    int nextlen = tree[0].Len; /* length of next code */    int count = 0;             /* repeat count of the current code */    int max_count = 7;         /* max repeat count */    int min_count = 4;         /* min repeat count */    if (nextlen == 0) max_count = 138, min_count = 3;    tree[max_code+1].Len = (ush)-1; /* guard */    for (n = 0; n <= max_code; n++) {        curlen = nextlen; nextlen = tree[n+1].Len;        if (++count < max_count && curlen == nextlen) {            continue;        } else if (count < min_count) {            bl_tree[curlen].Freq += (ush)count;        } else if (curlen != 0) {            if (curlen != prevlen) bl_tree[curlen].Freq++;            bl_tree[REP_3_6].Freq++;        } else if (count <= 10) {            bl_tree[REPZ_3_10].Freq++;        } else {            bl_tree[REPZ_11_138].Freq++;        }        count = 0; prevlen = curlen;        if (nextlen == 0) {            max_count = 138, min_count = 3;        } else if (curlen == nextlen) {            max_count = 6, min_count = 3;        } else {            max_count = 7, min_count = 4;        }    }}/* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */local void send_tree (tree, max_code)    ct_data near *tree; /* the tree to be scanned */    int max_code;       /* and its largest code of non zero frequency */{    int n;                     /* iterates over all tree elements */    int prevlen = -1;          /* last emitted length */    int curlen;                /* length of current code */    int nextlen = tree[0].Len; /* length of next code */    int count = 0;             /* repeat count of the current code */    int max_count = 7;         /* max repeat count */    int min_count = 4;         /* min repeat count */    /* tree[max_code+1].Len = -1; */  /* guard already set */    if (nextlen == 0) max_count = 138, min_count = 3;    for (n = 0; n <= max_code; n++) {        curlen = nextlen; nextlen = tree[n+1].Len;        if (++count < max_count && curlen == nextlen) {            continue;        } else if (count < min_count) {            do { send_code(curlen, bl_tree); } while (--count != 0);        } else if (curlen != 0) {            if (curlen != prevlen) {                send_code(curlen, bl_tree); count--;            }            Assert(count >= 3 && count <= 6, " 3_6?");            send_code(REP_3_6, bl_tree); send_bits(count-3, 2);        } else if (count <= 10) {            send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);        } else {            send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);        }        count = 0; prevlen = curlen;        if (nextlen == 0) {            max_count = 138, min_count = 3;        } else if (curlen == nextlen) {            max_count = 6, min_count = 3;        } else {            max_count = 7, min_count = 4;        }    }}/* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */local int build_bl_tree(){    int max_blindex;  /* index of last bit length code of non zero freq */    /* Determine the bit length frequencies for literal and distance trees */    scan_tree((ct_data near *)dyn_ltree, l_desc.max_code);    scan_tree((ct_data near *)dyn_dtree, d_desc.max_code);    /* Build the bit length tree: */    build_tree((tree_desc near *)(&bl_desc));    /* opt_len now includes the length of the tree representations, except     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.     */    /* Determine the number of bit length codes to send. The pkzip format     * requires that at least 4 bit length codes be sent. (appnote.txt says     * 3 but the actual value used is 4.)     */    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {        if (bl_tree[bl_order[max_blindex]].Len != 0) break;    }    /* Update opt_len to include the bit length tree and counts */    opt_len += 3*(max_blindex+1) + 5+5+4;    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));    return max_blindex;}/* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */local void send_all_trees(lcodes, dcodes, blcodes)    int lcodes, dcodes, blcodes; /* number of codes for each tree */{    int rank;                    /* index in bl_order */    Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");    Assert(lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,            "too many codes");    Tracev((stderr, "\nbl counts: "));    send_bits(lcodes-257, 5);    /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */    send_bits(dcodes-1,   5);    send_bits(blcodes-4,  4); /* not -3 as stated in appnote.txt */    for (rank = 0; rank < blcodes; rank++) {        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));        send_bits(bl_tree[bl_order[rank]].Len, 3);    }    Tracev((stderr, "\nbl tree: sent %ld", bits_sent));    send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */    Tracev((stderr, "\nlit tree: sent %ld", bits_sent));    send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */    Tracev((stderr, "\ndist tree: sent %ld", bits_sent));}/* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. This function * returns the total compressed length (in bytes) for the file so far. */ulg flush_block(buf, stored_len, eof)    char *buf;        /* input block, or NULL if too old */    ulg stored_len;   /* length of input block */    int eof;          /* true if this is the last block for a file */{    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */    int max_blindex;  /* index of last bit length code of non zero freq */    flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */     /* Check if the file is ascii or binary */    if (*file_type == (ush)UNKNOWN) set_file_type();    /* Construct the literal and distance trees */    build_tree((tree_desc near *)(&l_desc));    Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));    build_tree((tree_desc near *)(&d_desc));    Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));    /* At this point, opt_len and static_len are the total bit lengths of     * the compressed block data, excluding the tree representations.     */    /* Build the bit length tree for the above two trees, and get the index     * in bl_order of the last bit length code to send.     */    max_blindex = build_bl_tree();    /* Determine the best encoding. Compute first the block length in bytes */    opt_lenb = (opt_len+3+7)>>3;    static_lenb = (static_len+3+7)>>3;#ifdef DEBUG    input_len += stored_len; /* for debugging only */#endif    Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",            opt_lenb, opt_len, static_lenb, static_len, stored_len,            last_lit, last_dist));    if (static_lenb <= opt_lenb) opt_lenb = static_lenb;#ifndef PGP /* PGP can't handle stored blocks */    /* If compression failed and this is the first and last block,     * the whole file is transformed into a stored file:     */#ifdef FORCE_METHOD    if (level == 1 && eof && file_method != NULL &&        cmpr_bytelen == 0L && cmpr_len_bits == 0L) { /* force stored file */#else    if (stored_len <= opt_lenb && eof && file_method != NULL &&        cmpr_bytelen == 0L && cmpr_len_bits == 0L && seekable()) {#endif        /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */        if (buf == NULL) error ("block vanished");        copy_block(buf, (unsigned)stored_len, 0); /* without header */        cmpr_bytelen = stored_len;        *file_method = STORE;    } else#endif /* PGP */#ifdef FORCE_METHOD    if (level <= 2 && buf != (char*)NULL) { /* force stored block */#else    if (stored_len+4 <= opt_lenb && buf != (char*)NULL) {                       /* 4: two words for the lengths */#endif        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.         * Otherwise we can't have processed more than WSIZE input bytes since         * the last block flush, because compression would have been         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to         * transform a block into a stored block.         */        send_bits((STORED_BLOCK<<1)+eof, 3);  /* send block type */        cmpr_bytelen += ((cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4;        cmpr_len_bits = 0L;        copy_block(buf, (unsigned)stored_len, 1); /* with header */#ifdef FORCE_METHOD    } else if (level == 3) { /* force static trees */#else    } else if (static_lenb == opt_lenb) {#endif        send_bits((STATIC_TREES<<1)+eof, 3);        compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree);        cmpr_len_bits += 3 + static_len;        cmpr_bytelen += cmpr_len_bits >> 3;        cmpr_len_bits &= 7L;    } else {        send_bits((DYN_TREES<<1)+eof, 3);        send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);        compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree);        cmpr_len_bits += 3 + opt_len;        cmpr_bytelen += cmpr_len_bits >> 3;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -