📄 deflate.java
字号:
} } if(match_available!=0) { bflush=_tr_tally(0, window[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]; // 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; // 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); 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]; } } while ((cur_match = (prev[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); } int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy){ int noheader = 0; // byte[] my_version=ZLIB_VERSION; // // if (version == null || version[0] != my_version[0] // || stream_size != sizeof(z_stream)) { // return Z_VERSION_ERROR; // } strm.msg = null; if (level == Z_DEFAULT_COMPRESSION) level = 6; if (windowBits < 0) { // undocumented feature: suppress zlib header noheader = 1; windowBits = -windowBits; } if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } strm.dstate = (Deflate)this; this.noheader = noheader; w_bits = windowBits; w_size = 1 << w_bits; w_mask = w_size - 1; hash_bits = memLevel + 7; hash_size = 1 << hash_bits; hash_mask = hash_size - 1; hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); window = new byte[w_size*2]; prev = new short[w_size]; head = new short[hash_size]; lit_bufsize = 1 << (memLevel + 6); // 16K elements by default // We overlay pending_buf and d_buf+l_buf. This works since the average // output size for (length,distance) codes is <= 24 bits. pending_buf = new byte[lit_bufsize*4]; pending_buf_size = lit_bufsize*4; d_buf = lit_bufsize/2; l_buf = (1+2)*lit_bufsize; this.level = level;//System.out.println("level="+level); this.strategy = strategy; this.method = (byte)method; return deflateReset(strm); } int deflateReset(ZStream strm){ strm.total_in = strm.total_out = 0; strm.msg = null; // strm.data_type = Z_UNKNOWN; pending = 0; pending_out = 0; if(noheader < 0) { noheader = 0; // was set to -1 by deflate(..., Z_FINISH); } status = (noheader!=0) ? BUSY_STATE : INIT_STATE; strm.adler=strm._adler.adler32(0, null, 0, 0); last_flush = Z_NO_FLUSH; tr_init(); lm_init(); return Z_OK; } int deflateEnd(){ if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ return Z_STREAM_ERROR; } // Deallocate in reverse order of allocations: pending_buf=null; head=null; prev=null; window=null; // free // dstate=null; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } int deflateParams(ZStream strm, int _level, int _strategy){ int err=Z_OK; if(_level == Z_DEFAULT_COMPRESSION){ _level = 6; } if(_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } if(config_table[level].func!=config_table[_level].func && strm.total_in != 0) { // Flush the last buffer: err = strm.deflate(Z_PARTIAL_FLUSH); } if(level != _level) { level = _level; max_lazy_match = config_table[level].max_lazy; good_match = config_table[level].good_length; nice_match = config_table[level].nice_length; max_chain_length = config_table[level].max_chain; } strategy = _strategy; return err; } int deflateSetDictionary (ZStream strm, byte[] dictionary, int dictLength){ int length = dictLength; int index=0; if(dictionary == null || status != INIT_STATE) return Z_STREAM_ERROR; strm.adler=strm._adler.adler32(strm.adler, dictionary, 0, dictLength); if(length < MIN_MATCH) return Z_OK; if(length > w_size-MIN_LOOKAHEAD){ length = w_size-MIN_LOOKAHEAD; index=dictLength-length; // use the tail of the dictionary } System.arraycopy(dictionary, index, window, 0, length); strstart = length; block_start = length; // Insert all strings in the hash table (except for the last two bytes). // s->lookahead stays null, so s->ins_h will be recomputed at the next // call of fill_window. ins_h = window[0]&0xff; ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask; for(int n=0; n<=length-MIN_MATCH; n++){ ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask; prev[n&w_mask]=head[ins_h]; head[ins_h]=(short)n; } return Z_OK; } int deflate(ZStream strm, int flush){ int old_flush; if(flush>Z_FINISH || flush<0){ return Z_STREAM_ERROR; } if(strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == FINISH_STATE && flush != Z_FINISH)) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; return Z_STREAM_ERROR; } if(strm.avail_out == 0){ strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } this.strm = strm; // just in case old_flush = last_flush; last_flush = flush; // Write the zlib header if(status == INIT_STATE) { int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; int level_flags=((level-1)&0xff)>>1; if(level_flags>3) level_flags=3; header |= (level_flags<<6); if(strstart!=0) header |= PRESET_DICT; header+=31-(header % 31); status=BUSY_STATE; putShortMSB(header); // Save the adler32 of the preset dictionary: if(strstart!=0){ putShortMSB((int)(strm.adler>>>16)); putShortMSB((int)(strm.adler&0xffff)); } strm.adler=strm._adler.adler32(0, null, 0, 0); } // Flush as much pending output as possible if(pending != 0) { strm.flush_pending(); if(strm.avail_out == 0) { //System.out.println(" avail_out==0"); // Since avail_out is 0, deflate will be called again with // more output space, but possibly with both pending and // avail_in equal to zero. There won't be anything to do, // but this is not an error situation so make sure we // return OK instead of BUF_ERROR at next call of deflate: last_flush = -1; return Z_OK; } // Make sure there is something to do and avoid duplicate consecutive // flushes. For repeated and useless calls with Z_FINISH, we keep // returning Z_STREAM_END instead of Z_BUFF_ERROR. } else if(strm.avail_in==0 && flush <= old_flush && flush != Z_FINISH) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } // User must not provide more input after the first FINISH: if(status == FINISH_STATE && strm.avail_in != 0) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } // Start a new block or continue the current one. if(strm.avail_in!=0 || lookahead!=0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) { int bstate=-1; switch(config_table[level].func){ case STORED: bstate = deflate_stored(flush); break; case FAST: bstate = deflate_fast(flush); break; case SLOW: bstate = deflate_slow(flush); break; default: } if (bstate==FinishStarted || bstate==FinishDone) { status = FINISH_STATE; } if (bstate==NeedMore || bstate==FinishStarted) { if(strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR next call, see above } return Z_OK; // If flush != Z_NO_FLUSH && avail_out == 0, the next call // of deflate should use the same flush parameter to make sure // that the flush is complete. So we don't have to output an // empty block here, this will be done at next call. This also // ensures that for a very small output buffer, we emit at most // one empty block. } if (bstate==BlockDone) { if(flush == Z_PARTIAL_FLUSH) { _tr_align(); } else { // FULL_FLUSH or SYNC_FLUSH _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized // as a special marker by inflate_sync(). if(flush == Z_FULL_FLUSH) { //state.head[s.hash_size-1]=0; for(int i=0; i<hash_size/*-1*/; i++) // forget history head[i]=0; } } strm.flush_pending(); if(strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR at next call, see above return Z_OK; } } } if(flush!=Z_FINISH) return Z_OK; if(noheader!=0) return Z_STREAM_END; // Write the zlib trailer (adler32) putShortMSB((int)(strm.adler>>>16)); putShortMSB((int)(strm.adler&0xffff)); strm.flush_pending(); // If avail_out is zero, the application will call deflate again // to flush the rest. noheader = -1; // write the trailer only once! return pending != 0 ? Z_OK : Z_STREAM_END; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -