⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlib.c

📁 经典的ppp程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -