11cb0ef41Sopenharmony_ci/* deflate.c -- compress data using the deflation algorithm 21cb0ef41Sopenharmony_ci * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler 31cb0ef41Sopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 41cb0ef41Sopenharmony_ci */ 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci/* 71cb0ef41Sopenharmony_ci * ALGORITHM 81cb0ef41Sopenharmony_ci * 91cb0ef41Sopenharmony_ci * The "deflation" process depends on being able to identify portions 101cb0ef41Sopenharmony_ci * of the input text which are identical to earlier input (within a 111cb0ef41Sopenharmony_ci * sliding window trailing behind the input currently being processed). 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * The most straightforward technique turns out to be the fastest for 141cb0ef41Sopenharmony_ci * most input files: try all possible matches and select the longest. 151cb0ef41Sopenharmony_ci * The key feature of this algorithm is that insertions into the string 161cb0ef41Sopenharmony_ci * dictionary are very simple and thus fast, and deletions are avoided 171cb0ef41Sopenharmony_ci * completely. Insertions are performed at each input character, whereas 181cb0ef41Sopenharmony_ci * string matches are performed only when the previous match ends. So it 191cb0ef41Sopenharmony_ci * is preferable to spend more time in matches to allow very fast string 201cb0ef41Sopenharmony_ci * insertions and avoid deletions. The matching algorithm for small 211cb0ef41Sopenharmony_ci * strings is inspired from that of Rabin & Karp. A brute force approach 221cb0ef41Sopenharmony_ci * is used to find longer strings when a small match has been found. 231cb0ef41Sopenharmony_ci * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze 241cb0ef41Sopenharmony_ci * (by Leonid Broukhis). 251cb0ef41Sopenharmony_ci * A previous version of this file used a more sophisticated algorithm 261cb0ef41Sopenharmony_ci * (by Fiala and Greene) which is guaranteed to run in linear amortized 271cb0ef41Sopenharmony_ci * time, but has a larger average cost, uses more memory and is patented. 281cb0ef41Sopenharmony_ci * However the F&G algorithm may be faster for some highly redundant 291cb0ef41Sopenharmony_ci * files if the parameter max_chain_length (described below) is too large. 301cb0ef41Sopenharmony_ci * 311cb0ef41Sopenharmony_ci * ACKNOWLEDGEMENTS 321cb0ef41Sopenharmony_ci * 331cb0ef41Sopenharmony_ci * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and 341cb0ef41Sopenharmony_ci * I found it in 'freeze' written by Leonid Broukhis. 351cb0ef41Sopenharmony_ci * Thanks to many people for bug reports and testing. 361cb0ef41Sopenharmony_ci * 371cb0ef41Sopenharmony_ci * REFERENCES 381cb0ef41Sopenharmony_ci * 391cb0ef41Sopenharmony_ci * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". 401cb0ef41Sopenharmony_ci * Available in http://tools.ietf.org/html/rfc1951 411cb0ef41Sopenharmony_ci * 421cb0ef41Sopenharmony_ci * A description of the Rabin and Karp algorithm is given in the book 431cb0ef41Sopenharmony_ci * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. 441cb0ef41Sopenharmony_ci * 451cb0ef41Sopenharmony_ci * Fiala,E.R., and Greene,D.H. 461cb0ef41Sopenharmony_ci * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 471cb0ef41Sopenharmony_ci * 481cb0ef41Sopenharmony_ci */ 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci/* @(#) $Id$ */ 511cb0ef41Sopenharmony_ci#include <assert.h> 521cb0ef41Sopenharmony_ci#include "deflate.h" 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci#include "cpu_features.h" 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci#if defined(DEFLATE_SLIDE_HASH_SSE2) || defined(DEFLATE_SLIDE_HASH_NEON) 571cb0ef41Sopenharmony_ci#include "slide_hash_simd.h" 581cb0ef41Sopenharmony_ci#endif 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci#include "contrib/optimizations/insert_string.h" 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci#ifdef FASTEST 631cb0ef41Sopenharmony_ci/* See http://crbug.com/1113596 */ 641cb0ef41Sopenharmony_ci#error "FASTEST is not supported in Chromium's zlib." 651cb0ef41Sopenharmony_ci#endif 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ciconst char deflate_copyright[] = 681cb0ef41Sopenharmony_ci " deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; 691cb0ef41Sopenharmony_ci/* 701cb0ef41Sopenharmony_ci If you use the zlib library in a product, an acknowledgment is welcome 711cb0ef41Sopenharmony_ci in the documentation of your product. If for some reason you cannot 721cb0ef41Sopenharmony_ci include such an acknowledgment, I would appreciate that you keep this 731cb0ef41Sopenharmony_ci copyright string in the executable of your product. 741cb0ef41Sopenharmony_ci */ 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_citypedef enum { 771cb0ef41Sopenharmony_ci need_more, /* block not completed, need more input or more output */ 781cb0ef41Sopenharmony_ci block_done, /* block flush performed */ 791cb0ef41Sopenharmony_ci finish_started, /* finish started, need only more output at next deflate */ 801cb0ef41Sopenharmony_ci finish_done /* finish done, accept no more input or output */ 811cb0ef41Sopenharmony_ci} block_state; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_citypedef block_state (*compress_func)(deflate_state *s, int flush); 841cb0ef41Sopenharmony_ci/* Compression function. Returns the block state after the call. */ 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cilocal block_state deflate_stored(deflate_state *s, int flush); 871cb0ef41Sopenharmony_cilocal block_state deflate_fast(deflate_state *s, int flush); 881cb0ef41Sopenharmony_ci#ifndef FASTEST 891cb0ef41Sopenharmony_cilocal block_state deflate_slow(deflate_state *s, int flush); 901cb0ef41Sopenharmony_ci#endif 911cb0ef41Sopenharmony_cilocal block_state deflate_rle(deflate_state *s, int flush); 921cb0ef41Sopenharmony_cilocal block_state deflate_huff(deflate_state *s, int flush); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci/* From crc32.c */ 951cb0ef41Sopenharmony_ciextern void ZLIB_INTERNAL crc_reset(deflate_state *const s); 961cb0ef41Sopenharmony_ciextern void ZLIB_INTERNAL crc_finalize(deflate_state *const s); 971cb0ef41Sopenharmony_ciextern void ZLIB_INTERNAL copy_with_crc(z_streamp strm, Bytef *dst, long size); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci/* =========================================================================== 1001cb0ef41Sopenharmony_ci * Local data 1011cb0ef41Sopenharmony_ci */ 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci#define NIL 0 1041cb0ef41Sopenharmony_ci/* Tail of hash chains */ 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci#ifndef TOO_FAR 1071cb0ef41Sopenharmony_ci# define TOO_FAR 4096 1081cb0ef41Sopenharmony_ci#endif 1091cb0ef41Sopenharmony_ci/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci/* Values for max_lazy_match, good_match and max_chain_length, depending on 1121cb0ef41Sopenharmony_ci * the desired pack level (0..9). The values given below have been tuned to 1131cb0ef41Sopenharmony_ci * exclude worst case performance for pathological files. Better values may be 1141cb0ef41Sopenharmony_ci * found for specific files. 1151cb0ef41Sopenharmony_ci */ 1161cb0ef41Sopenharmony_citypedef struct config_s { 1171cb0ef41Sopenharmony_ci ush good_length; /* reduce lazy search above this match length */ 1181cb0ef41Sopenharmony_ci ush max_lazy; /* do not perform lazy search above this match length */ 1191cb0ef41Sopenharmony_ci ush nice_length; /* quit search above this match length */ 1201cb0ef41Sopenharmony_ci ush max_chain; 1211cb0ef41Sopenharmony_ci compress_func func; 1221cb0ef41Sopenharmony_ci} config; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci#ifdef FASTEST 1251cb0ef41Sopenharmony_cilocal const config configuration_table[2] = { 1261cb0ef41Sopenharmony_ci/* good lazy nice chain */ 1271cb0ef41Sopenharmony_ci/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ 1281cb0ef41Sopenharmony_ci/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ 1291cb0ef41Sopenharmony_ci#else 1301cb0ef41Sopenharmony_cilocal const config configuration_table[10] = { 1311cb0ef41Sopenharmony_ci/* good lazy nice chain */ 1321cb0ef41Sopenharmony_ci/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ 1331cb0ef41Sopenharmony_ci/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ 1341cb0ef41Sopenharmony_ci/* 2 */ {4, 5, 16, 8, deflate_fast}, 1351cb0ef41Sopenharmony_ci/* 3 */ {4, 6, 32, 32, deflate_fast}, 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ 1381cb0ef41Sopenharmony_ci/* 5 */ {8, 16, 32, 32, deflate_slow}, 1391cb0ef41Sopenharmony_ci/* 6 */ {8, 16, 128, 128, deflate_slow}, 1401cb0ef41Sopenharmony_ci/* 7 */ {8, 32, 128, 256, deflate_slow}, 1411cb0ef41Sopenharmony_ci/* 8 */ {32, 128, 258, 1024, deflate_slow}, 1421cb0ef41Sopenharmony_ci/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ 1431cb0ef41Sopenharmony_ci#endif 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 1461cb0ef41Sopenharmony_ci * For deflate_fast() (levels <= 3) good is ignored and lazy has a different 1471cb0ef41Sopenharmony_ci * meaning. 1481cb0ef41Sopenharmony_ci */ 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ 1511cb0ef41Sopenharmony_ci#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci/* =========================================================================== 1541cb0ef41Sopenharmony_ci * Initialize the hash table (avoiding 64K overflow for 16 bit systems). 1551cb0ef41Sopenharmony_ci * prev[] will be initialized on the fly. 1561cb0ef41Sopenharmony_ci * TODO(cavalcantii): optimization opportunity, check comments on: 1571cb0ef41Sopenharmony_ci * https://chromium-review.googlesource.com/c/chromium/src/+/3561506/ 1581cb0ef41Sopenharmony_ci */ 1591cb0ef41Sopenharmony_ci#define CLEAR_HASH(s) \ 1601cb0ef41Sopenharmony_ci do { \ 1611cb0ef41Sopenharmony_ci s->head[s->hash_size - 1] = NIL; \ 1621cb0ef41Sopenharmony_ci zmemzero((Bytef *)s->head, \ 1631cb0ef41Sopenharmony_ci (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ 1641cb0ef41Sopenharmony_ci } while (0) 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci/* =========================================================================== 1671cb0ef41Sopenharmony_ci * Slide the hash table when sliding the window down (could be avoided with 32 1681cb0ef41Sopenharmony_ci * bit values at the expense of memory usage). We slide even when level == 0 to 1691cb0ef41Sopenharmony_ci * keep the hash table consistent if we switch back to level > 0 later. 1701cb0ef41Sopenharmony_ci */ 1711cb0ef41Sopenharmony_ci#if defined(__has_feature) 1721cb0ef41Sopenharmony_ci# if __has_feature(memory_sanitizer) 1731cb0ef41Sopenharmony_ci __attribute__((no_sanitize("memory"))) 1741cb0ef41Sopenharmony_ci# endif 1751cb0ef41Sopenharmony_ci#endif 1761cb0ef41Sopenharmony_cilocal void slide_hash(deflate_state *s) { 1771cb0ef41Sopenharmony_ci#if defined(DEFLATE_SLIDE_HASH_SSE2) || defined(DEFLATE_SLIDE_HASH_NEON) 1781cb0ef41Sopenharmony_ci slide_hash_simd(s->head, s->prev, s->w_size, s->hash_size); 1791cb0ef41Sopenharmony_ci return; 1801cb0ef41Sopenharmony_ci#endif 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci unsigned n, m; 1831cb0ef41Sopenharmony_ci Posf *p; 1841cb0ef41Sopenharmony_ci uInt wsize = s->w_size; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci n = s->hash_size; 1871cb0ef41Sopenharmony_ci p = &s->head[n]; 1881cb0ef41Sopenharmony_ci do { 1891cb0ef41Sopenharmony_ci m = *--p; 1901cb0ef41Sopenharmony_ci *p = (Pos)(m >= wsize ? m - wsize : NIL); 1911cb0ef41Sopenharmony_ci } while (--n); 1921cb0ef41Sopenharmony_ci n = wsize; 1931cb0ef41Sopenharmony_ci#ifndef FASTEST 1941cb0ef41Sopenharmony_ci p = &s->prev[n]; 1951cb0ef41Sopenharmony_ci do { 1961cb0ef41Sopenharmony_ci m = *--p; 1971cb0ef41Sopenharmony_ci *p = (Pos)(m >= wsize ? m - wsize : NIL); 1981cb0ef41Sopenharmony_ci /* If n is not on any hash chain, prev[n] is garbage but 1991cb0ef41Sopenharmony_ci * its value will never be used. 2001cb0ef41Sopenharmony_ci */ 2011cb0ef41Sopenharmony_ci } while (--n); 2021cb0ef41Sopenharmony_ci#endif 2031cb0ef41Sopenharmony_ci} 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci/* =========================================================================== 2061cb0ef41Sopenharmony_ci * Read a new buffer from the current input stream, update the adler32 2071cb0ef41Sopenharmony_ci * and total number of bytes read. All deflate() input goes through 2081cb0ef41Sopenharmony_ci * this function so some applications may wish to modify it to avoid 2091cb0ef41Sopenharmony_ci * allocating a large strm->next_in buffer and copying from it. 2101cb0ef41Sopenharmony_ci * (See also flush_pending()). 2111cb0ef41Sopenharmony_ci */ 2121cb0ef41Sopenharmony_cilocal unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { 2131cb0ef41Sopenharmony_ci unsigned len = strm->avail_in; 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci if (len > size) len = size; 2161cb0ef41Sopenharmony_ci if (len == 0) return 0; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci strm->avail_in -= len; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci /* TODO(cavalcantii): verify if we can remove 'copy_with_crc', it is legacy 2211cb0ef41Sopenharmony_ci * of the Intel optimizations dating back to 2015. 2221cb0ef41Sopenharmony_ci */ 2231cb0ef41Sopenharmony_ci#ifdef GZIP 2241cb0ef41Sopenharmony_ci if (strm->state->wrap == 2) 2251cb0ef41Sopenharmony_ci copy_with_crc(strm, buf, len); 2261cb0ef41Sopenharmony_ci else 2271cb0ef41Sopenharmony_ci#endif 2281cb0ef41Sopenharmony_ci { 2291cb0ef41Sopenharmony_ci zmemcpy(buf, strm->next_in, len); 2301cb0ef41Sopenharmony_ci if (strm->state->wrap == 1) 2311cb0ef41Sopenharmony_ci strm->adler = adler32(strm->adler, buf, len); 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci strm->next_in += len; 2341cb0ef41Sopenharmony_ci strm->total_in += len; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci return len; 2371cb0ef41Sopenharmony_ci} 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci/* =========================================================================== 2401cb0ef41Sopenharmony_ci * Fill the window when the lookahead becomes insufficient. 2411cb0ef41Sopenharmony_ci * Updates strstart and lookahead. 2421cb0ef41Sopenharmony_ci * 2431cb0ef41Sopenharmony_ci * IN assertion: lookahead < MIN_LOOKAHEAD 2441cb0ef41Sopenharmony_ci * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD 2451cb0ef41Sopenharmony_ci * At least one byte has been read, or avail_in == 0; reads are 2461cb0ef41Sopenharmony_ci * performed for at least two bytes (required for the zip translate_eol 2471cb0ef41Sopenharmony_ci * option -- not supported here). 2481cb0ef41Sopenharmony_ci */ 2491cb0ef41Sopenharmony_cilocal void fill_window(deflate_state *s) { 2501cb0ef41Sopenharmony_ci unsigned n; 2511cb0ef41Sopenharmony_ci unsigned more; /* Amount of free space at the end of the window. */ 2521cb0ef41Sopenharmony_ci uInt wsize = s->w_size; 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci do { 2571cb0ef41Sopenharmony_ci more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci /* Deal with !@#$% 64K limit: */ 2601cb0ef41Sopenharmony_ci if (sizeof(int) <= 2) { 2611cb0ef41Sopenharmony_ci if (more == 0 && s->strstart == 0 && s->lookahead == 0) { 2621cb0ef41Sopenharmony_ci more = wsize; 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci } else if (more == (unsigned)(-1)) { 2651cb0ef41Sopenharmony_ci /* Very unlikely, but possible on 16 bit machine if 2661cb0ef41Sopenharmony_ci * strstart == 0 && lookahead == 1 (input done a byte at time) 2671cb0ef41Sopenharmony_ci */ 2681cb0ef41Sopenharmony_ci more--; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci /* If the window is almost full and there is insufficient lookahead, 2731cb0ef41Sopenharmony_ci * move the upper half to the lower one to make room in the upper half. 2741cb0ef41Sopenharmony_ci */ 2751cb0ef41Sopenharmony_ci if (s->strstart >= wsize + MAX_DIST(s)) { 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); 2781cb0ef41Sopenharmony_ci s->match_start -= wsize; 2791cb0ef41Sopenharmony_ci s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ 2801cb0ef41Sopenharmony_ci s->block_start -= (long) wsize; 2811cb0ef41Sopenharmony_ci if (s->insert > s->strstart) 2821cb0ef41Sopenharmony_ci s->insert = s->strstart; 2831cb0ef41Sopenharmony_ci slide_hash(s); 2841cb0ef41Sopenharmony_ci more += wsize; 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci if (s->strm->avail_in == 0) break; 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci /* If there was no sliding: 2891cb0ef41Sopenharmony_ci * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && 2901cb0ef41Sopenharmony_ci * more == window_size - lookahead - strstart 2911cb0ef41Sopenharmony_ci * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) 2921cb0ef41Sopenharmony_ci * => more >= window_size - 2*WSIZE + 2 2931cb0ef41Sopenharmony_ci * In the BIG_MEM or MMAP case (not yet supported), 2941cb0ef41Sopenharmony_ci * window_size == input_size + MIN_LOOKAHEAD && 2951cb0ef41Sopenharmony_ci * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. 2961cb0ef41Sopenharmony_ci * Otherwise, window_size == 2*WSIZE so more >= 2. 2971cb0ef41Sopenharmony_ci * If there was sliding, more >= WSIZE. So in all cases, more >= 2. 2981cb0ef41Sopenharmony_ci */ 2991cb0ef41Sopenharmony_ci Assert(more >= 2, "more < 2"); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); 3021cb0ef41Sopenharmony_ci s->lookahead += n; 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci /* Initialize the hash value now that we have some input: */ 3051cb0ef41Sopenharmony_ci if (s->chromium_zlib_hash) { 3061cb0ef41Sopenharmony_ci /* chromium hash reads 4 bytes */ 3071cb0ef41Sopenharmony_ci if (s->lookahead + s->insert > MIN_MATCH) { 3081cb0ef41Sopenharmony_ci uInt str = s->strstart - s->insert; 3091cb0ef41Sopenharmony_ci while (s->insert) { 3101cb0ef41Sopenharmony_ci insert_string(s, str); 3111cb0ef41Sopenharmony_ci str++; 3121cb0ef41Sopenharmony_ci s->insert--; 3131cb0ef41Sopenharmony_ci if (s->lookahead + s->insert <= MIN_MATCH) 3141cb0ef41Sopenharmony_ci break; 3151cb0ef41Sopenharmony_ci } 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci } else 3181cb0ef41Sopenharmony_ci /* Initialize the hash value now that we have some input: */ 3191cb0ef41Sopenharmony_ci if (s->lookahead + s->insert >= MIN_MATCH) { 3201cb0ef41Sopenharmony_ci uInt str = s->strstart - s->insert; 3211cb0ef41Sopenharmony_ci s->ins_h = s->window[str]; 3221cb0ef41Sopenharmony_ci UPDATE_HASH(s, s->ins_h, s->window[str + 1]); 3231cb0ef41Sopenharmony_ci#if MIN_MATCH != 3 3241cb0ef41Sopenharmony_ci Call UPDATE_HASH() MIN_MATCH-3 more times 3251cb0ef41Sopenharmony_ci#endif 3261cb0ef41Sopenharmony_ci while (s->insert) { 3271cb0ef41Sopenharmony_ci UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); 3281cb0ef41Sopenharmony_ci#ifndef FASTEST 3291cb0ef41Sopenharmony_ci s->prev[str & s->w_mask] = s->head[s->ins_h]; 3301cb0ef41Sopenharmony_ci#endif 3311cb0ef41Sopenharmony_ci s->head[s->ins_h] = (Pos)str; 3321cb0ef41Sopenharmony_ci str++; 3331cb0ef41Sopenharmony_ci s->insert--; 3341cb0ef41Sopenharmony_ci if (s->lookahead + s->insert < MIN_MATCH) 3351cb0ef41Sopenharmony_ci break; 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, 3391cb0ef41Sopenharmony_ci * but this is not important since only literal bytes will be emitted. 3401cb0ef41Sopenharmony_ci */ 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci /* If the WIN_INIT bytes after the end of the current data have never been 3451cb0ef41Sopenharmony_ci * written, then zero those bytes in order to avoid memory check reports of 3461cb0ef41Sopenharmony_ci * the use of uninitialized (or uninitialised as Julian writes) bytes by 3471cb0ef41Sopenharmony_ci * the longest match routines. Update the high water mark for the next 3481cb0ef41Sopenharmony_ci * time through here. WIN_INIT is set to MAX_MATCH since the longest match 3491cb0ef41Sopenharmony_ci * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. 3501cb0ef41Sopenharmony_ci */ 3511cb0ef41Sopenharmony_ci if (s->high_water < s->window_size) { 3521cb0ef41Sopenharmony_ci ulg curr = s->strstart + (ulg)(s->lookahead); 3531cb0ef41Sopenharmony_ci ulg init; 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci if (s->high_water < curr) { 3561cb0ef41Sopenharmony_ci /* Previous high water mark below current data -- zero WIN_INIT 3571cb0ef41Sopenharmony_ci * bytes or up to end of window, whichever is less. 3581cb0ef41Sopenharmony_ci */ 3591cb0ef41Sopenharmony_ci init = s->window_size - curr; 3601cb0ef41Sopenharmony_ci if (init > WIN_INIT) 3611cb0ef41Sopenharmony_ci init = WIN_INIT; 3621cb0ef41Sopenharmony_ci zmemzero(s->window + curr, (unsigned)init); 3631cb0ef41Sopenharmony_ci s->high_water = curr + init; 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci else if (s->high_water < (ulg)curr + WIN_INIT) { 3661cb0ef41Sopenharmony_ci /* High water mark at or above current data, but below current data 3671cb0ef41Sopenharmony_ci * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up 3681cb0ef41Sopenharmony_ci * to end of window, whichever is less. 3691cb0ef41Sopenharmony_ci */ 3701cb0ef41Sopenharmony_ci init = (ulg)curr + WIN_INIT - s->high_water; 3711cb0ef41Sopenharmony_ci if (init > s->window_size - s->high_water) 3721cb0ef41Sopenharmony_ci init = s->window_size - s->high_water; 3731cb0ef41Sopenharmony_ci zmemzero(s->window + s->high_water, (unsigned)init); 3741cb0ef41Sopenharmony_ci s->high_water += init; 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci } 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, 3791cb0ef41Sopenharmony_ci "not enough room for search"); 3801cb0ef41Sopenharmony_ci} 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci/* ========================================================================= */ 3831cb0ef41Sopenharmony_ciint ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, 3841cb0ef41Sopenharmony_ci int stream_size) { 3851cb0ef41Sopenharmony_ci return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, 3861cb0ef41Sopenharmony_ci Z_DEFAULT_STRATEGY, version, stream_size); 3871cb0ef41Sopenharmony_ci /* To do: ignore strm->next_in if we use it as window */ 3881cb0ef41Sopenharmony_ci} 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci/* ========================================================================= */ 3911cb0ef41Sopenharmony_ciint ZEXPORT deflateInit2_(z_streamp strm, int level, int method, 3921cb0ef41Sopenharmony_ci int windowBits, int memLevel, int strategy, 3931cb0ef41Sopenharmony_ci const char *version, int stream_size) { 3941cb0ef41Sopenharmony_ci unsigned window_padding = 8; 3951cb0ef41Sopenharmony_ci deflate_state *s; 3961cb0ef41Sopenharmony_ci int wrap = 1; 3971cb0ef41Sopenharmony_ci static const char my_version[] = ZLIB_VERSION; 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci // Needed to activate optimized insert_string() that helps compression 4001cb0ef41Sopenharmony_ci // for all wrapper formats (e.g. RAW, ZLIB, GZIP). 4011cb0ef41Sopenharmony_ci // Feature detection is not triggered while using RAW mode (i.e. we never 4021cb0ef41Sopenharmony_ci // call crc32() with a NULL buffer). 4031cb0ef41Sopenharmony_ci#if defined(CRC32_ARMV8_CRC32) || defined(CRC32_SIMD_SSE42_PCLMUL) 4041cb0ef41Sopenharmony_ci cpu_check_features(); 4051cb0ef41Sopenharmony_ci#endif 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci if (version == Z_NULL || version[0] != my_version[0] || 4081cb0ef41Sopenharmony_ci stream_size != sizeof(z_stream)) { 4091cb0ef41Sopenharmony_ci return Z_VERSION_ERROR; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci if (strm == Z_NULL) return Z_STREAM_ERROR; 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci strm->msg = Z_NULL; 4141cb0ef41Sopenharmony_ci if (strm->zalloc == (alloc_func)0) { 4151cb0ef41Sopenharmony_ci#ifdef Z_SOLO 4161cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 4171cb0ef41Sopenharmony_ci#else 4181cb0ef41Sopenharmony_ci strm->zalloc = zcalloc; 4191cb0ef41Sopenharmony_ci strm->opaque = (voidpf)0; 4201cb0ef41Sopenharmony_ci#endif 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci if (strm->zfree == (free_func)0) 4231cb0ef41Sopenharmony_ci#ifdef Z_SOLO 4241cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 4251cb0ef41Sopenharmony_ci#else 4261cb0ef41Sopenharmony_ci strm->zfree = zcfree; 4271cb0ef41Sopenharmony_ci#endif 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci#ifdef FASTEST 4301cb0ef41Sopenharmony_ci if (level != 0) level = 1; 4311cb0ef41Sopenharmony_ci#else 4321cb0ef41Sopenharmony_ci if (level == Z_DEFAULT_COMPRESSION) level = 6; 4331cb0ef41Sopenharmony_ci#endif 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci if (windowBits < 0) { /* suppress zlib wrapper */ 4361cb0ef41Sopenharmony_ci wrap = 0; 4371cb0ef41Sopenharmony_ci if (windowBits < -15) 4381cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 4391cb0ef41Sopenharmony_ci windowBits = -windowBits; 4401cb0ef41Sopenharmony_ci } 4411cb0ef41Sopenharmony_ci#ifdef GZIP 4421cb0ef41Sopenharmony_ci else if (windowBits > 15) { 4431cb0ef41Sopenharmony_ci wrap = 2; /* write gzip wrapper instead */ 4441cb0ef41Sopenharmony_ci windowBits -= 16; 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci#endif 4471cb0ef41Sopenharmony_ci if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || 4481cb0ef41Sopenharmony_ci windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || 4491cb0ef41Sopenharmony_ci strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { 4501cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ 4531cb0ef41Sopenharmony_ci s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); 4541cb0ef41Sopenharmony_ci if (s == Z_NULL) return Z_MEM_ERROR; 4551cb0ef41Sopenharmony_ci strm->state = (struct internal_state FAR *)s; 4561cb0ef41Sopenharmony_ci s->strm = strm; 4571cb0ef41Sopenharmony_ci s->status = INIT_STATE; /* to pass state test in deflateReset() */ 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci s->wrap = wrap; 4601cb0ef41Sopenharmony_ci s->gzhead = Z_NULL; 4611cb0ef41Sopenharmony_ci s->w_bits = (uInt)windowBits; 4621cb0ef41Sopenharmony_ci s->w_size = 1 << s->w_bits; 4631cb0ef41Sopenharmony_ci s->w_mask = s->w_size - 1; 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci s->chromium_zlib_hash = 1; 4661cb0ef41Sopenharmony_ci#if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH) 4671cb0ef41Sopenharmony_ci s->chromium_zlib_hash = 0; 4681cb0ef41Sopenharmony_ci#endif 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci s->hash_bits = memLevel + 7; 4711cb0ef41Sopenharmony_ci if (s->chromium_zlib_hash && s->hash_bits < 15) { 4721cb0ef41Sopenharmony_ci s->hash_bits = 15; 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci s->hash_size = 1 << s->hash_bits; 4761cb0ef41Sopenharmony_ci s->hash_mask = s->hash_size - 1; 4771cb0ef41Sopenharmony_ci s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci s->window = (Bytef *) ZALLOC(strm, 4801cb0ef41Sopenharmony_ci s->w_size + window_padding, 4811cb0ef41Sopenharmony_ci 2*sizeof(Byte)); 4821cb0ef41Sopenharmony_ci /* Avoid use of unitialized values in the window, see crbug.com/1137613 and 4831cb0ef41Sopenharmony_ci * crbug.com/1144420 */ 4841cb0ef41Sopenharmony_ci zmemzero(s->window, (s->w_size + window_padding) * (2 * sizeof(Byte))); 4851cb0ef41Sopenharmony_ci s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); 4861cb0ef41Sopenharmony_ci /* Avoid use of uninitialized value, see: 4871cb0ef41Sopenharmony_ci * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11360 4881cb0ef41Sopenharmony_ci */ 4891cb0ef41Sopenharmony_ci zmemzero(s->prev, s->w_size * sizeof(Pos)); 4901cb0ef41Sopenharmony_ci s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ci s->high_water = 0; /* nothing written to s->window yet */ 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci /* We overlay pending_buf and sym_buf. This works since the average size 4971cb0ef41Sopenharmony_ci * for length/distance pairs over any compressed block is assured to be 31 4981cb0ef41Sopenharmony_ci * bits or less. 4991cb0ef41Sopenharmony_ci * 5001cb0ef41Sopenharmony_ci * Analysis: The longest fixed codes are a length code of 8 bits plus 5 5011cb0ef41Sopenharmony_ci * extra bits, for lengths 131 to 257. The longest fixed distance codes are 5021cb0ef41Sopenharmony_ci * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest 5031cb0ef41Sopenharmony_ci * possible fixed-codes length/distance pair is then 31 bits total. 5041cb0ef41Sopenharmony_ci * 5051cb0ef41Sopenharmony_ci * sym_buf starts one-fourth of the way into pending_buf. So there are 5061cb0ef41Sopenharmony_ci * three bytes in sym_buf for every four bytes in pending_buf. Each symbol 5071cb0ef41Sopenharmony_ci * in sym_buf is three bytes -- two for the distance and one for the 5081cb0ef41Sopenharmony_ci * literal/length. As each symbol is consumed, the pointer to the next 5091cb0ef41Sopenharmony_ci * sym_buf value to read moves forward three bytes. From that symbol, up to 5101cb0ef41Sopenharmony_ci * 31 bits are written to pending_buf. The closest the written pending_buf 5111cb0ef41Sopenharmony_ci * bits gets to the next sym_buf symbol to read is just before the last 5121cb0ef41Sopenharmony_ci * code is written. At that time, 31*(n - 2) bits have been written, just 5131cb0ef41Sopenharmony_ci * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at 5141cb0ef41Sopenharmony_ci * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 5151cb0ef41Sopenharmony_ci * symbols are written.) The closest the writing gets to what is unread is 5161cb0ef41Sopenharmony_ci * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and 5171cb0ef41Sopenharmony_ci * can range from 128 to 32768. 5181cb0ef41Sopenharmony_ci * 5191cb0ef41Sopenharmony_ci * Therefore, at a minimum, there are 142 bits of space between what is 5201cb0ef41Sopenharmony_ci * written and what is read in the overlain buffers, so the symbols cannot 5211cb0ef41Sopenharmony_ci * be overwritten by the compressed data. That space is actually 139 bits, 5221cb0ef41Sopenharmony_ci * due to the three-bit fixed-code block header. 5231cb0ef41Sopenharmony_ci * 5241cb0ef41Sopenharmony_ci * That covers the case where either Z_FIXED is specified, forcing fixed 5251cb0ef41Sopenharmony_ci * codes, or when the use of fixed codes is chosen, because that choice 5261cb0ef41Sopenharmony_ci * results in a smaller compressed block than dynamic codes. That latter 5271cb0ef41Sopenharmony_ci * condition then assures that the above analysis also covers all dynamic 5281cb0ef41Sopenharmony_ci * blocks. A dynamic-code block will only be chosen to be emitted if it has 5291cb0ef41Sopenharmony_ci * fewer bits than a fixed-code block would for the same set of symbols. 5301cb0ef41Sopenharmony_ci * Therefore its average symbol length is assured to be less than 31. So 5311cb0ef41Sopenharmony_ci * the compressed data for a dynamic block also cannot overwrite the 5321cb0ef41Sopenharmony_ci * symbols from which it is being constructed. 5331cb0ef41Sopenharmony_ci */ 5341cb0ef41Sopenharmony_ci#ifdef LIT_MEM 5351cb0ef41Sopenharmony_ci s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 5); 5361cb0ef41Sopenharmony_ci#else 5371cb0ef41Sopenharmony_ci s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); 5381cb0ef41Sopenharmony_ci#endif 5391cb0ef41Sopenharmony_ci s->pending_buf_size = (ulg)s->lit_bufsize * 4; 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || 5421cb0ef41Sopenharmony_ci s->pending_buf == Z_NULL) { 5431cb0ef41Sopenharmony_ci s->status = FINISH_STATE; 5441cb0ef41Sopenharmony_ci strm->msg = ERR_MSG(Z_MEM_ERROR); 5451cb0ef41Sopenharmony_ci deflateEnd (strm); 5461cb0ef41Sopenharmony_ci return Z_MEM_ERROR; 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci#ifdef LIT_MEM 5491cb0ef41Sopenharmony_ci s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); 5501cb0ef41Sopenharmony_ci s->l_buf = s->pending_buf + (s->lit_bufsize << 2); 5511cb0ef41Sopenharmony_ci s->sym_end = s->lit_bufsize - 1; 5521cb0ef41Sopenharmony_ci#else 5531cb0ef41Sopenharmony_ci s->sym_buf = s->pending_buf + s->lit_bufsize; 5541cb0ef41Sopenharmony_ci s->sym_end = (s->lit_bufsize - 1) * 3; 5551cb0ef41Sopenharmony_ci#endif 5561cb0ef41Sopenharmony_ci /* We avoid equality with lit_bufsize*3 because of wraparound at 64K 5571cb0ef41Sopenharmony_ci * on 16 bit machines and because stored blocks are restricted to 5581cb0ef41Sopenharmony_ci * 64K-1 bytes. 5591cb0ef41Sopenharmony_ci */ 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci s->level = level; 5621cb0ef41Sopenharmony_ci s->strategy = strategy; 5631cb0ef41Sopenharmony_ci s->method = (Byte)method; 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci return deflateReset(strm); 5661cb0ef41Sopenharmony_ci} 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci/* ========================================================================= 5691cb0ef41Sopenharmony_ci * Check for a valid deflate stream state. Return 0 if ok, 1 if not. 5701cb0ef41Sopenharmony_ci */ 5711cb0ef41Sopenharmony_cilocal int deflateStateCheck(z_streamp strm) { 5721cb0ef41Sopenharmony_ci deflate_state *s; 5731cb0ef41Sopenharmony_ci if (strm == Z_NULL || 5741cb0ef41Sopenharmony_ci strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) 5751cb0ef41Sopenharmony_ci return 1; 5761cb0ef41Sopenharmony_ci s = strm->state; 5771cb0ef41Sopenharmony_ci if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && 5781cb0ef41Sopenharmony_ci#ifdef GZIP 5791cb0ef41Sopenharmony_ci s->status != GZIP_STATE && 5801cb0ef41Sopenharmony_ci#endif 5811cb0ef41Sopenharmony_ci s->status != EXTRA_STATE && 5821cb0ef41Sopenharmony_ci s->status != NAME_STATE && 5831cb0ef41Sopenharmony_ci s->status != COMMENT_STATE && 5841cb0ef41Sopenharmony_ci s->status != HCRC_STATE && 5851cb0ef41Sopenharmony_ci s->status != BUSY_STATE && 5861cb0ef41Sopenharmony_ci s->status != FINISH_STATE)) 5871cb0ef41Sopenharmony_ci return 1; 5881cb0ef41Sopenharmony_ci return 0; 5891cb0ef41Sopenharmony_ci} 5901cb0ef41Sopenharmony_ci 5911cb0ef41Sopenharmony_ci/* ========================================================================= */ 5921cb0ef41Sopenharmony_ciint ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, 5931cb0ef41Sopenharmony_ci uInt dictLength) { 5941cb0ef41Sopenharmony_ci deflate_state *s; 5951cb0ef41Sopenharmony_ci uInt str, n; 5961cb0ef41Sopenharmony_ci int wrap; 5971cb0ef41Sopenharmony_ci unsigned avail; 5981cb0ef41Sopenharmony_ci z_const unsigned char *next; 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci if (deflateStateCheck(strm) || dictionary == Z_NULL) 6011cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 6021cb0ef41Sopenharmony_ci s = strm->state; 6031cb0ef41Sopenharmony_ci wrap = s->wrap; 6041cb0ef41Sopenharmony_ci if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) 6051cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci /* when using zlib wrappers, compute Adler-32 for provided dictionary */ 6081cb0ef41Sopenharmony_ci if (wrap == 1) 6091cb0ef41Sopenharmony_ci strm->adler = adler32(strm->adler, dictionary, dictLength); 6101cb0ef41Sopenharmony_ci s->wrap = 0; /* avoid computing Adler-32 in read_buf */ 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci /* if dictionary would fill window, just replace the history */ 6131cb0ef41Sopenharmony_ci if (dictLength >= s->w_size) { 6141cb0ef41Sopenharmony_ci if (wrap == 0) { /* already empty otherwise */ 6151cb0ef41Sopenharmony_ci CLEAR_HASH(s); 6161cb0ef41Sopenharmony_ci s->strstart = 0; 6171cb0ef41Sopenharmony_ci s->block_start = 0L; 6181cb0ef41Sopenharmony_ci s->insert = 0; 6191cb0ef41Sopenharmony_ci } 6201cb0ef41Sopenharmony_ci dictionary += dictLength - s->w_size; /* use the tail */ 6211cb0ef41Sopenharmony_ci dictLength = s->w_size; 6221cb0ef41Sopenharmony_ci } 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci /* insert dictionary into window and hash */ 6251cb0ef41Sopenharmony_ci avail = strm->avail_in; 6261cb0ef41Sopenharmony_ci next = strm->next_in; 6271cb0ef41Sopenharmony_ci strm->avail_in = dictLength; 6281cb0ef41Sopenharmony_ci strm->next_in = (z_const Bytef *)dictionary; 6291cb0ef41Sopenharmony_ci fill_window(s); 6301cb0ef41Sopenharmony_ci while (s->lookahead >= MIN_MATCH) { 6311cb0ef41Sopenharmony_ci str = s->strstart; 6321cb0ef41Sopenharmony_ci n = s->lookahead - (MIN_MATCH-1); 6331cb0ef41Sopenharmony_ci do { 6341cb0ef41Sopenharmony_ci insert_string(s, str); 6351cb0ef41Sopenharmony_ci str++; 6361cb0ef41Sopenharmony_ci } while (--n); 6371cb0ef41Sopenharmony_ci s->strstart = str; 6381cb0ef41Sopenharmony_ci s->lookahead = MIN_MATCH-1; 6391cb0ef41Sopenharmony_ci fill_window(s); 6401cb0ef41Sopenharmony_ci } 6411cb0ef41Sopenharmony_ci s->strstart += s->lookahead; 6421cb0ef41Sopenharmony_ci s->block_start = (long)s->strstart; 6431cb0ef41Sopenharmony_ci s->insert = s->lookahead; 6441cb0ef41Sopenharmony_ci s->lookahead = 0; 6451cb0ef41Sopenharmony_ci s->match_length = s->prev_length = MIN_MATCH-1; 6461cb0ef41Sopenharmony_ci s->match_available = 0; 6471cb0ef41Sopenharmony_ci strm->next_in = next; 6481cb0ef41Sopenharmony_ci strm->avail_in = avail; 6491cb0ef41Sopenharmony_ci s->wrap = wrap; 6501cb0ef41Sopenharmony_ci return Z_OK; 6511cb0ef41Sopenharmony_ci} 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci/* ========================================================================= */ 6541cb0ef41Sopenharmony_ciint ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, 6551cb0ef41Sopenharmony_ci uInt *dictLength) { 6561cb0ef41Sopenharmony_ci deflate_state *s; 6571cb0ef41Sopenharmony_ci uInt len; 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) 6601cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 6611cb0ef41Sopenharmony_ci s = strm->state; 6621cb0ef41Sopenharmony_ci len = s->strstart + s->lookahead; 6631cb0ef41Sopenharmony_ci if (len > s->w_size) 6641cb0ef41Sopenharmony_ci len = s->w_size; 6651cb0ef41Sopenharmony_ci if (dictionary != Z_NULL && len) 6661cb0ef41Sopenharmony_ci zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); 6671cb0ef41Sopenharmony_ci if (dictLength != Z_NULL) 6681cb0ef41Sopenharmony_ci *dictLength = len; 6691cb0ef41Sopenharmony_ci return Z_OK; 6701cb0ef41Sopenharmony_ci} 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci/* ========================================================================= */ 6731cb0ef41Sopenharmony_ciint ZEXPORT deflateResetKeep(z_streamp strm) { 6741cb0ef41Sopenharmony_ci deflate_state *s; 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) { 6771cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 6781cb0ef41Sopenharmony_ci } 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci strm->total_in = strm->total_out = 0; 6811cb0ef41Sopenharmony_ci strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ 6821cb0ef41Sopenharmony_ci strm->data_type = Z_UNKNOWN; 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ci s = (deflate_state *)strm->state; 6851cb0ef41Sopenharmony_ci s->pending = 0; 6861cb0ef41Sopenharmony_ci s->pending_out = s->pending_buf; 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_ci if (s->wrap < 0) { 6891cb0ef41Sopenharmony_ci s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ 6901cb0ef41Sopenharmony_ci } 6911cb0ef41Sopenharmony_ci s->status = 6921cb0ef41Sopenharmony_ci#ifdef GZIP 6931cb0ef41Sopenharmony_ci s->wrap == 2 ? GZIP_STATE : 6941cb0ef41Sopenharmony_ci#endif 6951cb0ef41Sopenharmony_ci INIT_STATE; 6961cb0ef41Sopenharmony_ci strm->adler = 6971cb0ef41Sopenharmony_ci#ifdef GZIP 6981cb0ef41Sopenharmony_ci s->wrap == 2 ? crc32(0L, Z_NULL, 0) : 6991cb0ef41Sopenharmony_ci#endif 7001cb0ef41Sopenharmony_ci adler32(0L, Z_NULL, 0); 7011cb0ef41Sopenharmony_ci s->last_flush = -2; 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci _tr_init(s); 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci return Z_OK; 7061cb0ef41Sopenharmony_ci} 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ci/* =========================================================================== 7091cb0ef41Sopenharmony_ci * Initialize the "longest match" routines for a new zlib stream 7101cb0ef41Sopenharmony_ci */ 7111cb0ef41Sopenharmony_cilocal void lm_init(deflate_state *s) { 7121cb0ef41Sopenharmony_ci s->window_size = (ulg)2L*s->w_size; 7131cb0ef41Sopenharmony_ci 7141cb0ef41Sopenharmony_ci CLEAR_HASH(s); 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_ci /* Set the default configuration parameters: 7171cb0ef41Sopenharmony_ci */ 7181cb0ef41Sopenharmony_ci s->max_lazy_match = configuration_table[s->level].max_lazy; 7191cb0ef41Sopenharmony_ci s->good_match = configuration_table[s->level].good_length; 7201cb0ef41Sopenharmony_ci s->nice_match = configuration_table[s->level].nice_length; 7211cb0ef41Sopenharmony_ci s->max_chain_length = configuration_table[s->level].max_chain; 7221cb0ef41Sopenharmony_ci 7231cb0ef41Sopenharmony_ci s->strstart = 0; 7241cb0ef41Sopenharmony_ci s->block_start = 0L; 7251cb0ef41Sopenharmony_ci s->lookahead = 0; 7261cb0ef41Sopenharmony_ci s->insert = 0; 7271cb0ef41Sopenharmony_ci s->match_length = s->prev_length = MIN_MATCH-1; 7281cb0ef41Sopenharmony_ci s->match_available = 0; 7291cb0ef41Sopenharmony_ci s->ins_h = 0; 7301cb0ef41Sopenharmony_ci} 7311cb0ef41Sopenharmony_ci 7321cb0ef41Sopenharmony_ci/* ========================================================================= */ 7331cb0ef41Sopenharmony_ciint ZEXPORT deflateReset(z_streamp strm) { 7341cb0ef41Sopenharmony_ci int ret; 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci ret = deflateResetKeep(strm); 7371cb0ef41Sopenharmony_ci if (ret == Z_OK) 7381cb0ef41Sopenharmony_ci lm_init(strm->state); 7391cb0ef41Sopenharmony_ci return ret; 7401cb0ef41Sopenharmony_ci} 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_ci/* ========================================================================= */ 7431cb0ef41Sopenharmony_ciint ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { 7441cb0ef41Sopenharmony_ci if (deflateStateCheck(strm) || strm->state->wrap != 2) 7451cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 7461cb0ef41Sopenharmony_ci strm->state->gzhead = head; 7471cb0ef41Sopenharmony_ci return Z_OK; 7481cb0ef41Sopenharmony_ci} 7491cb0ef41Sopenharmony_ci 7501cb0ef41Sopenharmony_ci/* ========================================================================= */ 7511cb0ef41Sopenharmony_ciint ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { 7521cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) return Z_STREAM_ERROR; 7531cb0ef41Sopenharmony_ci if (pending != Z_NULL) 7541cb0ef41Sopenharmony_ci *pending = strm->state->pending; 7551cb0ef41Sopenharmony_ci if (bits != Z_NULL) 7561cb0ef41Sopenharmony_ci *bits = strm->state->bi_valid; 7571cb0ef41Sopenharmony_ci return Z_OK; 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci/* ========================================================================= */ 7611cb0ef41Sopenharmony_ciint ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { 7621cb0ef41Sopenharmony_ci deflate_state *s; 7631cb0ef41Sopenharmony_ci int put; 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) return Z_STREAM_ERROR; 7661cb0ef41Sopenharmony_ci s = strm->state; 7671cb0ef41Sopenharmony_ci#ifdef LIT_MEM 7681cb0ef41Sopenharmony_ci if (bits < 0 || bits > 16 || 7691cb0ef41Sopenharmony_ci (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) 7701cb0ef41Sopenharmony_ci return Z_BUF_ERROR; 7711cb0ef41Sopenharmony_ci#else 7721cb0ef41Sopenharmony_ci if (bits < 0 || bits > 16 || 7731cb0ef41Sopenharmony_ci s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) 7741cb0ef41Sopenharmony_ci return Z_BUF_ERROR; 7751cb0ef41Sopenharmony_ci#endif 7761cb0ef41Sopenharmony_ci do { 7771cb0ef41Sopenharmony_ci put = Buf_size - s->bi_valid; 7781cb0ef41Sopenharmony_ci if (put > bits) 7791cb0ef41Sopenharmony_ci put = bits; 7801cb0ef41Sopenharmony_ci s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); 7811cb0ef41Sopenharmony_ci s->bi_valid += put; 7821cb0ef41Sopenharmony_ci _tr_flush_bits(s); 7831cb0ef41Sopenharmony_ci value >>= put; 7841cb0ef41Sopenharmony_ci bits -= put; 7851cb0ef41Sopenharmony_ci } while (bits); 7861cb0ef41Sopenharmony_ci return Z_OK; 7871cb0ef41Sopenharmony_ci} 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci/* ========================================================================= */ 7901cb0ef41Sopenharmony_ciint ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { 7911cb0ef41Sopenharmony_ci deflate_state *s; 7921cb0ef41Sopenharmony_ci compress_func func; 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) return Z_STREAM_ERROR; 7951cb0ef41Sopenharmony_ci s = strm->state; 7961cb0ef41Sopenharmony_ci 7971cb0ef41Sopenharmony_ci#ifdef FASTEST 7981cb0ef41Sopenharmony_ci if (level != 0) level = 1; 7991cb0ef41Sopenharmony_ci#else 8001cb0ef41Sopenharmony_ci if (level == Z_DEFAULT_COMPRESSION) level = 6; 8011cb0ef41Sopenharmony_ci#endif 8021cb0ef41Sopenharmony_ci if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { 8031cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 8041cb0ef41Sopenharmony_ci } 8051cb0ef41Sopenharmony_ci func = configuration_table[s->level].func; 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci if ((strategy != s->strategy || func != configuration_table[level].func) && 8081cb0ef41Sopenharmony_ci s->last_flush != -2) { 8091cb0ef41Sopenharmony_ci /* Flush the last buffer: */ 8101cb0ef41Sopenharmony_ci int err = deflate(strm, Z_BLOCK); 8111cb0ef41Sopenharmony_ci if (err == Z_STREAM_ERROR) 8121cb0ef41Sopenharmony_ci return err; 8131cb0ef41Sopenharmony_ci if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) 8141cb0ef41Sopenharmony_ci return Z_BUF_ERROR; 8151cb0ef41Sopenharmony_ci } 8161cb0ef41Sopenharmony_ci if (s->level != level) { 8171cb0ef41Sopenharmony_ci if (s->level == 0 && s->matches != 0) { 8181cb0ef41Sopenharmony_ci if (s->matches == 1) 8191cb0ef41Sopenharmony_ci slide_hash(s); 8201cb0ef41Sopenharmony_ci else 8211cb0ef41Sopenharmony_ci CLEAR_HASH(s); 8221cb0ef41Sopenharmony_ci s->matches = 0; 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci s->level = level; 8251cb0ef41Sopenharmony_ci s->max_lazy_match = configuration_table[level].max_lazy; 8261cb0ef41Sopenharmony_ci s->good_match = configuration_table[level].good_length; 8271cb0ef41Sopenharmony_ci s->nice_match = configuration_table[level].nice_length; 8281cb0ef41Sopenharmony_ci s->max_chain_length = configuration_table[level].max_chain; 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci s->strategy = strategy; 8311cb0ef41Sopenharmony_ci return Z_OK; 8321cb0ef41Sopenharmony_ci} 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci/* ========================================================================= */ 8351cb0ef41Sopenharmony_ciint ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, 8361cb0ef41Sopenharmony_ci int nice_length, int max_chain) { 8371cb0ef41Sopenharmony_ci deflate_state *s; 8381cb0ef41Sopenharmony_ci 8391cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) return Z_STREAM_ERROR; 8401cb0ef41Sopenharmony_ci s = strm->state; 8411cb0ef41Sopenharmony_ci s->good_match = (uInt)good_length; 8421cb0ef41Sopenharmony_ci s->max_lazy_match = (uInt)max_lazy; 8431cb0ef41Sopenharmony_ci s->nice_match = nice_length; 8441cb0ef41Sopenharmony_ci s->max_chain_length = (uInt)max_chain; 8451cb0ef41Sopenharmony_ci return Z_OK; 8461cb0ef41Sopenharmony_ci} 8471cb0ef41Sopenharmony_ci 8481cb0ef41Sopenharmony_ci/* ========================================================================= 8491cb0ef41Sopenharmony_ci * For the default windowBits of 15 and memLevel of 8, this function returns a 8501cb0ef41Sopenharmony_ci * close to exact, as well as small, upper bound on the compressed size. This 8511cb0ef41Sopenharmony_ci * is an expansion of ~0.03%, plus a small constant. 8521cb0ef41Sopenharmony_ci * 8531cb0ef41Sopenharmony_ci * For any setting other than those defaults for windowBits and memLevel, one 8541cb0ef41Sopenharmony_ci * of two worst case bounds is returned. This is at most an expansion of ~4% or 8551cb0ef41Sopenharmony_ci * ~13%, plus a small constant. 8561cb0ef41Sopenharmony_ci * 8571cb0ef41Sopenharmony_ci * Both the 0.03% and 4% derive from the overhead of stored blocks. The first 8581cb0ef41Sopenharmony_ci * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second 8591cb0ef41Sopenharmony_ci * is for stored blocks of 127 bytes (the worst case memLevel == 1). The 8601cb0ef41Sopenharmony_ci * expansion results from five bytes of header for each stored block. 8611cb0ef41Sopenharmony_ci * 8621cb0ef41Sopenharmony_ci * The larger expansion of 13% results from a window size less than or equal to 8631cb0ef41Sopenharmony_ci * the symbols buffer size (windowBits <= memLevel + 7). In that case some of 8641cb0ef41Sopenharmony_ci * the data being compressed may have slid out of the sliding window, impeding 8651cb0ef41Sopenharmony_ci * a stored block from being emitted. Then the only choice is a fixed or 8661cb0ef41Sopenharmony_ci * dynamic block, where a fixed block limits the maximum expansion to 9 bits 8671cb0ef41Sopenharmony_ci * per 8-bit byte, plus 10 bits for every block. The smallest block size for 8681cb0ef41Sopenharmony_ci * which this can occur is 255 (memLevel == 2). 8691cb0ef41Sopenharmony_ci * 8701cb0ef41Sopenharmony_ci * Shifts are used to approximate divisions, for speed. 8711cb0ef41Sopenharmony_ci */ 8721cb0ef41Sopenharmony_ciuLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { 8731cb0ef41Sopenharmony_ci deflate_state *s; 8741cb0ef41Sopenharmony_ci uLong fixedlen, storelen, wraplen; 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci /* upper bound for fixed blocks with 9-bit literals and length 255 8771cb0ef41Sopenharmony_ci (memLevel == 2, which is the lowest that may not use stored blocks) -- 8781cb0ef41Sopenharmony_ci ~13% overhead plus a small constant */ 8791cb0ef41Sopenharmony_ci fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + 8801cb0ef41Sopenharmony_ci (sourceLen >> 9) + 4; 8811cb0ef41Sopenharmony_ci 8821cb0ef41Sopenharmony_ci /* upper bound for stored blocks with length 127 (memLevel == 1) -- 8831cb0ef41Sopenharmony_ci ~4% overhead plus a small constant */ 8841cb0ef41Sopenharmony_ci storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + 8851cb0ef41Sopenharmony_ci (sourceLen >> 11) + 7; 8861cb0ef41Sopenharmony_ci 8871cb0ef41Sopenharmony_ci /* if can't get parameters, return larger bound plus a zlib wrapper */ 8881cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) 8891cb0ef41Sopenharmony_ci return (fixedlen > storelen ? fixedlen : storelen) + 6; 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_ci /* compute wrapper length */ 8921cb0ef41Sopenharmony_ci s = strm->state; 8931cb0ef41Sopenharmony_ci switch (s->wrap) { 8941cb0ef41Sopenharmony_ci case 0: /* raw deflate */ 8951cb0ef41Sopenharmony_ci wraplen = 0; 8961cb0ef41Sopenharmony_ci break; 8971cb0ef41Sopenharmony_ci case 1: /* zlib wrapper */ 8981cb0ef41Sopenharmony_ci wraplen = 6 + (s->strstart ? 4 : 0); 8991cb0ef41Sopenharmony_ci break; 9001cb0ef41Sopenharmony_ci#ifdef GZIP 9011cb0ef41Sopenharmony_ci case 2: /* gzip wrapper */ 9021cb0ef41Sopenharmony_ci wraplen = 18; 9031cb0ef41Sopenharmony_ci if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ 9041cb0ef41Sopenharmony_ci Bytef *str; 9051cb0ef41Sopenharmony_ci if (s->gzhead->extra != Z_NULL) 9061cb0ef41Sopenharmony_ci wraplen += 2 + s->gzhead->extra_len; 9071cb0ef41Sopenharmony_ci str = s->gzhead->name; 9081cb0ef41Sopenharmony_ci if (str != Z_NULL) 9091cb0ef41Sopenharmony_ci do { 9101cb0ef41Sopenharmony_ci wraplen++; 9111cb0ef41Sopenharmony_ci } while (*str++); 9121cb0ef41Sopenharmony_ci str = s->gzhead->comment; 9131cb0ef41Sopenharmony_ci if (str != Z_NULL) 9141cb0ef41Sopenharmony_ci do { 9151cb0ef41Sopenharmony_ci wraplen++; 9161cb0ef41Sopenharmony_ci } while (*str++); 9171cb0ef41Sopenharmony_ci if (s->gzhead->hcrc) 9181cb0ef41Sopenharmony_ci wraplen += 2; 9191cb0ef41Sopenharmony_ci } 9201cb0ef41Sopenharmony_ci break; 9211cb0ef41Sopenharmony_ci#endif 9221cb0ef41Sopenharmony_ci default: /* for compiler happiness */ 9231cb0ef41Sopenharmony_ci wraplen = 6; 9241cb0ef41Sopenharmony_ci } 9251cb0ef41Sopenharmony_ci 9261cb0ef41Sopenharmony_ci /* if not default parameters, return one of the conservative bounds */ 9271cb0ef41Sopenharmony_ci if (s->w_bits != 15 || s->hash_bits != 8 + 7) 9281cb0ef41Sopenharmony_ci return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + 9291cb0ef41Sopenharmony_ci wraplen; 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ci /* default settings: return tight bound for that case -- ~0.03% overhead 9321cb0ef41Sopenharmony_ci plus a small constant */ 9331cb0ef41Sopenharmony_ci return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 9341cb0ef41Sopenharmony_ci (sourceLen >> 25) + 13 - 6 + wraplen; 9351cb0ef41Sopenharmony_ci} 9361cb0ef41Sopenharmony_ci 9371cb0ef41Sopenharmony_ci/* ========================================================================= 9381cb0ef41Sopenharmony_ci * Put a short in the pending buffer. The 16-bit value is put in MSB order. 9391cb0ef41Sopenharmony_ci * IN assertion: the stream state is correct and there is enough room in 9401cb0ef41Sopenharmony_ci * pending_buf. 9411cb0ef41Sopenharmony_ci */ 9421cb0ef41Sopenharmony_cilocal void putShortMSB(deflate_state *s, uInt b) { 9431cb0ef41Sopenharmony_ci put_byte(s, (Byte)(b >> 8)); 9441cb0ef41Sopenharmony_ci put_byte(s, (Byte)(b & 0xff)); 9451cb0ef41Sopenharmony_ci} 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci/* ========================================================================= 9481cb0ef41Sopenharmony_ci * Flush as much pending output as possible. All deflate() output, except for 9491cb0ef41Sopenharmony_ci * some deflate_stored() output, goes through this function so some 9501cb0ef41Sopenharmony_ci * applications may wish to modify it to avoid allocating a large 9511cb0ef41Sopenharmony_ci * strm->next_out buffer and copying into it. (See also read_buf()). 9521cb0ef41Sopenharmony_ci */ 9531cb0ef41Sopenharmony_cilocal void flush_pending(z_streamp strm) { 9541cb0ef41Sopenharmony_ci unsigned len; 9551cb0ef41Sopenharmony_ci deflate_state *s = strm->state; 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_ci _tr_flush_bits(s); 9581cb0ef41Sopenharmony_ci len = s->pending; 9591cb0ef41Sopenharmony_ci if (len > strm->avail_out) len = strm->avail_out; 9601cb0ef41Sopenharmony_ci if (len == 0) return; 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ci zmemcpy(strm->next_out, s->pending_out, len); 9631cb0ef41Sopenharmony_ci strm->next_out += len; 9641cb0ef41Sopenharmony_ci s->pending_out += len; 9651cb0ef41Sopenharmony_ci strm->total_out += len; 9661cb0ef41Sopenharmony_ci strm->avail_out -= len; 9671cb0ef41Sopenharmony_ci s->pending -= len; 9681cb0ef41Sopenharmony_ci if (s->pending == 0) { 9691cb0ef41Sopenharmony_ci s->pending_out = s->pending_buf; 9701cb0ef41Sopenharmony_ci } 9711cb0ef41Sopenharmony_ci} 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci/* =========================================================================== 9741cb0ef41Sopenharmony_ci * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. 9751cb0ef41Sopenharmony_ci */ 9761cb0ef41Sopenharmony_ci#define HCRC_UPDATE(beg) \ 9771cb0ef41Sopenharmony_ci do { \ 9781cb0ef41Sopenharmony_ci if (s->gzhead->hcrc && s->pending > (beg)) \ 9791cb0ef41Sopenharmony_ci strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ 9801cb0ef41Sopenharmony_ci s->pending - (beg)); \ 9811cb0ef41Sopenharmony_ci } while (0) 9821cb0ef41Sopenharmony_ci 9831cb0ef41Sopenharmony_ci/* ========================================================================= */ 9841cb0ef41Sopenharmony_ciint ZEXPORT deflate(z_streamp strm, int flush) { 9851cb0ef41Sopenharmony_ci int old_flush; /* value of flush param for previous deflate call */ 9861cb0ef41Sopenharmony_ci deflate_state *s; 9871cb0ef41Sopenharmony_ci 9881cb0ef41Sopenharmony_ci if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { 9891cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 9901cb0ef41Sopenharmony_ci } 9911cb0ef41Sopenharmony_ci s = strm->state; 9921cb0ef41Sopenharmony_ci 9931cb0ef41Sopenharmony_ci if (strm->next_out == Z_NULL || 9941cb0ef41Sopenharmony_ci (strm->avail_in != 0 && strm->next_in == Z_NULL) || 9951cb0ef41Sopenharmony_ci (s->status == FINISH_STATE && flush != Z_FINISH)) { 9961cb0ef41Sopenharmony_ci ERR_RETURN(strm, Z_STREAM_ERROR); 9971cb0ef41Sopenharmony_ci } 9981cb0ef41Sopenharmony_ci if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); 9991cb0ef41Sopenharmony_ci 10001cb0ef41Sopenharmony_ci old_flush = s->last_flush; 10011cb0ef41Sopenharmony_ci s->last_flush = flush; 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ci /* Flush as much pending output as possible */ 10041cb0ef41Sopenharmony_ci if (s->pending != 0) { 10051cb0ef41Sopenharmony_ci flush_pending(strm); 10061cb0ef41Sopenharmony_ci if (strm->avail_out == 0) { 10071cb0ef41Sopenharmony_ci /* Since avail_out is 0, deflate will be called again with 10081cb0ef41Sopenharmony_ci * more output space, but possibly with both pending and 10091cb0ef41Sopenharmony_ci * avail_in equal to zero. There won't be anything to do, 10101cb0ef41Sopenharmony_ci * but this is not an error situation so make sure we 10111cb0ef41Sopenharmony_ci * return OK instead of BUF_ERROR at next call of deflate: 10121cb0ef41Sopenharmony_ci */ 10131cb0ef41Sopenharmony_ci s->last_flush = -1; 10141cb0ef41Sopenharmony_ci return Z_OK; 10151cb0ef41Sopenharmony_ci } 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci /* Make sure there is something to do and avoid duplicate consecutive 10181cb0ef41Sopenharmony_ci * flushes. For repeated and useless calls with Z_FINISH, we keep 10191cb0ef41Sopenharmony_ci * returning Z_STREAM_END instead of Z_BUF_ERROR. 10201cb0ef41Sopenharmony_ci */ 10211cb0ef41Sopenharmony_ci } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && 10221cb0ef41Sopenharmony_ci flush != Z_FINISH) { 10231cb0ef41Sopenharmony_ci ERR_RETURN(strm, Z_BUF_ERROR); 10241cb0ef41Sopenharmony_ci } 10251cb0ef41Sopenharmony_ci 10261cb0ef41Sopenharmony_ci /* User must not provide more input after the first FINISH: */ 10271cb0ef41Sopenharmony_ci if (s->status == FINISH_STATE && strm->avail_in != 0) { 10281cb0ef41Sopenharmony_ci ERR_RETURN(strm, Z_BUF_ERROR); 10291cb0ef41Sopenharmony_ci } 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci /* Write the header */ 10321cb0ef41Sopenharmony_ci if (s->status == INIT_STATE && s->wrap == 0) 10331cb0ef41Sopenharmony_ci s->status = BUSY_STATE; 10341cb0ef41Sopenharmony_ci if (s->status == INIT_STATE) { 10351cb0ef41Sopenharmony_ci /* zlib header */ 10361cb0ef41Sopenharmony_ci uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; 10371cb0ef41Sopenharmony_ci uInt level_flags; 10381cb0ef41Sopenharmony_ci 10391cb0ef41Sopenharmony_ci if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) 10401cb0ef41Sopenharmony_ci level_flags = 0; 10411cb0ef41Sopenharmony_ci else if (s->level < 6) 10421cb0ef41Sopenharmony_ci level_flags = 1; 10431cb0ef41Sopenharmony_ci else if (s->level == 6) 10441cb0ef41Sopenharmony_ci level_flags = 2; 10451cb0ef41Sopenharmony_ci else 10461cb0ef41Sopenharmony_ci level_flags = 3; 10471cb0ef41Sopenharmony_ci header |= (level_flags << 6); 10481cb0ef41Sopenharmony_ci if (s->strstart != 0) header |= PRESET_DICT; 10491cb0ef41Sopenharmony_ci header += 31 - (header % 31); 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci putShortMSB(s, header); 10521cb0ef41Sopenharmony_ci 10531cb0ef41Sopenharmony_ci /* Save the adler32 of the preset dictionary: */ 10541cb0ef41Sopenharmony_ci if (s->strstart != 0) { 10551cb0ef41Sopenharmony_ci putShortMSB(s, (uInt)(strm->adler >> 16)); 10561cb0ef41Sopenharmony_ci putShortMSB(s, (uInt)(strm->adler & 0xffff)); 10571cb0ef41Sopenharmony_ci } 10581cb0ef41Sopenharmony_ci strm->adler = adler32(0L, Z_NULL, 0); 10591cb0ef41Sopenharmony_ci s->status = BUSY_STATE; 10601cb0ef41Sopenharmony_ci 10611cb0ef41Sopenharmony_ci /* Compression must start with an empty pending buffer */ 10621cb0ef41Sopenharmony_ci flush_pending(strm); 10631cb0ef41Sopenharmony_ci if (s->pending != 0) { 10641cb0ef41Sopenharmony_ci s->last_flush = -1; 10651cb0ef41Sopenharmony_ci return Z_OK; 10661cb0ef41Sopenharmony_ci } 10671cb0ef41Sopenharmony_ci } 10681cb0ef41Sopenharmony_ci#ifdef GZIP 10691cb0ef41Sopenharmony_ci if (s->status == GZIP_STATE) { 10701cb0ef41Sopenharmony_ci /* gzip header */ 10711cb0ef41Sopenharmony_ci crc_reset(s); 10721cb0ef41Sopenharmony_ci put_byte(s, 31); 10731cb0ef41Sopenharmony_ci put_byte(s, 139); 10741cb0ef41Sopenharmony_ci put_byte(s, 8); 10751cb0ef41Sopenharmony_ci if (s->gzhead == Z_NULL) { 10761cb0ef41Sopenharmony_ci put_byte(s, 0); 10771cb0ef41Sopenharmony_ci put_byte(s, 0); 10781cb0ef41Sopenharmony_ci put_byte(s, 0); 10791cb0ef41Sopenharmony_ci put_byte(s, 0); 10801cb0ef41Sopenharmony_ci put_byte(s, 0); 10811cb0ef41Sopenharmony_ci put_byte(s, s->level == 9 ? 2 : 10821cb0ef41Sopenharmony_ci (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 10831cb0ef41Sopenharmony_ci 4 : 0)); 10841cb0ef41Sopenharmony_ci put_byte(s, OS_CODE); 10851cb0ef41Sopenharmony_ci s->status = BUSY_STATE; 10861cb0ef41Sopenharmony_ci 10871cb0ef41Sopenharmony_ci /* Compression must start with an empty pending buffer */ 10881cb0ef41Sopenharmony_ci flush_pending(strm); 10891cb0ef41Sopenharmony_ci if (s->pending != 0) { 10901cb0ef41Sopenharmony_ci s->last_flush = -1; 10911cb0ef41Sopenharmony_ci return Z_OK; 10921cb0ef41Sopenharmony_ci } 10931cb0ef41Sopenharmony_ci } 10941cb0ef41Sopenharmony_ci else { 10951cb0ef41Sopenharmony_ci put_byte(s, (s->gzhead->text ? 1 : 0) + 10961cb0ef41Sopenharmony_ci (s->gzhead->hcrc ? 2 : 0) + 10971cb0ef41Sopenharmony_ci (s->gzhead->extra == Z_NULL ? 0 : 4) + 10981cb0ef41Sopenharmony_ci (s->gzhead->name == Z_NULL ? 0 : 8) + 10991cb0ef41Sopenharmony_ci (s->gzhead->comment == Z_NULL ? 0 : 16) 11001cb0ef41Sopenharmony_ci ); 11011cb0ef41Sopenharmony_ci put_byte(s, (Byte)(s->gzhead->time & 0xff)); 11021cb0ef41Sopenharmony_ci put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); 11031cb0ef41Sopenharmony_ci put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); 11041cb0ef41Sopenharmony_ci put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); 11051cb0ef41Sopenharmony_ci put_byte(s, s->level == 9 ? 2 : 11061cb0ef41Sopenharmony_ci (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 11071cb0ef41Sopenharmony_ci 4 : 0)); 11081cb0ef41Sopenharmony_ci put_byte(s, s->gzhead->os & 0xff); 11091cb0ef41Sopenharmony_ci if (s->gzhead->extra != Z_NULL) { 11101cb0ef41Sopenharmony_ci put_byte(s, s->gzhead->extra_len & 0xff); 11111cb0ef41Sopenharmony_ci put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); 11121cb0ef41Sopenharmony_ci } 11131cb0ef41Sopenharmony_ci if (s->gzhead->hcrc) 11141cb0ef41Sopenharmony_ci strm->adler = crc32(strm->adler, s->pending_buf, 11151cb0ef41Sopenharmony_ci s->pending); 11161cb0ef41Sopenharmony_ci s->gzindex = 0; 11171cb0ef41Sopenharmony_ci s->status = EXTRA_STATE; 11181cb0ef41Sopenharmony_ci } 11191cb0ef41Sopenharmony_ci } 11201cb0ef41Sopenharmony_ci if (s->status == EXTRA_STATE) { 11211cb0ef41Sopenharmony_ci if (s->gzhead->extra != Z_NULL) { 11221cb0ef41Sopenharmony_ci ulg beg = s->pending; /* start of bytes to update crc */ 11231cb0ef41Sopenharmony_ci uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; 11241cb0ef41Sopenharmony_ci while (s->pending + left > s->pending_buf_size) { 11251cb0ef41Sopenharmony_ci uInt copy = s->pending_buf_size - s->pending; 11261cb0ef41Sopenharmony_ci zmemcpy(s->pending_buf + s->pending, 11271cb0ef41Sopenharmony_ci s->gzhead->extra + s->gzindex, copy); 11281cb0ef41Sopenharmony_ci s->pending = s->pending_buf_size; 11291cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11301cb0ef41Sopenharmony_ci s->gzindex += copy; 11311cb0ef41Sopenharmony_ci flush_pending(strm); 11321cb0ef41Sopenharmony_ci if (s->pending != 0) { 11331cb0ef41Sopenharmony_ci s->last_flush = -1; 11341cb0ef41Sopenharmony_ci return Z_OK; 11351cb0ef41Sopenharmony_ci } 11361cb0ef41Sopenharmony_ci beg = 0; 11371cb0ef41Sopenharmony_ci left -= copy; 11381cb0ef41Sopenharmony_ci } 11391cb0ef41Sopenharmony_ci zmemcpy(s->pending_buf + s->pending, 11401cb0ef41Sopenharmony_ci s->gzhead->extra + s->gzindex, left); 11411cb0ef41Sopenharmony_ci s->pending += left; 11421cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11431cb0ef41Sopenharmony_ci s->gzindex = 0; 11441cb0ef41Sopenharmony_ci } 11451cb0ef41Sopenharmony_ci s->status = NAME_STATE; 11461cb0ef41Sopenharmony_ci } 11471cb0ef41Sopenharmony_ci if (s->status == NAME_STATE) { 11481cb0ef41Sopenharmony_ci if (s->gzhead->name != Z_NULL) { 11491cb0ef41Sopenharmony_ci ulg beg = s->pending; /* start of bytes to update crc */ 11501cb0ef41Sopenharmony_ci int val; 11511cb0ef41Sopenharmony_ci do { 11521cb0ef41Sopenharmony_ci if (s->pending == s->pending_buf_size) { 11531cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11541cb0ef41Sopenharmony_ci flush_pending(strm); 11551cb0ef41Sopenharmony_ci if (s->pending != 0) { 11561cb0ef41Sopenharmony_ci s->last_flush = -1; 11571cb0ef41Sopenharmony_ci return Z_OK; 11581cb0ef41Sopenharmony_ci } 11591cb0ef41Sopenharmony_ci beg = 0; 11601cb0ef41Sopenharmony_ci } 11611cb0ef41Sopenharmony_ci val = s->gzhead->name[s->gzindex++]; 11621cb0ef41Sopenharmony_ci put_byte(s, val); 11631cb0ef41Sopenharmony_ci } while (val != 0); 11641cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11651cb0ef41Sopenharmony_ci s->gzindex = 0; 11661cb0ef41Sopenharmony_ci } 11671cb0ef41Sopenharmony_ci s->status = COMMENT_STATE; 11681cb0ef41Sopenharmony_ci } 11691cb0ef41Sopenharmony_ci if (s->status == COMMENT_STATE) { 11701cb0ef41Sopenharmony_ci if (s->gzhead->comment != Z_NULL) { 11711cb0ef41Sopenharmony_ci ulg beg = s->pending; /* start of bytes to update crc */ 11721cb0ef41Sopenharmony_ci int val; 11731cb0ef41Sopenharmony_ci do { 11741cb0ef41Sopenharmony_ci if (s->pending == s->pending_buf_size) { 11751cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11761cb0ef41Sopenharmony_ci flush_pending(strm); 11771cb0ef41Sopenharmony_ci if (s->pending != 0) { 11781cb0ef41Sopenharmony_ci s->last_flush = -1; 11791cb0ef41Sopenharmony_ci return Z_OK; 11801cb0ef41Sopenharmony_ci } 11811cb0ef41Sopenharmony_ci beg = 0; 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci val = s->gzhead->comment[s->gzindex++]; 11841cb0ef41Sopenharmony_ci put_byte(s, val); 11851cb0ef41Sopenharmony_ci } while (val != 0); 11861cb0ef41Sopenharmony_ci HCRC_UPDATE(beg); 11871cb0ef41Sopenharmony_ci } 11881cb0ef41Sopenharmony_ci s->status = HCRC_STATE; 11891cb0ef41Sopenharmony_ci } 11901cb0ef41Sopenharmony_ci if (s->status == HCRC_STATE) { 11911cb0ef41Sopenharmony_ci if (s->gzhead->hcrc) { 11921cb0ef41Sopenharmony_ci if (s->pending + 2 > s->pending_buf_size) { 11931cb0ef41Sopenharmony_ci flush_pending(strm); 11941cb0ef41Sopenharmony_ci if (s->pending != 0) { 11951cb0ef41Sopenharmony_ci s->last_flush = -1; 11961cb0ef41Sopenharmony_ci return Z_OK; 11971cb0ef41Sopenharmony_ci } 11981cb0ef41Sopenharmony_ci } 11991cb0ef41Sopenharmony_ci put_byte(s, (Byte)(strm->adler & 0xff)); 12001cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); 12011cb0ef41Sopenharmony_ci strm->adler = crc32(0L, Z_NULL, 0); 12021cb0ef41Sopenharmony_ci } 12031cb0ef41Sopenharmony_ci s->status = BUSY_STATE; 12041cb0ef41Sopenharmony_ci 12051cb0ef41Sopenharmony_ci /* Compression must start with an empty pending buffer */ 12061cb0ef41Sopenharmony_ci flush_pending(strm); 12071cb0ef41Sopenharmony_ci if (s->pending != 0) { 12081cb0ef41Sopenharmony_ci s->last_flush = -1; 12091cb0ef41Sopenharmony_ci return Z_OK; 12101cb0ef41Sopenharmony_ci } 12111cb0ef41Sopenharmony_ci } 12121cb0ef41Sopenharmony_ci#endif 12131cb0ef41Sopenharmony_ci 12141cb0ef41Sopenharmony_ci /* Start a new block or continue the current one. 12151cb0ef41Sopenharmony_ci */ 12161cb0ef41Sopenharmony_ci if (strm->avail_in != 0 || s->lookahead != 0 || 12171cb0ef41Sopenharmony_ci (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { 12181cb0ef41Sopenharmony_ci block_state bstate; 12191cb0ef41Sopenharmony_ci 12201cb0ef41Sopenharmony_ci bstate = s->level == 0 ? deflate_stored(s, flush) : 12211cb0ef41Sopenharmony_ci s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : 12221cb0ef41Sopenharmony_ci s->strategy == Z_RLE ? deflate_rle(s, flush) : 12231cb0ef41Sopenharmony_ci (*(configuration_table[s->level].func))(s, flush); 12241cb0ef41Sopenharmony_ci 12251cb0ef41Sopenharmony_ci if (bstate == finish_started || bstate == finish_done) { 12261cb0ef41Sopenharmony_ci s->status = FINISH_STATE; 12271cb0ef41Sopenharmony_ci } 12281cb0ef41Sopenharmony_ci if (bstate == need_more || bstate == finish_started) { 12291cb0ef41Sopenharmony_ci if (strm->avail_out == 0) { 12301cb0ef41Sopenharmony_ci s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ 12311cb0ef41Sopenharmony_ci } 12321cb0ef41Sopenharmony_ci return Z_OK; 12331cb0ef41Sopenharmony_ci /* If flush != Z_NO_FLUSH && avail_out == 0, the next call 12341cb0ef41Sopenharmony_ci * of deflate should use the same flush parameter to make sure 12351cb0ef41Sopenharmony_ci * that the flush is complete. So we don't have to output an 12361cb0ef41Sopenharmony_ci * empty block here, this will be done at next call. This also 12371cb0ef41Sopenharmony_ci * ensures that for a very small output buffer, we emit at most 12381cb0ef41Sopenharmony_ci * one empty block. 12391cb0ef41Sopenharmony_ci */ 12401cb0ef41Sopenharmony_ci } 12411cb0ef41Sopenharmony_ci if (bstate == block_done) { 12421cb0ef41Sopenharmony_ci if (flush == Z_PARTIAL_FLUSH) { 12431cb0ef41Sopenharmony_ci _tr_align(s); 12441cb0ef41Sopenharmony_ci } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ 12451cb0ef41Sopenharmony_ci _tr_stored_block(s, (char*)0, 0L, 0); 12461cb0ef41Sopenharmony_ci /* For a full flush, this empty block will be recognized 12471cb0ef41Sopenharmony_ci * as a special marker by inflate_sync(). 12481cb0ef41Sopenharmony_ci */ 12491cb0ef41Sopenharmony_ci if (flush == Z_FULL_FLUSH) { 12501cb0ef41Sopenharmony_ci CLEAR_HASH(s); /* forget history */ 12511cb0ef41Sopenharmony_ci if (s->lookahead == 0) { 12521cb0ef41Sopenharmony_ci s->strstart = 0; 12531cb0ef41Sopenharmony_ci s->block_start = 0L; 12541cb0ef41Sopenharmony_ci s->insert = 0; 12551cb0ef41Sopenharmony_ci } 12561cb0ef41Sopenharmony_ci } 12571cb0ef41Sopenharmony_ci } 12581cb0ef41Sopenharmony_ci flush_pending(strm); 12591cb0ef41Sopenharmony_ci if (strm->avail_out == 0) { 12601cb0ef41Sopenharmony_ci s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ 12611cb0ef41Sopenharmony_ci return Z_OK; 12621cb0ef41Sopenharmony_ci } 12631cb0ef41Sopenharmony_ci } 12641cb0ef41Sopenharmony_ci } 12651cb0ef41Sopenharmony_ci 12661cb0ef41Sopenharmony_ci if (flush != Z_FINISH) return Z_OK; 12671cb0ef41Sopenharmony_ci if (s->wrap <= 0) return Z_STREAM_END; 12681cb0ef41Sopenharmony_ci 12691cb0ef41Sopenharmony_ci /* Write the trailer */ 12701cb0ef41Sopenharmony_ci#ifdef GZIP 12711cb0ef41Sopenharmony_ci if (s->wrap == 2) { 12721cb0ef41Sopenharmony_ci crc_finalize(s); 12731cb0ef41Sopenharmony_ci put_byte(s, (Byte)(strm->adler & 0xff)); 12741cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); 12751cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); 12761cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); 12771cb0ef41Sopenharmony_ci put_byte(s, (Byte)(strm->total_in & 0xff)); 12781cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); 12791cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); 12801cb0ef41Sopenharmony_ci put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); 12811cb0ef41Sopenharmony_ci } 12821cb0ef41Sopenharmony_ci else 12831cb0ef41Sopenharmony_ci#endif 12841cb0ef41Sopenharmony_ci { 12851cb0ef41Sopenharmony_ci putShortMSB(s, (uInt)(strm->adler >> 16)); 12861cb0ef41Sopenharmony_ci putShortMSB(s, (uInt)(strm->adler & 0xffff)); 12871cb0ef41Sopenharmony_ci } 12881cb0ef41Sopenharmony_ci flush_pending(strm); 12891cb0ef41Sopenharmony_ci /* If avail_out is zero, the application will call deflate again 12901cb0ef41Sopenharmony_ci * to flush the rest. 12911cb0ef41Sopenharmony_ci */ 12921cb0ef41Sopenharmony_ci if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ 12931cb0ef41Sopenharmony_ci return s->pending != 0 ? Z_OK : Z_STREAM_END; 12941cb0ef41Sopenharmony_ci} 12951cb0ef41Sopenharmony_ci 12961cb0ef41Sopenharmony_ci/* ========================================================================= */ 12971cb0ef41Sopenharmony_ciint ZEXPORT deflateEnd(z_streamp strm) { 12981cb0ef41Sopenharmony_ci int status; 12991cb0ef41Sopenharmony_ci 13001cb0ef41Sopenharmony_ci if (deflateStateCheck(strm)) return Z_STREAM_ERROR; 13011cb0ef41Sopenharmony_ci 13021cb0ef41Sopenharmony_ci status = strm->state->status; 13031cb0ef41Sopenharmony_ci 13041cb0ef41Sopenharmony_ci /* Deallocate in reverse order of allocations: */ 13051cb0ef41Sopenharmony_ci TRY_FREE(strm, strm->state->pending_buf); 13061cb0ef41Sopenharmony_ci TRY_FREE(strm, strm->state->head); 13071cb0ef41Sopenharmony_ci TRY_FREE(strm, strm->state->prev); 13081cb0ef41Sopenharmony_ci TRY_FREE(strm, strm->state->window); 13091cb0ef41Sopenharmony_ci 13101cb0ef41Sopenharmony_ci ZFREE(strm, strm->state); 13111cb0ef41Sopenharmony_ci strm->state = Z_NULL; 13121cb0ef41Sopenharmony_ci 13131cb0ef41Sopenharmony_ci return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; 13141cb0ef41Sopenharmony_ci} 13151cb0ef41Sopenharmony_ci 13161cb0ef41Sopenharmony_ci/* ========================================================================= 13171cb0ef41Sopenharmony_ci * Copy the source state to the destination state. 13181cb0ef41Sopenharmony_ci * To simplify the source, this is not supported for 16-bit MSDOS (which 13191cb0ef41Sopenharmony_ci * doesn't have enough memory anyway to duplicate compression states). 13201cb0ef41Sopenharmony_ci */ 13211cb0ef41Sopenharmony_ciint ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { 13221cb0ef41Sopenharmony_ci#ifdef MAXSEG_64K 13231cb0ef41Sopenharmony_ci (void)dest; 13241cb0ef41Sopenharmony_ci (void)source; 13251cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 13261cb0ef41Sopenharmony_ci#else 13271cb0ef41Sopenharmony_ci deflate_state *ds; 13281cb0ef41Sopenharmony_ci deflate_state *ss; 13291cb0ef41Sopenharmony_ci 13301cb0ef41Sopenharmony_ci 13311cb0ef41Sopenharmony_ci if (deflateStateCheck(source) || dest == Z_NULL) { 13321cb0ef41Sopenharmony_ci return Z_STREAM_ERROR; 13331cb0ef41Sopenharmony_ci } 13341cb0ef41Sopenharmony_ci 13351cb0ef41Sopenharmony_ci ss = source->state; 13361cb0ef41Sopenharmony_ci 13371cb0ef41Sopenharmony_ci zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_ci ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); 13401cb0ef41Sopenharmony_ci if (ds == Z_NULL) return Z_MEM_ERROR; 13411cb0ef41Sopenharmony_ci dest->state = (struct internal_state FAR *) ds; 13421cb0ef41Sopenharmony_ci zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); 13431cb0ef41Sopenharmony_ci ds->strm = dest; 13441cb0ef41Sopenharmony_ci 13451cb0ef41Sopenharmony_ci ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); 13461cb0ef41Sopenharmony_ci ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); 13471cb0ef41Sopenharmony_ci ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); 13481cb0ef41Sopenharmony_ci#ifdef LIT_MEM 13491cb0ef41Sopenharmony_ci ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 5); 13501cb0ef41Sopenharmony_ci#else 13511cb0ef41Sopenharmony_ci ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); 13521cb0ef41Sopenharmony_ci#endif 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_ci if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || 13551cb0ef41Sopenharmony_ci ds->pending_buf == Z_NULL) { 13561cb0ef41Sopenharmony_ci deflateEnd (dest); 13571cb0ef41Sopenharmony_ci return Z_MEM_ERROR; 13581cb0ef41Sopenharmony_ci } 13591cb0ef41Sopenharmony_ci /* following zmemcpy do not work for 16-bit MSDOS */ 13601cb0ef41Sopenharmony_ci zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); 13611cb0ef41Sopenharmony_ci zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); 13621cb0ef41Sopenharmony_ci zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); 13631cb0ef41Sopenharmony_ci#ifdef LIT_MEM 13641cb0ef41Sopenharmony_ci zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->lit_bufsize * 5); 13651cb0ef41Sopenharmony_ci#else 13661cb0ef41Sopenharmony_ci zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); 13671cb0ef41Sopenharmony_ci#endif 13681cb0ef41Sopenharmony_ci 13691cb0ef41Sopenharmony_ci ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); 13701cb0ef41Sopenharmony_ci#ifdef LIT_MEM 13711cb0ef41Sopenharmony_ci ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); 13721cb0ef41Sopenharmony_ci ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); 13731cb0ef41Sopenharmony_ci#else 13741cb0ef41Sopenharmony_ci ds->sym_buf = ds->pending_buf + ds->lit_bufsize; 13751cb0ef41Sopenharmony_ci#endif 13761cb0ef41Sopenharmony_ci 13771cb0ef41Sopenharmony_ci ds->l_desc.dyn_tree = ds->dyn_ltree; 13781cb0ef41Sopenharmony_ci ds->d_desc.dyn_tree = ds->dyn_dtree; 13791cb0ef41Sopenharmony_ci ds->bl_desc.dyn_tree = ds->bl_tree; 13801cb0ef41Sopenharmony_ci 13811cb0ef41Sopenharmony_ci return Z_OK; 13821cb0ef41Sopenharmony_ci#endif /* MAXSEG_64K */ 13831cb0ef41Sopenharmony_ci} 13841cb0ef41Sopenharmony_ci 13851cb0ef41Sopenharmony_ci#ifndef FASTEST 13861cb0ef41Sopenharmony_ci/* =========================================================================== 13871cb0ef41Sopenharmony_ci * Set match_start to the longest match starting at the given string and 13881cb0ef41Sopenharmony_ci * return its length. Matches shorter or equal to prev_length are discarded, 13891cb0ef41Sopenharmony_ci * in which case the result is equal to prev_length and match_start is 13901cb0ef41Sopenharmony_ci * garbage. 13911cb0ef41Sopenharmony_ci * IN assertions: cur_match is the head of the hash chain for the current 13921cb0ef41Sopenharmony_ci * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 13931cb0ef41Sopenharmony_ci * OUT assertion: the match length is not greater than s->lookahead. 13941cb0ef41Sopenharmony_ci */ 13951cb0ef41Sopenharmony_cilocal uInt longest_match(deflate_state *s, IPos cur_match) { 13961cb0ef41Sopenharmony_ci unsigned chain_length = s->max_chain_length;/* max hash chain length */ 13971cb0ef41Sopenharmony_ci register Bytef *scan = s->window + s->strstart; /* current string */ 13981cb0ef41Sopenharmony_ci register Bytef *match; /* matched string */ 13991cb0ef41Sopenharmony_ci register int len; /* length of current match */ 14001cb0ef41Sopenharmony_ci int best_len = (int)s->prev_length; /* best match length so far */ 14011cb0ef41Sopenharmony_ci int nice_match = s->nice_match; /* stop if match long enough */ 14021cb0ef41Sopenharmony_ci IPos limit = s->strstart > (IPos)MAX_DIST(s) ? 14031cb0ef41Sopenharmony_ci s->strstart - (IPos)MAX_DIST(s) : NIL; 14041cb0ef41Sopenharmony_ci /* Stop when cur_match becomes <= limit. To simplify the code, 14051cb0ef41Sopenharmony_ci * we prevent matches with the string of window index 0. 14061cb0ef41Sopenharmony_ci */ 14071cb0ef41Sopenharmony_ci Posf *prev = s->prev; 14081cb0ef41Sopenharmony_ci uInt wmask = s->w_mask; 14091cb0ef41Sopenharmony_ci 14101cb0ef41Sopenharmony_ci#ifdef UNALIGNED_OK 14111cb0ef41Sopenharmony_ci /* Compare two bytes at a time. Note: this is not always beneficial. 14121cb0ef41Sopenharmony_ci * Try with and without -DUNALIGNED_OK to check. 14131cb0ef41Sopenharmony_ci */ 14141cb0ef41Sopenharmony_ci register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; 14151cb0ef41Sopenharmony_ci register ush scan_start = *(ushf*)scan; 14161cb0ef41Sopenharmony_ci register ush scan_end = *(ushf*)(scan + best_len - 1); 14171cb0ef41Sopenharmony_ci#else 14181cb0ef41Sopenharmony_ci register Bytef *strend = s->window + s->strstart + MAX_MATCH; 14191cb0ef41Sopenharmony_ci register Byte scan_end1 = scan[best_len - 1]; 14201cb0ef41Sopenharmony_ci register Byte scan_end = scan[best_len]; 14211cb0ef41Sopenharmony_ci#endif 14221cb0ef41Sopenharmony_ci 14231cb0ef41Sopenharmony_ci /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 14241cb0ef41Sopenharmony_ci * It is easy to get rid of this optimization if necessary. 14251cb0ef41Sopenharmony_ci */ 14261cb0ef41Sopenharmony_ci Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); 14271cb0ef41Sopenharmony_ci 14281cb0ef41Sopenharmony_ci /* Do not waste too much time if we already have a good match: */ 14291cb0ef41Sopenharmony_ci if (s->prev_length >= s->good_match) { 14301cb0ef41Sopenharmony_ci chain_length >>= 2; 14311cb0ef41Sopenharmony_ci } 14321cb0ef41Sopenharmony_ci /* Do not look for matches beyond the end of the input. This is necessary 14331cb0ef41Sopenharmony_ci * to make deflate deterministic. 14341cb0ef41Sopenharmony_ci */ 14351cb0ef41Sopenharmony_ci if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; 14361cb0ef41Sopenharmony_ci 14371cb0ef41Sopenharmony_ci Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, 14381cb0ef41Sopenharmony_ci "need lookahead"); 14391cb0ef41Sopenharmony_ci 14401cb0ef41Sopenharmony_ci do { 14411cb0ef41Sopenharmony_ci Assert(cur_match < s->strstart, "no future"); 14421cb0ef41Sopenharmony_ci match = s->window + cur_match; 14431cb0ef41Sopenharmony_ci 14441cb0ef41Sopenharmony_ci /* Skip to next match if the match length cannot increase 14451cb0ef41Sopenharmony_ci * or if the match length is less than 2. Note that the checks below 14461cb0ef41Sopenharmony_ci * for insufficient lookahead only occur occasionally for performance 14471cb0ef41Sopenharmony_ci * reasons. Therefore uninitialized memory will be accessed, and 14481cb0ef41Sopenharmony_ci * conditional jumps will be made that depend on those values. 14491cb0ef41Sopenharmony_ci * However the length of the match is limited to the lookahead, so 14501cb0ef41Sopenharmony_ci * the output of deflate is not affected by the uninitialized values. 14511cb0ef41Sopenharmony_ci */ 14521cb0ef41Sopenharmony_ci#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) 14531cb0ef41Sopenharmony_ci /* This code assumes sizeof(unsigned short) == 2. Do not use 14541cb0ef41Sopenharmony_ci * UNALIGNED_OK if your compiler uses a different size. 14551cb0ef41Sopenharmony_ci */ 14561cb0ef41Sopenharmony_ci if (*(ushf*)(match + best_len - 1) != scan_end || 14571cb0ef41Sopenharmony_ci *(ushf*)match != scan_start) continue; 14581cb0ef41Sopenharmony_ci 14591cb0ef41Sopenharmony_ci /* It is not necessary to compare scan[2] and match[2] since they are 14601cb0ef41Sopenharmony_ci * always equal when the other bytes match, given that the hash keys 14611cb0ef41Sopenharmony_ci * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at 14621cb0ef41Sopenharmony_ci * strstart + 3, + 5, up to strstart + 257. We check for insufficient 14631cb0ef41Sopenharmony_ci * lookahead only every 4th comparison; the 128th check will be made 14641cb0ef41Sopenharmony_ci * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is 14651cb0ef41Sopenharmony_ci * necessary to put more guard bytes at the end of the window, or 14661cb0ef41Sopenharmony_ci * to check more often for insufficient lookahead. 14671cb0ef41Sopenharmony_ci */ 14681cb0ef41Sopenharmony_ci if (!s->chromium_zlib_hash) { 14691cb0ef41Sopenharmony_ci Assert(scan[2] == match[2], "scan[2]?"); 14701cb0ef41Sopenharmony_ci } else { 14711cb0ef41Sopenharmony_ci /* When using CRC hashing, scan[2] and match[2] may mismatch, but in 14721cb0ef41Sopenharmony_ci * that case at least one of the other hashed bytes will mismatch 14731cb0ef41Sopenharmony_ci * also. Bytes 0 and 1 were already checked above, and we know there 14741cb0ef41Sopenharmony_ci * are at least four bytes to check otherwise the mismatch would have 14751cb0ef41Sopenharmony_ci * been found by the scan_end comparison above, so: */ 14761cb0ef41Sopenharmony_ci Assert(scan[2] == match[2] || scan[3] != match[3], "scan[2]??"); 14771cb0ef41Sopenharmony_ci } 14781cb0ef41Sopenharmony_ci scan++, match++; 14791cb0ef41Sopenharmony_ci do { 14801cb0ef41Sopenharmony_ci } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && 14811cb0ef41Sopenharmony_ci *(ushf*)(scan += 2) == *(ushf*)(match += 2) && 14821cb0ef41Sopenharmony_ci *(ushf*)(scan += 2) == *(ushf*)(match += 2) && 14831cb0ef41Sopenharmony_ci *(ushf*)(scan += 2) == *(ushf*)(match += 2) && 14841cb0ef41Sopenharmony_ci scan < strend); 14851cb0ef41Sopenharmony_ci /* The funny "do {}" generates better code on most compilers */ 14861cb0ef41Sopenharmony_ci 14871cb0ef41Sopenharmony_ci /* Here, scan <= window + strstart + 257 */ 14881cb0ef41Sopenharmony_ci Assert(scan <= s->window+(unsigned)(s->window_size - 1), 14891cb0ef41Sopenharmony_ci "wild scan"); 14901cb0ef41Sopenharmony_ci if (*scan == *match) scan++; 14911cb0ef41Sopenharmony_ci 14921cb0ef41Sopenharmony_ci len = (MAX_MATCH - 1) - (int)(strend - scan); 14931cb0ef41Sopenharmony_ci scan = strend - (MAX_MATCH-1); 14941cb0ef41Sopenharmony_ci 14951cb0ef41Sopenharmony_ci#else /* UNALIGNED_OK */ 14961cb0ef41Sopenharmony_ci 14971cb0ef41Sopenharmony_ci if (match[best_len] != scan_end || 14981cb0ef41Sopenharmony_ci match[best_len - 1] != scan_end1 || 14991cb0ef41Sopenharmony_ci *match != *scan || 15001cb0ef41Sopenharmony_ci *++match != scan[1]) continue; 15011cb0ef41Sopenharmony_ci 15021cb0ef41Sopenharmony_ci /* The check at best_len - 1 can be removed because it will be made 15031cb0ef41Sopenharmony_ci * again later. (This heuristic is not always a win.) 15041cb0ef41Sopenharmony_ci * It is not necessary to compare scan[2] and match[2] since they 15051cb0ef41Sopenharmony_ci * are always equal when the other bytes match, given that 15061cb0ef41Sopenharmony_ci * the hash keys are equal and that HASH_BITS >= 8. 15071cb0ef41Sopenharmony_ci */ 15081cb0ef41Sopenharmony_ci scan += 2, match++; 15091cb0ef41Sopenharmony_ci if (!s->chromium_zlib_hash) { 15101cb0ef41Sopenharmony_ci Assert(*scan == *match, "match[2]?"); 15111cb0ef41Sopenharmony_ci } else { 15121cb0ef41Sopenharmony_ci /* When using CRC hashing, scan[2] and match[2] may mismatch, but in 15131cb0ef41Sopenharmony_ci * that case at least one of the other hashed bytes will mismatch 15141cb0ef41Sopenharmony_ci * also. Bytes 0 and 1 were already checked above, and we know there 15151cb0ef41Sopenharmony_ci * are at least four bytes to check otherwise the mismatch would have 15161cb0ef41Sopenharmony_ci * been found by the scan_end comparison above, so: */ 15171cb0ef41Sopenharmony_ci Assert(*scan == *match || scan[1] != match[1], "match[2]??"); 15181cb0ef41Sopenharmony_ci } 15191cb0ef41Sopenharmony_ci 15201cb0ef41Sopenharmony_ci /* We check for insufficient lookahead only every 8th comparison; 15211cb0ef41Sopenharmony_ci * the 256th check will be made at strstart + 258. 15221cb0ef41Sopenharmony_ci */ 15231cb0ef41Sopenharmony_ci do { 15241cb0ef41Sopenharmony_ci } while (*++scan == *++match && *++scan == *++match && 15251cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 15261cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 15271cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 15281cb0ef41Sopenharmony_ci scan < strend); 15291cb0ef41Sopenharmony_ci 15301cb0ef41Sopenharmony_ci Assert(scan <= s->window + (unsigned)(s->window_size - 1), 15311cb0ef41Sopenharmony_ci "wild scan"); 15321cb0ef41Sopenharmony_ci 15331cb0ef41Sopenharmony_ci len = MAX_MATCH - (int)(strend - scan); 15341cb0ef41Sopenharmony_ci scan = strend - MAX_MATCH; 15351cb0ef41Sopenharmony_ci 15361cb0ef41Sopenharmony_ci#endif /* UNALIGNED_OK */ 15371cb0ef41Sopenharmony_ci 15381cb0ef41Sopenharmony_ci if (len > best_len) { 15391cb0ef41Sopenharmony_ci s->match_start = cur_match; 15401cb0ef41Sopenharmony_ci best_len = len; 15411cb0ef41Sopenharmony_ci if (len >= nice_match) break; 15421cb0ef41Sopenharmony_ci#ifdef UNALIGNED_OK 15431cb0ef41Sopenharmony_ci scan_end = *(ushf*)(scan + best_len - 1); 15441cb0ef41Sopenharmony_ci#else 15451cb0ef41Sopenharmony_ci scan_end1 = scan[best_len - 1]; 15461cb0ef41Sopenharmony_ci scan_end = scan[best_len]; 15471cb0ef41Sopenharmony_ci#endif 15481cb0ef41Sopenharmony_ci } 15491cb0ef41Sopenharmony_ci } while ((cur_match = prev[cur_match & wmask]) > limit 15501cb0ef41Sopenharmony_ci && --chain_length != 0); 15511cb0ef41Sopenharmony_ci 15521cb0ef41Sopenharmony_ci if ((uInt)best_len <= s->lookahead) return (uInt)best_len; 15531cb0ef41Sopenharmony_ci return s->lookahead; 15541cb0ef41Sopenharmony_ci} 15551cb0ef41Sopenharmony_ci 15561cb0ef41Sopenharmony_ci#else /* FASTEST */ 15571cb0ef41Sopenharmony_ci 15581cb0ef41Sopenharmony_ci/* --------------------------------------------------------------------------- 15591cb0ef41Sopenharmony_ci * Optimized version for FASTEST only 15601cb0ef41Sopenharmony_ci */ 15611cb0ef41Sopenharmony_cilocal uInt longest_match(deflate_state *s, IPos cur_match) { 15621cb0ef41Sopenharmony_ci register Bytef *scan = s->window + s->strstart; /* current string */ 15631cb0ef41Sopenharmony_ci register Bytef *match; /* matched string */ 15641cb0ef41Sopenharmony_ci register int len; /* length of current match */ 15651cb0ef41Sopenharmony_ci register Bytef *strend = s->window + s->strstart + MAX_MATCH; 15661cb0ef41Sopenharmony_ci 15671cb0ef41Sopenharmony_ci /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 15681cb0ef41Sopenharmony_ci * It is easy to get rid of this optimization if necessary. 15691cb0ef41Sopenharmony_ci */ 15701cb0ef41Sopenharmony_ci Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); 15711cb0ef41Sopenharmony_ci 15721cb0ef41Sopenharmony_ci Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, 15731cb0ef41Sopenharmony_ci "need lookahead"); 15741cb0ef41Sopenharmony_ci 15751cb0ef41Sopenharmony_ci Assert(cur_match < s->strstart, "no future"); 15761cb0ef41Sopenharmony_ci 15771cb0ef41Sopenharmony_ci match = s->window + cur_match; 15781cb0ef41Sopenharmony_ci 15791cb0ef41Sopenharmony_ci /* Return failure if the match length is less than 2: 15801cb0ef41Sopenharmony_ci */ 15811cb0ef41Sopenharmony_ci if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; 15821cb0ef41Sopenharmony_ci 15831cb0ef41Sopenharmony_ci /* The check at best_len - 1 can be removed because it will be made 15841cb0ef41Sopenharmony_ci * again later. (This heuristic is not always a win.) 15851cb0ef41Sopenharmony_ci * It is not necessary to compare scan[2] and match[2] since they 15861cb0ef41Sopenharmony_ci * are always equal when the other bytes match, given that 15871cb0ef41Sopenharmony_ci * the hash keys are equal and that HASH_BITS >= 8. 15881cb0ef41Sopenharmony_ci */ 15891cb0ef41Sopenharmony_ci scan += 2, match += 2; 15901cb0ef41Sopenharmony_ci Assert(*scan == *match, "match[2]?"); 15911cb0ef41Sopenharmony_ci 15921cb0ef41Sopenharmony_ci /* We check for insufficient lookahead only every 8th comparison; 15931cb0ef41Sopenharmony_ci * the 256th check will be made at strstart + 258. 15941cb0ef41Sopenharmony_ci */ 15951cb0ef41Sopenharmony_ci do { 15961cb0ef41Sopenharmony_ci } while (*++scan == *++match && *++scan == *++match && 15971cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 15981cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 15991cb0ef41Sopenharmony_ci *++scan == *++match && *++scan == *++match && 16001cb0ef41Sopenharmony_ci scan < strend); 16011cb0ef41Sopenharmony_ci 16021cb0ef41Sopenharmony_ci Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); 16031cb0ef41Sopenharmony_ci 16041cb0ef41Sopenharmony_ci len = MAX_MATCH - (int)(strend - scan); 16051cb0ef41Sopenharmony_ci 16061cb0ef41Sopenharmony_ci if (len < MIN_MATCH) return MIN_MATCH - 1; 16071cb0ef41Sopenharmony_ci 16081cb0ef41Sopenharmony_ci s->match_start = cur_match; 16091cb0ef41Sopenharmony_ci return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; 16101cb0ef41Sopenharmony_ci} 16111cb0ef41Sopenharmony_ci 16121cb0ef41Sopenharmony_ci#endif /* FASTEST */ 16131cb0ef41Sopenharmony_ci 16141cb0ef41Sopenharmony_ci#ifdef ZLIB_DEBUG 16151cb0ef41Sopenharmony_ci 16161cb0ef41Sopenharmony_ci#define EQUAL 0 16171cb0ef41Sopenharmony_ci/* result of memcmp for equal strings */ 16181cb0ef41Sopenharmony_ci 16191cb0ef41Sopenharmony_ci/* =========================================================================== 16201cb0ef41Sopenharmony_ci * Check that the match at match_start is indeed a match. 16211cb0ef41Sopenharmony_ci */ 16221cb0ef41Sopenharmony_cilocal void check_match(deflate_state *s, IPos start, IPos match, int length) { 16231cb0ef41Sopenharmony_ci /* check that the match is indeed a match */ 16241cb0ef41Sopenharmony_ci if (zmemcmp(s->window + match, 16251cb0ef41Sopenharmony_ci s->window + start, length) != EQUAL) { 16261cb0ef41Sopenharmony_ci fprintf(stderr, " start %u, match %u, length %d\n", 16271cb0ef41Sopenharmony_ci start, match, length); 16281cb0ef41Sopenharmony_ci do { 16291cb0ef41Sopenharmony_ci fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); 16301cb0ef41Sopenharmony_ci } while (--length != 0); 16311cb0ef41Sopenharmony_ci z_error("invalid match"); 16321cb0ef41Sopenharmony_ci } 16331cb0ef41Sopenharmony_ci if (z_verbose > 1) { 16341cb0ef41Sopenharmony_ci fprintf(stderr,"\\[%d,%d]", start - match, length); 16351cb0ef41Sopenharmony_ci do { putc(s->window[start++], stderr); } while (--length != 0); 16361cb0ef41Sopenharmony_ci } 16371cb0ef41Sopenharmony_ci} 16381cb0ef41Sopenharmony_ci#else 16391cb0ef41Sopenharmony_ci# define check_match(s, start, match, length) 16401cb0ef41Sopenharmony_ci#endif /* ZLIB_DEBUG */ 16411cb0ef41Sopenharmony_ci 16421cb0ef41Sopenharmony_ci/* =========================================================================== 16431cb0ef41Sopenharmony_ci * Flush the current block, with given end-of-file flag. 16441cb0ef41Sopenharmony_ci * IN assertion: strstart is set to the end of the current match. 16451cb0ef41Sopenharmony_ci */ 16461cb0ef41Sopenharmony_ci#define FLUSH_BLOCK_ONLY(s, last) { \ 16471cb0ef41Sopenharmony_ci _tr_flush_block(s, (s->block_start >= 0L ? \ 16481cb0ef41Sopenharmony_ci (charf *)&s->window[(unsigned)s->block_start] : \ 16491cb0ef41Sopenharmony_ci (charf *)Z_NULL), \ 16501cb0ef41Sopenharmony_ci (ulg)((long)s->strstart - s->block_start), \ 16511cb0ef41Sopenharmony_ci (last)); \ 16521cb0ef41Sopenharmony_ci s->block_start = s->strstart; \ 16531cb0ef41Sopenharmony_ci flush_pending(s->strm); \ 16541cb0ef41Sopenharmony_ci Tracev((stderr,"[FLUSH]")); \ 16551cb0ef41Sopenharmony_ci} 16561cb0ef41Sopenharmony_ci 16571cb0ef41Sopenharmony_ci/* Same but force premature exit if necessary. */ 16581cb0ef41Sopenharmony_ci#define FLUSH_BLOCK(s, last) { \ 16591cb0ef41Sopenharmony_ci FLUSH_BLOCK_ONLY(s, last); \ 16601cb0ef41Sopenharmony_ci if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ 16611cb0ef41Sopenharmony_ci} 16621cb0ef41Sopenharmony_ci 16631cb0ef41Sopenharmony_ci/* Maximum stored block length in deflate format (not including header). */ 16641cb0ef41Sopenharmony_ci#define MAX_STORED 65535 16651cb0ef41Sopenharmony_ci 16661cb0ef41Sopenharmony_ci/* Minimum of a and b. */ 16671cb0ef41Sopenharmony_ci#define MIN(a, b) ((a) > (b) ? (b) : (a)) 16681cb0ef41Sopenharmony_ci 16691cb0ef41Sopenharmony_ci/* =========================================================================== 16701cb0ef41Sopenharmony_ci * Copy without compression as much as possible from the input stream, return 16711cb0ef41Sopenharmony_ci * the current block state. 16721cb0ef41Sopenharmony_ci * 16731cb0ef41Sopenharmony_ci * In case deflateParams() is used to later switch to a non-zero compression 16741cb0ef41Sopenharmony_ci * level, s->matches (otherwise unused when storing) keeps track of the number 16751cb0ef41Sopenharmony_ci * of hash table slides to perform. If s->matches is 1, then one hash table 16761cb0ef41Sopenharmony_ci * slide will be done when switching. If s->matches is 2, the maximum value 16771cb0ef41Sopenharmony_ci * allowed here, then the hash table will be cleared, since two or more slides 16781cb0ef41Sopenharmony_ci * is the same as a clear. 16791cb0ef41Sopenharmony_ci * 16801cb0ef41Sopenharmony_ci * deflate_stored() is written to minimize the number of times an input byte is 16811cb0ef41Sopenharmony_ci * copied. It is most efficient with large input and output buffers, which 16821cb0ef41Sopenharmony_ci * maximizes the opportunities to have a single copy from next_in to next_out. 16831cb0ef41Sopenharmony_ci */ 16841cb0ef41Sopenharmony_cilocal block_state deflate_stored(deflate_state *s, int flush) { 16851cb0ef41Sopenharmony_ci /* Smallest worthy block size when not flushing or finishing. By default 16861cb0ef41Sopenharmony_ci * this is 32K. This can be as small as 507 bytes for memLevel == 1. For 16871cb0ef41Sopenharmony_ci * large input and output buffers, the stored block size will be larger. 16881cb0ef41Sopenharmony_ci */ 16891cb0ef41Sopenharmony_ci unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); 16901cb0ef41Sopenharmony_ci 16911cb0ef41Sopenharmony_ci /* Copy as many min_block or larger stored blocks directly to next_out as 16921cb0ef41Sopenharmony_ci * possible. If flushing, copy the remaining available input to next_out as 16931cb0ef41Sopenharmony_ci * stored blocks, if there is enough space. 16941cb0ef41Sopenharmony_ci */ 16951cb0ef41Sopenharmony_ci unsigned len, left, have, last = 0; 16961cb0ef41Sopenharmony_ci unsigned used = s->strm->avail_in; 16971cb0ef41Sopenharmony_ci do { 16981cb0ef41Sopenharmony_ci /* Set len to the maximum size block that we can copy directly with the 16991cb0ef41Sopenharmony_ci * available input data and output space. Set left to how much of that 17001cb0ef41Sopenharmony_ci * would be copied from what's left in the window. 17011cb0ef41Sopenharmony_ci */ 17021cb0ef41Sopenharmony_ci len = MAX_STORED; /* maximum deflate stored block length */ 17031cb0ef41Sopenharmony_ci have = (s->bi_valid + 42) >> 3; /* number of header bytes */ 17041cb0ef41Sopenharmony_ci if (s->strm->avail_out < have) /* need room for header */ 17051cb0ef41Sopenharmony_ci break; 17061cb0ef41Sopenharmony_ci /* maximum stored block length that will fit in avail_out: */ 17071cb0ef41Sopenharmony_ci have = s->strm->avail_out - have; 17081cb0ef41Sopenharmony_ci left = s->strstart - s->block_start; /* bytes left in window */ 17091cb0ef41Sopenharmony_ci if (len > (ulg)left + s->strm->avail_in) 17101cb0ef41Sopenharmony_ci len = left + s->strm->avail_in; /* limit len to the input */ 17111cb0ef41Sopenharmony_ci if (len > have) 17121cb0ef41Sopenharmony_ci len = have; /* limit len to the output */ 17131cb0ef41Sopenharmony_ci 17141cb0ef41Sopenharmony_ci /* If the stored block would be less than min_block in length, or if 17151cb0ef41Sopenharmony_ci * unable to copy all of the available input when flushing, then try 17161cb0ef41Sopenharmony_ci * copying to the window and the pending buffer instead. Also don't 17171cb0ef41Sopenharmony_ci * write an empty block when flushing -- deflate() does that. 17181cb0ef41Sopenharmony_ci */ 17191cb0ef41Sopenharmony_ci if (len < min_block && ((len == 0 && flush != Z_FINISH) || 17201cb0ef41Sopenharmony_ci flush == Z_NO_FLUSH || 17211cb0ef41Sopenharmony_ci len != left + s->strm->avail_in)) 17221cb0ef41Sopenharmony_ci break; 17231cb0ef41Sopenharmony_ci 17241cb0ef41Sopenharmony_ci /* Make a dummy stored block in pending to get the header bytes, 17251cb0ef41Sopenharmony_ci * including any pending bits. This also updates the debugging counts. 17261cb0ef41Sopenharmony_ci */ 17271cb0ef41Sopenharmony_ci last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; 17281cb0ef41Sopenharmony_ci _tr_stored_block(s, (char *)0, 0L, last); 17291cb0ef41Sopenharmony_ci 17301cb0ef41Sopenharmony_ci /* Replace the lengths in the dummy stored block with len. */ 17311cb0ef41Sopenharmony_ci s->pending_buf[s->pending - 4] = len; 17321cb0ef41Sopenharmony_ci s->pending_buf[s->pending - 3] = len >> 8; 17331cb0ef41Sopenharmony_ci s->pending_buf[s->pending - 2] = ~len; 17341cb0ef41Sopenharmony_ci s->pending_buf[s->pending - 1] = ~len >> 8; 17351cb0ef41Sopenharmony_ci 17361cb0ef41Sopenharmony_ci /* Write the stored block header bytes. */ 17371cb0ef41Sopenharmony_ci flush_pending(s->strm); 17381cb0ef41Sopenharmony_ci 17391cb0ef41Sopenharmony_ci#ifdef ZLIB_DEBUG 17401cb0ef41Sopenharmony_ci /* Update debugging counts for the data about to be copied. */ 17411cb0ef41Sopenharmony_ci s->compressed_len += len << 3; 17421cb0ef41Sopenharmony_ci s->bits_sent += len << 3; 17431cb0ef41Sopenharmony_ci#endif 17441cb0ef41Sopenharmony_ci 17451cb0ef41Sopenharmony_ci /* Copy uncompressed bytes from the window to next_out. */ 17461cb0ef41Sopenharmony_ci if (left) { 17471cb0ef41Sopenharmony_ci if (left > len) 17481cb0ef41Sopenharmony_ci left = len; 17491cb0ef41Sopenharmony_ci zmemcpy(s->strm->next_out, s->window + s->block_start, left); 17501cb0ef41Sopenharmony_ci s->strm->next_out += left; 17511cb0ef41Sopenharmony_ci s->strm->avail_out -= left; 17521cb0ef41Sopenharmony_ci s->strm->total_out += left; 17531cb0ef41Sopenharmony_ci s->block_start += left; 17541cb0ef41Sopenharmony_ci len -= left; 17551cb0ef41Sopenharmony_ci } 17561cb0ef41Sopenharmony_ci 17571cb0ef41Sopenharmony_ci /* Copy uncompressed bytes directly from next_in to next_out, updating 17581cb0ef41Sopenharmony_ci * the check value. 17591cb0ef41Sopenharmony_ci */ 17601cb0ef41Sopenharmony_ci if (len) { 17611cb0ef41Sopenharmony_ci read_buf(s->strm, s->strm->next_out, len); 17621cb0ef41Sopenharmony_ci s->strm->next_out += len; 17631cb0ef41Sopenharmony_ci s->strm->avail_out -= len; 17641cb0ef41Sopenharmony_ci s->strm->total_out += len; 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci } while (last == 0); 17671cb0ef41Sopenharmony_ci 17681cb0ef41Sopenharmony_ci /* Update the sliding window with the last s->w_size bytes of the copied 17691cb0ef41Sopenharmony_ci * data, or append all of the copied data to the existing window if less 17701cb0ef41Sopenharmony_ci * than s->w_size bytes were copied. Also update the number of bytes to 17711cb0ef41Sopenharmony_ci * insert in the hash tables, in the event that deflateParams() switches to 17721cb0ef41Sopenharmony_ci * a non-zero compression level. 17731cb0ef41Sopenharmony_ci */ 17741cb0ef41Sopenharmony_ci used -= s->strm->avail_in; /* number of input bytes directly copied */ 17751cb0ef41Sopenharmony_ci if (used) { 17761cb0ef41Sopenharmony_ci /* If any input was used, then no unused input remains in the window, 17771cb0ef41Sopenharmony_ci * therefore s->block_start == s->strstart. 17781cb0ef41Sopenharmony_ci */ 17791cb0ef41Sopenharmony_ci if (used >= s->w_size) { /* supplant the previous history */ 17801cb0ef41Sopenharmony_ci s->matches = 2; /* clear hash */ 17811cb0ef41Sopenharmony_ci zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); 17821cb0ef41Sopenharmony_ci s->strstart = s->w_size; 17831cb0ef41Sopenharmony_ci s->insert = s->strstart; 17841cb0ef41Sopenharmony_ci } 17851cb0ef41Sopenharmony_ci else { 17861cb0ef41Sopenharmony_ci if (s->window_size - s->strstart <= used) { 17871cb0ef41Sopenharmony_ci /* Slide the window down. */ 17881cb0ef41Sopenharmony_ci s->strstart -= s->w_size; 17891cb0ef41Sopenharmony_ci zmemcpy(s->window, s->window + s->w_size, s->strstart); 17901cb0ef41Sopenharmony_ci if (s->matches < 2) 17911cb0ef41Sopenharmony_ci s->matches++; /* add a pending slide_hash() */ 17921cb0ef41Sopenharmony_ci if (s->insert > s->strstart) 17931cb0ef41Sopenharmony_ci s->insert = s->strstart; 17941cb0ef41Sopenharmony_ci } 17951cb0ef41Sopenharmony_ci zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); 17961cb0ef41Sopenharmony_ci s->strstart += used; 17971cb0ef41Sopenharmony_ci s->insert += MIN(used, s->w_size - s->insert); 17981cb0ef41Sopenharmony_ci } 17991cb0ef41Sopenharmony_ci s->block_start = s->strstart; 18001cb0ef41Sopenharmony_ci } 18011cb0ef41Sopenharmony_ci if (s->high_water < s->strstart) 18021cb0ef41Sopenharmony_ci s->high_water = s->strstart; 18031cb0ef41Sopenharmony_ci 18041cb0ef41Sopenharmony_ci /* If the last block was written to next_out, then done. */ 18051cb0ef41Sopenharmony_ci if (last) 18061cb0ef41Sopenharmony_ci return finish_done; 18071cb0ef41Sopenharmony_ci 18081cb0ef41Sopenharmony_ci /* If flushing and all input has been consumed, then done. */ 18091cb0ef41Sopenharmony_ci if (flush != Z_NO_FLUSH && flush != Z_FINISH && 18101cb0ef41Sopenharmony_ci s->strm->avail_in == 0 && (long)s->strstart == s->block_start) 18111cb0ef41Sopenharmony_ci return block_done; 18121cb0ef41Sopenharmony_ci 18131cb0ef41Sopenharmony_ci /* Fill the window with any remaining input. */ 18141cb0ef41Sopenharmony_ci have = s->window_size - s->strstart; 18151cb0ef41Sopenharmony_ci if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { 18161cb0ef41Sopenharmony_ci /* Slide the window down. */ 18171cb0ef41Sopenharmony_ci s->block_start -= s->w_size; 18181cb0ef41Sopenharmony_ci s->strstart -= s->w_size; 18191cb0ef41Sopenharmony_ci zmemcpy(s->window, s->window + s->w_size, s->strstart); 18201cb0ef41Sopenharmony_ci if (s->matches < 2) 18211cb0ef41Sopenharmony_ci s->matches++; /* add a pending slide_hash() */ 18221cb0ef41Sopenharmony_ci have += s->w_size; /* more space now */ 18231cb0ef41Sopenharmony_ci if (s->insert > s->strstart) 18241cb0ef41Sopenharmony_ci s->insert = s->strstart; 18251cb0ef41Sopenharmony_ci } 18261cb0ef41Sopenharmony_ci if (have > s->strm->avail_in) 18271cb0ef41Sopenharmony_ci have = s->strm->avail_in; 18281cb0ef41Sopenharmony_ci if (have) { 18291cb0ef41Sopenharmony_ci read_buf(s->strm, s->window + s->strstart, have); 18301cb0ef41Sopenharmony_ci s->strstart += have; 18311cb0ef41Sopenharmony_ci s->insert += MIN(have, s->w_size - s->insert); 18321cb0ef41Sopenharmony_ci } 18331cb0ef41Sopenharmony_ci if (s->high_water < s->strstart) 18341cb0ef41Sopenharmony_ci s->high_water = s->strstart; 18351cb0ef41Sopenharmony_ci 18361cb0ef41Sopenharmony_ci /* There was not enough avail_out to write a complete worthy or flushed 18371cb0ef41Sopenharmony_ci * stored block to next_out. Write a stored block to pending instead, if we 18381cb0ef41Sopenharmony_ci * have enough input for a worthy block, or if flushing and there is enough 18391cb0ef41Sopenharmony_ci * room for the remaining input as a stored block in the pending buffer. 18401cb0ef41Sopenharmony_ci */ 18411cb0ef41Sopenharmony_ci have = (s->bi_valid + 42) >> 3; /* number of header bytes */ 18421cb0ef41Sopenharmony_ci /* maximum stored block length that will fit in pending: */ 18431cb0ef41Sopenharmony_ci have = MIN(s->pending_buf_size - have, MAX_STORED); 18441cb0ef41Sopenharmony_ci min_block = MIN(have, s->w_size); 18451cb0ef41Sopenharmony_ci left = s->strstart - s->block_start; 18461cb0ef41Sopenharmony_ci if (left >= min_block || 18471cb0ef41Sopenharmony_ci ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && 18481cb0ef41Sopenharmony_ci s->strm->avail_in == 0 && left <= have)) { 18491cb0ef41Sopenharmony_ci len = MIN(left, have); 18501cb0ef41Sopenharmony_ci last = flush == Z_FINISH && s->strm->avail_in == 0 && 18511cb0ef41Sopenharmony_ci len == left ? 1 : 0; 18521cb0ef41Sopenharmony_ci _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); 18531cb0ef41Sopenharmony_ci s->block_start += len; 18541cb0ef41Sopenharmony_ci flush_pending(s->strm); 18551cb0ef41Sopenharmony_ci } 18561cb0ef41Sopenharmony_ci 18571cb0ef41Sopenharmony_ci /* We've done all we can with the available input and output. */ 18581cb0ef41Sopenharmony_ci return last ? finish_started : need_more; 18591cb0ef41Sopenharmony_ci} 18601cb0ef41Sopenharmony_ci 18611cb0ef41Sopenharmony_ci/* =========================================================================== 18621cb0ef41Sopenharmony_ci * Compress as much as possible from the input stream, return the current 18631cb0ef41Sopenharmony_ci * block state. 18641cb0ef41Sopenharmony_ci * This function does not perform lazy evaluation of matches and inserts 18651cb0ef41Sopenharmony_ci * new strings in the dictionary only for unmatched strings or for short 18661cb0ef41Sopenharmony_ci * matches. It is used only for the fast compression options. 18671cb0ef41Sopenharmony_ci */ 18681cb0ef41Sopenharmony_cilocal block_state deflate_fast(deflate_state *s, int flush) { 18691cb0ef41Sopenharmony_ci IPos hash_head; /* head of the hash chain */ 18701cb0ef41Sopenharmony_ci int bflush; /* set if current block must be flushed */ 18711cb0ef41Sopenharmony_ci 18721cb0ef41Sopenharmony_ci for (;;) { 18731cb0ef41Sopenharmony_ci /* Make sure that we always have enough lookahead, except 18741cb0ef41Sopenharmony_ci * at the end of the input file. We need MAX_MATCH bytes 18751cb0ef41Sopenharmony_ci * for the next match, plus MIN_MATCH bytes to insert the 18761cb0ef41Sopenharmony_ci * string following the next match. 18771cb0ef41Sopenharmony_ci */ 18781cb0ef41Sopenharmony_ci if (s->lookahead < MIN_LOOKAHEAD) { 18791cb0ef41Sopenharmony_ci fill_window(s); 18801cb0ef41Sopenharmony_ci if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { 18811cb0ef41Sopenharmony_ci return need_more; 18821cb0ef41Sopenharmony_ci } 18831cb0ef41Sopenharmony_ci if (s->lookahead == 0) break; /* flush the current block */ 18841cb0ef41Sopenharmony_ci } 18851cb0ef41Sopenharmony_ci 18861cb0ef41Sopenharmony_ci /* Insert the string window[strstart .. strstart + 2] in the 18871cb0ef41Sopenharmony_ci * dictionary, and set hash_head to the head of the hash chain: 18881cb0ef41Sopenharmony_ci */ 18891cb0ef41Sopenharmony_ci hash_head = NIL; 18901cb0ef41Sopenharmony_ci if (s->lookahead >= MIN_MATCH) { 18911cb0ef41Sopenharmony_ci hash_head = insert_string(s, s->strstart); 18921cb0ef41Sopenharmony_ci } 18931cb0ef41Sopenharmony_ci 18941cb0ef41Sopenharmony_ci /* Find the longest match, discarding those <= prev_length. 18951cb0ef41Sopenharmony_ci * At this point we have always match_length < MIN_MATCH 18961cb0ef41Sopenharmony_ci */ 18971cb0ef41Sopenharmony_ci if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { 18981cb0ef41Sopenharmony_ci /* To simplify the code, we prevent matches with the string 18991cb0ef41Sopenharmony_ci * of window index 0 (in particular we have to avoid a match 19001cb0ef41Sopenharmony_ci * of the string with itself at the start of the input file). 19011cb0ef41Sopenharmony_ci */ 19021cb0ef41Sopenharmony_ci s->match_length = longest_match (s, hash_head); 19031cb0ef41Sopenharmony_ci /* longest_match() sets match_start */ 19041cb0ef41Sopenharmony_ci } 19051cb0ef41Sopenharmony_ci if (s->match_length >= MIN_MATCH) { 19061cb0ef41Sopenharmony_ci check_match(s, s->strstart, s->match_start, s->match_length); 19071cb0ef41Sopenharmony_ci 19081cb0ef41Sopenharmony_ci _tr_tally_dist(s, s->strstart - s->match_start, 19091cb0ef41Sopenharmony_ci s->match_length - MIN_MATCH, bflush); 19101cb0ef41Sopenharmony_ci 19111cb0ef41Sopenharmony_ci s->lookahead -= s->match_length; 19121cb0ef41Sopenharmony_ci 19131cb0ef41Sopenharmony_ci /* Insert new strings in the hash table only if the match length 19141cb0ef41Sopenharmony_ci * is not too large. This saves time but degrades compression. 19151cb0ef41Sopenharmony_ci */ 19161cb0ef41Sopenharmony_ci#ifndef FASTEST 19171cb0ef41Sopenharmony_ci if (s->match_length <= s->max_insert_length && 19181cb0ef41Sopenharmony_ci s->lookahead >= MIN_MATCH) { 19191cb0ef41Sopenharmony_ci s->match_length--; /* string at strstart already in table */ 19201cb0ef41Sopenharmony_ci do { 19211cb0ef41Sopenharmony_ci s->strstart++; 19221cb0ef41Sopenharmony_ci hash_head = insert_string(s, s->strstart); 19231cb0ef41Sopenharmony_ci /* strstart never exceeds WSIZE-MAX_MATCH, so there are 19241cb0ef41Sopenharmony_ci * always MIN_MATCH bytes ahead. 19251cb0ef41Sopenharmony_ci */ 19261cb0ef41Sopenharmony_ci } while (--s->match_length != 0); 19271cb0ef41Sopenharmony_ci s->strstart++; 19281cb0ef41Sopenharmony_ci } else 19291cb0ef41Sopenharmony_ci#endif 19301cb0ef41Sopenharmony_ci { 19311cb0ef41Sopenharmony_ci s->strstart += s->match_length; 19321cb0ef41Sopenharmony_ci s->match_length = 0; 19331cb0ef41Sopenharmony_ci 19341cb0ef41Sopenharmony_ci if (!s->chromium_zlib_hash) { 19351cb0ef41Sopenharmony_ci s->ins_h = s->window[s->strstart]; 19361cb0ef41Sopenharmony_ci UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); 19371cb0ef41Sopenharmony_ci#if MIN_MATCH != 3 19381cb0ef41Sopenharmony_ci Call UPDATE_HASH() MIN_MATCH-3 more times 19391cb0ef41Sopenharmony_ci#endif 19401cb0ef41Sopenharmony_ci /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not 19411cb0ef41Sopenharmony_ci * matter since it will be recomputed at next deflate call. 19421cb0ef41Sopenharmony_ci */ 19431cb0ef41Sopenharmony_ci } 19441cb0ef41Sopenharmony_ci } 19451cb0ef41Sopenharmony_ci } else { 19461cb0ef41Sopenharmony_ci /* No match, output a literal byte */ 19471cb0ef41Sopenharmony_ci Tracevv((stderr,"%c", s->window[s->strstart])); 19481cb0ef41Sopenharmony_ci _tr_tally_lit(s, s->window[s->strstart], bflush); 19491cb0ef41Sopenharmony_ci s->lookahead--; 19501cb0ef41Sopenharmony_ci s->strstart++; 19511cb0ef41Sopenharmony_ci } 19521cb0ef41Sopenharmony_ci if (bflush) FLUSH_BLOCK(s, 0); 19531cb0ef41Sopenharmony_ci } 19541cb0ef41Sopenharmony_ci s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; 19551cb0ef41Sopenharmony_ci if (flush == Z_FINISH) { 19561cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 1); 19571cb0ef41Sopenharmony_ci return finish_done; 19581cb0ef41Sopenharmony_ci } 19591cb0ef41Sopenharmony_ci if (s->sym_next) 19601cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 0); 19611cb0ef41Sopenharmony_ci return block_done; 19621cb0ef41Sopenharmony_ci} 19631cb0ef41Sopenharmony_ci 19641cb0ef41Sopenharmony_ci#ifndef FASTEST 19651cb0ef41Sopenharmony_ci/* =========================================================================== 19661cb0ef41Sopenharmony_ci * Same as above, but achieves better compression. We use a lazy 19671cb0ef41Sopenharmony_ci * evaluation for matches: a match is finally adopted only if there is 19681cb0ef41Sopenharmony_ci * no better match at the next window position. 19691cb0ef41Sopenharmony_ci */ 19701cb0ef41Sopenharmony_cilocal block_state deflate_slow(deflate_state *s, int flush) { 19711cb0ef41Sopenharmony_ci IPos hash_head; /* head of hash chain */ 19721cb0ef41Sopenharmony_ci int bflush; /* set if current block must be flushed */ 19731cb0ef41Sopenharmony_ci 19741cb0ef41Sopenharmony_ci /* Process the input block. */ 19751cb0ef41Sopenharmony_ci for (;;) { 19761cb0ef41Sopenharmony_ci /* Make sure that we always have enough lookahead, except 19771cb0ef41Sopenharmony_ci * at the end of the input file. We need MAX_MATCH bytes 19781cb0ef41Sopenharmony_ci * for the next match, plus MIN_MATCH bytes to insert the 19791cb0ef41Sopenharmony_ci * string following the next match. 19801cb0ef41Sopenharmony_ci */ 19811cb0ef41Sopenharmony_ci if (s->lookahead < MIN_LOOKAHEAD) { 19821cb0ef41Sopenharmony_ci fill_window(s); 19831cb0ef41Sopenharmony_ci if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { 19841cb0ef41Sopenharmony_ci return need_more; 19851cb0ef41Sopenharmony_ci } 19861cb0ef41Sopenharmony_ci if (s->lookahead == 0) break; /* flush the current block */ 19871cb0ef41Sopenharmony_ci } 19881cb0ef41Sopenharmony_ci 19891cb0ef41Sopenharmony_ci /* Insert the string window[strstart .. strstart + 2] in the 19901cb0ef41Sopenharmony_ci * dictionary, and set hash_head to the head of the hash chain: 19911cb0ef41Sopenharmony_ci */ 19921cb0ef41Sopenharmony_ci hash_head = NIL; 19931cb0ef41Sopenharmony_ci if (s->lookahead >= MIN_MATCH) { 19941cb0ef41Sopenharmony_ci hash_head = insert_string(s, s->strstart); 19951cb0ef41Sopenharmony_ci } 19961cb0ef41Sopenharmony_ci 19971cb0ef41Sopenharmony_ci /* Find the longest match, discarding those <= prev_length. 19981cb0ef41Sopenharmony_ci */ 19991cb0ef41Sopenharmony_ci s->prev_length = s->match_length, s->prev_match = s->match_start; 20001cb0ef41Sopenharmony_ci s->match_length = MIN_MATCH-1; 20011cb0ef41Sopenharmony_ci 20021cb0ef41Sopenharmony_ci if (hash_head != NIL && s->prev_length < s->max_lazy_match && 20031cb0ef41Sopenharmony_ci s->strstart - hash_head <= MAX_DIST(s)) { 20041cb0ef41Sopenharmony_ci /* To simplify the code, we prevent matches with the string 20051cb0ef41Sopenharmony_ci * of window index 0 (in particular we have to avoid a match 20061cb0ef41Sopenharmony_ci * of the string with itself at the start of the input file). 20071cb0ef41Sopenharmony_ci */ 20081cb0ef41Sopenharmony_ci s->match_length = longest_match (s, hash_head); 20091cb0ef41Sopenharmony_ci /* longest_match() sets match_start */ 20101cb0ef41Sopenharmony_ci 20111cb0ef41Sopenharmony_ci if (s->match_length <= 5 && (s->strategy == Z_FILTERED 20121cb0ef41Sopenharmony_ci#if TOO_FAR <= 32767 20131cb0ef41Sopenharmony_ci || (s->match_length == MIN_MATCH && 20141cb0ef41Sopenharmony_ci s->strstart - s->match_start > TOO_FAR) 20151cb0ef41Sopenharmony_ci#endif 20161cb0ef41Sopenharmony_ci )) { 20171cb0ef41Sopenharmony_ci 20181cb0ef41Sopenharmony_ci /* If prev_match is also MIN_MATCH, match_start is garbage 20191cb0ef41Sopenharmony_ci * but we will ignore the current match anyway. 20201cb0ef41Sopenharmony_ci */ 20211cb0ef41Sopenharmony_ci s->match_length = MIN_MATCH-1; 20221cb0ef41Sopenharmony_ci } 20231cb0ef41Sopenharmony_ci } 20241cb0ef41Sopenharmony_ci /* If there was a match at the previous step and the current 20251cb0ef41Sopenharmony_ci * match is not better, output the previous match: 20261cb0ef41Sopenharmony_ci */ 20271cb0ef41Sopenharmony_ci if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { 20281cb0ef41Sopenharmony_ci uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; 20291cb0ef41Sopenharmony_ci /* Do not insert strings in hash table beyond this. */ 20301cb0ef41Sopenharmony_ci 20311cb0ef41Sopenharmony_ci if (s->prev_match == -1) { 20321cb0ef41Sopenharmony_ci /* The window has slid one byte past the previous match, 20331cb0ef41Sopenharmony_ci * so the first byte cannot be compared. */ 20341cb0ef41Sopenharmony_ci check_match(s, s->strstart, s->prev_match + 1, s->prev_length - 1); 20351cb0ef41Sopenharmony_ci } else { 20361cb0ef41Sopenharmony_ci check_match(s, s->strstart - 1, s->prev_match, s->prev_length); 20371cb0ef41Sopenharmony_ci } 20381cb0ef41Sopenharmony_ci 20391cb0ef41Sopenharmony_ci _tr_tally_dist(s, s->strstart - 1 - s->prev_match, 20401cb0ef41Sopenharmony_ci s->prev_length - MIN_MATCH, bflush); 20411cb0ef41Sopenharmony_ci 20421cb0ef41Sopenharmony_ci /* Insert in hash table all strings up to the end of the match. 20431cb0ef41Sopenharmony_ci * strstart - 1 and strstart are already inserted. If there is not 20441cb0ef41Sopenharmony_ci * enough lookahead, the last two strings are not inserted in 20451cb0ef41Sopenharmony_ci * the hash table. 20461cb0ef41Sopenharmony_ci */ 20471cb0ef41Sopenharmony_ci s->lookahead -= s->prev_length - 1; 20481cb0ef41Sopenharmony_ci s->prev_length -= 2; 20491cb0ef41Sopenharmony_ci do { 20501cb0ef41Sopenharmony_ci if (++s->strstart <= max_insert) { 20511cb0ef41Sopenharmony_ci hash_head = insert_string(s, s->strstart); 20521cb0ef41Sopenharmony_ci } 20531cb0ef41Sopenharmony_ci } while (--s->prev_length != 0); 20541cb0ef41Sopenharmony_ci s->match_available = 0; 20551cb0ef41Sopenharmony_ci s->match_length = MIN_MATCH-1; 20561cb0ef41Sopenharmony_ci s->strstart++; 20571cb0ef41Sopenharmony_ci 20581cb0ef41Sopenharmony_ci if (bflush) FLUSH_BLOCK(s, 0); 20591cb0ef41Sopenharmony_ci 20601cb0ef41Sopenharmony_ci } else if (s->match_available) { 20611cb0ef41Sopenharmony_ci /* If there was no match at the previous position, output a 20621cb0ef41Sopenharmony_ci * single literal. If there was a match but the current match 20631cb0ef41Sopenharmony_ci * is longer, truncate the previous match to a single literal. 20641cb0ef41Sopenharmony_ci */ 20651cb0ef41Sopenharmony_ci Tracevv((stderr,"%c", s->window[s->strstart - 1])); 20661cb0ef41Sopenharmony_ci _tr_tally_lit(s, s->window[s->strstart - 1], bflush); 20671cb0ef41Sopenharmony_ci if (bflush) { 20681cb0ef41Sopenharmony_ci FLUSH_BLOCK_ONLY(s, 0); 20691cb0ef41Sopenharmony_ci } 20701cb0ef41Sopenharmony_ci s->strstart++; 20711cb0ef41Sopenharmony_ci s->lookahead--; 20721cb0ef41Sopenharmony_ci if (s->strm->avail_out == 0) return need_more; 20731cb0ef41Sopenharmony_ci } else { 20741cb0ef41Sopenharmony_ci /* There is no previous match to compare with, wait for 20751cb0ef41Sopenharmony_ci * the next step to decide. 20761cb0ef41Sopenharmony_ci */ 20771cb0ef41Sopenharmony_ci s->match_available = 1; 20781cb0ef41Sopenharmony_ci s->strstart++; 20791cb0ef41Sopenharmony_ci s->lookahead--; 20801cb0ef41Sopenharmony_ci } 20811cb0ef41Sopenharmony_ci } 20821cb0ef41Sopenharmony_ci Assert (flush != Z_NO_FLUSH, "no flush?"); 20831cb0ef41Sopenharmony_ci if (s->match_available) { 20841cb0ef41Sopenharmony_ci Tracevv((stderr,"%c", s->window[s->strstart - 1])); 20851cb0ef41Sopenharmony_ci _tr_tally_lit(s, s->window[s->strstart - 1], bflush); 20861cb0ef41Sopenharmony_ci s->match_available = 0; 20871cb0ef41Sopenharmony_ci } 20881cb0ef41Sopenharmony_ci s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; 20891cb0ef41Sopenharmony_ci if (flush == Z_FINISH) { 20901cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 1); 20911cb0ef41Sopenharmony_ci return finish_done; 20921cb0ef41Sopenharmony_ci } 20931cb0ef41Sopenharmony_ci if (s->sym_next) 20941cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 0); 20951cb0ef41Sopenharmony_ci return block_done; 20961cb0ef41Sopenharmony_ci} 20971cb0ef41Sopenharmony_ci#endif /* FASTEST */ 20981cb0ef41Sopenharmony_ci 20991cb0ef41Sopenharmony_ci/* =========================================================================== 21001cb0ef41Sopenharmony_ci * For Z_RLE, simply look for runs of bytes, generate matches only of distance 21011cb0ef41Sopenharmony_ci * one. Do not maintain a hash table. (It will be regenerated if this run of 21021cb0ef41Sopenharmony_ci * deflate switches away from Z_RLE.) 21031cb0ef41Sopenharmony_ci */ 21041cb0ef41Sopenharmony_cilocal block_state deflate_rle(deflate_state *s, int flush) { 21051cb0ef41Sopenharmony_ci int bflush; /* set if current block must be flushed */ 21061cb0ef41Sopenharmony_ci uInt prev; /* byte at distance one to match */ 21071cb0ef41Sopenharmony_ci Bytef *scan, *strend; /* scan goes up to strend for length of run */ 21081cb0ef41Sopenharmony_ci 21091cb0ef41Sopenharmony_ci for (;;) { 21101cb0ef41Sopenharmony_ci /* Make sure that we always have enough lookahead, except 21111cb0ef41Sopenharmony_ci * at the end of the input file. We need MAX_MATCH bytes 21121cb0ef41Sopenharmony_ci * for the longest run, plus one for the unrolled loop. 21131cb0ef41Sopenharmony_ci */ 21141cb0ef41Sopenharmony_ci if (s->lookahead <= MAX_MATCH) { 21151cb0ef41Sopenharmony_ci fill_window(s); 21161cb0ef41Sopenharmony_ci if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { 21171cb0ef41Sopenharmony_ci return need_more; 21181cb0ef41Sopenharmony_ci } 21191cb0ef41Sopenharmony_ci if (s->lookahead == 0) break; /* flush the current block */ 21201cb0ef41Sopenharmony_ci } 21211cb0ef41Sopenharmony_ci 21221cb0ef41Sopenharmony_ci /* See how many times the previous byte repeats */ 21231cb0ef41Sopenharmony_ci s->match_length = 0; 21241cb0ef41Sopenharmony_ci if (s->lookahead >= MIN_MATCH && s->strstart > 0) { 21251cb0ef41Sopenharmony_ci scan = s->window + s->strstart - 1; 21261cb0ef41Sopenharmony_ci prev = *scan; 21271cb0ef41Sopenharmony_ci if (prev == *++scan && prev == *++scan && prev == *++scan) { 21281cb0ef41Sopenharmony_ci strend = s->window + s->strstart + MAX_MATCH; 21291cb0ef41Sopenharmony_ci do { 21301cb0ef41Sopenharmony_ci } while (prev == *++scan && prev == *++scan && 21311cb0ef41Sopenharmony_ci prev == *++scan && prev == *++scan && 21321cb0ef41Sopenharmony_ci prev == *++scan && prev == *++scan && 21331cb0ef41Sopenharmony_ci prev == *++scan && prev == *++scan && 21341cb0ef41Sopenharmony_ci scan < strend); 21351cb0ef41Sopenharmony_ci s->match_length = MAX_MATCH - (uInt)(strend - scan); 21361cb0ef41Sopenharmony_ci if (s->match_length > s->lookahead) 21371cb0ef41Sopenharmony_ci s->match_length = s->lookahead; 21381cb0ef41Sopenharmony_ci } 21391cb0ef41Sopenharmony_ci Assert(scan <= s->window + (uInt)(s->window_size - 1), 21401cb0ef41Sopenharmony_ci "wild scan"); 21411cb0ef41Sopenharmony_ci } 21421cb0ef41Sopenharmony_ci 21431cb0ef41Sopenharmony_ci /* Emit match if have run of MIN_MATCH or longer, else emit literal */ 21441cb0ef41Sopenharmony_ci if (s->match_length >= MIN_MATCH) { 21451cb0ef41Sopenharmony_ci check_match(s, s->strstart, s->strstart - 1, s->match_length); 21461cb0ef41Sopenharmony_ci 21471cb0ef41Sopenharmony_ci _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); 21481cb0ef41Sopenharmony_ci 21491cb0ef41Sopenharmony_ci s->lookahead -= s->match_length; 21501cb0ef41Sopenharmony_ci s->strstart += s->match_length; 21511cb0ef41Sopenharmony_ci s->match_length = 0; 21521cb0ef41Sopenharmony_ci } else { 21531cb0ef41Sopenharmony_ci /* No match, output a literal byte */ 21541cb0ef41Sopenharmony_ci Tracevv((stderr,"%c", s->window[s->strstart])); 21551cb0ef41Sopenharmony_ci _tr_tally_lit(s, s->window[s->strstart], bflush); 21561cb0ef41Sopenharmony_ci s->lookahead--; 21571cb0ef41Sopenharmony_ci s->strstart++; 21581cb0ef41Sopenharmony_ci } 21591cb0ef41Sopenharmony_ci if (bflush) FLUSH_BLOCK(s, 0); 21601cb0ef41Sopenharmony_ci } 21611cb0ef41Sopenharmony_ci s->insert = 0; 21621cb0ef41Sopenharmony_ci if (flush == Z_FINISH) { 21631cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 1); 21641cb0ef41Sopenharmony_ci return finish_done; 21651cb0ef41Sopenharmony_ci } 21661cb0ef41Sopenharmony_ci if (s->sym_next) 21671cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 0); 21681cb0ef41Sopenharmony_ci return block_done; 21691cb0ef41Sopenharmony_ci} 21701cb0ef41Sopenharmony_ci 21711cb0ef41Sopenharmony_ci/* =========================================================================== 21721cb0ef41Sopenharmony_ci * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. 21731cb0ef41Sopenharmony_ci * (It will be regenerated if this run of deflate switches away from Huffman.) 21741cb0ef41Sopenharmony_ci */ 21751cb0ef41Sopenharmony_cilocal block_state deflate_huff(deflate_state *s, int flush) { 21761cb0ef41Sopenharmony_ci int bflush; /* set if current block must be flushed */ 21771cb0ef41Sopenharmony_ci 21781cb0ef41Sopenharmony_ci for (;;) { 21791cb0ef41Sopenharmony_ci /* Make sure that we have a literal to write. */ 21801cb0ef41Sopenharmony_ci if (s->lookahead == 0) { 21811cb0ef41Sopenharmony_ci fill_window(s); 21821cb0ef41Sopenharmony_ci if (s->lookahead == 0) { 21831cb0ef41Sopenharmony_ci if (flush == Z_NO_FLUSH) 21841cb0ef41Sopenharmony_ci return need_more; 21851cb0ef41Sopenharmony_ci break; /* flush the current block */ 21861cb0ef41Sopenharmony_ci } 21871cb0ef41Sopenharmony_ci } 21881cb0ef41Sopenharmony_ci 21891cb0ef41Sopenharmony_ci /* Output a literal byte */ 21901cb0ef41Sopenharmony_ci s->match_length = 0; 21911cb0ef41Sopenharmony_ci Tracevv((stderr,"%c", s->window[s->strstart])); 21921cb0ef41Sopenharmony_ci _tr_tally_lit(s, s->window[s->strstart], bflush); 21931cb0ef41Sopenharmony_ci s->lookahead--; 21941cb0ef41Sopenharmony_ci s->strstart++; 21951cb0ef41Sopenharmony_ci if (bflush) FLUSH_BLOCK(s, 0); 21961cb0ef41Sopenharmony_ci } 21971cb0ef41Sopenharmony_ci s->insert = 0; 21981cb0ef41Sopenharmony_ci if (flush == Z_FINISH) { 21991cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 1); 22001cb0ef41Sopenharmony_ci return finish_done; 22011cb0ef41Sopenharmony_ci } 22021cb0ef41Sopenharmony_ci if (s->sym_next) 22031cb0ef41Sopenharmony_ci FLUSH_BLOCK(s, 0); 22041cb0ef41Sopenharmony_ci return block_done; 22051cb0ef41Sopenharmony_ci} 2206