📄 deflate.java
字号:
} if (stored_len + 4 <= opt_lenb && buf != -1) { // 4: two words for the lengths // 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. _tr_stored_block(buf, stored_len, eof); } else if (static_lenb == opt_lenb) { send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3); compress_block(StaticTree.static_ltree, StaticTree.static_dtree); } else { send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3); send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); compress_block(dyn_ltree, dyn_dtree); } // The above check is made mod 2^32, for files larger than 512 MB // and uLong implemented on 32 bits. init_block(); if (eof) { bi_windup(); } } // Fill the window when the lookahead becomes insufficient. // Updates strstart and lookahead. // // IN assertion: lookahead < MIN_LOOKAHEAD // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD // At least one byte has been read, or avail_in == 0; reads are // performed for at least two bytes (required for the zip translate_eol // option -- not supported here). void fill_window() { int n, m; int p; int more; // Amount of free space at the end of the window. do { more = (window_size - lookahead - strstart); // Deal with !@#$% 64K limit: if (more == 0 && strstart == 0 && lookahead == 0) { more = w_size; } else if (more == -1) { // Very unlikely, but possible on 16 bit machine if strstart == 0 // and lookahead == 1 (input done one byte at time) more--; // If the window is almost full and there is insufficient lookahead, // move the upper half to the lower one to make room in the upper half. } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) { //System.arraycopy(window, w_size, window, 0, w_size); byte_array.Copy(window, w_size, window, 0, w_size); match_start -= w_size; strstart -= w_size; // we now have strstart >= MAX_DIST block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values // at the expense of memory usage). We slide even when level == 0 // to keep the hash table consistent if we switch back to level > 0 // later. (Using level 0 permanently is not an optimal usage of // zlib, so we don't care about this pathological case.) n = hash_size; p = n; do { //m = (head[--p]&0xffff); m = (head.get(--p) & 0xffff); //head[p]=(m>=w_size ? (short)(m-w_size) : 0); head.set(p, (m >= w_size ? (short) (m - w_size) : 0)); } while (--n != 0); n = w_size; p = n; do { // m = (prev[--p]&0xffff); m = (prev.get(--p) & 0xffff); //prev[p] = (m >= w_size ? (short)(m-w_size) : 0); prev.set(p, (m >= w_size ? (short) (m - w_size) : 0)); // If n is not on any hash chain, prev[n] is garbage but // its value will never be used. } while (--n != 0); more += w_size; } if (strm.avail_in == 0) { return; } // If there was no sliding: // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && // more == window_size - lookahead - strstart // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) // => more >= window_size - 2*WSIZE + 2 // In the BIG_MEM or MMAP case (not yet supported), // window_size == input_size + MIN_LOOKAHEAD && // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. // Otherwise, window_size == 2*WSIZE so more >= 2. // If there was sliding, more >= WSIZE. So in all cases, more >= 2. n = strm.read_buf(window, strstart + lookahead, more); lookahead += n; // Initialize the hash value now that we have some input: if (lookahead >= MIN_MATCH) { //ins_h = window[strstart]&0xff; //ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask; ins_h = window.get(strstart) & 0xff; ins_h = (((ins_h) << hash_shift) ^ (window.get(strstart + 1) & 0xff)) & hash_mask; } // If the whole input has less than MIN_MATCH bytes, ins_h is garbage, // but this is not important since only literal bytes will be emitted. } while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0); } // Compress as much as possible from the input stream, return the current // block state. // This function does not perform lazy evaluation of matches and inserts // new strings in the dictionary only for unmatched strings or for short // matches. It is used only for the fast compression options. int deflate_fast(int flush) {// short hash_head = 0; // head of the hash chain int hash_head = 0; // head of the hash chain boolean bflush; // set if current block must be flushed 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -