details for the parameter block (which is allocated alongside zlib-ng
state) and the window (which must be page-aligned).
-Software and hardware deflate window formats don't match, therefore,
-`deflateSetDictionary()` and `deflateGetDictionary()` need special handling,
-which is triggered using `DEFLATE_SET_DICTIONARY_HOOK()` and
-`DEFLATE_GET_DICTIONARY_HOOK()` macros.
+While inflate software and hardware window formats match, this is not
+the case for deflate. Therefore, `deflateSetDictionary()` and
+`deflateGetDictionary()` need special handling, which is triggered using
+`DEFLATE_SET_DICTIONARY_HOOK()` and `DEFLATE_GET_DICTIONARY_HOOK()`
+macros.
`deflateResetKeep()` and `inflateResetKeep()` update the DFLTCC
parameter block using `DEFLATE_RESET_KEEP_HOOK()` and
return the correct results for the hardware implementation.
Actual compression and decompression are handled by `DEFLATE_HOOK()` and
-`INFLATE_TYPEDO_HOOK()` macros.
-
-Software and hardware inflate window formats don't match, therefore,
-`inflateSetDictionary()` and `inflateGetDictionary()` need special handling,
-which is triggered using `INFLATE_SET_DICTIONARY_HOOK()` and
-`INFLATE_GET_DICTIONARY_HOOK()` macros. Furthermore, calling
-`window_output_flush()` is suppressed using
-`INFLATE_NEED_WINDOW_OUTPUT_FLUSH()` macro.
+`INFLATE_TYPEDO_HOOK()` macros. Since inflation with DFLTCC manages the
+window on its own, calling `updatewindow()` is suppressed using
+`INFLATE_NEED_UPDATEWINDOW()` macro.
In addition to compression, DFLTCC computes CRC-32 and Adler-32
checksums, therefore, whenever it's used, software checksumming is
return reproducible != state->reproducible && !dfltcc_was_deflate_used(strm);
}
+/*
+ Preloading history.
+*/
+static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count) {
+ size_t offset;
+ size_t n;
+
+ /* Do not use more than 32K */
+ if (count > HB_SIZE) {
+ buf += count - HB_SIZE;
+ count = HB_SIZE;
+ }
+ offset = (param->ho + param->hl) % HB_SIZE;
+ if (offset + count <= HB_SIZE)
+ /* Circular history buffer does not wrap - copy one chunk */
+ memcpy(history + offset, buf, count);
+ else {
+ /* Circular history buffer wraps - copy two chunks */
+ n = HB_SIZE - offset;
+ memcpy(history + offset, buf, n);
+ memcpy(history, buf + n, count - n);
+ }
+ n = param->hl + count;
+ if (n <= HB_SIZE)
+ /* All history fits into buffer - no need to discard anything */
+ param->hl = n;
+ else {
+ /* History does not fit into buffer - discard extra bytes */
+ param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE;
+ param->hl = HB_SIZE;
+ }
+}
+
int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm,
const unsigned char *dictionary, uInt dict_length) {
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
struct dfltcc_param_v0 *param = &dfltcc_state->param;
- dfltcc_append_history(param, state->window, dictionary, dict_length);
+ append_history(param, state->window, dictionary, dict_length);
state->strstart = 1; /* Add FDICT to zlib header */
state->block_start = state->strstart; /* Make deflate_stored happy */
return Z_OK;
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
struct dfltcc_param_v0 *param = &dfltcc_state->param;
- dfltcc_get_history(param, state->window, dictionary, dict_length);
+ if (dictionary) {
+ if (param->ho + param->hl <= HB_SIZE)
+ /* Circular history buffer does not wrap - copy one chunk */
+ memcpy(dictionary, state->window + param->ho, param->hl);
+ else {
+ /* Circular history buffer wraps - copy two chunks */
+ memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho);
+ memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE);
+ }
+ }
+ if (dict_length)
+ *dict_length = param->hl;
return Z_OK;
}
#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8)))
-
-static inline void dfltcc_get_history(struct dfltcc_param_v0 *param, const unsigned char *history,
- unsigned char *buf, uInt *count) {
- if (buf) {
- if (param->ho + param->hl <= HB_SIZE)
- /* Circular history buffer does not wrap - copy one chunk */
- memcpy(buf, history + param->ho, param->hl);
- else {
- /* Circular history buffer wraps - copy two chunks */
- memcpy(buf, history + param->ho, HB_SIZE - param->ho);
- memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE);
- }
- }
- if (count)
- *count = param->hl;
-}
-
-static inline void dfltcc_append_history(struct dfltcc_param_v0 *param, unsigned char *history,
- const unsigned char *buf, uInt count) {
- size_t offset;
- size_t n;
-
- /* Do not use more than 32K */
- if (count > HB_SIZE) {
- buf += count - HB_SIZE;
- count = HB_SIZE;
- }
- offset = (param->ho + param->hl) % HB_SIZE;
- if (offset + count <= HB_SIZE)
- /* Circular history buffer does not wrap - copy one chunk */
- memcpy(history + offset, buf, count);
- else {
- /* Circular history buffer wraps - copy two chunks */
- n = HB_SIZE - offset;
- memcpy(history + offset, buf, n);
- memcpy(history, buf + n, count - n);
- }
- n = param->hl + count;
- if (n <= HB_SIZE)
- /* All history fits into buffer - no need to discard anything */
- param->hl = n;
- else {
- /* History does not fit into buffer - discard extra bytes */
- param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE;
- param->hl = HB_SIZE;
- }
-}
/* Translate stream to parameter block */
param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32;
param->sbb = state->bits;
+ param->hl = state->whave; /* Software and hardware history formats match */
+ param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1);
if (param->hl)
param->nt = 0; /* Honor history for the first block */
param->cv = state->flags ? ZSWAP32(state->check) : state->check;
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
state->last = cc == DFLTCC_CC_OK;
state->bits = param->sbb;
+ state->whave = param->hl;
+ state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
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 */
int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) {
struct inflate_state *state = (struct inflate_state *)strm->state;
struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
- struct dfltcc_param_v0 *param = &dfltcc_state->param;
- uInt count;
if (!dfltcc_can_inflate(strm))
return 0;
return 1;
/* DFLTCC was not used yet - decompress in software */
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
- /* Convert window from hardware to software format. Use its second part as scratch space. */
- dfltcc_get_history(param, state->window, state->window + state->wsize, &count);
- state->whave = count;
- state->wnext = 0;
- memcpy(state->window + state->wsize - state->whave, state->window + state->wsize, state->whave);
return 0;
}
-
-int Z_INTERNAL 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_state *dfltcc_state = GET_DFLTCC_STATE(state);
- struct dfltcc_param_v0 *param = &dfltcc_state->param;
-
- dfltcc_append_history(param, state->window, dictionary, dict_length);
- state->havedict = 1;
- return Z_OK;
-}
-
-int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) {
- struct inflate_state *state = (struct inflate_state *)strm->state;
- struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
- struct dfltcc_param_v0 *param = &dfltcc_state->param;
-
- dfltcc_get_history(param, state->window, dictionary, dict_length);
- return Z_OK;
-}
dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret);
int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm);
int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm);
-int Z_INTERNAL dfltcc_inflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length);
-int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length);
#define INFLATE_RESET_KEEP_HOOK(strm) \
dfltcc_reset((strm), sizeof(struct inflate_state))
#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
-#define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) (!dfltcc_can_inflate((strm)))
+#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
#define INFLATE_MARK_HOOK(strm) \
do { \
if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \
} while (0)
-#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \
- do { \
- if (dfltcc_can_inflate((strm))) \
- return dfltcc_inflate_set_dictionary((strm), (dict), (dict_len)); \
- } while (0)
-
-#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \
- do { \
- if (dfltcc_can_inflate((strm))) \
- return dfltcc_inflate_get_dictionary((strm), (dict), (dict_len)); \
- } while (0)
-
#endif
break;
case CHECK:
- if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm)) {
- RESTORE();
- window_output_flush(strm);
- LOAD();
- if (strm->avail_out == 0 && state->wnext)
- goto inf_leave;
- }
+ RESTORE();
+ window_output_flush(strm);
+ LOAD();
+ if (strm->avail_out == 0 && state->wnext)
+ goto inf_leave;
if (state->wrap) {
NEEDBITS(32);
out -= left;
inf_leave:
RESTORE();
- if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) && strm->avail_out && state->wnext)
+ if (strm->avail_out && state->wnext)
window_output_flush(strm);
in -= strm->avail_in;
/* check state */
if (inflateStateCheck(strm))
return Z_STREAM_ERROR;
- INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */
state = (struct inflate_state *)strm->state;
/* copy dictionary */
- if (state->whave && dictionary != NULL)
- memcpy(dictionary, state->window + state->wsize - state->whave, state->whave);
+ if (state->whave && dictionary != NULL) {
+ memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext);
+ memcpy(dictionary + state->whave - state->wnext, state->window, state->wnext);
+ }
if (dictLength != NULL)
*dictLength = state->whave;
return Z_OK;
int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) {
struct inflate_state *state;
unsigned long dictid, dict_copy, hist_copy;
- const unsigned char *dict_from;
+ const unsigned char *dict_from, *hist_from;
unsigned char *dict_to, *hist_to;
int ret;
Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output"));
- INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */
-
/* copy dictionary to window and amend if necessary */
dict_from = dictionary;
dict_copy = dictLength;
}
dict_to = state->window + state->wsize - dict_copy;
+ hist_from = state->window + state->wsize - state->whave;
hist_copy = state->wsize - dict_copy;
if (hist_copy > state->whave)
hist_copy = state->whave;
hist_to = dict_to - hist_copy;
if (hist_copy)
- memcpy(hist_to, state->window + state->wsize - hist_copy, hist_copy);
+ memcpy(hist_to, hist_from, hist_copy);
if (dict_copy)
memcpy(dict_to, dict_from, dict_copy);
# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */
# define INFLATE_NEED_CHECKSUM(strm) 1
-/* Returns whether zlib-ng should flush the window to the output buffer.
- Set to 0 if arch-specific inflation code already does that. */
-# define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) 1
+/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */
+# define INFLATE_NEED_UPDATEWINDOW(strm) 1
/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */
# define INFLATE_MARK_HOOK(strm) do {} while (0)
/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */
# define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
-/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */
-# define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
-/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */
-# define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
#endif