void ZipDeflate::compress_block(zip_ct_data* ltree, zip_ct_data* dtree) { UINT dist, lx(0), code; int lc, extra; if(last_lit) do { dist = d_buf[lx]; lc = l_buf[lx++]; if(dist == 0) { send_code(lc, ltree); } else { code = _length_code[lc]; send_code(code + LITERALS + 1, ltree); extra = extra_lbits[code]; if(extra) {lc -= base_length[code]; send_bits(lc, extra);} dist--; code = d_code(dist); send_code(code, dtree); extra = extra_dbits[code]; if(extra) {dist -= base_dist[code]; send_bits(dist, extra);} } } while(lx < last_lit); send_code(END_BLOCK, ltree); }
/* Save the match info and tally the frequency counts. Return true if the current block must be flushed. */ int CodeTree::ct_tally (int dist, int lc) { l_buf[last_lit++] = (byte)lc; if (dist == 0) { /* lc is the unmatched char */ dyn_ltree[lc].Freq++; } else { /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ assert((word16)dist < (word16)MAX_DIST && (word16)lc <= (word16)(MAX_MATCH-MIN_MATCH) && (word16)d_code(dist) < (word16)D_CODES); dyn_ltree[length_code[lc]+LITERALS+1].Freq++; dyn_dtree[d_code(dist)].Freq++; d_buf[last_dist++] = dist; flags |= flag_bit; } flag_bit <<= 1; /* Output the flags if they fill a byte: */ if ((last_lit & 7) == 0) { flag_buf[last_flags++] = flags; flags = 0, flag_bit = 1; } /* Try to guess if it is profitable to stop the current block here */ if (deflate_level > 2 && (last_lit & 0xfff) == 0) { /* Compute an upper bound for the compressed length */ word32 out_length = (word32)last_lit*8L; word32 in_length = (word32)strstart-block_start; int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (word32)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]); } out_length >>= 3; // Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", // last_lit, last_dist, in_length, out_length, // 100L - out_length*100L/in_length)); if (last_dist < last_lit/2 && out_length < in_length/2) return 1; }