deflate.java

来自「zlib 算法在j2me 中的应用」· Java 代码 · 共 1,764 行 · 第 1/5 页

JAVA
1,764
字号
    while(true){      // Make sure that we always have enough lookahead, except      // at the end of the input file. We need MAX_MATCH bytes      // for the next match, plus MIN_MATCH bytes to insert the      // string following the next match.      if(lookahead < MIN_LOOKAHEAD){	fill_window();	if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH){	  return NeedMore;	}	if(lookahead == 0) break; // flush the current block      }      // Insert the string window[strstart .. strstart+2] in the      // dictionary, and set hash_head to the head of the hash chain:      if(lookahead >= MIN_MATCH){	//	ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;	ins_h=(((ins_h)<<hash_shift)^(window.get((strstart)+(MIN_MATCH-1)) &0xff))&hash_mask;        //hash_head=(head[ins_h]&0xffff);        hash_head=(head.get(ins_h)&0xffff);	//	prev[strstart&w_mask]=head[ins_h];	prev.set(strstart&w_mask,head.get(ins_h));		//head[ins_h]=(short)strstart;	head.set(ins_h,(short)strstart);      }      // Find the longest match, discarding those <= prev_length.      // At this point we have always match_length < MIN_MATCH      if(hash_head!=0L && strstart-hash_head<=w_size-MIN_LOOKAHEAD) {	// To simplify the code, we prevent matches with the string	// of window index 0 (in particular we have to avoid a match	// of the string with itself at the start of the input file).	if(strategy != Z_HUFFMAN_ONLY){	  match_length=longest_match (hash_head);	}	// longest_match() sets match_start      }      if(match_length>=MIN_MATCH){	//        check_match(strstart, match_start, match_length);	bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH);	lookahead -= match_length;	// Insert new strings in the hash table only if the match length	// is not too large. This saves time but degrades compression.	if(match_length <= max_lazy_match &&	   lookahead >= MIN_MATCH) {	  match_length--; // string at strstart already in hash table	  do{	    strstart++;	    //ins_h=((ins_h<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;	    ins_h=((ins_h<<hash_shift)^(window.get((strstart)+(MIN_MATCH-1)) &0xff))&hash_mask;	    	    //hash_head=(head[ins_h]&0xffff);	    hash_head=(head.get(ins_h)&0xffff);	    //prev[strstart&w_mask]=head[ins_h];	    prev.set(strstart&w_mask,head.get(ins_h)); 	    //head[ins_h]=(short)strstart;	    head.set(ins_h,(short)strstart); 	    // strstart never exceeds WSIZE-MAX_MATCH, so there are	    // always MIN_MATCH bytes ahead.	  }	  while (--match_length != 0);	  strstart++; 	}	else{	  strstart += match_length;	  match_length = 0;	  //ins_h = window[strstart]&0xff;	  ins_h = window.get(strstart)&0xff;	  	  //ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask;	  ins_h=(((ins_h)<<hash_shift)^(window.get(strstart+1)&0xff))&hash_mask;	  	  // If lookahead < MIN_MATCH, ins_h is garbage, but it does not	  // matter since it will be recomputed at next deflate call.	}      }      else {	// No match, output a literal byte	//bflush=_tr_tally(0, window[strstart]&0xff);	bflush=_tr_tally(0, window.get(strstart)&0xff);		lookahead--;	strstart++;       }      if (bflush){	flush_block_only(false);	if(strm.avail_out==0) return NeedMore;      }    }    flush_block_only(flush == Z_FINISH);    if(strm.avail_out==0){      if(flush == Z_FINISH) return FinishStarted;      else return NeedMore;    }    return flush==Z_FINISH ? FinishDone : BlockDone;  }  // Same as above, but achieves better compression. We use a lazy  // evaluation for matches: a match is finally adopted only if there is  // no better match at the next window position.  int deflate_slow(int flush){//    short hash_head = 0;    // head of hash chain    int hash_head = 0;    // head of hash chain    boolean bflush;         // set if current block must be flushed    // Process the input block.    while(true){      // Make sure that we always have enough lookahead, except      // at the end of the input file. We need MAX_MATCH bytes      // for the next match, plus MIN_MATCH bytes to insert the      // string following the next match.      if (lookahead < MIN_LOOKAHEAD) {	fill_window();	if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {	  return NeedMore;	}	if(lookahead == 0) break; // flush the current block      }      // Insert the string window[strstart .. strstart+2] in the      // dictionary, and set hash_head to the head of the hash chain:      if(lookahead >= MIN_MATCH) {	//ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff)) & hash_mask;	ins_h=(((ins_h)<<hash_shift)^(window.get((strstart)+(MIN_MATCH-1))&0xff)) & hash_mask;		//hash_head=(head[ins_h]&0xffff);	hash_head=(head.get(ins_h)&0xffff);	//prev[strstart&w_mask]=head[ins_h];	prev.set(strstart&w_mask,head.get(ins_h));	//head[ins_h]=(short)strstart;	head.set(ins_h,(short)strstart);      }      // Find the longest match, discarding those <= prev_length.      prev_length = match_length; prev_match = match_start;      match_length = MIN_MATCH-1;      if (hash_head != 0 && prev_length < max_lazy_match &&	  strstart - hash_head <= w_size-MIN_LOOKAHEAD) {	// To simplify the code, we prevent matches with the string	// of window index 0 (in particular we have to avoid a match	// of the string with itself at the start of the input file).	if(strategy != Z_HUFFMAN_ONLY) {	  match_length = longest_match(hash_head);	}	// longest_match() sets match_start	if (match_length <= 5 && (strategy == Z_FILTERED ||				  (match_length == MIN_MATCH &&				   strstart - match_start > 4096))) {	  // If prev_match is also MIN_MATCH, match_start is garbage	  // but we will ignore the current match anyway.	  match_length = MIN_MATCH-1;	}      }      // If there was a match at the previous step and the current      // match is not better, output the previous match:      if(prev_length >= MIN_MATCH && match_length <= prev_length) {	int max_insert = strstart + lookahead - MIN_MATCH;	// Do not insert strings in hash table beyond this.	//          check_match(strstart-1, prev_match, prev_length);	bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH);	// Insert in hash table all strings up to the end of the match.	// strstart-1 and strstart are already inserted. If there is not	// enough lookahead, the last two strings are not inserted in	// the hash table.	lookahead -= prev_length-1;	prev_length -= 2;	do{	  if(++strstart <= max_insert) {	    //ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;	    ins_h=(((ins_h)<<hash_shift)^(window.get((strstart)+(MIN_MATCH-1))&0xff))&hash_mask;	    	    //hash_head=(head[ins_h]&0xffff);	    hash_head=(head.get(ins_h)&0xffff);	    //prev[strstart&w_mask]=head[ins_h];	    prev.set(strstart&w_mask,head.get(ins_h)); 	    //head[ins_h]=(short)strstart;                  head.set(ins_h,(short)strstart);	  }	}	while(--prev_length != 0);	match_available = 0;	match_length = MIN_MATCH-1;	strstart++;	if (bflush){	  flush_block_only(false);	  if(strm.avail_out==0) return NeedMore;	}      } else if (match_available!=0) {	// If there was no match at the previous position, output a	// single literal. If there was a match but the current match	// is longer, truncate the previous match to a single literal.	//bflush=_tr_tally(0, window[strstart-1]&0xff);	bflush=_tr_tally(0, window.get(strstart-1)&0xff);		if (bflush) {	  flush_block_only(false);	}	strstart++;	lookahead--;	if(strm.avail_out == 0) return NeedMore;      } else {	// There is no previous match to compare with, wait for	// the next step to decide.	match_available = 1;	strstart++;	lookahead--;      }    }    if(match_available!=0) {      //bflush=_tr_tally(0, window[strstart-1]&0xff);      bflush=_tr_tally(0, window.get(strstart-1)&0xff);            match_available = 0;    }    flush_block_only(flush == Z_FINISH);    if(strm.avail_out==0){      if(flush == Z_FINISH) return FinishStarted;      else return NeedMore;    }    return flush == Z_FINISH ? FinishDone : BlockDone;  }  int longest_match(int cur_match){    int chain_length = max_chain_length; // max hash chain length    int scan = strstart;                 // current string    int match;                           // matched string    int len;                             // length of current match    int best_len = prev_length;          // best match length so far    int limit = strstart>(w_size-MIN_LOOKAHEAD) ?      strstart-(w_size-MIN_LOOKAHEAD) : 0;    int nice_match=this.nice_match;    // Stop when cur_match becomes <= limit. To simplify the code,    // we prevent matches with the string of window index 0.    int wmask = w_mask;    int strend = strstart + MAX_MATCH;    //byte scan_end1 = window[scan+best_len-1];    //byte scan_end = window[scan+best_len];    byte scan_end1 = window.get(scan+best_len-1);    byte scan_end = window.get(scan+best_len);    // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.    // It is easy to get rid of this optimization if necessary.    // Do not waste too much time if we already have a good match:    if (prev_length >= good_match) {      chain_length >>= 2;    }    // Do not look for matches beyond the end of the input. This is necessary    // to make deflate deterministic.    if (nice_match > lookahead) nice_match = lookahead;    do {      match = cur_match;      // Skip to next match if the match length cannot increase      // or if the match length is less than 2:      //      if (window[match+best_len]   != scan_end  ||      //	  window[match+best_len-1] != scan_end1 ||      //	  window[match]       != window[scan]     ||      //	  window[++match]     != window[scan+1])      continue;            if (window.get(match+best_len)   != scan_end  ||	  window.get(match+best_len-1) != scan_end1 ||	  window.get(match)       != window.get(scan)     ||	  window.get(++match)     != window.get(scan+1))      continue;            // The check at best_len-1 can be removed because it will be made      // again later. (This heuristic is not always a win.)      // It is not necessary to compare scan[2] and match[2] since they      // are always equal when the other bytes match, given that      // the hash keys are equal and that HASH_BITS >= 8.      scan += 2; match++;      // We check for insufficient lookahead only every 8th comparison;      // the 256th check will be made at strstart+258.      do {	      //} while (window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     window[++scan] == window[++match] &&	//     scan < strend);      } while (window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       window.get(++scan) == window.get(++match) &&	       scan < strend);      len = MAX_MATCH - (int)(strend - scan);      scan = strend - MAX_MATCH;      if(len>best_len) {	match_start = cur_match;	best_len = len;	if (len >= nice_match) break;	//scan_end1  = window[scan+best_len-1];	//scan_end   = window[scan+best_len];	scan_end1  = window.get(scan+best_len-1);	scan_end   = window.get(scan+best_len);      }    //} while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit    } while ((cur_match = (prev.get(cur_match & wmask)&0xffff)) > limit	     	     && --chain_length != 0);    if (best_len <= lookahead) return best_len;    return lookahead;  }      int deflateInit(ZStream strm, int level, int bits){    return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL,			Z_DEFAULT_STRATEGY);  }  int deflateInit(ZStream strm, int level){    return deflateInit(strm, level, MAX_WBITS);

⌨️ 快捷键说明

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