igzip: Add stateful dictionary support
Change-Id: I75dbac947787bc0041674468c88d0aa41b8b082f Signed-off-by: Roy Oursler <roy.j.oursler@intel.com>
This commit is contained in:
parent
82a6ac65dc
commit
ed15402f5b
@ -59,7 +59,8 @@ lsrc_x86_64 += \
|
||||
igzip/igzip_inflate_multibinary.asm \
|
||||
igzip/encode_df_04.asm \
|
||||
igzip/encode_df_06.asm \
|
||||
igzip/proc_heap.asm
|
||||
igzip/proc_heap.asm \
|
||||
igzip/igzip_deflate_hash.asm
|
||||
|
||||
src_include += -I $(srcdir)/igzip
|
||||
extern_hdrs += include/igzip_lib.h
|
||||
|
@ -222,4 +222,10 @@ _STORED_BLK equ 0
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
IGZIP_NO_HIST equ 0
|
||||
IGZIP_HIST equ 1
|
||||
IGZIP_DICT_HIST equ 2
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -66,6 +66,7 @@
|
||||
# define to_be32(x) _byteswap_ulong(x)
|
||||
#endif
|
||||
|
||||
extern void isal_deflate_hash_lvl0(struct isal_zstream *stream, uint8_t * dict, int dict_len);
|
||||
extern const uint8_t gzip_hdr[];
|
||||
extern const uint32_t gzip_hdr_bytes;
|
||||
extern const uint32_t gzip_trl_bytes;
|
||||
@ -125,6 +126,9 @@ struct slver isal_deflate_stateless_slver = { 0x0083, 0x01, 0x01 };
|
||||
struct slver isal_deflate_set_hufftables_slver_00_01_008b;
|
||||
struct slver isal_deflate_set_hufftables_slver = { 0x008b, 0x01, 0x00 };
|
||||
|
||||
struct slver isal_deflate_set_dict_slver_00_01_008c;
|
||||
struct slver isal_deflate_set_dict_slver = { 0x008c, 0x01, 0x00 };
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
// isal_adler32_bam1 - adler with (B | A minus 1) storage
|
||||
@ -188,7 +192,7 @@ void sync_flush(struct isal_zstream *stream)
|
||||
if (stream->flush == FULL_FLUSH) {
|
||||
/* Clear match history so there are no cross
|
||||
* block length distance pairs */
|
||||
reset_match_history(stream);
|
||||
state->has_hist = IGZIP_NO_HIST;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -757,7 +761,7 @@ static inline void reset_match_history(struct isal_zstream *stream)
|
||||
uint16_t *head = stream->internal_state.head;
|
||||
int i = 0;
|
||||
|
||||
state->has_hist = 0;
|
||||
state->has_hist = IGZIP_NO_HIST;
|
||||
|
||||
if ((stream->total_in & 0xFFFF) == 0)
|
||||
memset(stream->internal_state.head, 0, sizeof(stream->internal_state.head));
|
||||
@ -786,21 +790,17 @@ void isal_deflate_init(struct isal_zstream *stream)
|
||||
state->b_bytes_processed = 0;
|
||||
state->has_eob = 0;
|
||||
state->has_eob_hdr = 0;
|
||||
state->has_hist = 0;
|
||||
state->has_hist = IGZIP_NO_HIST;
|
||||
state->state = ZSTATE_NEW_HDR;
|
||||
state->count = 0;
|
||||
|
||||
state->tmp_out_start = 0;
|
||||
state->tmp_out_end = 0;
|
||||
|
||||
state->file_start = stream->next_in;
|
||||
|
||||
init(&state->bitbuf);
|
||||
|
||||
state->crc = 0;
|
||||
|
||||
memset(state->head, 0, sizeof(state->head));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -844,6 +844,40 @@ void isal_deflate_stateless_init(struct isal_zstream *stream)
|
||||
return;
|
||||
}
|
||||
|
||||
void isal_deflate_hash(struct isal_zstream *stream, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
isal_deflate_hash_lvl0(stream, dict, dict_len);
|
||||
stream->internal_state.has_hist = IGZIP_HIST;
|
||||
}
|
||||
|
||||
int isal_deflate_set_dict(struct isal_zstream *stream, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
struct isal_zstate *state = &stream->internal_state;
|
||||
|
||||
if (state->state != ZSTATE_NEW_HDR || state->b_bytes_processed != state->b_bytes_valid)
|
||||
return ISAL_INVALID_STATE;
|
||||
|
||||
if (dict_len <= 0)
|
||||
return COMP_OK;
|
||||
|
||||
if (dict_len > IGZIP_HIST_SIZE) {
|
||||
dict = dict + dict_len - IGZIP_HIST_SIZE;
|
||||
dict_len = IGZIP_HIST_SIZE;
|
||||
}
|
||||
|
||||
memcpy(state->buffer, dict, dict_len);
|
||||
state->b_bytes_processed = dict_len;
|
||||
state->b_bytes_valid = dict_len;
|
||||
|
||||
/* Reset history to prevent out of bounds matches this works because
|
||||
* dictionary must set at least 1 element in the history */
|
||||
memset(stream->internal_state.head, -1, sizeof(stream->internal_state.head));
|
||||
|
||||
state->has_hist = IGZIP_DICT_HIST;
|
||||
|
||||
return COMP_OK;
|
||||
}
|
||||
|
||||
int isal_deflate_stateless(struct isal_zstream *stream)
|
||||
{
|
||||
uint8_t *next_in = stream->next_in;
|
||||
@ -963,6 +997,11 @@ int isal_deflate(struct isal_zstream *stream)
|
||||
avail_in = stream->avail_in;
|
||||
stream->total_in -= state->b_bytes_valid - state->b_bytes_processed;
|
||||
|
||||
if (state->has_hist == IGZIP_NO_HIST)
|
||||
reset_match_history(stream);
|
||||
else if (state->has_hist == IGZIP_DICT_HIST)
|
||||
isal_deflate_hash(stream, state->buffer, state->b_bytes_processed);
|
||||
|
||||
do {
|
||||
size = avail_in;
|
||||
if (size > sizeof(state->buffer) - state->b_bytes_valid) {
|
||||
|
@ -208,3 +208,22 @@ void isal_deflate_finish_base(struct isal_zstream *stream)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void isal_deflate_hash_lvl0_base(struct isal_zstream *stream, uint8_t * dict,
|
||||
uint32_t dict_len)
|
||||
{
|
||||
uint8_t *next_in = dict;
|
||||
uint8_t *end_in = dict + dict_len - SHORTEST_MATCH;
|
||||
uint32_t literal;
|
||||
uint32_t hash;
|
||||
uint16_t lookup_val = stream->total_in - dict_len;
|
||||
uint16_t *last_seen = stream->internal_state.head;
|
||||
|
||||
while (next_in <= end_in) {
|
||||
literal = *(uint32_t *) next_in;
|
||||
hash = compute_hash(literal) & HASH_MASK;
|
||||
last_seen[hash] = lookup_val;
|
||||
lookup_val++;
|
||||
next_in++;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ struct deflate_icf *encode_deflate_icf_base(struct deflate_icf *next_in,
|
||||
uint32_t crc32_gzip_base(uint32_t init_crc, const unsigned char *buf, uint64_t len);
|
||||
uint32_t adler32_base(uint32_t init, const unsigned char *buf, uint64_t len);
|
||||
int decode_huffman_code_block_stateless_base(struct inflate_state *s);
|
||||
void isal_deflate_hash_lvl0_base(struct isal_zstream *stream, uint8_t * dict,
|
||||
uint32_t dict_len);
|
||||
|
||||
void isal_deflate_body(struct isal_zstream *stream)
|
||||
{
|
||||
@ -91,3 +93,8 @@ int decode_huffman_code_block_stateless(struct inflate_state *s)
|
||||
{
|
||||
return decode_huffman_code_block_stateless_base(s);
|
||||
}
|
||||
|
||||
void isal_deflate_hash_lvl0(struct isal_zstream *stream, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
return isal_deflate_hash_lvl0_base(stream, dict, dict_len);
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ MARK __body_compute_hash_ %+ ARCH
|
||||
and hash, HASH_MASK
|
||||
and hash2, HASH_MASK
|
||||
|
||||
cmp dword [stream + _internal_state_has_hist], 0
|
||||
cmp dword [stream + _internal_state_has_hist], IGZIP_NO_HIST
|
||||
je write_first_byte
|
||||
|
||||
jmp loop2
|
||||
@ -545,7 +545,7 @@ write_first_byte:
|
||||
cmp m_out_buf, [stream + _internal_state_bitbuf_m_out_end]
|
||||
ja output_end
|
||||
|
||||
mov dword [stream + _internal_state_has_hist], 1
|
||||
mov dword [stream + _internal_state_has_hist], IGZIP_HIST
|
||||
|
||||
mov [stream + _internal_state_head + 2 * hash], f_i %+ w
|
||||
|
||||
|
@ -363,6 +363,7 @@ decode_huffman_code_block_stateless_ %+ ARCH %+ :
|
||||
mov dword [state + _copy_overflow_dist], 0
|
||||
|
||||
mov tmp3 %+ d, dword [state + _total_out]
|
||||
add tmp3 %+ d, dword [state + _dict_length]
|
||||
sub tmp3, next_out
|
||||
neg tmp3
|
||||
|
||||
@ -658,6 +659,7 @@ end:
|
||||
sub end_out, next_out
|
||||
mov dword [state + _avail_out], end_out %+ d
|
||||
sub next_out, [rsp + start_out_mem_offset]
|
||||
sub next_out %+ d, [state + _dict_length]
|
||||
mov [state + _total_out], next_out %+ d
|
||||
mov [state + _next_in], next_in
|
||||
sub end_in, next_in
|
||||
|
61
igzip/igzip_deflate_hash.asm
Normal file
61
igzip/igzip_deflate_hash.asm
Normal file
@ -0,0 +1,61 @@
|
||||
%include "options.asm"
|
||||
%include "lz0a_const.asm"
|
||||
%include "data_struct2.asm"
|
||||
%include "huffman.asm"
|
||||
%include "reg_sizes.asm"
|
||||
|
||||
%define DICT_SLOP 4
|
||||
|
||||
%ifidn __OUTPUT_FORMAT__, win64
|
||||
%define arg1 rcx
|
||||
%define arg2 rdx
|
||||
%define arg3 r8
|
||||
%else
|
||||
%define arg1 rdi
|
||||
%define arg2 rsi
|
||||
%define arg3 rdx
|
||||
%endif
|
||||
|
||||
%define stream arg1
|
||||
|
||||
%define dict_offset arg2
|
||||
|
||||
%define dict_len arg3
|
||||
%define f_i arg3
|
||||
|
||||
%define data r9
|
||||
|
||||
%define hash r10
|
||||
|
||||
%define f_i_end r11
|
||||
|
||||
global isal_deflate_hash_lvl0_01
|
||||
isal_deflate_hash_lvl0_01:
|
||||
%ifnidn (arg1, stream)
|
||||
mov stream, arg1
|
||||
%endif
|
||||
%ifnidn (arg2, dict_next)
|
||||
mov dict_offset, arg2
|
||||
%endif
|
||||
|
||||
mov f_i_end %+ d, dword [stream + _total_in]
|
||||
neg f_i
|
||||
add f_i, f_i_end
|
||||
|
||||
sub dict_offset, f_i
|
||||
|
||||
sub f_i_end, DICT_SLOP
|
||||
cmp f_i, f_i_end
|
||||
jg end
|
||||
|
||||
main_loop:
|
||||
mov data %+ d, [f_i + dict_offset]
|
||||
compute_hash hash, data
|
||||
and hash, HASH_MASK
|
||||
mov [stream + _internal_state_head + 2 * hash], f_i %+ w
|
||||
|
||||
add f_i, 1
|
||||
cmp f_i, f_i_end
|
||||
jle main_loop
|
||||
end:
|
||||
ret
|
@ -52,26 +52,31 @@ int usage(void)
|
||||
" -X use compression level X with 0 <= X <= 1\n"
|
||||
" -b <size> input buffer size, 0 buffers all the input\n"
|
||||
" -i <iter> number of iterations (at least 1)\n"
|
||||
" -o <file> output file for compresed data\n");
|
||||
" -o <file> output file for compresed data\n"
|
||||
" -d <file> dictionary file used by compression\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *in = NULL, *out = NULL;
|
||||
unsigned char *inbuf, *outbuf, *level_buf = NULL;
|
||||
FILE *in = NULL, *out = NULL, *dict = NULL;
|
||||
unsigned char *inbuf, *outbuf, *level_buf = NULL, *dictbuf = NULL;
|
||||
int i, c, iterations = 0, inbuf_size = 0;
|
||||
uint64_t infile_size, outbuf_size;
|
||||
uint64_t infile_size, outbuf_size, dictfile_size;
|
||||
struct isal_huff_histogram histogram;
|
||||
struct isal_hufftables hufftables_custom;
|
||||
int level = 0, level_size = 0, avail_in;
|
||||
char *in_file_name = NULL, *out_file_name = NULL;
|
||||
char *in_file_name = NULL, *out_file_name = NULL, *dict_file_name = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, "h01i:b:o:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "h01i:b:o:d:")) != -1) {
|
||||
switch (c) {
|
||||
case 'o':
|
||||
out_file_name = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
dict_file_name = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
iterations = atoi(optarg);
|
||||
if (iterations < 1)
|
||||
@ -112,6 +117,15 @@ int main(int argc, char *argv[])
|
||||
printf("outfile=%s\n", out_file_name);
|
||||
}
|
||||
|
||||
if (dict_file_name != NULL) {
|
||||
dict = fopen(dict_file_name, "rb");
|
||||
if (!dict) {
|
||||
fprintf(stderr, "Can't open %s for reading\n", dict_file_name);
|
||||
exit(0);
|
||||
}
|
||||
printf("outfile=%s\n", dict_file_name);
|
||||
}
|
||||
|
||||
printf("Window Size: %d K\n", IGZIP_HIST_SIZE / 1024);
|
||||
printf("igzip_file_perf: \n");
|
||||
fflush(0);
|
||||
@ -123,6 +137,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
outbuf_size = 2 * infile_size + BUF_SIZE;
|
||||
|
||||
dictfile_size = 0;
|
||||
if (dict_file_name != NULL)
|
||||
dictfile_size = get_filesize(dict);
|
||||
|
||||
if (iterations == 0) {
|
||||
iterations = infile_size ? RUN_MEM_SIZE / infile_size : MIN_TEST_LOOPS;
|
||||
if (iterations < MIN_TEST_LOOPS)
|
||||
@ -140,6 +158,14 @@ int main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (dictfile_size != 0) {
|
||||
dictbuf = malloc(dictfile_size);
|
||||
if (dictbuf == NULL) {
|
||||
fprintf(stderr, "Can't allocate dictionary buffer memory\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (level_size != 0) {
|
||||
level_buf = malloc(level_size);
|
||||
if (level_buf == NULL) {
|
||||
@ -158,11 +184,18 @@ int main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (dictfile_size != (uint32_t) fread(dictbuf, 1, dictfile_size, dict)) {
|
||||
fprintf(stderr, "Couldn't fit all of dictionary file into buffer\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct perf start, stop;
|
||||
perf_start(&start);
|
||||
|
||||
for (i = 0; i < iterations; i++) {
|
||||
isal_deflate_init(&stream);
|
||||
if (dict_file_name != NULL)
|
||||
isal_deflate_set_dict(&stream, dictbuf, dictfile_size);
|
||||
stream.end_of_stream = 0;
|
||||
stream.flush = NO_FLUSH;
|
||||
stream.level = level;
|
||||
|
@ -126,7 +126,7 @@ skip_SLOP:
|
||||
|
||||
mov curr_data %+ d, [file_start + f_i]
|
||||
|
||||
cmp dword [stream + _internal_state_has_hist], 0
|
||||
cmp dword [stream + _internal_state_has_hist], IGZIP_NO_HIST
|
||||
jne skip_write_first_byte
|
||||
|
||||
cmp m_out_buf, [stream + _internal_state_bitbuf_m_out_end]
|
||||
@ -135,7 +135,7 @@ skip_SLOP:
|
||||
compute_hash hash, curr_data
|
||||
and hash %+ d, HASH_MASK
|
||||
mov [stream + _internal_state_head + 2 * hash], f_i %+ w
|
||||
mov dword [stream + _internal_state_has_hist], 1
|
||||
mov dword [stream + _internal_state_has_hist], IGZIP_HIST
|
||||
jmp encode_literal
|
||||
|
||||
skip_write_first_byte:
|
||||
|
@ -193,7 +193,7 @@ MARK __body_compute_hash_ %+ ARCH
|
||||
and hash, HASH_MASK
|
||||
and hash2, HASH_MASK
|
||||
|
||||
cmp dword [stream + _internal_state_has_hist], 0
|
||||
cmp dword [stream + _internal_state_has_hist], IGZIP_NO_HIST
|
||||
je write_first_byte
|
||||
|
||||
jmp loop2
|
||||
@ -482,7 +482,7 @@ write_first_byte:
|
||||
cmp m_out_buf, [rsp + m_out_end]
|
||||
ja output_end
|
||||
|
||||
mov dword [stream + _internal_state_has_hist], 1
|
||||
mov dword [stream + _internal_state_has_hist], IGZIP_HIST
|
||||
|
||||
mov [stream + _internal_state_head + 2 * hash], f_i %+ w
|
||||
|
||||
|
@ -122,7 +122,7 @@ isal_deflate_icf_finish_01:
|
||||
|
||||
mov curr_data %+ d, [file_start + f_i]
|
||||
|
||||
cmp dword [stream + _internal_state_has_hist], 0
|
||||
cmp dword [stream + _internal_state_has_hist], IGZIP_NO_HIST
|
||||
jne skip_write_first_byte
|
||||
|
||||
cmp m_out_buf, [rsp + m_out_end]
|
||||
@ -131,7 +131,7 @@ isal_deflate_icf_finish_01:
|
||||
compute_hash hash, curr_data
|
||||
and hash %+ d, HASH_MASK
|
||||
mov [stream + _internal_state_head + 2 * hash], f_i %+ w
|
||||
mov dword [stream + _internal_state_has_hist], 1
|
||||
mov dword [stream + _internal_state_has_hist], IGZIP_HIST
|
||||
jmp encode_literal
|
||||
|
||||
skip_write_first_byte:
|
||||
|
@ -87,6 +87,9 @@ struct slver isal_inflate_stateless_slver = { 0x0089, 0x01, 0x00 };
|
||||
struct slver isal_inflate_slver_0001008a;
|
||||
struct slver isal_inflate_slver = { 0x008a, 0x01, 0x00 };
|
||||
|
||||
struct slver isal_inflate_set_dict_slver_0001008d;
|
||||
struct slver isal_inflate_set_dict_slver = { 0x008d, 0x01, 0x00 };
|
||||
|
||||
/*Performs a copy of length repeat_length data starting at dest -
|
||||
* lookback_distance into dest. This copy copies data previously copied when the
|
||||
* src buffer and the dest buffer overlap. */
|
||||
@ -1064,7 +1067,7 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
||||
return ISAL_END_INPUT;
|
||||
}
|
||||
|
||||
if (look_back_dist > state->total_out)
|
||||
if (look_back_dist > state->total_out + state->dict_length)
|
||||
return ISAL_INVALID_LOOKBACK;
|
||||
|
||||
if (state->avail_out < repeat_length) {
|
||||
@ -1103,6 +1106,7 @@ void isal_inflate_init(struct inflate_state *state)
|
||||
state->next_out = NULL;
|
||||
state->avail_out = 0;
|
||||
state->total_out = 0;
|
||||
state->dict_length = 0;
|
||||
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||
state->bfinal = 0;
|
||||
state->crc_flag = 0;
|
||||
@ -1115,6 +1119,26 @@ void isal_inflate_init(struct inflate_state *state)
|
||||
state->tmp_out_valid = 0;
|
||||
}
|
||||
|
||||
int isal_inflate_set_dict(struct inflate_state *state, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
|
||||
if (state->block_state != ISAL_BLOCK_NEW_HDR
|
||||
|| state->tmp_out_processed != state->tmp_out_valid)
|
||||
return ISAL_INVALID_STATE;
|
||||
|
||||
if (dict_len > IGZIP_HIST_SIZE) {
|
||||
dict = dict + dict_len - IGZIP_HIST_SIZE;
|
||||
dict_len = IGZIP_HIST_SIZE;
|
||||
}
|
||||
|
||||
memcpy(state->tmp_out_buffer, dict, dict_len);
|
||||
state->tmp_out_processed = dict_len;
|
||||
state->tmp_out_valid = dict_len;
|
||||
state->dict_length = dict_len;
|
||||
|
||||
return COMP_OK;
|
||||
}
|
||||
|
||||
int isal_inflate_stateless(struct inflate_state *state)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
@ -1123,6 +1147,7 @@ int isal_inflate_stateless(struct inflate_state *state)
|
||||
state->read_in = 0;
|
||||
state->read_in_length = 0;
|
||||
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||
state->dict_length = 0;
|
||||
state->bfinal = 0;
|
||||
state->crc = 0;
|
||||
state->total_out = 0;
|
||||
|
@ -71,6 +71,9 @@ extern adler32_base
|
||||
extern adler32_avx2_4
|
||||
extern adler32_sse
|
||||
|
||||
extern isal_deflate_hash_lvl0_base
|
||||
extern isal_deflate_hash_lvl0_01
|
||||
|
||||
section .text
|
||||
|
||||
%include "multibinary.asm"
|
||||
@ -101,3 +104,6 @@ mbin_dispatch_init5 crc32_gzip, crc32_gzip_base, crc32_gzip_base, crc32_gzip_01,
|
||||
|
||||
mbin_interface isal_adler32
|
||||
mbin_dispatch_init5 isal_adler32, adler32_base, adler32_sse, adler32_sse, adler32_avx2_4
|
||||
|
||||
mbin_interface isal_deflate_hash_lvl0
|
||||
mbin_dispatch_init5 isal_deflate_hash_lvl0, isal_deflate_hash_lvl0_base, isal_deflate_hash_lvl0_01, isal_deflate_hash_lvl0_01, isal_deflate_hash_lvl0_01
|
||||
|
@ -210,6 +210,29 @@ void create_rand_repeat_data(uint8_t * data, int size)
|
||||
}
|
||||
}
|
||||
|
||||
void create_rand_dict(uint8_t * dict, uint32_t dict_len, uint8_t * buf, uint32_t buf_len)
|
||||
{
|
||||
uint32_t dict_chunk_size, buf_chunk_size;
|
||||
while (dict_len > 0) {
|
||||
dict_chunk_size = rand() % IGZIP_K;
|
||||
dict_chunk_size = (dict_len >= dict_chunk_size) ? dict_chunk_size : dict_len;
|
||||
|
||||
buf_chunk_size = rand() % IGZIP_K;
|
||||
buf_chunk_size = (buf_len >= buf_chunk_size) ? buf_chunk_size : buf_len;
|
||||
|
||||
if (rand() % 3 == 0 && buf_len >= dict_len)
|
||||
memcpy(dict, buf, dict_chunk_size);
|
||||
else
|
||||
create_rand_repeat_data(dict, dict_chunk_size);
|
||||
|
||||
dict_len -= dict_chunk_size;
|
||||
dict += dict_chunk_size;
|
||||
buf_len -= buf_chunk_size;
|
||||
buf += buf_chunk_size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int get_rand_data_length(void)
|
||||
{
|
||||
int max_mask =
|
||||
@ -435,7 +458,8 @@ int inflate_stateless_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||
}
|
||||
|
||||
int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||
uint8_t * uncompress_buf, uint32_t * uncompress_len, uint32_t gzip_flag)
|
||||
uint8_t * uncompress_buf, uint32_t * uncompress_len, uint32_t gzip_flag,
|
||||
uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
struct inflate_state *state = NULL;
|
||||
int ret = 0;
|
||||
@ -452,6 +476,9 @@ int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||
|
||||
isal_inflate_init(state);
|
||||
|
||||
if (dict != NULL)
|
||||
isal_inflate_set_dict(state, dict, dict_len);
|
||||
|
||||
state->next_in = NULL;
|
||||
state->next_out = NULL;
|
||||
state->avail_in = 0;
|
||||
@ -583,7 +610,7 @@ int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||
|
||||
/* Inflate the compressed data and check that the decompressed data agrees with the input data */
|
||||
int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size,
|
||||
uint32_t gzip_flag)
|
||||
uint32_t gzip_flag, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
/* Test inflate with reference inflate */
|
||||
|
||||
@ -613,11 +640,13 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size,
|
||||
z_size -= zlib_hdr_bytes;
|
||||
}
|
||||
|
||||
if (inflate_type == 0) {
|
||||
if (inflate_type == 0 && dict == NULL) {
|
||||
ret = inflate_stateless_pass(z_buf, z_size, test_buf, &test_size, gzip_flag);
|
||||
inflate_type = 1;
|
||||
} else {
|
||||
ret = inflate_multi_pass(z_buf, z_size, test_buf, &test_size, gzip_flag);
|
||||
ret =
|
||||
inflate_multi_pass(z_buf, z_size, test_buf, &test_size, gzip_flag, dict,
|
||||
dict_len);
|
||||
inflate_type = 0;
|
||||
}
|
||||
|
||||
@ -796,7 +825,7 @@ void set_random_hufftable(struct isal_zstream *stream)
|
||||
* compression*/
|
||||
int compress_multi_pass(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
|
||||
uint32_t * compressed_size, uint32_t flush_type, uint32_t gzip_flag,
|
||||
uint32_t level)
|
||||
uint32_t level, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
int ret = IGZIP_COMP_OK;
|
||||
uint8_t *in_buf = NULL, *out_buf = NULL;
|
||||
@ -946,7 +975,7 @@ int compress_multi_pass(uint8_t * data, uint32_t data_size, uint8_t * compressed
|
||||
/* Compress the input data into the outbuffer in one call to isal_deflate */
|
||||
int compress_single_pass(uint8_t * data, uint32_t data_size, uint8_t * compressed_buf,
|
||||
uint32_t * compressed_size, uint32_t flush_type, uint32_t gzip_flag,
|
||||
uint32_t level)
|
||||
uint32_t level, uint8_t * dict, uint32_t dict_len)
|
||||
{
|
||||
int ret = IGZIP_COMP_OK;
|
||||
struct isal_zstream stream;
|
||||
@ -967,6 +996,9 @@ int compress_single_pass(uint8_t * data, uint32_t data_size, uint8_t * compresse
|
||||
if (state->state != ZSTATE_NEW_HDR)
|
||||
return COMPRESS_INCORRECT_STATE;
|
||||
|
||||
if (dict != NULL)
|
||||
isal_deflate_set_dict(&stream, dict, dict_len);
|
||||
|
||||
stream.flush = flush_type;
|
||||
stream.avail_in = data_size;
|
||||
stream.next_in = data;
|
||||
@ -1153,7 +1185,9 @@ int compress_stateless_full_flush(uint8_t * data, uint32_t data_size, uint8_t *
|
||||
break;
|
||||
|
||||
/* Verify that blocks are independent */
|
||||
ret = inflate_check(out_buf, stream.next_out - out_buf, in_buf, in_size, 0);
|
||||
ret =
|
||||
inflate_check(out_buf, stream.next_out - out_buf, in_buf, in_size, 0, NULL,
|
||||
0);
|
||||
|
||||
if (ret == INFLATE_INVALID_LOOK_BACK_DISTANCE) {
|
||||
break;
|
||||
@ -1272,7 +1306,7 @@ int compress_full_flush(uint8_t * data, uint32_t data_size, uint8_t * compressed
|
||||
if (state->state == ZSTATE_NEW_HDR || state->state == ZSTATE_END) {
|
||||
ret =
|
||||
inflate_check(out_buf, stream.next_out - out_buf, in_buf, in_size,
|
||||
0);
|
||||
0, NULL, 0);
|
||||
|
||||
if (ret == INFLATE_INVALID_LOOK_BACK_DISTANCE)
|
||||
break;
|
||||
@ -1425,7 +1459,7 @@ int test_compress_stateless(uint8_t * in_data, uint32_t in_size, uint32_t flush_
|
||||
compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0);
|
||||
|
||||
#ifdef VERBOSE
|
||||
if (ret) {
|
||||
@ -1473,7 +1507,7 @@ int test_compress_stateless(uint8_t * in_data, uint32_t in_size, uint32_t flush_
|
||||
ret =
|
||||
compress_stateless(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level);
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0);
|
||||
#ifdef VERBOSE
|
||||
if (ret) {
|
||||
printf("Compressed array at level %d with gzip flag %d: ", level, gzip_flag);
|
||||
@ -1511,7 +1545,8 @@ int test_compress_stateless(uint8_t * in_data, uint32_t in_size, uint32_t flush_
|
||||
print_error(overflow);
|
||||
if (overflow == 0) {
|
||||
overflow =
|
||||
inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag,
|
||||
NULL, 0);
|
||||
printf("inflate ret = %d\n", overflow);
|
||||
print_error(overflow);
|
||||
}
|
||||
@ -1553,7 +1588,7 @@ int test_compress_stateless(uint8_t * in_data, uint32_t in_size, uint32_t flush_
|
||||
ret = compress_stateless_full_flush(in_buf, in_size, z_buf, &z_size, level);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, 0);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, 0, NULL, 0);
|
||||
else if (ret == COMPRESS_LOOP_COUNT_OVERFLOW)
|
||||
ret = 0;
|
||||
|
||||
@ -1583,8 +1618,8 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
{
|
||||
int ret = IGZIP_COMP_OK, fin_ret = IGZIP_COMP_OK;
|
||||
uint32_t overflow = 0, gzip_flag, level;
|
||||
uint32_t z_size = 0, z_size_max = 0, z_compressed_size;
|
||||
uint8_t *z_buf = NULL;
|
||||
uint32_t z_size = 0, z_size_max = 0, z_compressed_size, dict_len = 0;
|
||||
uint8_t *z_buf = NULL, *dict = NULL;
|
||||
|
||||
/* Test a non overflow case */
|
||||
if (flush_type == NO_FLUSH)
|
||||
@ -1617,17 +1652,32 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
}
|
||||
create_rand_repeat_data(z_buf, z_size);
|
||||
|
||||
if (rand() % 8 == 0) {
|
||||
dict_len = (rand() % IGZIP_HIST_SIZE) + 1;
|
||||
dict = malloc(dict_len);
|
||||
if (dict == NULL) {
|
||||
print_error(MALLOC_FAILED);
|
||||
return MALLOC_FAILED;
|
||||
}
|
||||
create_rand_dict(dict, dict_len, z_buf, z_size);
|
||||
}
|
||||
|
||||
ret = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
|
||||
gzip_flag, level);
|
||||
gzip_flag, level, dict, dict_len);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict, dict_len);
|
||||
|
||||
if (ret) {
|
||||
#ifdef VERBOSE
|
||||
printf("Compressed array at level %d with gzip flag %d: ", level, gzip_flag);
|
||||
print_uint8_t(z_buf, z_size);
|
||||
printf("\n");
|
||||
if (dict != NULL) {
|
||||
printf("Using Dictionary: ");
|
||||
print_uint8_t(dict, dict_len);
|
||||
printf("\n");
|
||||
}
|
||||
printf("Data: ");
|
||||
print_uint8_t(in_buf, in_size);
|
||||
#endif
|
||||
@ -1635,23 +1685,45 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
print_error(ret);
|
||||
}
|
||||
|
||||
if (dict != NULL) {
|
||||
free(dict);
|
||||
dict = NULL;
|
||||
dict_len = 0;
|
||||
}
|
||||
|
||||
fin_ret |= ret;
|
||||
|
||||
z_compressed_size = z_size;
|
||||
z_size = z_size_max;
|
||||
create_rand_repeat_data(z_buf, z_size_max);
|
||||
|
||||
if (rand() % 8 == 0) {
|
||||
dict_len = (rand() % IGZIP_HIST_SIZE) + 1;
|
||||
dict = malloc(dict_len);
|
||||
if (dict == NULL) {
|
||||
print_error(MALLOC_FAILED);
|
||||
return MALLOC_FAILED;
|
||||
}
|
||||
create_rand_dict(dict, dict_len, z_buf, z_size);
|
||||
}
|
||||
|
||||
ret =
|
||||
compress_multi_pass(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level);
|
||||
compress_multi_pass(in_buf, in_size, z_buf, &z_size, flush_type, gzip_flag, level,
|
||||
dict, dict_len);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict, dict_len);
|
||||
|
||||
if (ret) {
|
||||
#ifdef VERBOSE
|
||||
printf("Compressed array at level %d with gzip flag %d: ", level, gzip_flag);
|
||||
print_uint8_t(z_buf, z_size);
|
||||
printf("\n");
|
||||
if (dict != NULL) {
|
||||
printf("Using Dictionary: ");
|
||||
print_uint8_t(dict, dict_len);
|
||||
printf("\n");
|
||||
}
|
||||
printf("Data: ");
|
||||
print_uint8_t(in_buf, in_size);
|
||||
#endif
|
||||
@ -1659,6 +1731,12 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
print_error(ret);
|
||||
}
|
||||
|
||||
if (dict != NULL) {
|
||||
free(dict);
|
||||
dict = NULL;
|
||||
dict_len = 0;
|
||||
}
|
||||
|
||||
fin_ret |= ret;
|
||||
|
||||
ret = 0;
|
||||
@ -1671,11 +1749,13 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
create_rand_repeat_data(z_buf, z_size_max);
|
||||
|
||||
overflow = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
|
||||
gzip_flag, level);
|
||||
gzip_flag, level, dict, dict_len);
|
||||
|
||||
if (overflow != COMPRESS_OUT_BUFFER_OVERFLOW) {
|
||||
if (overflow == 0)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret =
|
||||
inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, dict,
|
||||
dict_len);
|
||||
|
||||
/* Rarely single pass overflow will compresses data
|
||||
* better than the initial run. This is to stop that
|
||||
@ -1707,11 +1787,13 @@ int test_compress(uint8_t * in_buf, uint32_t in_size, uint32_t flush_type)
|
||||
|
||||
overflow =
|
||||
compress_multi_pass(in_buf, in_size, z_buf, &z_size, flush_type,
|
||||
gzip_flag, level);
|
||||
gzip_flag, level, dict, dict_len);
|
||||
|
||||
if (overflow != COMPRESS_OUT_BUFFER_OVERFLOW) {
|
||||
if (overflow == 0)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret =
|
||||
inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag,
|
||||
dict, dict_len);
|
||||
|
||||
/* Rarely multi pass overflow will compresses data
|
||||
* better than the initial run. This is to stop that
|
||||
@ -1775,7 +1857,7 @@ int test_flush(uint8_t * in_buf, uint32_t in_size)
|
||||
|
||||
/* Test invalid flush */
|
||||
ret = compress_single_pass(in_buf, in_size, z_buf, &z_size, flush_type,
|
||||
gzip_flag, level);
|
||||
gzip_flag, level, NULL, 0);
|
||||
|
||||
if (ret == COMPRESS_GENERAL_ERROR)
|
||||
ret = 0;
|
||||
@ -1793,7 +1875,7 @@ int test_flush(uint8_t * in_buf, uint32_t in_size)
|
||||
ret = compress_swap_flush(in_buf, in_size, z_buf, &z_size, rand() % 3, gzip_flag);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0);
|
||||
|
||||
if (ret) {
|
||||
#ifdef VERBOSE
|
||||
@ -1844,7 +1926,7 @@ int test_full_flush(uint8_t * in_buf, uint32_t in_size)
|
||||
ret = compress_full_flush(in_buf, in_size, z_buf, &z_size, gzip_flag, level);
|
||||
|
||||
if (!ret)
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag);
|
||||
ret = inflate_check(z_buf, z_size, in_buf, in_size, gzip_flag, NULL, 0);
|
||||
|
||||
if (ret) {
|
||||
#ifdef VERBOSE
|
||||
@ -1887,7 +1969,8 @@ int test_inflate(struct vect_result *in_vector)
|
||||
ret = IGZIP_COMP_OK;
|
||||
|
||||
if (!ret) {
|
||||
ret = inflate_multi_pass(compress_buf, compress_len, out_buf, &out_size, 0);
|
||||
ret = inflate_multi_pass(compress_buf, compress_len, out_buf, &out_size,
|
||||
0, NULL, 0);
|
||||
|
||||
if (ret == INFLATE_LEFTOVER_INPUT)
|
||||
ret = ISAL_DECOMP_OK;
|
||||
|
@ -89,6 +89,7 @@ FIELD _read_in_length,4, 4
|
||||
FIELD _lit_huff_code, _inflate_huff_code_large_size, _inflate_huff_code_large_align
|
||||
FIELD _dist_huff_code,_inflate_huff_code_small_size, _inflate_huff_code_small_align
|
||||
FIELD _block_state, 4, 4
|
||||
FIELD _dict_length, 4, 4
|
||||
FIELD _bfinal, 4, 4
|
||||
FIELD _crc_flag, 4, 4
|
||||
FIELD _crc, 4, 4
|
||||
|
@ -156,7 +156,7 @@ enum {IGZIP_LIT_TABLE_SIZE = ISAL_DEF_LIT_SYMBOLS};
|
||||
#define STATELESS_OVERFLOW -1
|
||||
#define ISAL_INVALID_OPERATION -9
|
||||
#define ISAL_INVALID_LEVEL -4 /* Invalid Compression level set */
|
||||
|
||||
#define ISAL_INVALID_STATE -3
|
||||
/**
|
||||
* @enum isal_zstate_state
|
||||
* @brief Compression State please note ZSTATE_TRL only applies for GZIP compression
|
||||
@ -264,6 +264,10 @@ struct isal_mod_hist {
|
||||
#define ISAL_DEF_LVL1_EXTRA_LARGE (ISAL_DEF_LVL1_REQ + ISAL_DEF_LVL1_TOKEN_SIZE * 128 * IGZIP_K)
|
||||
#define ISAL_DEF_LVL1_DEFAULT ISAL_DEF_LVL1_LARGE
|
||||
|
||||
#define IGZIP_NO_HIST 0
|
||||
#define IGZIP_HIST 1
|
||||
#define IGZIP_DICT_HIST 2
|
||||
|
||||
/** @brief Holds Bit Buffer information*/
|
||||
struct BitBuf2 {
|
||||
uint64_t m_bits; //!< bits in the bit buffer
|
||||
@ -410,6 +414,7 @@ struct inflate_state {
|
||||
struct inflate_huff_code_large lit_huff_code; //!< Structure for decoding lit/len symbols
|
||||
struct inflate_huff_code_small dist_huff_code; //!< Structure for decoding dist symbols
|
||||
enum isal_block_state block_state; //!< Current decompression state
|
||||
uint32_t dict_length; //!< Length of dictionary used
|
||||
uint32_t bfinal; //!< Flag identifying final block
|
||||
uint32_t crc_flag; //!< Flag identifying whether to track of crc
|
||||
uint32_t crc; //!< Contains crc of output if crc_flag is set
|
||||
@ -506,6 +511,22 @@ int isal_deflate_set_hufftables(struct isal_zstream *stream,
|
||||
void isal_deflate_stateless_init(struct isal_zstream *stream);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set compression dictionary to use
|
||||
*
|
||||
* This function is to be called after isal_deflate_init, or after completing a
|
||||
* SYNC_FLUSH or FULL_FLUSH and before the next call do isal_deflate. If the
|
||||
* dictionary is longer than IGZIP_HIST_SIZE, only the last IGZIP_HIST_SIZE
|
||||
* bytes will be used.
|
||||
*
|
||||
* @param stream Structure holding state information on the compression streams.
|
||||
* @param dict: Array containing dictionary to use.
|
||||
* @param dict_len: Lenth of dict.
|
||||
* @returns COMP_OK,
|
||||
* ISAL_INVALID_STATE (dictionary could not be set)
|
||||
*/
|
||||
int isal_deflate_set_dict(struct isal_zstream *stream, uint8_t *dict, uint32_t dict_len);
|
||||
|
||||
/**
|
||||
* @brief Fast data (deflate) compression for storage applications.
|
||||
*
|
||||
@ -546,6 +567,9 @@ void isal_deflate_stateless_init(struct isal_zstream *stream);
|
||||
* not include previous blocks so new blocks are fully independent. Switching
|
||||
* between flush types is supported.
|
||||
*
|
||||
* If a compression dictionary is required, the dictionary can be set calling
|
||||
* isal_deflate_set_dictionary before calling isal_deflate.
|
||||
*
|
||||
* If the gzip_flag is set to IGZIP_GZIP, a generic gzip header and the gzip
|
||||
* trailer are written around the deflate compressed data. If gzip_flag is set
|
||||
* to IGZIP_GZIP_NO_HDR, then only the gzip trailer is written.
|
||||
@ -598,6 +622,21 @@ int isal_deflate_stateless(struct isal_zstream *stream);
|
||||
*/
|
||||
void isal_inflate_init(struct inflate_state *state);
|
||||
|
||||
/**
|
||||
* @brief Set decompression dictionary to use
|
||||
*
|
||||
* This function is to be called after isal_inflate_init. If the dictionary is
|
||||
* longer than IGZIP_HIST_SIZE, only the last IGZIP_HIST_SIZE bytes will be
|
||||
* used.
|
||||
*
|
||||
* @param state: Structure holding state information on the decompression stream.
|
||||
* @param dict: Array containing dictionary to use.
|
||||
* @param dict_len: Lenth of dict.
|
||||
* @returns COMP_OK,
|
||||
* ISAL_INVALID_STATE (dictionary could not be set)
|
||||
*/
|
||||
int isal_inflate_set_dict(struct inflate_state *state, uint8_t *dict, uint32_t dict_len);
|
||||
|
||||
/**
|
||||
* @brief Fast data (deflate) decompression for storage applications.
|
||||
*
|
||||
@ -617,6 +656,9 @@ void isal_inflate_init(struct inflate_state *state);
|
||||
* in state->crc. Alternatively, if the crc_flag is set to ISAL_ZLIB_NO_HDR the
|
||||
* adler32 of the output is stored in state->crc.
|
||||
*
|
||||
* If a dictionary is required, a call to isal_inflate_set_dict will set the
|
||||
* dictionary.
|
||||
*
|
||||
* @param state Structure holding state information on the compression streams.
|
||||
* @return ISAL_DECOMP_OK (if everything is ok),
|
||||
* ISAL_END_INPUT (if all input was decompressed),
|
||||
@ -625,6 +667,7 @@ void isal_inflate_init(struct inflate_state *state);
|
||||
* ISAL_INVALID_SYMBOL,
|
||||
* ISAL_INVALID_LOOKBACK.
|
||||
*/
|
||||
|
||||
int isal_inflate(struct inflate_state *state);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user