igzip: Add stateful dictionary support

Change-Id: I75dbac947787bc0041674468c88d0aa41b8b082f
Signed-off-by: Roy Oursler <roy.j.oursler@intel.com>
This commit is contained in:
Roy Oursler 2017-06-07 13:40:34 -07:00 committed by Xiaodong Liu
parent 82a6ac65dc
commit ed15402f5b
17 changed files with 376 additions and 50 deletions

View File

@ -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

View File

@ -222,4 +222,10 @@ _STORED_BLK equ 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IGZIP_NO_HIST equ 0
IGZIP_HIST equ 1
IGZIP_DICT_HIST equ 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -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) {

View File

@ -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++;
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View 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

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
/**