^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: Zlib
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "../zlib_deflate/defutil.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "dfltcc_util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "dfltcc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/zutil.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Compress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) int dfltcc_can_deflate(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) z_streamp strm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) deflate_state *state = (deflate_state *)strm->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Check for kernel dfltcc command line parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Unsupported compression settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) dfltcc_state->level_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Unsupported hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) EXPORT_SYMBOL(dfltcc_can_deflate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static void dfltcc_gdht(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) z_streamp strm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) deflate_state *state = (deflate_state *)strm->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) size_t avail_in = avail_in = strm->avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) dfltcc(DFLTCC_GDHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) param, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) &strm->next_in, &avail_in, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static dfltcc_cc dfltcc_cmpr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) z_streamp strm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) deflate_state *state = (deflate_state *)strm->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) size_t avail_in = strm->avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) size_t avail_out = strm->avail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dfltcc_cc cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) param, &strm->next_out, &avail_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) &strm->next_in, &avail_in, state->window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) strm->total_in += (strm->avail_in - avail_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) strm->total_out += (strm->avail_out - avail_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) strm->avail_in = avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) strm->avail_out = avail_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void send_eobs(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) z_streamp strm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const struct dfltcc_param_v0 *param
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) deflate_state *state = (deflate_state *)strm->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) zlib_tr_send_bits(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) param->eobl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) flush_pending(strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (state->pending != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* The remaining data is located in pending_out[0:pending]. If someone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * calls put_byte() - this might happen in deflate() - the byte will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * placed into pending_buf[pending], which is incorrect. Move the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * remaining data to the beginning of pending_buf so that put_byte() is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * usable again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memmove(state->pending_buf, state->pending_out, state->pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) state->pending_out = state->pending_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #ifdef ZLIB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) state->compressed_len += param->eobl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int dfltcc_deflate(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) z_streamp strm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) block_state *result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) deflate_state *state = (deflate_state *)strm->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct dfltcc_param_v0 *param = &dfltcc_state->param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) uInt masked_avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dfltcc_cc cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int need_empty_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int soft_bcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int no_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!dfltcc_can_deflate(strm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) masked_avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) soft_bcc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) no_flush = flush == Z_NO_FLUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Trailing empty block. Switch to software, except when Continuation Flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * is set, which means that DFLTCC has buffered some output in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * parameter block and needs to be called again in order to flush it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (param->bcf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* A block is still open, and the hardware does not support closing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * blocks without adding data. Thus, close it manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) send_eobs(strm, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) param->bcf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (strm->avail_in == 0 && !param->cf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *result = need_more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* There is an open non-BFINAL block, we are not going to close it just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * DHT in order to adapt to a possibly changed input data distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (param->bcf && no_flush &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) strm->total_in > dfltcc_state->block_threshold &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) strm->avail_in >= dfltcc_state->dht_threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (param->cf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* We need to flush the DFLTCC buffer before writing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * End-of-block Symbol. Mask the input data and proceed as usual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) masked_avail_in += strm->avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) strm->avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) no_flush = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* DFLTCC buffer is empty, so we can manually write the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * End-of-block Symbol right away.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) send_eobs(strm, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) param->bcf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dfltcc_state->block_threshold =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) strm->total_in + dfltcc_state->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (strm->avail_out == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *result = need_more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* The caller gave us too much data. Pass only one block worth of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * uncompressed data to DFLTCC and mask the rest, so that on the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * iteration we start a new block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (no_flush && strm->avail_in > dfltcc_state->block_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) strm->avail_in = dfltcc_state->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* When we have an open non-BFINAL deflate block and caller indicates that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * the stream is ending, we need to close an open deflate block and open a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * BFINAL one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Translate stream to parameter block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) param->cvt = CVT_ADLER32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!no_flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* We need to close a block. Always do this in software - when there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * no input data, the hardware will not nohor BCC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) soft_bcc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (flush == Z_FINISH && !param->bcf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* We are about to open a BFINAL block, set Block Header Final bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * until the stream ends.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) param->bhf = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * higher precedence are empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) Assert(state->pending == 0, "There must be no pending bytes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) param->sbb = (unsigned int)state->bi_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (param->sbb > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *strm->next_out = (Byte)state->bi_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (param->hl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) param->nt = 0; /* Honor history */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) param->cv = strm->adler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* When opening a block, choose a Huffman-Table Type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!param->bcf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) param->htt = HTT_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) param->htt = HTT_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) dfltcc_gdht(strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* Deflate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) cc = dfltcc_cmpr(strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (strm->avail_in < 4096 && masked_avail_in > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* We are about to call DFLTCC with a small input buffer, which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * inefficient. Since there is masked data, there will be at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * one more DFLTCC call, so skip the current one and make the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * one handle more data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) } while (cc == DFLTCC_CC_AGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* Translate parameter block to stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) state->bi_valid = param->sbb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (state->bi_valid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) state->bi_buf = 0; /* Avoid accessing next_out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) strm->adler = param->cv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Unmask the input data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) strm->avail_in += masked_avail_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) masked_avail_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* If we encounter an error, it means there is a bug in DFLTCC call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Update Block-Continuation Flag. It will be used to check whether to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * GDHT the next time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (cc == DFLTCC_CC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (soft_bcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) send_eobs(strm, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) param->bcf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dfltcc_state->block_threshold =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) strm->total_in + dfltcc_state->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) param->bcf = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (flush == Z_FINISH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (need_empty_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Make the current deflate() call also close the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) bi_windup(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *result = finish_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (flush == Z_FULL_FLUSH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) param->hl = 0; /* Clear history */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *result = flush == Z_NO_FLUSH ? need_more : block_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) param->bcf = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *result = need_more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (strm->avail_in != 0 && strm->avail_out != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) goto again; /* deflate() must use all input or all output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) EXPORT_SYMBOL(dfltcc_deflate);