📄 zlib.c
字号:
if (strm->next_in == Z_NULL && strm->avail_in != 0) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); state->strm = strm; /* just in case */ /* Write the zlib header */ if (state->status == INIT_STATE) { uInt header = (DEFLATED + ((state->w_bits-8)<<4)) << 8; uInt level_flags = (state->level-1) >> 1; if (level_flags > 3) level_flags = 3; header |= (level_flags << 6); header += 31 - (header % 31); state->status = BUSY_STATE; putShortMSB(state, header); } /* Flush as much pending output as possible */ if (state->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) return Z_OK; } /* If we came back in here to get the last output from * a previous flush, we're done for now. */ if (state->status == FLUSH_STATE) { state->status = BUSY_STATE; if (flush != Z_NO_FLUSH && flush != Z_FINISH) return Z_OK; } /* User must not provide more input after the first FINISH: */ if (state->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || state->lookahead != 0 || (flush == Z_FINISH && state->status != FINISH_STATE)) { int quit; if (flush == Z_FINISH) { state->status = FINISH_STATE; } if (state->level <= 3) { quit = deflate_fast(state, flush); } else { quit = deflate_slow(state, flush); } if (quit || strm->avail_out == 0) 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 a flush was requested, we have a little more to output now. */ if (flush != Z_NO_FLUSH && flush != Z_FINISH && state->status != FINISH_STATE) { switch (flush) { case Z_PARTIAL_FLUSH: ct_align(state); break; case Z_PACKET_FLUSH: /* Output just the 3-bit `stored' block type value, but not a zero length. */ ct_stored_type_only(state); break; default: ct_stored_block(state, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(state); /* forget history */ } } flush_pending(strm); if (strm->avail_out == 0) { /* We'll have to come back to get the rest of the output; * this ensures we don't output a second zero-length stored * block (or whatever). */ state->status = FLUSH_STATE; return Z_OK; } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (state->noheader) return Z_STREAM_END; /* Write the zlib trailer (adler32) */ putShortMSB(state, (uInt)(state->adler >> 16)); putShortMSB(state, (uInt)(state->adler & 0xffff)); flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ state->noheader = -1; /* write the trailer only once! */ return state->pending != 0 ? Z_OK : Z_STREAM_END;}/* ========================================================================= */int deflateEnd (strm) z_stream *strm;{ deflate_state *state = (deflate_state *) strm->state; if (strm == Z_NULL || state == Z_NULL) return Z_STREAM_ERROR; TRY_FREE(strm, state->window, state->w_size * 2 * sizeof(Byte)); TRY_FREE(strm, state->prev, state->w_size * sizeof(Pos)); TRY_FREE(strm, state->head, state->hash_size * sizeof(Pos)); TRY_FREE(strm, state->pending_buf, state->lit_bufsize * 2 * sizeof(ush)); ZFREE(strm, state, sizeof(deflate_state)); strm->state = Z_NULL; return Z_OK;}/* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. */local int read_buf(strm, buf, size) z_stream *strm; charf *buf; unsigned size;{ unsigned len = strm->avail_in; deflate_state *state = (deflate_state *) strm->state; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; if (!state->noheader) { state->adler = adler32(state->adler, strm->next_in, len); } zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; return (int)len;}/* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */local void lm_init (s) deflate_state *s;{ s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->match_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0;#ifdef ASMV match_init(); /* initialize the asm code */#endif}/* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 */#ifndef ASMV/* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */local int longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */{ unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask;#ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1);#else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len];#endif /* 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. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2: */#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* 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. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1);#else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != 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++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH;#endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= s->nice_match) break;#ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1);#else scan_end1 = scan[best_len-1]; scan_end = scan[best_len];#endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); return best_len;}#endif /* ASMV */#ifdef DEBUG_ZLIB/* =========================================================================== * Check that the match at match_start is indeed a match. */local void check_match(s, start, match, length) deflate_state *s; IPos start, match; int length;{ /* check that the match is indeed a match */ if (memcmp((charf *)s->window + match, (charf *)s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); }}#else# define check_match(s, start, match, length)#endif/* =========================================================================== * 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).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -