mirror of
https://github.com/intel/isa-l.git
synced 2025-07-04 17:40:07 +02:00
igzip: Implement stateful inflate.
Signed-off-by: Roy Oursler <roy.j.oursler@intel.com> Reviewed-by: Greg Tucker <greg.b.tucker@intel.com>
This commit is contained in:
parent
6b2bedfe28
commit
340e0f99df
@ -348,7 +348,12 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
|||||||
z_size -= gzip_hdr_bytes;
|
z_size -= gzip_hdr_bytes;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isal_inflate_init(&gstream, z_buf, z_size, test_buf, test_size);
|
isal_inflate_init(&gstream);
|
||||||
|
gstream.next_in = z_buf;
|
||||||
|
gstream.avail_in = z_size;
|
||||||
|
gstream.next_out = test_buf;
|
||||||
|
gstream.avail_out = test_size;
|
||||||
|
|
||||||
ret = isal_inflate_stateless(&gstream);
|
ret = isal_inflate_stateless(&gstream);
|
||||||
|
|
||||||
if (test_buf != NULL)
|
if (test_buf != NULL)
|
||||||
|
@ -79,7 +79,9 @@ extern rfc1951_lookup_table
|
|||||||
%define rfc_lookup r15
|
%define rfc_lookup r15
|
||||||
|
|
||||||
start_out_mem_offset equ 0
|
start_out_mem_offset equ 0
|
||||||
stack_size equ 8
|
read_in_mem_offset equ 8
|
||||||
|
read_in_length_mem_offset equ 16
|
||||||
|
stack_size equ 4 * 8 + 8
|
||||||
|
|
||||||
%define _dist_extra_bit_count 264
|
%define _dist_extra_bit_count 264
|
||||||
%define _dist_start _dist_extra_bit_count + 1*32
|
%define _dist_start _dist_extra_bit_count + 1*32
|
||||||
@ -280,6 +282,9 @@ decode_huffman_code_block_stateless_ %+ ARCH %+ :
|
|||||||
mov end_in %+ d, dword [state + _avail_in]
|
mov end_in %+ d, dword [state + _avail_in]
|
||||||
add end_in, next_in
|
add end_in, next_in
|
||||||
|
|
||||||
|
mov dword [state + _copy_overflow_len], 0
|
||||||
|
mov dword [state + _copy_overflow_dist], 0
|
||||||
|
|
||||||
mov tmp3 %+ d, dword [state + _total_out]
|
mov tmp3 %+ d, dword [state + _total_out]
|
||||||
sub tmp3, next_out
|
sub tmp3, next_out
|
||||||
neg tmp3
|
neg tmp3
|
||||||
@ -292,8 +297,12 @@ decode_huffman_code_block_stateless_ %+ ARCH %+ :
|
|||||||
cmp next_in, end_in
|
cmp next_in, end_in
|
||||||
jg end_loop_block_pre
|
jg end_loop_block_pre
|
||||||
|
|
||||||
|
cmp read_in_length, 64
|
||||||
|
je skip_load
|
||||||
|
|
||||||
inflate_in_load next_in, end_in, read_in, read_in_length, tmp1, tmp2
|
inflate_in_load next_in, end_in, read_in, read_in_length, tmp1, tmp2
|
||||||
|
|
||||||
|
skip_load:
|
||||||
mov tmp3, read_in
|
mov tmp3, read_in
|
||||||
and tmp3, (1 << DECODE_LOOKUP_SIZE_LARGE) - 1
|
and tmp3, (1 << DECODE_LOOKUP_SIZE_LARGE) - 1
|
||||||
movzx next_sym, word [state + _lit_huff_code + 2 * tmp3]
|
movzx next_sym, word [state + _lit_huff_code + 2 * tmp3]
|
||||||
@ -395,7 +404,7 @@ decode_len_dist:
|
|||||||
sub copy_start, repeat_length
|
sub copy_start, repeat_length
|
||||||
sub copy_start, look_back_dist2
|
sub copy_start, look_back_dist2
|
||||||
|
|
||||||
;; ;; Check if a valid look back distances was decoded
|
;; ;; ;; Check if a valid look back distances was decoded
|
||||||
cmp copy_start, [rsp + start_out_mem_offset]
|
cmp copy_start, [rsp + start_out_mem_offset]
|
||||||
jl invalid_look_back_distance
|
jl invalid_look_back_distance
|
||||||
MOVDQU xmm1, [copy_start]
|
MOVDQU xmm1, [copy_start]
|
||||||
@ -443,9 +452,13 @@ end_loop_block_pre:
|
|||||||
;; Fix up in buffer and out buffer to reflect the actual buffer end
|
;; Fix up in buffer and out buffer to reflect the actual buffer end
|
||||||
add end_out, OUT_BUFFER_SLOP
|
add end_out, OUT_BUFFER_SLOP
|
||||||
add end_in, IN_BUFFER_SLOP
|
add end_in, IN_BUFFER_SLOP
|
||||||
|
|
||||||
end_loop_block:
|
end_loop_block:
|
||||||
;; Load read in buffer and decode next lit/len symbol
|
;; Load read in buffer and decode next lit/len symbol
|
||||||
inflate_in_small_load next_in, end_in, read_in, read_in_length, tmp1, tmp2
|
inflate_in_small_load next_in, end_in, read_in, read_in_length, tmp1, tmp2
|
||||||
|
mov [rsp + read_in_mem_offset], read_in
|
||||||
|
mov [rsp + read_in_length_mem_offset], read_in_length
|
||||||
|
|
||||||
decode_next state, DECODE_LOOKUP_SIZE_LARGE, _lit_huff_code, read_in, read_in_length, next_sym, tmp1, tmp2
|
decode_next state, DECODE_LOOKUP_SIZE_LARGE, _lit_huff_code, read_in, read_in_length, next_sym, tmp1, tmp2
|
||||||
|
|
||||||
;; Check that enough input was available to decode symbol
|
;; Check that enough input was available to decode symbol
|
||||||
@ -457,7 +470,6 @@ end_loop_block:
|
|||||||
je end_symbol
|
je end_symbol
|
||||||
|
|
||||||
decode_len_dist_2:
|
decode_len_dist_2:
|
||||||
|
|
||||||
;; Load length exta bits
|
;; Load length exta bits
|
||||||
mov next_bits, read_in
|
mov next_bits, read_in
|
||||||
|
|
||||||
@ -484,8 +496,8 @@ decode_len_dist_2:
|
|||||||
;; Calculate the look back distance and check for enough input
|
;; Calculate the look back distance and check for enough input
|
||||||
BZHI next_bits, next_bits, rcx, tmp1
|
BZHI next_bits, next_bits, rcx, tmp1
|
||||||
SHRX read_in, read_in, rcx
|
SHRX read_in, read_in, rcx
|
||||||
sub read_in_length, rcx
|
|
||||||
add look_back_dist, next_bits
|
add look_back_dist, next_bits
|
||||||
|
sub read_in_length, rcx
|
||||||
jl end_of_input
|
jl end_of_input
|
||||||
|
|
||||||
;; Setup code for byte copy using rep movsb
|
;; Setup code for byte copy using rep movsb
|
||||||
@ -494,32 +506,53 @@ decode_len_dist_2:
|
|||||||
mov rcx, repeat_length
|
mov rcx, repeat_length
|
||||||
sub rsi, look_back_dist
|
sub rsi, look_back_dist
|
||||||
|
|
||||||
;; Check for out buffer overflow
|
|
||||||
add next_out, repeat_length
|
|
||||||
cmp next_out, end_out
|
|
||||||
jg out_buffer_overflow
|
|
||||||
|
|
||||||
;; Check if a valid look back distance was decoded
|
;; Check if a valid look back distance was decoded
|
||||||
cmp rsi, [rsp + start_out_mem_offset]
|
cmp rsi, [rsp + start_out_mem_offset]
|
||||||
jl invalid_look_back_distance
|
jl invalid_look_back_distance
|
||||||
|
|
||||||
|
;; Check for out buffer overflow
|
||||||
|
add repeat_length, next_out
|
||||||
|
cmp repeat_length, end_out
|
||||||
|
jg out_buffer_overflow_repeat
|
||||||
|
|
||||||
|
mov next_out, repeat_length
|
||||||
|
|
||||||
rep movsb
|
rep movsb
|
||||||
jmp end_loop_block
|
jmp end_loop_block
|
||||||
|
|
||||||
decode_literal:
|
decode_literal:
|
||||||
;; Store literal decoded from the input stream
|
;; Store literal decoded from the input stream
|
||||||
add next_out, 1
|
|
||||||
cmp next_out, end_out
|
cmp next_out, end_out
|
||||||
jg out_buffer_overflow
|
jge out_buffer_overflow_lit
|
||||||
|
add next_out, 1
|
||||||
mov byte [next_out - 1], next_sym %+ b
|
mov byte [next_out - 1], next_sym %+ b
|
||||||
jmp end_loop_block
|
jmp end_loop_block
|
||||||
|
|
||||||
;; Set exit codes
|
;; Set exit codes
|
||||||
end_of_input:
|
end_of_input:
|
||||||
|
mov read_in, [rsp + read_in_mem_offset]
|
||||||
|
mov read_in_length, [rsp + read_in_length_mem_offset]
|
||||||
mov rax, END_OF_INPUT
|
mov rax, END_OF_INPUT
|
||||||
jmp end
|
jmp end
|
||||||
|
|
||||||
out_buffer_overflow:
|
out_buffer_overflow_repeat:
|
||||||
|
mov rcx, end_out
|
||||||
|
sub rcx, next_out
|
||||||
|
sub repeat_length, rcx
|
||||||
|
sub repeat_length, next_out
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
mov [state + _copy_overflow_len], repeat_length %+ d
|
||||||
|
mov [state + _copy_overflow_dist], look_back_dist %+ d
|
||||||
|
|
||||||
|
mov next_out, end_out
|
||||||
|
|
||||||
|
mov rax, OUT_BUFFER_OVERFLOW
|
||||||
|
jmp end
|
||||||
|
|
||||||
|
out_buffer_overflow_lit:
|
||||||
|
mov read_in, [rsp + read_in_mem_offset]
|
||||||
|
mov read_in_length, [rsp + read_in_length_mem_offset]
|
||||||
mov rax, OUT_BUFFER_OVERFLOW
|
mov rax, OUT_BUFFER_OVERFLOW
|
||||||
jmp end
|
jmp end
|
||||||
|
|
||||||
@ -533,7 +566,7 @@ end_symbol_pre:
|
|||||||
add end_in, IN_BUFFER_SLOP
|
add end_in, IN_BUFFER_SLOP
|
||||||
end_symbol:
|
end_symbol:
|
||||||
;; Set flag identifying a new block is required
|
;; Set flag identifying a new block is required
|
||||||
mov byte [state + _new_block], 1
|
mov byte [state + _block_state], ISAL_BLOCK_NEW_HDR
|
||||||
xor rax, rax
|
xor rax, rax
|
||||||
end:
|
end:
|
||||||
;; Save current buffer states
|
;; Save current buffer states
|
||||||
|
@ -83,15 +83,15 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
|||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
memset(histogram, 0, sizeof(struct isal_huff_histogram));
|
memset(histogram, 0, sizeof(struct isal_huff_histogram));
|
||||||
while (state->new_block == 0 || state->bfinal == 0) {
|
while (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
||||||
if (state->new_block != 0) {
|
if (state->block_state == ISAL_BLOCK_NEW_HDR) {
|
||||||
tmp = read_header(state);
|
tmp = read_header(state);
|
||||||
|
|
||||||
if (tmp)
|
if (tmp)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->btype == 0) {
|
if (state->block_state == ISAL_BLOCK_TYPE0) {
|
||||||
/* If the block is uncompressed, update state data accordingly */
|
/* If the block is uncompressed, update state data accordingly */
|
||||||
if (state->avail_in < 4)
|
if (state->avail_in < 4)
|
||||||
return END_OF_INPUT;
|
return END_OF_INPUT;
|
||||||
@ -108,18 +108,18 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
|||||||
if (state->avail_in < len)
|
if (state->avail_in < len)
|
||||||
len = state->avail_in;
|
len = state->avail_in;
|
||||||
else
|
else
|
||||||
state->new_block = 1;
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
|
|
||||||
state->total_out += len;
|
state->total_out += len;
|
||||||
state->next_in += len;
|
state->next_in += len;
|
||||||
state->avail_in -= len + 4;
|
state->avail_in -= len + 4;
|
||||||
|
|
||||||
if (state->avail_in == 0 && state->new_block == 0)
|
if (state->avail_in == 0 && state->block_state == 0)
|
||||||
return END_OF_INPUT;
|
return END_OF_INPUT;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Else decode a huffman encoded block */
|
/* Else decode a huffman encoded block */
|
||||||
while (state->new_block == 0) {
|
while (state->block_state == ISAL_BLOCK_CODED) {
|
||||||
/* While not at the end of block, decode the next
|
/* While not at the end of block, decode the next
|
||||||
* symbol */
|
* symbol */
|
||||||
next_lit = decode_next_large(state, &state->lit_huff_code);
|
next_lit = decode_next_large(state, &state->lit_huff_code);
|
||||||
@ -135,7 +135,7 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
|||||||
|
|
||||||
else if (next_lit == 256)
|
else if (next_lit == 256)
|
||||||
/* Next symbol is end of block */
|
/* Next symbol is end of block */
|
||||||
state->new_block = 1;
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
|
|
||||||
else if (next_lit < 286) {
|
else if (next_lit < 286) {
|
||||||
/* Next symbol is a repeat length followed by a
|
/* Next symbol is a repeat length followed by a
|
||||||
@ -168,6 +168,9 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
|||||||
return INVALID_SYMBOL;
|
return INVALID_SYMBOL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->bfinal != 0 && state->block_state == ISAL_BLOCK_NEW_HDR)
|
||||||
|
state->block_state = ISAL_BLOCK_INPUT_DONE;
|
||||||
}
|
}
|
||||||
state->next_in -= state->read_in_length / 8;
|
state->next_in -= state->read_in_length / 8;
|
||||||
state->avail_in += state->read_in_length / 8;
|
state->avail_in += state->read_in_length / 8;
|
||||||
@ -340,7 +343,9 @@ int main(int argc, char *argv[])
|
|||||||
stream.hufftables = &hufftables_custom;
|
stream.hufftables = &hufftables_custom;
|
||||||
isal_deflate_stateless(&stream);
|
isal_deflate_stateless(&stream);
|
||||||
|
|
||||||
isal_inflate_init(&gstream, outbuf, stream.total_out, NULL, 0);
|
isal_inflate_init(&gstream);
|
||||||
|
gstream.next_in = outbuf;
|
||||||
|
gstream.avail_in = outbuf_size;
|
||||||
isal_inflate_hist(&gstream, &histogram2);
|
isal_inflate_hist(&gstream, &histogram2);
|
||||||
|
|
||||||
printf("Histogram Error \n");
|
printf("Histogram Error \n");
|
||||||
|
@ -72,6 +72,9 @@ void inline inflate_in_load(struct inflate_state *state, int min_required)
|
|||||||
uint64_t temp = 0;
|
uint64_t temp = 0;
|
||||||
uint8_t new_bytes;
|
uint8_t new_bytes;
|
||||||
|
|
||||||
|
if (state->read_in_length >= 64)
|
||||||
|
return;
|
||||||
|
|
||||||
if (state->avail_in >= 8) {
|
if (state->avail_in >= 8) {
|
||||||
/* If there is enough space to load a 64 bits, load the data and use
|
/* If there is enough space to load a 64 bits, load the data and use
|
||||||
* that to fill read_in */
|
* that to fill read_in */
|
||||||
@ -94,7 +97,6 @@ void inline inflate_in_load(struct inflate_state *state, int min_required)
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the next bit_count bits from the in stream and shifts the stream over
|
/* Returns the next bit_count bits from the in stream and shifts the stream over
|
||||||
@ -443,6 +445,8 @@ int inline setup_static_header(struct inflate_state *state)
|
|||||||
make_inflate_huff_code_small(&state->dist_huff_code, dist_code, DIST_LEN + 2,
|
make_inflate_huff_code_small(&state->dist_huff_code, dist_code, DIST_LEN + 2,
|
||||||
dist_count);
|
dist_count);
|
||||||
|
|
||||||
|
state->block_state = ISAL_BLOCK_CODED;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,6 +690,8 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
|||||||
make_inflate_huff_code_small(&state->dist_huff_code, &lit_and_dist_huff[LIT_LEN],
|
make_inflate_huff_code_small(&state->dist_huff_code, &lit_and_dist_huff[LIT_LEN],
|
||||||
DIST_LEN, dist_count);
|
DIST_LEN, dist_count);
|
||||||
|
|
||||||
|
state->block_state = ISAL_BLOCK_CODED;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,61 +700,133 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
|||||||
int read_header(struct inflate_state *state)
|
int read_header(struct inflate_state *state)
|
||||||
{
|
{
|
||||||
uint8_t bytes;
|
uint8_t bytes;
|
||||||
|
uint32_t btype;
|
||||||
state->new_block = 0;
|
uint16_t len, nlen;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
/* btype and bfinal are defined in RFC 1951, bfinal represents whether
|
/* btype and bfinal are defined in RFC 1951, bfinal represents whether
|
||||||
* the current block is the end of block, and btype represents the
|
* the current block is the end of block, and btype represents the
|
||||||
* encoding method on the current block. */
|
* encoding method on the current block. */
|
||||||
|
|
||||||
state->bfinal = inflate_in_read_bits(state, 1);
|
state->bfinal = inflate_in_read_bits(state, 1);
|
||||||
state->btype = inflate_in_read_bits(state, 2);
|
btype = inflate_in_read_bits(state, 2);
|
||||||
|
|
||||||
if (state->read_in_length < 0)
|
if (state->read_in_length < 0)
|
||||||
return END_OF_INPUT;
|
ret = END_OF_INPUT;
|
||||||
|
|
||||||
|
else if (btype == 0) {
|
||||||
|
inflate_in_load(state, 40);
|
||||||
|
bytes = state->read_in_length / 8;
|
||||||
|
|
||||||
|
if (bytes < 4)
|
||||||
|
return END_OF_INPUT;
|
||||||
|
|
||||||
|
state->read_in >>= state->read_in_length % 8;
|
||||||
|
state->read_in_length = bytes * 8;
|
||||||
|
|
||||||
|
len = state->read_in & 0xFFFF;
|
||||||
|
state->read_in >>= 16;
|
||||||
|
nlen = state->read_in & 0xFFFF;
|
||||||
|
state->read_in >>= 16;
|
||||||
|
state->read_in_length -= 32;
|
||||||
|
|
||||||
if (state->btype == 0) {
|
|
||||||
bytes = state->read_in_length / 8;
|
bytes = state->read_in_length / 8;
|
||||||
|
|
||||||
state->read_in = 0;
|
|
||||||
state->read_in_length = 0;
|
|
||||||
state->next_in -= bytes;
|
state->next_in -= bytes;
|
||||||
state->avail_in += bytes;
|
state->avail_in += bytes;
|
||||||
return 0;
|
state->read_in = 0;
|
||||||
|
state->read_in_length = 0;
|
||||||
|
|
||||||
} else if (state->btype == 1)
|
/* Check if len and nlen match */
|
||||||
return setup_static_header(state);
|
if (len != (~nlen & 0xffff))
|
||||||
|
return INVALID_NON_COMPRESSED_BLOCK_LENGTH;
|
||||||
|
|
||||||
else if (state->btype == 2)
|
state->type0_block_len = len;
|
||||||
return setup_dynamic_header(state);
|
state->block_state = ISAL_BLOCK_TYPE0;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
} else if (btype == 1)
|
||||||
|
ret = setup_static_header(state);
|
||||||
|
|
||||||
|
else if (btype == 2)
|
||||||
|
ret = setup_dynamic_header(state);
|
||||||
|
|
||||||
|
else
|
||||||
|
ret = INVALID_BLOCK_HEADER;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads in the header pointed to by in_stream and sets up state to reflect that
|
||||||
|
* header information*/
|
||||||
|
int read_header_stateful(struct inflate_state *state)
|
||||||
|
{
|
||||||
|
uint64_t read_in_start = state->read_in;
|
||||||
|
int32_t read_in_length_start = state->read_in_length;
|
||||||
|
uint8_t *next_in_start = state->next_in;
|
||||||
|
uint32_t avail_in_start = state->avail_in;
|
||||||
|
int block_state_start = state->block_state;
|
||||||
|
int ret;
|
||||||
|
int copy_size;
|
||||||
|
int bytes_read;
|
||||||
|
|
||||||
|
if (block_state_start == ISAL_BLOCK_HDR) {
|
||||||
|
/* Setup so read_header decodes data in tmp_in_buffer */
|
||||||
|
copy_size = ISAL_INFLATE_MAX_HDR_SIZE - state->tmp_in_size;
|
||||||
|
if (copy_size > state->avail_in)
|
||||||
|
copy_size = state->avail_in;
|
||||||
|
|
||||||
|
memcpy(&state->tmp_in_buffer[state->tmp_in_size], state->next_in, copy_size);
|
||||||
|
state->next_in = state->tmp_in_buffer;
|
||||||
|
state->avail_in = state->tmp_in_size + copy_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read_header(state);
|
||||||
|
|
||||||
|
if (block_state_start == ISAL_BLOCK_HDR) {
|
||||||
|
/* Setup so state is restored to a valid state */
|
||||||
|
bytes_read = state->next_in - state->tmp_in_buffer - state->tmp_in_size;
|
||||||
|
if (bytes_read < 0)
|
||||||
|
bytes_read = 0;
|
||||||
|
state->next_in = next_in_start + bytes_read;
|
||||||
|
state->avail_in = avail_in_start - bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == END_OF_INPUT) {
|
||||||
|
/* Save off data so header can be decoded again with more data */
|
||||||
|
state->read_in = read_in_start;
|
||||||
|
state->read_in_length = read_in_length_start;
|
||||||
|
memcpy(&state->tmp_in_buffer[state->tmp_in_size], next_in_start,
|
||||||
|
avail_in_start);
|
||||||
|
state->tmp_in_size += avail_in_start;
|
||||||
|
state->avail_in = 0;
|
||||||
|
state->next_in = next_in_start + avail_in_start;
|
||||||
|
state->block_state = ISAL_BLOCK_HDR;
|
||||||
|
} else
|
||||||
|
state->tmp_in_size = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
return INVALID_BLOCK_HEADER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int inline decode_literal_block(struct inflate_state *state)
|
int inline decode_literal_block(struct inflate_state *state)
|
||||||
{
|
{
|
||||||
uint16_t len, nlen;
|
uint32_t len = state->type0_block_len;
|
||||||
/* If the block is uncompressed, perform a memcopy while
|
/* If the block is uncompressed, perform a memcopy while
|
||||||
* updating state data */
|
* updating state data */
|
||||||
if (state->avail_in < 4)
|
|
||||||
return END_OF_INPUT;
|
|
||||||
|
|
||||||
len = *(uint16_t *) state->next_in;
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
state->next_in += 2;
|
|
||||||
nlen = *(uint16_t *) state->next_in;
|
|
||||||
state->next_in += 2;
|
|
||||||
|
|
||||||
/* Check if len and nlen match */
|
if (state->avail_out < len) {
|
||||||
if (len != (~nlen & 0xffff))
|
len = state->avail_out;
|
||||||
return INVALID_NON_COMPRESSED_BLOCK_LENGTH;
|
state->block_state = ISAL_BLOCK_TYPE0;
|
||||||
|
}
|
||||||
|
|
||||||
if (state->avail_out < len)
|
if (state->avail_in < len) {
|
||||||
return OUT_BUFFER_OVERFLOW;
|
|
||||||
|
|
||||||
if (state->avail_in < len)
|
|
||||||
len = state->avail_in;
|
len = state->avail_in;
|
||||||
|
state->block_state = ISAL_BLOCK_TYPE0;
|
||||||
else
|
}
|
||||||
state->new_block = 1;
|
|
||||||
|
|
||||||
memcpy(state->next_out, state->next_in, len);
|
memcpy(state->next_out, state->next_in, len);
|
||||||
|
|
||||||
@ -756,11 +834,15 @@ int inline decode_literal_block(struct inflate_state *state)
|
|||||||
state->avail_out -= len;
|
state->avail_out -= len;
|
||||||
state->total_out += len;
|
state->total_out += len;
|
||||||
state->next_in += len;
|
state->next_in += len;
|
||||||
state->avail_in -= len + 4;
|
state->avail_in -= len;
|
||||||
|
state->type0_block_len -= len;
|
||||||
|
|
||||||
if (state->avail_in == 0 && state->new_block == 0)
|
if (state->avail_in == 0 && state->block_state != ISAL_BLOCK_NEW_HDR)
|
||||||
return END_OF_INPUT;
|
return END_OF_INPUT;
|
||||||
|
|
||||||
|
if (state->avail_out == 0 && state->type0_block_len > 0)
|
||||||
|
return OUT_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -772,22 +854,45 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
uint8_t next_dist;
|
uint8_t next_dist;
|
||||||
uint32_t repeat_length;
|
uint32_t repeat_length;
|
||||||
uint32_t look_back_dist;
|
uint32_t look_back_dist;
|
||||||
|
uint64_t read_in_tmp;
|
||||||
|
int32_t read_in_length_tmp;
|
||||||
|
uint8_t *next_in_tmp;
|
||||||
|
uint32_t avail_in_tmp;
|
||||||
|
|
||||||
while (state->new_block == 0) {
|
state->copy_overflow_length = 0;
|
||||||
|
state->copy_overflow_distance = 0;
|
||||||
|
|
||||||
|
while (state->block_state == ISAL_BLOCK_CODED) {
|
||||||
/* While not at the end of block, decode the next
|
/* While not at the end of block, decode the next
|
||||||
* symbol */
|
* symbol */
|
||||||
|
inflate_in_load(state, 0);
|
||||||
|
|
||||||
|
read_in_tmp = state->read_in;
|
||||||
|
read_in_length_tmp = state->read_in_length;
|
||||||
|
next_in_tmp = state->next_in;
|
||||||
|
avail_in_tmp = state->avail_in;
|
||||||
|
|
||||||
next_lit = decode_next_large(state, &state->lit_huff_code);
|
next_lit = decode_next_large(state, &state->lit_huff_code);
|
||||||
|
|
||||||
if (state->read_in_length < 0)
|
if (state->read_in_length < 0) {
|
||||||
|
state->read_in = read_in_tmp;
|
||||||
|
state->read_in_length = read_in_length_tmp;
|
||||||
|
state->next_in = next_in_tmp;
|
||||||
|
state->avail_in = avail_in_tmp;
|
||||||
return END_OF_INPUT;
|
return END_OF_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (next_lit < 256) {
|
if (next_lit < 256) {
|
||||||
/* If the next symbol is a literal,
|
/* If the next symbol is a literal,
|
||||||
* write out the symbol and update state
|
* write out the symbol and update state
|
||||||
* data accordingly. */
|
* data accordingly. */
|
||||||
if (state->avail_out < 1)
|
if (state->avail_out < 1) {
|
||||||
|
state->read_in = read_in_tmp;
|
||||||
|
state->read_in_length = read_in_length_tmp;
|
||||||
|
state->next_in = next_in_tmp;
|
||||||
|
state->avail_in = avail_in_tmp;
|
||||||
return OUT_BUFFER_OVERFLOW;
|
return OUT_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
*state->next_out = next_lit;
|
*state->next_out = next_lit;
|
||||||
state->next_out++;
|
state->next_out++;
|
||||||
@ -798,7 +903,7 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
/* If the next symbol is the end of
|
/* If the next symbol is the end of
|
||||||
* block, update the state data
|
* block, update the state data
|
||||||
* accordingly */
|
* accordingly */
|
||||||
state->new_block = 1;
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
|
|
||||||
} else if (next_lit < 286) {
|
} else if (next_lit < 286) {
|
||||||
/* Else if the next symbol is a repeat
|
/* Else if the next symbol is a repeat
|
||||||
@ -812,10 +917,6 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
inflate_in_read_bits(state,
|
inflate_in_read_bits(state,
|
||||||
rfc_lookup_table.len_extra_bit_count[next_lit
|
rfc_lookup_table.len_extra_bit_count[next_lit
|
||||||
- 257]);
|
- 257]);
|
||||||
|
|
||||||
if (state->avail_out < repeat_length)
|
|
||||||
return OUT_BUFFER_OVERFLOW;
|
|
||||||
|
|
||||||
next_dist = decode_next_small(state, &state->dist_huff_code);
|
next_dist = decode_next_small(state, &state->dist_huff_code);
|
||||||
|
|
||||||
look_back_dist = rfc_lookup_table.dist_start[next_dist] +
|
look_back_dist = rfc_lookup_table.dist_start[next_dist] +
|
||||||
@ -823,12 +924,23 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
rfc_lookup_table.dist_extra_bit_count
|
rfc_lookup_table.dist_extra_bit_count
|
||||||
[next_dist]);
|
[next_dist]);
|
||||||
|
|
||||||
if (state->read_in_length < 0)
|
if (state->read_in_length < 0) {
|
||||||
|
state->read_in = read_in_tmp;
|
||||||
|
state->read_in_length = read_in_length_tmp;
|
||||||
|
state->next_in = next_in_tmp;
|
||||||
|
state->avail_in = avail_in_tmp;
|
||||||
return END_OF_INPUT;
|
return END_OF_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (look_back_dist > state->total_out)
|
if (look_back_dist > state->total_out)
|
||||||
return INVALID_LOOK_BACK_DISTANCE;
|
return INVALID_LOOK_BACK_DISTANCE;
|
||||||
|
|
||||||
|
if (state->avail_out < repeat_length) {
|
||||||
|
state->copy_overflow_length = repeat_length - state->avail_out;
|
||||||
|
state->copy_overflow_distance = look_back_dist;
|
||||||
|
repeat_length = state->avail_out;
|
||||||
|
}
|
||||||
|
|
||||||
if (look_back_dist > repeat_length)
|
if (look_back_dist > repeat_length)
|
||||||
memcpy(state->next_out,
|
memcpy(state->next_out,
|
||||||
state->next_out - look_back_dist, repeat_length);
|
state->next_out - look_back_dist, repeat_length);
|
||||||
@ -838,6 +950,9 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
state->next_out += repeat_length;
|
state->next_out += repeat_length;
|
||||||
state->avail_out -= repeat_length;
|
state->avail_out -= repeat_length;
|
||||||
state->total_out += repeat_length;
|
state->total_out += repeat_length;
|
||||||
|
|
||||||
|
if (state->copy_overflow_length > 0)
|
||||||
|
return OUT_BUFFER_OVERFLOW;
|
||||||
} else
|
} else
|
||||||
/* Else the read in bits do not
|
/* Else the read in bits do not
|
||||||
* correspond to any valid symbol */
|
* correspond to any valid symbol */
|
||||||
@ -846,45 +961,206 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void isal_inflate_init(struct inflate_state *state, uint8_t * in_stream, uint32_t in_size,
|
void isal_inflate_init(struct inflate_state *state)
|
||||||
uint8_t * out_stream, uint64_t out_size)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
state->read_in = 0;
|
state->read_in = 0;
|
||||||
state->read_in_length = 0;
|
state->read_in_length = 0;
|
||||||
state->next_in = in_stream;
|
state->next_in = NULL;
|
||||||
state->avail_in = in_size;
|
state->avail_in = 0;
|
||||||
state->next_out = out_stream;
|
state->next_out = NULL;
|
||||||
state->avail_out = out_size;
|
state->avail_out = 0;
|
||||||
state->total_out = 0;
|
state->total_out = 0;
|
||||||
state->new_block = 1;
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
state->bfinal = 0;
|
state->bfinal = 0;
|
||||||
|
state->type0_block_len = 0;
|
||||||
|
state->copy_overflow_length = 0;
|
||||||
|
state->copy_overflow_distance = 0;
|
||||||
|
state->tmp_in_size = 0;
|
||||||
|
state->tmp_out_processed = 0;
|
||||||
|
state->tmp_out_valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isal_inflate_stateless(struct inflate_state *state)
|
int isal_inflate_stateless(struct inflate_state *state)
|
||||||
{
|
{
|
||||||
uint32_t ret;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
while (state->new_block == 0 || state->bfinal == 0) {
|
state->read_in = 0;
|
||||||
if (state->new_block != 0) {
|
state->read_in_length = 0;
|
||||||
|
state->block_state = ISAL_BLOCK_NEW_HDR;
|
||||||
|
state->bfinal = 0;
|
||||||
|
state->total_out = 0;
|
||||||
|
|
||||||
|
while (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
||||||
|
if (state->block_state == ISAL_BLOCK_NEW_HDR) {
|
||||||
ret = read_header(state);
|
ret = read_header(state);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->btype == 0)
|
if (state->block_state == ISAL_BLOCK_TYPE0)
|
||||||
ret = decode_literal_block(state);
|
ret = decode_literal_block(state);
|
||||||
else
|
else
|
||||||
ret = decode_huffman_code_block_stateless(state);
|
ret = decode_huffman_code_block_stateless(state);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
break;
|
||||||
|
if (state->bfinal != 0 && state->block_state == ISAL_BLOCK_NEW_HDR)
|
||||||
|
state->block_state = ISAL_BLOCK_INPUT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Undo count stuff of bytes read into the read buffer */
|
/* Undo count stuff of bytes read into the read buffer */
|
||||||
state->next_in -= state->read_in_length / 8;
|
state->next_in -= state->read_in_length / 8;
|
||||||
state->avail_in += state->read_in_length / 8;
|
state->avail_in += state->read_in_length / 8;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isal_inflate(struct inflate_state *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t *next_out = state->next_out;
|
||||||
|
uint32_t avail_out = state->avail_out;
|
||||||
|
uint32_t copy_size = 0;
|
||||||
|
int32_t shift_size = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (state->block_state != ISAL_BLOCK_FINISH) {
|
||||||
|
/* If space in tmp_out buffer, decompress into the tmp_out_buffer */
|
||||||
|
if (state->tmp_out_valid < 2 * ISAL_INFLATE_HIST_SIZE) {
|
||||||
|
/* Setup to start decoding into temp buffer */
|
||||||
|
state->next_out = &state->tmp_out_buffer[state->tmp_out_valid];
|
||||||
|
state->avail_out =
|
||||||
|
sizeof(state->tmp_out_buffer) - ISAL_INFLATE_SLOP -
|
||||||
|
state->tmp_out_valid;
|
||||||
|
|
||||||
|
if ((int32_t) state->avail_out < 0)
|
||||||
|
state->avail_out = 0;
|
||||||
|
|
||||||
|
/* Decode into internal buffer until exit */
|
||||||
|
while (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
||||||
|
if (state->block_state == ISAL_BLOCK_NEW_HDR
|
||||||
|
|| state->block_state == ISAL_BLOCK_HDR) {
|
||||||
|
ret = read_header_stateful(state);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->block_state == ISAL_BLOCK_TYPE0) {
|
||||||
|
ret = decode_literal_block(state);
|
||||||
|
} else
|
||||||
|
ret = decode_huffman_code_block_stateless(state);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
if (state->bfinal != 0
|
||||||
|
&& state->block_state == ISAL_BLOCK_NEW_HDR)
|
||||||
|
state->block_state = ISAL_BLOCK_INPUT_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy valid data from internal buffer into out_buffer */
|
||||||
|
if (state->copy_overflow_length != 0) {
|
||||||
|
byte_copy(state->next_out, state->copy_overflow_distance,
|
||||||
|
state->copy_overflow_length);
|
||||||
|
state->tmp_out_valid += state->copy_overflow_length;
|
||||||
|
state->next_out += state->copy_overflow_length;
|
||||||
|
state->total_out += state->copy_overflow_length;
|
||||||
|
state->copy_overflow_distance = 0;
|
||||||
|
state->copy_overflow_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->tmp_out_valid = state->next_out - state->tmp_out_buffer;
|
||||||
|
|
||||||
|
/* Setup state for decompressing into out_buffer */
|
||||||
|
state->next_out = next_out;
|
||||||
|
state->avail_out = avail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy data from tmp_out buffer into out_buffer */
|
||||||
|
copy_size = state->tmp_out_valid - state->tmp_out_processed;
|
||||||
|
if (copy_size > avail_out)
|
||||||
|
copy_size = avail_out;
|
||||||
|
|
||||||
|
memcpy(state->next_out,
|
||||||
|
&state->tmp_out_buffer[state->tmp_out_processed], copy_size);
|
||||||
|
|
||||||
|
state->tmp_out_processed += copy_size;
|
||||||
|
state->avail_out -= copy_size;
|
||||||
|
state->next_out += copy_size;
|
||||||
|
|
||||||
|
if (ret == INVALID_LOOK_BACK_DISTANCE || ret == INVALID_BLOCK_HEADER
|
||||||
|
|| ret == INVALID_NON_COMPRESSED_BLOCK_LENGTH) {
|
||||||
|
/* Set total_out to not count data in tmp_out_buffer */
|
||||||
|
state->total_out -= state->tmp_out_valid - state->tmp_out_processed;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all data from tmp_out buffer has been processed, start
|
||||||
|
* decompressing into the out buffer */
|
||||||
|
if (state->tmp_out_processed == state->tmp_out_valid) {
|
||||||
|
while (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
||||||
|
if (state->block_state == ISAL_BLOCK_NEW_HDR
|
||||||
|
|| state->block_state == ISAL_BLOCK_HDR) {
|
||||||
|
ret = read_header_stateful(state);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->block_state == ISAL_BLOCK_TYPE0)
|
||||||
|
ret = decode_literal_block(state);
|
||||||
|
else
|
||||||
|
ret = decode_huffman_code_block_stateless(state);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
if (state->bfinal != 0
|
||||||
|
&& state->block_state == ISAL_BLOCK_NEW_HDR)
|
||||||
|
state->block_state = ISAL_BLOCK_INPUT_DONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
||||||
|
/* Save decompression history in tmp_out buffer */
|
||||||
|
if (state->tmp_out_valid == state->tmp_out_processed
|
||||||
|
&& avail_out - state->avail_out >= ISAL_INFLATE_HIST_SIZE) {
|
||||||
|
memcpy(state->tmp_out_buffer,
|
||||||
|
state->next_out - ISAL_INFLATE_HIST_SIZE,
|
||||||
|
ISAL_INFLATE_HIST_SIZE);
|
||||||
|
state->tmp_out_valid = ISAL_INFLATE_HIST_SIZE;
|
||||||
|
state->tmp_out_processed = ISAL_INFLATE_HIST_SIZE;
|
||||||
|
|
||||||
|
} else if (state->tmp_out_processed >= ISAL_INFLATE_HIST_SIZE) {
|
||||||
|
shift_size = state->tmp_out_valid - ISAL_INFLATE_HIST_SIZE;
|
||||||
|
if (shift_size > state->tmp_out_processed)
|
||||||
|
shift_size = state->tmp_out_processed;
|
||||||
|
|
||||||
|
memmove(state->tmp_out_buffer,
|
||||||
|
&state->tmp_out_buffer[shift_size],
|
||||||
|
state->tmp_out_valid - shift_size);
|
||||||
|
state->tmp_out_valid -= shift_size;
|
||||||
|
state->tmp_out_processed -= shift_size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->copy_overflow_length != 0) {
|
||||||
|
byte_copy(&state->tmp_out_buffer[state->tmp_out_valid],
|
||||||
|
state->copy_overflow_distance,
|
||||||
|
state->copy_overflow_length);
|
||||||
|
state->tmp_out_valid += state->copy_overflow_length;
|
||||||
|
state->total_out += state->copy_overflow_length;
|
||||||
|
state->copy_overflow_distance = 0;
|
||||||
|
state->copy_overflow_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == INVALID_LOOK_BACK_DISTANCE
|
||||||
|
|| ret == INVALID_BLOCK_HEADER
|
||||||
|
|| ret == INVALID_NON_COMPRESSED_BLOCK_LENGTH)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
} else if (state->tmp_out_valid == state->tmp_out_processed)
|
||||||
|
state->block_state = ISAL_BLOCK_FINISH;
|
||||||
|
}
|
||||||
|
|
||||||
return DECOMPRESSION_FINISHED;
|
return DECOMPRESSION_FINISHED;
|
||||||
}
|
}
|
||||||
|
@ -208,9 +208,13 @@ int main(int argc, char *argv[])
|
|||||||
perf_start(&start);
|
perf_start(&start);
|
||||||
|
|
||||||
for (i = 0; i < iterations; i++) {
|
for (i = 0; i < iterations; i++) {
|
||||||
isal_inflate_init(&state, inbuf, inbuf_size, outbuf, outbuf_size);
|
isal_inflate_init(&state);
|
||||||
|
state.next_in = inbuf;
|
||||||
|
state.avail_in = inbuf_size;
|
||||||
|
state.next_out = outbuf;
|
||||||
|
state.avail_out = outbuf_size;
|
||||||
|
|
||||||
check = isal_inflate_stateless(&state);
|
check = isal_inflate(&state);
|
||||||
if (check) {
|
if (check) {
|
||||||
printf("Error in decompression with error %d\n", check);
|
printf("Error in decompression with error %d\n", check);
|
||||||
break;
|
break;
|
||||||
|
@ -37,24 +37,129 @@
|
|||||||
* are done in a stateless manner. */
|
* are done in a stateless manner. */
|
||||||
#define MAX_INPUT_FILE_SIZE 2L*1024L*1024L*1024L
|
#define MAX_INPUT_FILE_SIZE 2L*1024L*1024L*1024L
|
||||||
|
|
||||||
int test(uint8_t * compressed_stream, uint64_t * compressed_length,
|
int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||||
uint8_t * uncompressed_stream, int uncompressed_length,
|
uint8_t * uncompress_buf, uint32_t * uncompress_len)
|
||||||
uint8_t * uncompressed_test_stream, int uncompressed_test_stream_length)
|
{
|
||||||
|
struct inflate_state *state = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
uint8_t *comp_tmp = NULL, *uncomp_tmp = NULL;
|
||||||
|
uint32_t comp_tmp_size = 0, uncomp_tmp_size = 0;
|
||||||
|
uint32_t comp_processed = 0, uncomp_processed = 0;
|
||||||
|
|
||||||
|
state = malloc(sizeof(struct inflate_state));
|
||||||
|
if (state == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isal_inflate_init(state);
|
||||||
|
|
||||||
|
state->next_in = NULL;
|
||||||
|
state->next_out = NULL;
|
||||||
|
state->avail_in = 0;
|
||||||
|
state->avail_out = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (state->avail_in == 0) {
|
||||||
|
comp_tmp_size = rand() % (compress_len + 1);
|
||||||
|
|
||||||
|
if (comp_tmp_size >= compress_len - comp_processed)
|
||||||
|
comp_tmp_size = compress_len - comp_processed;
|
||||||
|
|
||||||
|
if (comp_tmp_size != 0) {
|
||||||
|
if (comp_tmp != NULL) {
|
||||||
|
free(comp_tmp);
|
||||||
|
comp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp_tmp = malloc(comp_tmp_size);
|
||||||
|
|
||||||
|
if (comp_tmp == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(comp_tmp, compress_buf + comp_processed, comp_tmp_size);
|
||||||
|
comp_processed += comp_tmp_size;
|
||||||
|
|
||||||
|
state->next_in = comp_tmp;
|
||||||
|
state->avail_in = comp_tmp_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->avail_out == 0) {
|
||||||
|
/* Save uncompressed data into uncompress_buf */
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
memcpy(uncompress_buf + uncomp_processed, uncomp_tmp,
|
||||||
|
uncomp_tmp_size);
|
||||||
|
uncomp_processed += uncomp_tmp_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncomp_tmp_size = rand() % (*uncompress_len + 1);
|
||||||
|
|
||||||
|
/* Limit size of buffer to be smaller than maximum */
|
||||||
|
if (uncomp_tmp_size > *uncompress_len - uncomp_processed)
|
||||||
|
uncomp_tmp_size = *uncompress_len - uncomp_processed;
|
||||||
|
|
||||||
|
if (uncomp_tmp_size != 0) {
|
||||||
|
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
fflush(0);
|
||||||
|
free(uncomp_tmp);
|
||||||
|
uncomp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncomp_tmp = malloc(uncomp_tmp_size);
|
||||||
|
if (uncomp_tmp == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->avail_out = uncomp_tmp_size;
|
||||||
|
state->next_out = uncomp_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = isal_inflate(state);
|
||||||
|
|
||||||
|
if (state->block_state == ISAL_BLOCK_FINISH || ret != 0) {
|
||||||
|
memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, uncomp_tmp_size);
|
||||||
|
*uncompress_len = state->total_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp_tmp != NULL) {
|
||||||
|
free(comp_tmp);
|
||||||
|
comp_tmp = NULL;
|
||||||
|
}
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
free(uncomp_tmp);
|
||||||
|
uncomp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test(uint8_t * compressed_stream,
|
||||||
|
uint64_t * compressed_length,
|
||||||
|
uint8_t * uncompressed_stream, uint32_t uncompressed_length,
|
||||||
|
uint8_t * uncompressed_test_stream, uint32_t uncompressed_test_stream_length)
|
||||||
{
|
{
|
||||||
struct inflate_state state;
|
|
||||||
int ret;
|
int ret;
|
||||||
ret =
|
ret =
|
||||||
compress2(compressed_stream, compressed_length, uncompressed_stream,
|
compress2(compressed_stream, compressed_length,
|
||||||
uncompressed_length, 6);
|
uncompressed_stream, uncompressed_length, 6);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("Failed compressing input with exit code %d", ret);
|
printf("Failed compressing input with exit code %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
isal_inflate_init(&state, compressed_stream + 2, *compressed_length - 2,
|
ret =
|
||||||
uncompressed_test_stream, uncompressed_test_stream_length);
|
inflate_multi_pass(compressed_stream + 2,
|
||||||
ret = isal_inflate_stateless(&state);
|
*compressed_length - 2 - 4,
|
||||||
|
uncompressed_test_stream, &uncompressed_test_stream_length);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
@ -88,10 +193,10 @@ int test(uint8_t * compressed_stream, uint64_t * compressed_length,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.total_out != uncompressed_length) {
|
if (uncompressed_test_stream_length != uncompressed_length) {
|
||||||
printf("incorrect amount of data was decompressed from compressed data\n");
|
printf("incorrect amount of data was decompressed from compressed data\n");
|
||||||
printf("%d decompressed of %d compressed", state.total_out,
|
printf("%d decompressed of %d compressed",
|
||||||
uncompressed_length);
|
uncompressed_test_stream_length, uncompressed_length);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (memcmp(uncompressed_stream, uncompressed_test_stream, uncompressed_length)) {
|
if (memcmp(uncompressed_stream, uncompressed_test_stream, uncompressed_length)) {
|
||||||
@ -105,6 +210,7 @@ int test(uint8_t * compressed_stream, uint64_t * compressed_length,
|
|||||||
printf(" decompressed data is not the same as the compressed data\n");
|
printf(" decompressed data is not the same as the compressed data\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +226,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
printf("Error, no input file\n");
|
printf("Error, no input file\n");
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
file = fopen(argv[i], "r");
|
file = fopen(argv[i], "r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
@ -128,7 +233,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
} else
|
} else
|
||||||
printf("Starting file %s", argv[i]);
|
printf("Starting file %s", argv[i]);
|
||||||
|
fflush(0);
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
file_length = ftell(file);
|
file_length = ftell(file);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
@ -145,7 +250,6 @@ int main(int argc, char **argv)
|
|||||||
uncompressed_test_stream = malloc(file_length);
|
uncompressed_test_stream = malloc(file_length);
|
||||||
}
|
}
|
||||||
compressed_stream = malloc(compressed_length);
|
compressed_stream = malloc(compressed_length);
|
||||||
|
|
||||||
if (uncompressed_stream == NULL && file_length != 0) {
|
if (uncompressed_stream == NULL && file_length != 0) {
|
||||||
printf("Failed to allocate memory\n");
|
printf("Failed to allocate memory\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -163,7 +267,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
uncompressed_length = fread(uncompressed_stream, 1, file_length, file);
|
uncompressed_length = fread(uncompressed_stream, 1, file_length, file);
|
||||||
uncompressed_test_stream_length = uncompressed_length;
|
uncompressed_test_stream_length = uncompressed_length;
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
test(compressed_stream, &compressed_length, uncompressed_stream,
|
test(compressed_stream, &compressed_length, uncompressed_stream,
|
||||||
uncompressed_length, uncompressed_test_stream,
|
uncompressed_length, uncompressed_test_stream,
|
||||||
@ -175,10 +278,8 @@ int main(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
printf(" ");
|
printf(" ");
|
||||||
printf("0x%02x,", compressed_stream[j]);
|
printf("0x%02x,", compressed_stream[j]);
|
||||||
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(0);
|
fflush(0);
|
||||||
@ -188,13 +289,11 @@ int main(int argc, char **argv)
|
|||||||
free(uncompressed_stream);
|
free(uncompressed_stream);
|
||||||
if (uncompressed_test_stream != NULL)
|
if (uncompressed_test_stream != NULL)
|
||||||
free(uncompressed_test_stream);
|
free(uncompressed_test_stream);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf(" ... Fail with exit code %d\n", ret);
|
printf(" ... Fail with exit code %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
} else
|
} else
|
||||||
printf(" ... Pass\n");
|
printf(" ... Pass\n");
|
||||||
|
|
||||||
fin_ret |= ret;
|
fin_ret |= ret;
|
||||||
}
|
}
|
||||||
return fin_ret;
|
return fin_ret;
|
||||||
|
@ -113,6 +113,8 @@ const int gzip_extra_bytes = 0;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int inflate_type = 0;
|
||||||
|
|
||||||
struct isal_hufftables *hufftables = NULL;
|
struct isal_hufftables *hufftables = NULL;
|
||||||
|
|
||||||
#define HISTORY_SIZE 32*1024
|
#define HISTORY_SIZE 32*1024
|
||||||
@ -306,29 +308,192 @@ uint32_t check_gzip_header(uint8_t * z_buf)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t check_gzip_trl(struct inflate_state * gstream)
|
uint32_t check_gzip_trl(uint64_t gzip_crc, uint8_t * uncompress_buf, uint32_t uncompress_len)
|
||||||
{
|
{
|
||||||
uint8_t *index = NULL;
|
uint64_t crc, ret = 0;
|
||||||
uint32_t crc, ret = 0;
|
|
||||||
|
|
||||||
index = gstream->next_out - gstream->total_out;
|
crc = find_crc(uncompress_buf, uncompress_len);
|
||||||
crc = find_crc(index, gstream->total_out);
|
|
||||||
|
|
||||||
if (gstream->total_out != *(uint32_t *) (gstream->next_in + 4) ||
|
crc = ((uint64_t) uncompress_len << 32) | crc;
|
||||||
crc != *(uint32_t *) gstream->next_in)
|
|
||||||
|
if (crc != gzip_crc)
|
||||||
ret = INCORRECT_GZIP_TRAILER;
|
ret = INCORRECT_GZIP_TRAILER;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int inflate_stateless_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||||
|
uint8_t * uncompress_buf, uint32_t * uncompress_len)
|
||||||
|
{
|
||||||
|
struct inflate_state state;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
state.next_in = compress_buf;
|
||||||
|
state.avail_in = compress_len;
|
||||||
|
state.next_out = uncompress_buf;
|
||||||
|
state.avail_out = *uncompress_len;
|
||||||
|
|
||||||
|
ret = isal_inflate_stateless(&state);
|
||||||
|
|
||||||
|
*uncompress_len = state.total_out;
|
||||||
|
|
||||||
|
#ifndef DEFLATE
|
||||||
|
if (!ret)
|
||||||
|
ret =
|
||||||
|
check_gzip_trl(*(uint64_t *) state.next_in, uncompress_buf,
|
||||||
|
*uncompress_len);
|
||||||
|
state.avail_in -= 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret == 0 && state.avail_in != 0)
|
||||||
|
ret = INFLATE_LEFTOVER_INPUT;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inflate_multi_pass(uint8_t * compress_buf, uint64_t compress_len,
|
||||||
|
uint8_t * uncompress_buf, uint32_t * uncompress_len)
|
||||||
|
{
|
||||||
|
struct inflate_state *state = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
uint8_t *comp_tmp = NULL, *uncomp_tmp = NULL;
|
||||||
|
uint32_t comp_tmp_size = 0, uncomp_tmp_size = 0;
|
||||||
|
uint32_t comp_processed = 0, uncomp_processed = 0;
|
||||||
|
int32_t read_in_old = 0;
|
||||||
|
|
||||||
|
state = malloc(sizeof(struct inflate_state));
|
||||||
|
if (state == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isal_inflate_init(state);
|
||||||
|
|
||||||
|
state->next_in = NULL;
|
||||||
|
state->next_out = NULL;
|
||||||
|
state->avail_in = 0;
|
||||||
|
state->avail_out = 0;
|
||||||
|
|
||||||
|
#ifndef DEFLATE
|
||||||
|
compress_len -= 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (state->avail_in == 0) {
|
||||||
|
comp_tmp_size = rand() % (compress_len + 1);
|
||||||
|
|
||||||
|
if (comp_tmp_size >= compress_len - comp_processed)
|
||||||
|
comp_tmp_size = compress_len - comp_processed;
|
||||||
|
|
||||||
|
if (comp_tmp_size != 0) {
|
||||||
|
if (comp_tmp != NULL) {
|
||||||
|
free(comp_tmp);
|
||||||
|
comp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp_tmp = malloc(comp_tmp_size);
|
||||||
|
|
||||||
|
if (comp_tmp == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
return MALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(comp_tmp, compress_buf + comp_processed, comp_tmp_size);
|
||||||
|
comp_processed += comp_tmp_size;
|
||||||
|
|
||||||
|
state->next_in = comp_tmp;
|
||||||
|
state->avail_in = comp_tmp_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->avail_out == 0) {
|
||||||
|
/* Save uncompressed data into uncompress_buf */
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
memcpy(uncompress_buf + uncomp_processed, uncomp_tmp,
|
||||||
|
uncomp_tmp_size);
|
||||||
|
uncomp_processed += uncomp_tmp_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncomp_tmp_size = rand() % (*uncompress_len + 1);
|
||||||
|
|
||||||
|
/* Limit size of buffer to be smaller than maximum */
|
||||||
|
if (uncomp_tmp_size > *uncompress_len - uncomp_processed)
|
||||||
|
uncomp_tmp_size = *uncompress_len - uncomp_processed;
|
||||||
|
|
||||||
|
if (uncomp_tmp_size != 0) {
|
||||||
|
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
fflush(0);
|
||||||
|
free(uncomp_tmp);
|
||||||
|
uncomp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncomp_tmp = malloc(uncomp_tmp_size);
|
||||||
|
if (uncomp_tmp == NULL) {
|
||||||
|
printf("Failed to allocate memory\n");
|
||||||
|
return MALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->avail_out = uncomp_tmp_size;
|
||||||
|
state->next_out = uncomp_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = isal_inflate(state);
|
||||||
|
|
||||||
|
if (state->block_state == ISAL_BLOCK_FINISH || ret != 0) {
|
||||||
|
memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, uncomp_tmp_size);
|
||||||
|
*uncompress_len = state->total_out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*uncompress_len - uncomp_processed == 0 && state->avail_out == 0
|
||||||
|
&& state->tmp_out_valid - state->tmp_out_processed > 0) {
|
||||||
|
ret = INFLATE_OUT_BUFFER_OVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compress_len - comp_processed == 0 && state->avail_in == 0
|
||||||
|
&& (state->block_state != ISAL_BLOCK_INPUT_DONE)
|
||||||
|
&& state->tmp_out_valid - state->tmp_out_processed == 0) {
|
||||||
|
if (state->read_in_length == read_in_old) {
|
||||||
|
ret = INFLATE_END_OF_INPUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read_in_old = state->read_in_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DEFLATE
|
||||||
|
if (!ret)
|
||||||
|
ret =
|
||||||
|
check_gzip_trl(*(uint64_t *) & compress_buf[compress_len],
|
||||||
|
uncompress_buf, *uncompress_len);
|
||||||
|
#endif
|
||||||
|
if (ret == 0 && state->avail_in != 0)
|
||||||
|
ret = INFLATE_LEFTOVER_INPUT;
|
||||||
|
|
||||||
|
if (comp_tmp != NULL) {
|
||||||
|
free(comp_tmp);
|
||||||
|
comp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uncomp_tmp != NULL) {
|
||||||
|
free(uncomp_tmp);
|
||||||
|
uncomp_tmp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Inflate the compressed data and check that the decompressed data agrees with the input data */
|
/* 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)
|
int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
||||||
{
|
{
|
||||||
/* Test inflate with reference inflate */
|
/* Test inflate with reference inflate */
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct inflate_state gstream;
|
|
||||||
uint32_t test_size = in_size;
|
uint32_t test_size = in_size;
|
||||||
uint8_t *test_buf = NULL;
|
uint8_t *test_buf = NULL;
|
||||||
int mem_result = 0;
|
int mem_result = 0;
|
||||||
@ -336,23 +501,27 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
|||||||
if (in_size > 0) {
|
if (in_size > 0) {
|
||||||
assert(in_buf != NULL);
|
assert(in_buf != NULL);
|
||||||
test_buf = malloc(test_size);
|
test_buf = malloc(test_size);
|
||||||
|
|
||||||
if (test_buf == NULL)
|
if (test_buf == NULL)
|
||||||
return MALLOC_FAILED;
|
return MALLOC_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_buf != NULL)
|
if (test_buf != NULL)
|
||||||
memset(test_buf, 0xff, test_size);
|
memset(test_buf, 0xff, test_size);
|
||||||
|
|
||||||
#ifndef DEFLATE
|
#ifndef DEFLATE
|
||||||
int gzip_hdr_result, gzip_trl_result;
|
int gzip_hdr_result = 0, gzip_trl_result = 0;
|
||||||
|
|
||||||
gzip_hdr_result = check_gzip_header(z_buf);
|
gzip_hdr_result = check_gzip_header(z_buf);
|
||||||
z_buf += gzip_hdr_bytes;
|
z_buf += gzip_hdr_bytes;
|
||||||
z_size -= gzip_hdr_bytes;
|
z_size -= gzip_hdr_bytes;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isal_inflate_init(&gstream, z_buf, z_size, test_buf, test_size);
|
if (inflate_type == 0) {
|
||||||
ret = isal_inflate_stateless(&gstream);
|
ret = inflate_stateless_pass(z_buf, z_size, test_buf, &test_size);
|
||||||
|
inflate_type = 1;
|
||||||
|
} else {
|
||||||
|
ret = inflate_multi_pass(z_buf, z_size, test_buf, &test_size);
|
||||||
|
inflate_type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (test_buf != NULL)
|
if (test_buf != NULL)
|
||||||
mem_result = memcmp(in_buf, test_buf, in_size);
|
mem_result = memcmp(in_buf, test_buf, in_size);
|
||||||
@ -362,22 +531,16 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
|||||||
if (mem_result)
|
if (mem_result)
|
||||||
for (i = 0; i < in_size; i++) {
|
for (i = 0; i < in_size; i++) {
|
||||||
if (in_buf[i] != test_buf[i]) {
|
if (in_buf[i] != test_buf[i]) {
|
||||||
printf("First incorrect data at 0x%x of 0x%x, 0x%x != 0x%x\n",
|
printf
|
||||||
i, in_size, in_buf[i], test_buf[i]);
|
("First incorrect data at 0x%x of 0x%x, 0x%x != 0x%x\n",
|
||||||
|
i, in_size, in_buf[i], test_buf[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEFLATE
|
|
||||||
gzip_trl_result = check_gzip_trl(&gstream);
|
|
||||||
gstream.avail_in -= gzip_trl_bytes;
|
|
||||||
gstream.next_in += gzip_trl_bytes;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (test_buf != NULL)
|
if (test_buf != NULL)
|
||||||
free(test_buf);
|
free(test_buf);
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
@ -399,17 +562,22 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
|||||||
case INVALID_LOOK_BACK_DISTANCE:
|
case INVALID_LOOK_BACK_DISTANCE:
|
||||||
return INFLATE_INVALID_LOOK_BACK_DISTANCE;
|
return INFLATE_INVALID_LOOK_BACK_DISTANCE;
|
||||||
break;
|
break;
|
||||||
|
case INFLATE_LEFTOVER_INPUT:
|
||||||
|
return INFLATE_LEFTOVER_INPUT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifndef DEFLATE
|
||||||
|
case INCORRECT_GZIP_TRAILER:
|
||||||
|
gzip_trl_result = INCORRECT_GZIP_TRAILER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return INFLATE_GENERAL_ERROR;
|
return INFLATE_GENERAL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gstream.avail_in != 0) {
|
if (test_size != in_size)
|
||||||
printf("leftover = %d\n", gstream.avail_in);
|
|
||||||
return INFLATE_LEFTOVER_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gstream.total_out != in_size)
|
|
||||||
return INFLATE_INCORRECT_OUTPUT_SIZE;
|
return INFLATE_INCORRECT_OUTPUT_SIZE;
|
||||||
|
|
||||||
if (mem_result)
|
if (mem_result)
|
||||||
|
@ -61,9 +61,11 @@ FIELD _avail_in, 4, 4
|
|||||||
FIELD _read_in_length,4, 4
|
FIELD _read_in_length,4, 4
|
||||||
FIELD _lit_huff_code, _inflate_huff_code_large_size, _inflate_huff_code_large_align
|
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 _dist_huff_code,_inflate_huff_code_small_size, _inflate_huff_code_small_align
|
||||||
FIELD _new_block, 1, 1
|
FIELD _block_state, 4, 4
|
||||||
FIELD _bfinal, 1, 1
|
FIELD _bfinal, 4, 4
|
||||||
FIELD _btype, 1, 1
|
FIELD _type0_block_len, 4, 4
|
||||||
|
FIELD _copy_overflow_len, 4, 4
|
||||||
|
FIELD _copy_overflow_dist, 4, 4
|
||||||
|
|
||||||
%assign _inflate_state_size _FIELD_OFFSET
|
%assign _inflate_state_size _FIELD_OFFSET
|
||||||
%assign _inflate_state_align _STRUCT_ALIGN
|
%assign _inflate_state_align _STRUCT_ALIGN
|
||||||
@ -74,7 +76,12 @@ _lit_huff_code_long_code_lookup equ _lit_huff_code+_long_code_lookup_large
|
|||||||
_dist_huff_code_small_code_lookup equ _dist_huff_code+_small_code_lookup_small
|
_dist_huff_code_small_code_lookup equ _dist_huff_code+_small_code_lookup_small
|
||||||
_dist_huff_code_long_code_lookup equ _dist_huff_code+_long_code_lookup_small
|
_dist_huff_code_long_code_lookup equ _dist_huff_code+_long_code_lookup_small
|
||||||
|
|
||||||
|
ISAL_BLOCK_NEW_HDR equ 0
|
||||||
|
ISAL_BLOCK_HDR equ 1
|
||||||
|
ISAL_BLOCK_TYPE0 equ 2
|
||||||
|
ISAL_BLOCK_CODED equ 3
|
||||||
|
ISAL_BLOCK_END equ 4
|
||||||
|
ISAL_BLOCK_FINISH equ 5
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -16,6 +16,18 @@
|
|||||||
#define DECODE_LOOKUP_SIZE_LARGE 13
|
#define DECODE_LOOKUP_SIZE_LARGE 13
|
||||||
#define DECODE_LOOKUP_SIZE_SMALL 10
|
#define DECODE_LOOKUP_SIZE_SMALL 10
|
||||||
|
|
||||||
|
#define ISAL_INFLATE_HIST_SIZE (32*1024)
|
||||||
|
#define ISAL_INFLATE_SLOP 17*16
|
||||||
|
#define ISAL_INFLATE_MAX_HDR_SIZE 360
|
||||||
|
enum isal_block_state {
|
||||||
|
ISAL_BLOCK_NEW_HDR, /* Just starting a new block */
|
||||||
|
ISAL_BLOCK_HDR, /* In the middle of reading in a block header */
|
||||||
|
ISAL_BLOCK_TYPE0, /* Decoding a type 0 block */
|
||||||
|
ISAL_BLOCK_CODED, /* Decoding a huffman coded block */
|
||||||
|
ISAL_BLOCK_INPUT_DONE, /* Decompression of input is completed */
|
||||||
|
ISAL_BLOCK_FINISH /* Decompression of input is completed and all data has been flushed to output */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structure used to store a Huffman code for fast lookup. It works by
|
* Data structure used to store a Huffman code for fast lookup. It works by
|
||||||
* performing a lookup in small_code_lookup that hopefully yields the correct
|
* performing a lookup in small_code_lookup that hopefully yields the correct
|
||||||
@ -62,14 +74,13 @@
|
|||||||
* code length and code value forces the maximum offset to be less than 288.
|
* code length and code value forces the maximum offset to be less than 288.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct inflate_huff_code_large{
|
struct inflate_huff_code_large {
|
||||||
uint16_t short_code_lookup[ 1 << (DECODE_LOOKUP_SIZE_LARGE)];
|
uint16_t short_code_lookup[1 << (DECODE_LOOKUP_SIZE_LARGE)];
|
||||||
uint16_t long_code_lookup[288 + (1 << (15 - DECODE_LOOKUP_SIZE_LARGE))];
|
uint16_t long_code_lookup[288 + (1 << (15 - DECODE_LOOKUP_SIZE_LARGE))];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct inflate_huff_code_small {
|
||||||
struct inflate_huff_code_small{
|
uint16_t short_code_lookup[1 << (DECODE_LOOKUP_SIZE_SMALL)];
|
||||||
uint16_t short_code_lookup[ 1 << (DECODE_LOOKUP_SIZE_SMALL)];
|
|
||||||
uint16_t long_code_lookup[32 + (1 << (15 - DECODE_LOOKUP_SIZE_SMALL))];
|
uint16_t long_code_lookup[32 + (1 << (15 - DECODE_LOOKUP_SIZE_SMALL))];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,18 +95,27 @@ struct inflate_state {
|
|||||||
int32_t read_in_length;
|
int32_t read_in_length;
|
||||||
struct inflate_huff_code_large lit_huff_code;
|
struct inflate_huff_code_large lit_huff_code;
|
||||||
struct inflate_huff_code_small dist_huff_code;
|
struct inflate_huff_code_small dist_huff_code;
|
||||||
uint8_t new_block;
|
enum isal_block_state block_state;
|
||||||
uint8_t bfinal;
|
uint32_t bfinal;
|
||||||
uint8_t btype;
|
int32_t type0_block_len;
|
||||||
|
int32_t copy_overflow_length;
|
||||||
|
int32_t copy_overflow_distance;
|
||||||
|
int32_t tmp_in_size;
|
||||||
|
int32_t tmp_out_valid;
|
||||||
|
int32_t tmp_out_processed;
|
||||||
|
uint8_t tmp_in_buffer[ISAL_INFLATE_MAX_HDR_SIZE];
|
||||||
|
uint8_t tmp_out_buffer[2 * ISAL_INFLATE_HIST_SIZE + ISAL_INFLATE_SLOP];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize a struct inflate_state for deflate compressed input data at in_stream and to output
|
/* Initialize a struct inflate_state for deflate compressed input data at in_stream and to output
|
||||||
* data into out_stream */
|
* data into out_stream */
|
||||||
void isal_inflate_init(struct inflate_state *state, uint8_t *in_stream, uint32_t in_size,
|
void isal_inflate_init(struct inflate_state *state);
|
||||||
uint8_t *out_stream, uint64_t out_size);
|
|
||||||
|
|
||||||
/* Decompress a deflate data. This function assumes a call to igzip_inflate_init
|
/* Decompress a deflate data. This function assumes a call to igzip_inflate_init
|
||||||
* has been made to set up the state structure to allow for decompression.*/
|
* has been made to set up the state structure to allow for decompression.*/
|
||||||
int isal_inflate_stateless(struct inflate_state *state);
|
int isal_inflate_stateless(struct inflate_state *state);
|
||||||
|
|
||||||
|
/* Decompress a deflate data. This function assumes a call to igzip_inflate_init
|
||||||
|
* has been made to set up the state structure to allow for decompression.*/
|
||||||
|
int isal_inflate(struct inflate_state *state);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user