You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
11 KiB
299 lines
11 KiB
--- a/contrib/s390/dfltcc.c |
|
+++ b/contrib/s390/dfltcc.c |
|
@@ -539,10 +539,6 @@ int ZLIB_INTERNAL dfltcc_can_inflate(strm) |
|
struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state; |
|
struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); |
|
|
|
- /* Unsupported compression settings */ |
|
- if (state->wbits != HB_BITS) |
|
- return 0; |
|
- |
|
/* Unsupported hardware */ |
|
return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && |
|
is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); |
|
@@ -606,8 +602,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret) |
|
/* 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; |
|
@@ -621,8 +615,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret) |
|
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); |
|
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 */ |
|
@@ -644,11 +636,52 @@ int ZLIB_INTERNAL dfltcc_was_inflate_used(strm) |
|
return !param->nt; |
|
} |
|
|
|
+/* |
|
+ Rotates a circular buffer. |
|
+ The implementation is based on https://cplusplus.com/reference/algorithm/rotate/ |
|
+ */ |
|
+local void rotate OF((Bytef *start, Bytef *pivot, Bytef *end)); |
|
+local void rotate(start, pivot, end) |
|
+ Bytef *start; |
|
+ Bytef *pivot; |
|
+ Bytef *end; |
|
+{ |
|
+ Bytef *p = pivot; |
|
+ Bytef tmp; |
|
+ |
|
+ while (p != start) { |
|
+ tmp = *start; |
|
+ *start = *p; |
|
+ *p = tmp; |
|
+ |
|
+ start++; |
|
+ p++; |
|
+ |
|
+ if (p == end) |
|
+ p = pivot; |
|
+ else if (start == pivot) |
|
+ pivot = p; |
|
+ } |
|
+} |
|
+ |
|
+#define MIN(x, y) ({ \ |
|
+ typeof(x) _x = (x); \ |
|
+ typeof(y) _y = (y); \ |
|
+ _x < _y ? _x : _y; \ |
|
+}) |
|
+ |
|
+#define MAX(x, y) ({ \ |
|
+ typeof(x) _x = (x); \ |
|
+ typeof(y) _y = (y); \ |
|
+ _x > _y ? _x : _y; \ |
|
+}) |
|
+ |
|
int ZLIB_INTERNAL dfltcc_inflate_disable(strm) |
|
z_streamp strm; |
|
{ |
|
struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state; |
|
struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); |
|
+ struct dfltcc_param_v0 *param = &dfltcc_state->param; |
|
|
|
if (!dfltcc_can_inflate(strm)) |
|
return 0; |
|
@@ -660,6 +693,9 @@ int ZLIB_INTERNAL dfltcc_inflate_disable(strm) |
|
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; |
|
} |
|
|
|
@@ -830,9 +866,9 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size) |
|
voidpf p, w; |
|
|
|
/* To simplify freeing, we store the pointer to the allocated buffer right |
|
- * before the window. |
|
+ * before the window. Note that DFLTCC always uses HB_SIZE bytes. |
|
*/ |
|
- p = ZALLOC(strm, sizeof(voidpf) + items * size + PAGE_ALIGN, |
|
+ p = ZALLOC(strm, sizeof(voidpf) + MAX(items * size, HB_SIZE) + PAGE_ALIGN, |
|
sizeof(unsigned char)); |
|
if (p == NULL) |
|
return NULL; |
|
@@ -841,6 +877,14 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size) |
|
return w; |
|
} |
|
|
|
+void ZLIB_INTERNAL dfltcc_copy_window(dest, src, n) |
|
+ void *dest; |
|
+ const void *src; |
|
+ size_t n; |
|
+{ |
|
+ memcpy(dest, src, MAX(n, HB_SIZE)); |
|
+} |
|
+ |
|
void ZLIB_INTERNAL dfltcc_free_window(strm, w) |
|
z_streamp strm; |
|
voidpf w; |
|
@@ -951,6 +995,24 @@ local void append_history(param, history, buf, count) |
|
} |
|
} |
|
|
|
+local void get_history OF((struct dfltcc_param_v0 FAR *param, |
|
+ const Bytef *history, |
|
+ Bytef *buf)); |
|
+local void get_history(param, history, buf) |
|
+ struct dfltcc_param_v0 FAR *param; |
|
+ const Bytef *history; |
|
+ Bytef *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); |
|
+ } |
|
+} |
|
+ |
|
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(strm, dictionary, dict_length) |
|
z_streamp strm; |
|
const Bytef *dictionary; |
|
@@ -975,20 +1037,43 @@ int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(strm, dictionary, dict_length) |
|
struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); |
|
struct dfltcc_param_v0 FAR *param = &dfltcc_state->param; |
|
|
|
- if (dictionary) { |
|
- if (param->ho + param->hl <= HB_SIZE) |
|
- /* Circular history buffer does not wrap - copy one chunk */ |
|
- zmemcpy(dictionary, state->window + param->ho, param->hl); |
|
- else { |
|
- /* Circular history buffer wraps - copy two chunks */ |
|
- zmemcpy(dictionary, |
|
- state->window + param->ho, |
|
- HB_SIZE - param->ho); |
|
- zmemcpy(dictionary + HB_SIZE - param->ho, |
|
- state->window, |
|
- param->ho + param->hl - HB_SIZE); |
|
- } |
|
+ if (dictionary) |
|
+ get_history(param, state->window, dictionary); |
|
+ if (dict_length) |
|
+ *dict_length = param->hl; |
|
+ return Z_OK; |
|
+} |
|
+ |
|
+int ZLIB_INTERNAL dfltcc_inflate_set_dictionary(strm, dictionary, dict_length) |
|
+ z_streamp strm; |
|
+ const Bytef *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; |
|
+ |
|
+ if (inflate_ensure_window(state)) { |
|
+ state->mode = MEM; |
|
+ return Z_MEM_ERROR; |
|
} |
|
+ |
|
+ append_history(param, state->window, dictionary, dict_length); |
|
+ state->havedict = 1; |
|
+ return Z_OK; |
|
+} |
|
+ |
|
+int ZLIB_INTERNAL dfltcc_inflate_get_dictionary(strm, dictionary, dict_length) |
|
+ z_streamp strm; |
|
+ Bytef *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; |
|
+ |
|
+ if (dictionary && state->window) |
|
+ get_history(param, state->window, dictionary); |
|
if (dict_length) |
|
*dict_length = param->hl; |
|
return Z_OK; |
|
--- a/contrib/s390/dfltcc.h |
|
+++ b/contrib/s390/dfltcc.h |
|
@@ -11,6 +11,8 @@ void ZLIB_INTERNAL dfltcc_copy_state OF((voidpf dst, const voidpf src, |
|
void ZLIB_INTERNAL dfltcc_reset OF((z_streamp strm, uInt size)); |
|
voidpf ZLIB_INTERNAL dfltcc_alloc_window OF((z_streamp strm, uInt items, |
|
uInt size)); |
|
+void ZLIB_INTERNAL dfltcc_copy_window OF((void *dest, const void *src, |
|
+ size_t n)); |
|
void ZLIB_INTERNAL dfltcc_free_window OF((z_streamp strm, voidpf w)); |
|
#define DFLTCC_BLOCK_HEADER_BITS 3 |
|
#define DFLTCC_HLITS_COUNT_BITS 5 |
|
@@ -44,11 +46,18 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate OF((z_streamp strm, |
|
int flush, int *ret)); |
|
int ZLIB_INTERNAL dfltcc_was_inflate_used OF((z_streamp strm)); |
|
int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm)); |
|
+int ZLIB_INTERNAL dfltcc_inflate_set_dictionary OF((z_streamp strm, |
|
+ const Bytef *dictionary, |
|
+ uInt dict_length)); |
|
+int ZLIB_INTERNAL dfltcc_inflate_get_dictionary OF((z_streamp strm, |
|
+ Bytef *dictionary, |
|
+ uInt* dict_length)); |
|
|
|
#define ZALLOC_STATE dfltcc_alloc_state |
|
#define ZFREE_STATE ZFREE |
|
#define ZCOPY_STATE dfltcc_copy_state |
|
#define ZALLOC_WINDOW dfltcc_alloc_window |
|
+#define ZCOPY_WINDOW dfltcc_copy_window |
|
#define ZFREE_WINDOW dfltcc_free_window |
|
#define TRY_FREE_WINDOW dfltcc_free_window |
|
#define INFLATE_RESET_KEEP_HOOK(strm) \ |
|
@@ -77,5 +86,15 @@ int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp 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 |
|
\ No newline at end of file |
|
diff --git a/inflate.c b/inflate.c |
|
index 3750152..a0e2169 100644 |
|
--- a/inflate.c |
|
+++ b/inflate.c |
|
@@ -93,6 +93,7 @@ |
|
#define ZFREE_STATE ZFREE |
|
#define ZCOPY_STATE zmemcpy |
|
#define ZALLOC_WINDOW ZALLOC |
|
+#define ZCOPY_WINDOW zmemcpy |
|
#define ZFREE_WINDOW ZFREE |
|
#define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) |
|
#define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) |
|
@@ -101,6 +102,8 @@ |
|
#define INFLATE_NEED_UPDATEWINDOW(strm) 1 |
|
#define INFLATE_MARK_HOOK(strm) do {} while (0) |
|
#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) |
|
+#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) |
|
+#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) |
|
#endif |
|
|
|
#ifdef MAKEFIXED |
|
@@ -1330,6 +1333,8 @@ uInt *dictLength; |
|
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; |
|
state = (struct inflate_state FAR *)strm->state; |
|
|
|
+ INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); |
|
+ |
|
/* copy dictionary */ |
|
if (state->whave && dictionary != Z_NULL) { |
|
zmemcpy(dictionary, state->window + state->wnext, |
|
@@ -1365,6 +1370,8 @@ uInt dictLength; |
|
return Z_DATA_ERROR; |
|
} |
|
|
|
+ INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); |
|
+ |
|
/* copy dictionary to window using updatewindow(), which will amend the |
|
existing dictionary if appropriate */ |
|
ret = updatewindow(strm, dictionary + dictLength, dictLength); |
|
@@ -1529,8 +1536,7 @@ z_streamp source; |
|
} |
|
copy->next = copy->codes + (state->next - state->codes); |
|
if (window != Z_NULL) { |
|
- wsize = 1U << state->wbits; |
|
- zmemcpy(window, state->window, wsize); |
|
+ ZCOPY_WINDOW(window, state->window, 1U << state->wbits); |
|
} |
|
copy->window = window; |
|
dest->state = (struct internal_state FAR *)copy;
|
|
|