Exemple #1
0
	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;
   }