mirror of
https://github.com/opencv/opencv.git
synced 2024-12-16 02:19:12 +08:00
192 lines
6.2 KiB
C
192 lines
6.2 KiB
C
|
/* dfltcc_inflate.c - IBM Z DEFLATE CONVERSION CALL decompression support. */
|
||
|
|
||
|
/*
|
||
|
Use the following commands to build zlib-ng with DFLTCC decompression support:
|
||
|
|
||
|
$ ./configure --with-dfltcc-inflate
|
||
|
or
|
||
|
|
||
|
$ cmake -DWITH_DFLTCC_INFLATE=1 .
|
||
|
|
||
|
and then
|
||
|
|
||
|
$ make
|
||
|
*/
|
||
|
|
||
|
#include "zbuild.h"
|
||
|
#include "zutil.h"
|
||
|
#include "inftrees.h"
|
||
|
#include "inflate.h"
|
||
|
#include "dfltcc_inflate.h"
|
||
|
#include "dfltcc_detail.h"
|
||
|
|
||
|
void Z_INTERNAL PREFIX(dfltcc_reset_inflate_state)(PREFIX3(streamp) strm) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
|
||
|
dfltcc_reset_state(&state->arch.common);
|
||
|
}
|
||
|
|
||
|
int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_state *dfltcc_state = &state->arch.common;
|
||
|
|
||
|
/* Unsupported hardware */
|
||
|
return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
|
||
|
}
|
||
|
|
||
|
static inline dfltcc_cc dfltcc_xpnd(PREFIX3(streamp) strm) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_param_v0 *param = &state->arch.common.param;
|
||
|
size_t avail_in = strm->avail_in;
|
||
|
size_t avail_out = strm->avail_out;
|
||
|
dfltcc_cc cc;
|
||
|
|
||
|
cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
|
||
|
param, &strm->next_out, &avail_out,
|
||
|
&strm->next_in, &avail_in, state->window);
|
||
|
strm->avail_in = avail_in;
|
||
|
strm->avail_out = avail_out;
|
||
|
return cc;
|
||
|
}
|
||
|
|
||
|
dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, int flush, int *ret) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_state *dfltcc_state = &state->arch.common;
|
||
|
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||
|
dfltcc_cc cc;
|
||
|
|
||
|
if (flush == Z_BLOCK || flush == Z_TREES) {
|
||
|
/* DFLTCC does not support stopping on block boundaries */
|
||
|
if (PREFIX(dfltcc_inflate_disable)(strm)) {
|
||
|
*ret = Z_STREAM_ERROR;
|
||
|
return DFLTCC_INFLATE_BREAK;
|
||
|
} else
|
||
|
return DFLTCC_INFLATE_SOFTWARE;
|
||
|
}
|
||
|
|
||
|
if (state->last) {
|
||
|
if (state->bits != 0) {
|
||
|
strm->next_in++;
|
||
|
strm->avail_in--;
|
||
|
state->bits = 0;
|
||
|
}
|
||
|
state->mode = CHECK;
|
||
|
return DFLTCC_INFLATE_CONTINUE;
|
||
|
}
|
||
|
|
||
|
if (strm->avail_in == 0 && !param->cf)
|
||
|
return DFLTCC_INFLATE_BREAK;
|
||
|
|
||
|
/* if window not in use yet, initialize */
|
||
|
if (state->wsize == 0)
|
||
|
state->wsize = 1U << state->wbits;
|
||
|
|
||
|
/* Translate stream to parameter block */
|
||
|
param->cvt = ((state->wrap & 4) && state->flags) ? CVT_CRC32 : CVT_ADLER32;
|
||
|
param->sbb = state->bits;
|
||
|
if (param->hl)
|
||
|
param->nt = 0; /* Honor history for the first block */
|
||
|
if (state->wrap & 4)
|
||
|
param->cv = state->flags ? ZSWAP32(state->check) : state->check;
|
||
|
|
||
|
/* Inflate */
|
||
|
do {
|
||
|
cc = dfltcc_xpnd(strm);
|
||
|
} while (cc == DFLTCC_CC_AGAIN);
|
||
|
|
||
|
/* Translate parameter block to stream */
|
||
|
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
|
||
|
state->last = cc == DFLTCC_CC_OK;
|
||
|
state->bits = param->sbb;
|
||
|
if (state->wrap & 4)
|
||
|
strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv;
|
||
|
if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
|
||
|
/* Report an error if stream is corrupted */
|
||
|
state->mode = BAD;
|
||
|
return DFLTCC_INFLATE_CONTINUE;
|
||
|
}
|
||
|
state->mode = TYPEDO;
|
||
|
/* Break if operands are exhausted, otherwise continue looping */
|
||
|
return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
|
||
|
DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
|
||
|
}
|
||
|
|
||
|
int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
|
||
|
return !state->arch.common.param.nt;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Rotates a circular buffer.
|
||
|
The implementation is based on https://cplusplus.com/reference/algorithm/rotate/
|
||
|
*/
|
||
|
static void rotate(unsigned char *start, unsigned char *pivot, unsigned char *end) {
|
||
|
unsigned char *p = pivot;
|
||
|
unsigned char tmp;
|
||
|
|
||
|
while (p != start) {
|
||
|
tmp = *start;
|
||
|
*start = *p;
|
||
|
*p = tmp;
|
||
|
|
||
|
start++;
|
||
|
p++;
|
||
|
|
||
|
if (p == end)
|
||
|
p = pivot;
|
||
|
else if (start == pivot)
|
||
|
pivot = p;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_state *dfltcc_state = &state->arch.common;
|
||
|
struct dfltcc_param_v0 *param = &dfltcc_state->param;
|
||
|
|
||
|
if (!PREFIX(dfltcc_can_inflate)(strm))
|
||
|
return 0;
|
||
|
if (PREFIX(dfltcc_was_inflate_used)(strm))
|
||
|
/* DFLTCC has already decompressed some data. Since there is not
|
||
|
* enough information to resume decompression in software, the call
|
||
|
* must fail.
|
||
|
*/
|
||
|
return 1;
|
||
|
/* DFLTCC was not used yet - decompress in software */
|
||
|
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
|
||
|
/* Convert the window from the hardware to the software format */
|
||
|
rotate(state->window, state->window + param->ho, state->window + HB_SIZE);
|
||
|
state->whave = state->wnext = MIN(param->hl, state->wsize);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Preloading history.
|
||
|
*/
|
||
|
int Z_INTERNAL PREFIX(dfltcc_inflate_set_dictionary)(PREFIX3(streamp) strm,
|
||
|
const unsigned char *dictionary, uInt dict_length) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_param_v0 *param = &state->arch.common.param;
|
||
|
|
||
|
/* if window not in use yet, initialize */
|
||
|
if (state->wsize == 0)
|
||
|
state->wsize = 1U << state->wbits;
|
||
|
|
||
|
append_history(param, state->window, dictionary, dict_length);
|
||
|
state->havedict = 1;
|
||
|
return Z_OK;
|
||
|
}
|
||
|
|
||
|
int Z_INTERNAL PREFIX(dfltcc_inflate_get_dictionary)(PREFIX3(streamp) strm,
|
||
|
unsigned char *dictionary, uInt *dict_length) {
|
||
|
struct inflate_state *state = (struct inflate_state *)strm->state;
|
||
|
struct dfltcc_param_v0 *param = &state->arch.common.param;
|
||
|
|
||
|
if (dictionary && state->window)
|
||
|
get_history(param, state->window, dictionary);
|
||
|
if (dict_length)
|
||
|
*dict_length = param->hl;
|
||
|
return Z_OK;
|
||
|
}
|