mirror of
https://github.com/intel/isa-l.git
synced 2025-11-02 14:03:39 +01:00
igzip: Implement multibyte decode
Change-Id: I923a57a01f696f2082945fafcc2773655b9a5beb Signed-off-by: Roy Oursler <roy.j.oursler@intel.com>
This commit is contained in:
@@ -24,10 +24,25 @@ default rel
|
|||||||
extern rfc1951_lookup_table
|
extern rfc1951_lookup_table
|
||||||
|
|
||||||
|
|
||||||
%define LARGE_CODE_LENGTH_OFFSET 9
|
|
||||||
%define LARGE_FLAG_BIT_OFFSET 15
|
%define LARGE_SHORT_SYM_LEN 25
|
||||||
|
%define LARGE_SHORT_SYM_MASK ((1 << LARGE_SHORT_SYM_LEN) - 1)
|
||||||
|
%define LARGE_LONG_SYM_LEN 9
|
||||||
|
%define LARGE_LONG_SYM_MASK ((1 << LARGE_LONG_SYM_LEN) - 1)
|
||||||
|
%define LARGE_SHORT_CODE_LEN_OFFSET 28
|
||||||
|
%define LARGE_LONG_CODE_LEN_OFFSET 9
|
||||||
|
%define LARGE_FLAG_BIT_OFFSET 27
|
||||||
%define LARGE_FLAG_BIT (1 << LARGE_FLAG_BIT_OFFSET)
|
%define LARGE_FLAG_BIT (1 << LARGE_FLAG_BIT_OFFSET)
|
||||||
%define SMALL_CODE_LENGTH_OFFSET 9
|
%define LARGE_SYM_COUNT_OFFSET 25
|
||||||
|
%define LARGE_SYM_COUNT_LEN 2
|
||||||
|
%define LARGE_SYM_COUNT_MASK ((1 << LARGE_SYM_COUNT_LEN) - 1)
|
||||||
|
|
||||||
|
%define SMALL_SHORT_SYM_LEN 9
|
||||||
|
%define SMALL_SHORT_SYM_MASK ((1 << SMALL_SHORT_SYM_LEN) - 1)
|
||||||
|
%define SMALL_LONG_SYM_LEN 9
|
||||||
|
%define SMALL_LONG_SYM_MASK ((1 << SMALL_LONG_SYM_LEN) - 1)
|
||||||
|
%define SMALL_SHORT_CODE_LEN_OFFSET 9
|
||||||
|
%define SMALL_LONG_CODE_LEN_OFFSET 9
|
||||||
%define SMALL_FLAG_BIT_OFFSET 15
|
%define SMALL_FLAG_BIT_OFFSET 15
|
||||||
%define SMALL_FLAG_BIT (1 << SMALL_FLAG_BIT_OFFSET)
|
%define SMALL_FLAG_BIT (1 << SMALL_FLAG_BIT_OFFSET)
|
||||||
|
|
||||||
@@ -50,6 +65,7 @@ extern rfc1951_lookup_table
|
|||||||
|
|
||||||
;; rsi arg2
|
;; rsi arg2
|
||||||
%define tmp2 rsi
|
%define tmp2 rsi
|
||||||
|
%define next_sym_num rsi
|
||||||
%define next_bits rsi
|
%define next_bits rsi
|
||||||
|
|
||||||
;; rbx ; Saved
|
;; rbx ; Saved
|
||||||
@@ -85,8 +101,9 @@ extern rfc1951_lookup_table
|
|||||||
start_out_mem_offset equ 0
|
start_out_mem_offset equ 0
|
||||||
read_in_mem_offset equ 8
|
read_in_mem_offset equ 8
|
||||||
read_in_length_mem_offset equ 16
|
read_in_length_mem_offset equ 16
|
||||||
gpr_save_mem_offset equ 24
|
next_out_mem_offset equ 24
|
||||||
stack_size equ 3 * 8 + 8 * 8
|
gpr_save_mem_offset equ 32
|
||||||
|
stack_size equ 4 * 8 + 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
|
||||||
@@ -262,65 +279,74 @@ stack_size equ 3 * 8 + 8 * 8
|
|||||||
|
|
||||||
;; Decode next symbol
|
;; Decode next symbol
|
||||||
;; Clobber rcx
|
;; Clobber rcx
|
||||||
%macro decode_next_large 7
|
%macro decode_next_large 8
|
||||||
%define %%state %1 ; State structure associated with compressed stream
|
%define %%state %1 ; State structure associated with compressed stream
|
||||||
%define %%lookup_size %2 ; Number of bits used for small lookup
|
%define %%lookup_size %2 ; Number of bits used for small lookup
|
||||||
%define %%state_offset %3 ; Type of huff code, should be either LIT or DIST
|
%define %%state_offset %3 ; Type of huff code, should be either LIT or DIST
|
||||||
%define %%read_in %4 ; Bits read in from compressed stream
|
%define %%read_in %4 ; Bits read in from compressed stream
|
||||||
%define %%read_in_length %5 ; Number of valid bits in read_in
|
%define %%read_in_length %5 ; Number of valid bits in read_in
|
||||||
%define %%next_sym %6 ; Returned symobl
|
%define %%next_sym %6 ; Returned symbols
|
||||||
%define %%next_bits %7
|
%define %%next_sym_num %7 ; Returned symbols count
|
||||||
|
%define %%next_bits %8
|
||||||
|
|
||||||
;; Save length associated with symbol
|
;; Save length associated with symbol
|
||||||
mov %%next_bits, %%read_in
|
mov %%next_bits, %%read_in
|
||||||
shr %%next_bits, %%lookup_size
|
shr %%next_bits, %%lookup_size
|
||||||
|
|
||||||
mov rcx, %%next_sym
|
mov rcx, %%next_sym
|
||||||
shr rcx, LARGE_CODE_LENGTH_OFFSET
|
shr rcx, LARGE_SHORT_CODE_LEN_OFFSET
|
||||||
jz invalid_symbol
|
jz invalid_symbol
|
||||||
|
|
||||||
|
mov %%next_sym_num, %%next_sym
|
||||||
|
shr %%next_sym_num, LARGE_SYM_COUNT_OFFSET
|
||||||
|
and %%next_sym_num, LARGE_SYM_COUNT_MASK
|
||||||
|
|
||||||
;; Check if symbol or hint was looked up
|
;; Check if symbol or hint was looked up
|
||||||
and %%next_sym, 0x81FF
|
and %%next_sym, LARGE_FLAG_BIT | LARGE_SHORT_SYM_MASK
|
||||||
cmp %%next_sym, LARGE_FLAG_BIT
|
test %%next_sym, LARGE_FLAG_BIT
|
||||||
jl %%end
|
jz %%end
|
||||||
|
|
||||||
;; Extract the 15-DECODE_LOOKUP_SIZE bits beyond the first %%lookup_size bits.
|
;; Extract the 15-DECODE_LOOKUP_SIZE bits beyond the first %%lookup_size bits.
|
||||||
lea %%next_sym, [%%state + LARGE_LONG_CODE_SIZE * %%next_sym]
|
|
||||||
|
|
||||||
CLEAR_HIGH_BITS %%next_bits, rcx, %%lookup_size
|
CLEAR_HIGH_BITS %%next_bits, rcx, %%lookup_size
|
||||||
|
|
||||||
|
and %%next_sym, LARGE_SHORT_SYM_MASK
|
||||||
|
add %%next_sym, %%next_bits
|
||||||
|
lea %%next_sym, [%%state + LARGE_LONG_CODE_SIZE * %%next_sym]
|
||||||
|
|
||||||
;; Lookup actual next symbol
|
;; Lookup actual next symbol
|
||||||
movzx %%next_sym, word [%%next_sym + %%state_offset + LARGE_LONG_CODE_SIZE * %%next_bits + LARGE_SHORT_CODE_SIZE * (1 << %%lookup_size) - LARGE_LONG_CODE_SIZE * LARGE_FLAG_BIT]
|
movzx %%next_sym, word [%%next_sym + %%state_offset + LARGE_SHORT_CODE_SIZE * (1 << %%lookup_size)]
|
||||||
|
mov %%next_sym_num, 1
|
||||||
|
|
||||||
;; Save length associated with symbol
|
;; Save length associated with symbol
|
||||||
mov rcx, %%next_sym
|
mov rcx, %%next_sym
|
||||||
shr rcx, LARGE_CODE_LENGTH_OFFSET
|
shr rcx, LARGE_LONG_CODE_LEN_OFFSET
|
||||||
jz invalid_symbol
|
jz invalid_symbol
|
||||||
and %%next_sym, 0x1FF
|
and %%next_sym, LARGE_LONG_SYM_MASK
|
||||||
|
|
||||||
%%end:
|
%%end:
|
||||||
;; Updated read_in to reflect the bits which were decoded
|
;; Updated read_in to reflect the bits which were decoded
|
||||||
SHRX %%read_in, %%read_in, rcx
|
SHRX %%read_in, %%read_in, rcx
|
||||||
sub %%read_in_length, rcx
|
sub %%read_in_length, rcx
|
||||||
%endm
|
%endm
|
||||||
|
|
||||||
;; Decode next symbol
|
;; Decode next symbol
|
||||||
;; Clobber rcx
|
;; Clobber rcx
|
||||||
%macro decode_next_large_with_load 7
|
%macro decode_next_large_with_load 8
|
||||||
%define %%state %1 ; State structure associated with compressed stream
|
%define %%state %1 ; State structure associated with compressed stream
|
||||||
%define %%lookup_size %2 ; Number of bits used for small lookup
|
%define %%lookup_size %2 ; Number of bits used for small lookup
|
||||||
%define %%state_offset %3
|
%define %%state_offset %3
|
||||||
%define %%read_in %4 ; Bits read in from compressed stream
|
%define %%read_in %4 ; Bits read in from compressed stream
|
||||||
%define %%read_in_length %5 ; Number of valid bits in read_in
|
%define %%read_in_length %5 ; Number of valid bits in read_in
|
||||||
%define %%next_sym %6 ; Returned symobl
|
%define %%next_sym %6 ; Returned symbols
|
||||||
%define %%next_bits %7
|
%define %%next_sym_num %7 ; Returned symbols count
|
||||||
|
%define %%next_bits %8
|
||||||
|
|
||||||
;; Lookup possible next symbol
|
;; Lookup possible next symbol
|
||||||
mov %%next_bits, %%read_in
|
mov %%next_bits, %%read_in
|
||||||
and %%next_bits, (1 << %%lookup_size) - 1
|
and %%next_bits, (1 << %%lookup_size) - 1
|
||||||
mov %%next_sym %+ d, dword [%%state + %%state_offset + LARGE_SHORT_CODE_SIZE * %%next_bits]
|
mov %%next_sym %+ d, dword [%%state + %%state_offset + LARGE_SHORT_CODE_SIZE * %%next_bits]
|
||||||
|
|
||||||
decode_next_large %%state, %%lookup_size, %%state_offset, %%read_in, %%read_in_length, %%next_sym, %%next_bits
|
decode_next_large %%state, %%lookup_size, %%state_offset, %%read_in, %%read_in_length, %%next_sym, %%next_sym_num, %%next_bits
|
||||||
%endm
|
%endm
|
||||||
|
|
||||||
;; Decode next symbol
|
;; Decode next symbol
|
||||||
@@ -339,13 +365,13 @@ stack_size equ 3 * 8 + 8 * 8
|
|||||||
shr %%next_bits, %%lookup_size
|
shr %%next_bits, %%lookup_size
|
||||||
|
|
||||||
mov rcx, %%next_sym
|
mov rcx, %%next_sym
|
||||||
shr rcx, SMALL_CODE_LENGTH_OFFSET
|
shr rcx, SMALL_SHORT_CODE_LEN_OFFSET
|
||||||
jz invalid_symbol
|
jz invalid_symbol
|
||||||
|
|
||||||
;; Check if symbol or hint was looked up
|
;; Check if symbol or hint was looked up
|
||||||
and %%next_sym, 0x81FF
|
and %%next_sym, SMALL_FLAG_BIT | SMALL_SHORT_SYM_MASK
|
||||||
cmp %%next_sym, SMALL_FLAG_BIT
|
test %%next_sym, SMALL_FLAG_BIT
|
||||||
jl %%end
|
jz %%end
|
||||||
|
|
||||||
;; Extract the 15-DECODE_LOOKUP_SIZE bits beyond the first %%lookup_size bits.
|
;; Extract the 15-DECODE_LOOKUP_SIZE bits beyond the first %%lookup_size bits.
|
||||||
lea %%next_sym, [%%state + SMALL_LONG_CODE_SIZE * %%next_sym]
|
lea %%next_sym, [%%state + SMALL_LONG_CODE_SIZE * %%next_sym]
|
||||||
@@ -357,9 +383,9 @@ stack_size equ 3 * 8 + 8 * 8
|
|||||||
|
|
||||||
;; Save length associated with symbol
|
;; Save length associated with symbol
|
||||||
mov rcx, %%next_sym
|
mov rcx, %%next_sym
|
||||||
shr rcx, SMALL_CODE_LENGTH_OFFSET
|
shr rcx, SMALL_LONG_CODE_LEN_OFFSET
|
||||||
jz invalid_symbol
|
jz invalid_symbol
|
||||||
and %%next_sym, 0x1FF
|
and %%next_sym, SMALL_LONG_SYM_MASK
|
||||||
|
|
||||||
%%end:
|
%%end:
|
||||||
;; Updated read_in to reflect the bits which were decoded
|
;; Updated read_in to reflect the bits which were decoded
|
||||||
@@ -440,10 +466,13 @@ loop_block:
|
|||||||
jg end_loop_block_pre
|
jg end_loop_block_pre
|
||||||
|
|
||||||
;; Decode next symbol and reload the read_in buffer
|
;; Decode next symbol and reload the read_in buffer
|
||||||
decode_next_large state, ISAL_DECODE_LONG_BITS, _lit_huff_code, read_in, read_in_length, next_sym, tmp1
|
decode_next_large state, ISAL_DECODE_LONG_BITS, _lit_huff_code, read_in, read_in_length, next_sym, next_sym_num, tmp1
|
||||||
|
|
||||||
;; Save next_sym in next_sym2 so next_sym can be preloaded
|
;; Specutively write next_sym2 if it is a literal
|
||||||
mov next_sym2, next_sym
|
mov [next_out], next_sym
|
||||||
|
add next_out, next_sym_num
|
||||||
|
lea next_sym_num, [8 * next_sym_num - 8]
|
||||||
|
SHRX next_sym2, next_sym, next_sym_num
|
||||||
|
|
||||||
;; Find index to specutively preload next_sym from
|
;; Find index to specutively preload next_sym from
|
||||||
mov tmp3, read_in
|
mov tmp3, read_in
|
||||||
@@ -478,10 +507,6 @@ loop_block:
|
|||||||
and next_bits2, (1 << ISAL_DECODE_SHORT_BITS) - 1
|
and next_bits2, (1 << ISAL_DECODE_SHORT_BITS) - 1
|
||||||
movzx next_sym3, word [state + _dist_huff_code + SMALL_SHORT_CODE_SIZE * next_bits2]
|
movzx next_sym3, word [state + _dist_huff_code + SMALL_SHORT_CODE_SIZE * next_bits2]
|
||||||
|
|
||||||
;; Specutively write next_sym2 if it is a literal
|
|
||||||
mov [next_out], next_sym2
|
|
||||||
add next_out, 1
|
|
||||||
|
|
||||||
;; Check if next_sym2 is a literal, length, or end of block symbol
|
;; Check if next_sym2 is a literal, length, or end of block symbol
|
||||||
cmp next_sym2, 256
|
cmp next_sym2, 256
|
||||||
jl loop_block
|
jl loop_block
|
||||||
@@ -581,13 +606,18 @@ end_loop_block:
|
|||||||
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_mem_offset], read_in
|
||||||
mov [rsp + read_in_length_mem_offset], read_in_length
|
mov [rsp + read_in_length_mem_offset], read_in_length
|
||||||
|
mov [rsp + next_out_mem_offset], next_out
|
||||||
|
|
||||||
decode_next_large_with_load state, ISAL_DECODE_LONG_BITS, _lit_huff_code, read_in, read_in_length, next_sym, tmp1
|
decode_next_large_with_load state, ISAL_DECODE_LONG_BITS, _lit_huff_code, read_in, read_in_length, next_sym, next_sym_num, tmp1
|
||||||
|
|
||||||
;; Check that enough input was available to decode symbol
|
;; Check that enough input was available to decode symbol
|
||||||
cmp read_in_length, 0
|
cmp read_in_length, 0
|
||||||
jl end_of_input
|
jl end_of_input
|
||||||
|
|
||||||
|
multi_symbol_start:
|
||||||
|
cmp next_sym_num, 1
|
||||||
|
jg decode_literal
|
||||||
|
|
||||||
cmp next_sym, 256
|
cmp next_sym, 256
|
||||||
jl decode_literal
|
jl decode_literal
|
||||||
je end_symbol
|
je end_symbol
|
||||||
@@ -649,12 +679,19 @@ decode_literal:
|
|||||||
jge out_buffer_overflow_lit
|
jge out_buffer_overflow_lit
|
||||||
add next_out, 1
|
add next_out, 1
|
||||||
mov byte [next_out - 1], next_sym %+ b
|
mov byte [next_out - 1], next_sym %+ b
|
||||||
jmp end_loop_block
|
sub next_sym_num, 1
|
||||||
|
jz end_loop_block
|
||||||
|
shr next_sym, 8
|
||||||
|
jmp multi_symbol_start
|
||||||
|
|
||||||
;; Set exit codes
|
;; Set exit codes
|
||||||
end_of_input:
|
end_of_input:
|
||||||
mov read_in, [rsp + read_in_mem_offset]
|
mov read_in, [rsp + read_in_mem_offset]
|
||||||
mov read_in_length, [rsp + read_in_length_mem_offset]
|
mov read_in_length, [rsp + read_in_length_mem_offset]
|
||||||
|
mov next_out, [rsp + next_out_mem_offset]
|
||||||
|
xor tmp1, tmp1
|
||||||
|
mov dword [state + _write_overflow_lits], tmp1 %+ d
|
||||||
|
mov dword [state + _write_overflow_len], tmp1 %+ d
|
||||||
mov rax, END_INPUT
|
mov rax, END_INPUT
|
||||||
jmp end
|
jmp end
|
||||||
|
|
||||||
@@ -674,10 +711,18 @@ out_buffer_overflow_repeat:
|
|||||||
jmp end
|
jmp end
|
||||||
|
|
||||||
out_buffer_overflow_lit:
|
out_buffer_overflow_lit:
|
||||||
mov read_in, [rsp + read_in_mem_offset]
|
mov dword [state + _write_overflow_lits], next_sym %+ d
|
||||||
mov read_in_length, [rsp + read_in_length_mem_offset]
|
mov dword [state + _write_overflow_len], next_sym_num %+ d
|
||||||
|
sub next_sym_num, 1
|
||||||
|
shl next_sym_num, 3
|
||||||
|
SHRX next_sym, next_sym, next_sym_num
|
||||||
mov rax, OUT_OVERFLOW
|
mov rax, OUT_OVERFLOW
|
||||||
jmp end
|
shr next_sym_num, 3
|
||||||
|
cmp next_sym, 256
|
||||||
|
jl end
|
||||||
|
mov dword [state + _write_overflow_len], next_sym_num %+ d
|
||||||
|
jg decode_len_dist_2
|
||||||
|
jmp end_state
|
||||||
|
|
||||||
invalid_look_back_distance:
|
invalid_look_back_distance:
|
||||||
mov rax, INVALID_LOOKBACK
|
mov rax, INVALID_LOOKBACK
|
||||||
@@ -689,12 +734,18 @@ invalid_symbol:
|
|||||||
|
|
||||||
end_symbol_pre:
|
end_symbol_pre:
|
||||||
;; Fix up in buffer and out buffer to reflect the actual buffer
|
;; Fix up in buffer and out buffer to reflect the actual buffer
|
||||||
|
sub next_out, 1
|
||||||
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_symbol:
|
end_symbol:
|
||||||
|
xor rax, rax
|
||||||
|
end_state:
|
||||||
;; Set flag identifying a new block is required
|
;; Set flag identifying a new block is required
|
||||||
mov byte [state + _block_state], ISAL_BLOCK_NEW_HDR
|
mov byte [state + _block_state], ISAL_BLOCK_NEW_HDR
|
||||||
xor rax, rax
|
cmp dword [state + _bfinal], 0
|
||||||
|
je end
|
||||||
|
mov byte [state + _block_state], ISAL_BLOCK_INPUT_DONE
|
||||||
|
|
||||||
end:
|
end:
|
||||||
;; Save current buffer states
|
;; Save current buffer states
|
||||||
mov [state + _read_in], read_in
|
mov [state + _read_in], read_in
|
||||||
|
|||||||
@@ -34,6 +34,28 @@
|
|||||||
|
|
||||||
extern int decode_huffman_code_block_stateless(struct inflate_state *);
|
extern int decode_huffman_code_block_stateless(struct inflate_state *);
|
||||||
|
|
||||||
|
#define LARGE_SHORT_SYM_LEN 25
|
||||||
|
#define LARGE_SHORT_SYM_MASK ((1 << LARGE_SHORT_SYM_LEN) - 1)
|
||||||
|
#define LARGE_LONG_SYM_LEN 9
|
||||||
|
#define LARGE_LONG_SYM_MASK ((1 << LARGE_LONG_SYM_LEN) - 1)
|
||||||
|
#define LARGE_SHORT_CODE_LEN_OFFSET 28
|
||||||
|
#define LARGE_LONG_CODE_LEN_OFFSET 9
|
||||||
|
#define LARGE_FLAG_BIT_OFFSET 27
|
||||||
|
#define LARGE_FLAG_BIT (1 << LARGE_FLAG_BIT_OFFSET)
|
||||||
|
#define LARGE_SYM_COUNT_OFFSET 25
|
||||||
|
#define LARGE_SYM_COUNT_LEN 2
|
||||||
|
#define LARGE_SYM_COUNT_MASK ((1 << LARGE_SYM_COUNT_LEN) - 1)
|
||||||
|
|
||||||
|
#define SMALL_SHORT_SYM_LEN 9
|
||||||
|
#define SMALL_SHORT_SYM_MASK ((1 << SMALL_SHORT_SYM_LEN) - 1)
|
||||||
|
#define SMALL_LONG_SYM_LEN 9
|
||||||
|
#define SMALL_LONG_SYM_MASK ((1 << SMALL_LONG_SYM_LEN) - 1)
|
||||||
|
#define SMALL_SHORT_CODE_LEN_OFFSET 9
|
||||||
|
#define SMALL_LONG_CODE_LEN_OFFSET 9
|
||||||
|
#define SMALL_FLAG_BIT_OFFSET 15
|
||||||
|
#define SMALL_FLAG_BIT (1 << SMALL_FLAG_BIT_OFFSET)
|
||||||
|
|
||||||
|
#define INVALID_SYMBOL 0x1FF
|
||||||
/* structure contain lookup data based on RFC 1951 */
|
/* structure contain lookup data based on RFC 1951 */
|
||||||
struct rfc1951_tables {
|
struct rfc1951_tables {
|
||||||
uint8_t dist_extra_bit_count[32];
|
uint8_t dist_extra_bit_count[32];
|
||||||
@@ -275,7 +297,8 @@ static void inline make_inflate_huff_code_large(struct inflate_huff_code_large *
|
|||||||
|
|
||||||
if (i < max_symbol)
|
if (i < max_symbol)
|
||||||
short_code_lookup[huff_code_table[i].code] =
|
short_code_lookup[huff_code_table[i].code] =
|
||||||
i | (huff_code_table[i].length) << 9;
|
i | (huff_code_table[i].length) << LARGE_SHORT_CODE_LEN_OFFSET |
|
||||||
|
(1 << LARGE_SYM_COUNT_OFFSET);
|
||||||
|
|
||||||
else
|
else
|
||||||
short_code_lookup[huff_code_table[i].code] = 0;
|
short_code_lookup[huff_code_table[i].code] = 0;
|
||||||
@@ -339,12 +362,13 @@ static void inline make_inflate_huff_code_large(struct inflate_huff_code_large *
|
|||||||
for (; long_bits < (1 << (max_length - ISAL_DECODE_LONG_BITS));
|
for (; long_bits < (1 << (max_length - ISAL_DECODE_LONG_BITS));
|
||||||
long_bits += min_increment) {
|
long_bits += min_increment) {
|
||||||
result->long_code_lookup[long_code_lookup_length + long_bits] =
|
result->long_code_lookup[long_code_lookup_length + long_bits] =
|
||||||
temp_code_list[j] | (code_length << 9);
|
temp_code_list[j] |
|
||||||
|
(code_length << LARGE_LONG_CODE_LEN_OFFSET);
|
||||||
}
|
}
|
||||||
huff_code_table[temp_code_list[j]].code = 0xFFFF;
|
huff_code_table[temp_code_list[j]].code = 0xFFFF;
|
||||||
}
|
}
|
||||||
result->short_code_lookup[first_bits] =
|
result->short_code_lookup[first_bits] = long_code_lookup_length |
|
||||||
long_code_lookup_length | (max_length << 9) | 0x8000;
|
(max_length << LARGE_SHORT_CODE_LEN_OFFSET) | LARGE_FLAG_BIT;
|
||||||
long_code_lookup_length += 1 << (max_length - ISAL_DECODE_LONG_BITS);
|
long_code_lookup_length += 1 << (max_length - ISAL_DECODE_LONG_BITS);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -434,7 +458,7 @@ static void inline make_inflate_huff_code_small(struct inflate_huff_code_small *
|
|||||||
* bit 15 is a flag representing this is a symbol*/
|
* bit 15 is a flag representing this is a symbol*/
|
||||||
if (i < max_symbol)
|
if (i < max_symbol)
|
||||||
short_code_lookup[huff_code_table[i].code] =
|
short_code_lookup[huff_code_table[i].code] =
|
||||||
i | (huff_code_table[i].length) << 9;
|
i | (huff_code_table[i].length) << SMALL_SHORT_CODE_LEN_OFFSET;
|
||||||
else
|
else
|
||||||
short_code_lookup[huff_code_table[i].code] = 0;
|
short_code_lookup[huff_code_table[i].code] = 0;
|
||||||
}
|
}
|
||||||
@@ -496,12 +520,13 @@ static void inline make_inflate_huff_code_small(struct inflate_huff_code_small *
|
|||||||
for (; long_bits < (1 << (max_length - ISAL_DECODE_SHORT_BITS));
|
for (; long_bits < (1 << (max_length - ISAL_DECODE_SHORT_BITS));
|
||||||
long_bits += min_increment) {
|
long_bits += min_increment) {
|
||||||
result->long_code_lookup[long_code_lookup_length + long_bits] =
|
result->long_code_lookup[long_code_lookup_length + long_bits] =
|
||||||
temp_code_list[j] | (code_length << 9);
|
temp_code_list[j] |
|
||||||
|
(code_length << SMALL_LONG_CODE_LEN_OFFSET);
|
||||||
}
|
}
|
||||||
huff_code_table[temp_code_list[j]].code = 0xFFFF;
|
huff_code_table[temp_code_list[j]].code = 0xFFFF;
|
||||||
}
|
}
|
||||||
result->short_code_lookup[first_bits] =
|
result->short_code_lookup[first_bits] = long_code_lookup_length |
|
||||||
long_code_lookup_length | (max_length << 9) | 0x8000;
|
(max_length << SMALL_SHORT_CODE_LEN_OFFSET) | SMALL_FLAG_BIT;
|
||||||
long_code_lookup_length += 1 << (max_length - ISAL_DECODE_SHORT_BITS);
|
long_code_lookup_length += 1 << (max_length - ISAL_DECODE_SHORT_BITS);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -556,12 +581,13 @@ static int inline setup_static_header(struct inflate_state *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Decodes the next symbol symbol in in_buffer using the huff code defined by
|
/* Decodes the next symbol symbol in in_buffer using the huff code defined by
|
||||||
* huff_code */
|
* huff_code and returns the value in next_lits and sym_count */
|
||||||
static uint16_t inline decode_next_large(struct inflate_state *state,
|
static void inline decode_next_large(uint32_t * next_lits, uint32_t * sym_count,
|
||||||
struct inflate_huff_code_large *huff_code)
|
struct inflate_state *state,
|
||||||
|
struct inflate_huff_code_large *huff_code)
|
||||||
{
|
{
|
||||||
uint16_t next_bits;
|
uint16_t next_bits;
|
||||||
uint16_t next_sym;
|
uint32_t next_sym;
|
||||||
uint32_t bit_count;
|
uint32_t bit_count;
|
||||||
uint32_t bit_mask;
|
uint32_t bit_mask;
|
||||||
|
|
||||||
@@ -578,36 +604,37 @@ static uint16_t inline decode_next_large(struct inflate_state *state,
|
|||||||
* first actual symbol in the long code list.*/
|
* first actual symbol in the long code list.*/
|
||||||
next_sym = huff_code->short_code_lookup[next_bits];
|
next_sym = huff_code->short_code_lookup[next_bits];
|
||||||
|
|
||||||
if (next_sym < 0x8000) {
|
if ((next_sym & LARGE_FLAG_BIT) == 0) {
|
||||||
/* Return symbol found if next_code is a complete huffman code
|
/* Return symbol found if next_code is a complete huffman code
|
||||||
* and shift in buffer over by the length of the next_code */
|
* and shift in buffer over by the length of the next_code */
|
||||||
bit_count = next_sym >> 9;
|
bit_count = next_sym >> LARGE_SHORT_CODE_LEN_OFFSET;
|
||||||
state->read_in >>= bit_count;
|
state->read_in >>= bit_count;
|
||||||
state->read_in_length -= bit_count;
|
state->read_in_length -= bit_count;
|
||||||
|
|
||||||
if (bit_count == 0)
|
if (bit_count == 0)
|
||||||
next_sym = 0x1FF;
|
next_sym = INVALID_SYMBOL;
|
||||||
|
|
||||||
return next_sym & 0x1FF;
|
*sym_count = (next_sym >> LARGE_SYM_COUNT_OFFSET) & LARGE_SYM_COUNT_MASK;
|
||||||
|
*next_lits = next_sym & LARGE_SHORT_SYM_MASK;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* If a symbol is not found, perform a linear search of the long code
|
/* If a symbol is not found, do a lookup in the long code
|
||||||
* list starting from the hint in next_sym */
|
* list starting from the hint in next_sym */
|
||||||
bit_mask = (next_sym - 0x8000) >> 9;
|
bit_mask = (next_sym - LARGE_FLAG_BIT) >> LARGE_SHORT_CODE_LEN_OFFSET;
|
||||||
bit_mask = (1 << bit_mask) - 1;
|
bit_mask = (1 << bit_mask) - 1;
|
||||||
next_bits = state->read_in & bit_mask;
|
next_bits = state->read_in & bit_mask;
|
||||||
next_sym =
|
next_sym =
|
||||||
huff_code->long_code_lookup[(next_sym & 0x1FF) +
|
huff_code->long_code_lookup[(next_sym & LARGE_SHORT_SYM_MASK) +
|
||||||
(next_bits >> ISAL_DECODE_LONG_BITS)];
|
(next_bits >> ISAL_DECODE_LONG_BITS)];
|
||||||
bit_count = next_sym >> 9;
|
bit_count = next_sym >> LARGE_LONG_CODE_LEN_OFFSET;
|
||||||
state->read_in >>= bit_count;
|
state->read_in >>= bit_count;
|
||||||
state->read_in_length -= bit_count;
|
state->read_in_length -= bit_count;
|
||||||
|
|
||||||
if (bit_count == 0)
|
if (bit_count == 0)
|
||||||
next_sym = 0x1FF;
|
next_sym = INVALID_SYMBOL;
|
||||||
|
|
||||||
return next_sym & 0x1FF;
|
|
||||||
|
|
||||||
|
*sym_count = 1;
|
||||||
|
*next_lits = next_sym & LARGE_LONG_SYM_MASK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,31 +659,31 @@ static uint16_t inline decode_next_small(struct inflate_state *state,
|
|||||||
* first actual symbol in the long code list.*/
|
* first actual symbol in the long code list.*/
|
||||||
next_sym = huff_code->short_code_lookup[next_bits];
|
next_sym = huff_code->short_code_lookup[next_bits];
|
||||||
|
|
||||||
if (next_sym < 0x8000) {
|
if ((next_sym & SMALL_FLAG_BIT) == 0) {
|
||||||
/* Return symbol found if next_code is a complete huffman code
|
/* Return symbol found if next_code is a complete huffman code
|
||||||
* and shift in buffer over by the length of the next_code */
|
* and shift in buffer over by the length of the next_code */
|
||||||
bit_count = next_sym >> 9;
|
bit_count = next_sym >> SMALL_SHORT_CODE_LEN_OFFSET;
|
||||||
state->read_in >>= bit_count;
|
state->read_in >>= bit_count;
|
||||||
state->read_in_length -= bit_count;
|
state->read_in_length -= bit_count;
|
||||||
|
|
||||||
if (bit_count == 0)
|
if (bit_count == 0)
|
||||||
next_sym = 0x1FF;
|
next_sym = INVALID_SYMBOL;
|
||||||
|
|
||||||
return next_sym & 0x1FF;
|
return next_sym & SMALL_SHORT_SYM_MASK;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* If a symbol is not found, perform a linear search of the long code
|
/* If a symbol is not found, perform a linear search of the long code
|
||||||
* list starting from the hint in next_sym */
|
* list starting from the hint in next_sym */
|
||||||
bit_mask = (next_sym - 0x8000) >> 9;
|
bit_mask = (next_sym - SMALL_FLAG_BIT) >> SMALL_SHORT_CODE_LEN_OFFSET;
|
||||||
bit_mask = (1 << bit_mask) - 1;
|
bit_mask = (1 << bit_mask) - 1;
|
||||||
next_bits = state->read_in & bit_mask;
|
next_bits = state->read_in & bit_mask;
|
||||||
next_sym =
|
next_sym =
|
||||||
huff_code->long_code_lookup[(next_sym & 0x1FF) +
|
huff_code->long_code_lookup[(next_sym & SMALL_SHORT_SYM_MASK) +
|
||||||
(next_bits >> ISAL_DECODE_SHORT_BITS)];
|
(next_bits >> ISAL_DECODE_SHORT_BITS)];
|
||||||
bit_count = next_sym >> 9;
|
bit_count = next_sym >> SMALL_LONG_CODE_LEN_OFFSET;
|
||||||
state->read_in >>= bit_count;
|
state->read_in >>= bit_count;
|
||||||
state->read_in_length -= bit_count;
|
state->read_in_length -= bit_count;
|
||||||
return next_sym & 0x1FF;
|
return next_sym & SMALL_LONG_SYM_MASK;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,13 +892,6 @@ static int read_header(struct inflate_state *state)
|
|||||||
state->read_in >>= 16;
|
state->read_in >>= 16;
|
||||||
state->read_in_length -= 32;
|
state->read_in_length -= 32;
|
||||||
|
|
||||||
bytes = state->read_in_length / 8;
|
|
||||||
|
|
||||||
state->next_in -= bytes;
|
|
||||||
state->avail_in += bytes;
|
|
||||||
state->read_in = 0;
|
|
||||||
state->read_in_length = 0;
|
|
||||||
|
|
||||||
/* Check if len and nlen match */
|
/* Check if len and nlen match */
|
||||||
if (len != (~nlen & 0xffff))
|
if (len != (~nlen & 0xffff))
|
||||||
return ISAL_INVALID_BLOCK;
|
return ISAL_INVALID_BLOCK;
|
||||||
@@ -948,21 +968,48 @@ static int read_header_stateful(struct inflate_state *state)
|
|||||||
static int inline decode_literal_block(struct inflate_state *state)
|
static int inline decode_literal_block(struct inflate_state *state)
|
||||||
{
|
{
|
||||||
uint32_t len = state->type0_block_len;
|
uint32_t len = state->type0_block_len;
|
||||||
|
uint32_t bytes = state->read_in_length / 8;
|
||||||
/* If the block is uncompressed, perform a memcopy while
|
/* If the block is uncompressed, perform a memcopy while
|
||||||
* updating state data */
|
* updating state data */
|
||||||
|
state->block_state = state->bfinal ? ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR;
|
||||||
state->block_state = ISAL_BLOCK_NEW_HDR;
|
|
||||||
|
|
||||||
if (state->avail_out < len) {
|
if (state->avail_out < len) {
|
||||||
len = state->avail_out;
|
len = state->avail_out;
|
||||||
state->block_state = ISAL_BLOCK_TYPE0;
|
state->block_state = ISAL_BLOCK_TYPE0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->avail_in < len) {
|
if (state->avail_in + bytes < len) {
|
||||||
len = state->avail_in;
|
len = state->avail_in + bytes;
|
||||||
state->block_state = ISAL_BLOCK_TYPE0;
|
state->block_state = ISAL_BLOCK_TYPE0;
|
||||||
}
|
}
|
||||||
|
if (state->read_in_length) {
|
||||||
|
if (len >= bytes) {
|
||||||
|
memcpy(state->next_out, &state->read_in, bytes);
|
||||||
|
|
||||||
|
state->next_out += bytes;
|
||||||
|
state->avail_out -= bytes;
|
||||||
|
state->total_out += bytes;
|
||||||
|
state->type0_block_len -= bytes;
|
||||||
|
|
||||||
|
state->read_in = 0;
|
||||||
|
state->read_in_length = 0;
|
||||||
|
len -= bytes;
|
||||||
|
bytes = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
memcpy(state->next_out, &state->read_in, len);
|
||||||
|
|
||||||
|
state->next_out += len;
|
||||||
|
state->avail_out -= len;
|
||||||
|
state->total_out += len;
|
||||||
|
state->type0_block_len -= len;
|
||||||
|
|
||||||
|
state->read_in >>= 8 * len;
|
||||||
|
state->read_in_length -= 8 * len;
|
||||||
|
bytes -= len;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(state->next_out, state->next_in, len);
|
memcpy(state->next_out, state->next_in, len);
|
||||||
|
|
||||||
state->next_out += len;
|
state->next_out += len;
|
||||||
@@ -972,7 +1019,7 @@ static int inline decode_literal_block(struct inflate_state *state)
|
|||||||
state->avail_in -= len;
|
state->avail_in -= len;
|
||||||
state->type0_block_len -= len;
|
state->type0_block_len -= len;
|
||||||
|
|
||||||
if (state->avail_in == 0 && state->block_state != ISAL_BLOCK_NEW_HDR)
|
if (state->avail_in + bytes == 0 && state->block_state != ISAL_BLOCK_INPUT_DONE)
|
||||||
return ISAL_END_INPUT;
|
return ISAL_END_INPUT;
|
||||||
|
|
||||||
if (state->avail_out == 0 && state->type0_block_len > 0)
|
if (state->avail_out == 0 && state->type0_block_len > 0)
|
||||||
@@ -991,8 +1038,9 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
uint32_t look_back_dist;
|
uint32_t look_back_dist;
|
||||||
uint64_t read_in_tmp;
|
uint64_t read_in_tmp;
|
||||||
int32_t read_in_length_tmp;
|
int32_t read_in_length_tmp;
|
||||||
uint8_t *next_in_tmp;
|
uint8_t *next_in_tmp, *next_out_tmp;
|
||||||
uint32_t avail_in_tmp;
|
uint32_t avail_in_tmp, avail_out_tmp, total_out_tmp;
|
||||||
|
uint32_t next_lits, sym_count;
|
||||||
|
|
||||||
state->copy_overflow_length = 0;
|
state->copy_overflow_length = 0;
|
||||||
state->copy_overflow_distance = 0;
|
state->copy_overflow_distance = 0;
|
||||||
@@ -1006,8 +1054,14 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
read_in_length_tmp = state->read_in_length;
|
read_in_length_tmp = state->read_in_length;
|
||||||
next_in_tmp = state->next_in;
|
next_in_tmp = state->next_in;
|
||||||
avail_in_tmp = state->avail_in;
|
avail_in_tmp = state->avail_in;
|
||||||
|
next_out_tmp = state->next_out;
|
||||||
|
avail_out_tmp = state->avail_out;
|
||||||
|
total_out_tmp = state->total_out;
|
||||||
|
|
||||||
next_lit = decode_next_large(state, &state->lit_huff_code);
|
decode_next_large(&next_lits, &sym_count, state, &state->lit_huff_code);
|
||||||
|
|
||||||
|
if (sym_count == 0)
|
||||||
|
return ISAL_INVALID_SYMBOL;
|
||||||
|
|
||||||
if (state->read_in_length < 0) {
|
if (state->read_in_length < 0) {
|
||||||
state->read_in = read_in_tmp;
|
state->read_in = read_in_tmp;
|
||||||
@@ -1017,84 +1071,111 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
|||||||
return ISAL_END_INPUT;
|
return ISAL_END_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_lit < 256) {
|
while (sym_count > 0) {
|
||||||
/* If the next symbol is a literal,
|
next_lit = next_lits & 0xffff;
|
||||||
* write out the symbol and update state
|
if (next_lit < 256 || sym_count > 1) {
|
||||||
* data accordingly. */
|
/* If the next symbol is a literal,
|
||||||
if (state->avail_out < 1) {
|
* write out the symbol and update state
|
||||||
state->read_in = read_in_tmp;
|
* data accordingly. */
|
||||||
state->read_in_length = read_in_length_tmp;
|
if (state->avail_out < 1) {
|
||||||
state->next_in = next_in_tmp;
|
state->write_overflow_lits = next_lits;
|
||||||
state->avail_in = avail_in_tmp;
|
state->write_overflow_len = sym_count;
|
||||||
return ISAL_OUT_OVERFLOW;
|
next_lits = next_lits >> (8 * (sym_count - 1));
|
||||||
}
|
sym_count = 1;
|
||||||
|
|
||||||
*state->next_out = next_lit;
|
if (next_lits < 256)
|
||||||
state->next_out++;
|
return ISAL_OUT_OVERFLOW;
|
||||||
state->avail_out--;
|
else if (next_lits == 256) {
|
||||||
state->total_out++;
|
state->write_overflow_len -= 1;
|
||||||
|
state->block_state = state->bfinal ?
|
||||||
|
ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR;
|
||||||
|
return ISAL_OUT_OVERFLOW;
|
||||||
|
} else {
|
||||||
|
state->write_overflow_len -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (next_lit == 256) {
|
*state->next_out = next_lit;
|
||||||
/* If the next symbol is the end of
|
state->next_out++;
|
||||||
* block, update the state data
|
state->avail_out--;
|
||||||
* accordingly */
|
state->total_out++;
|
||||||
state->block_state = ISAL_BLOCK_NEW_HDR;
|
|
||||||
|
|
||||||
} else if (next_lit < 286) {
|
} else if (next_lit == 256) {
|
||||||
/* Else if the next symbol is a repeat
|
/* If the next symbol is the end of
|
||||||
* length, read in the length extra
|
* block, update the state data
|
||||||
* bits, the distance code, the distance
|
* accordingly */
|
||||||
* extra bits. Then write out the
|
state->block_state = state->bfinal ?
|
||||||
* corresponding data and update the
|
ISAL_BLOCK_INPUT_DONE : ISAL_BLOCK_NEW_HDR;
|
||||||
* state data accordingly*/
|
|
||||||
repeat_length =
|
|
||||||
rfc_lookup_table.len_start[next_lit - 257] +
|
|
||||||
inflate_in_read_bits(state,
|
|
||||||
rfc_lookup_table.len_extra_bit_count[next_lit
|
|
||||||
- 257]);
|
|
||||||
next_dist = decode_next_small(state, &state->dist_huff_code);
|
|
||||||
|
|
||||||
if (next_dist >= DIST_LEN)
|
} else if (next_lit < 286) {
|
||||||
|
/* Else if the next symbol is a repeat
|
||||||
|
* length, read in the length extra
|
||||||
|
* bits, the distance code, the distance
|
||||||
|
* extra bits. Then write out the
|
||||||
|
* corresponding data and update the
|
||||||
|
* state data accordingly*/
|
||||||
|
repeat_length =
|
||||||
|
rfc_lookup_table.len_start[next_lit - 257] +
|
||||||
|
inflate_in_read_bits(state,
|
||||||
|
rfc_lookup_table.len_extra_bit_count
|
||||||
|
[next_lit - 257]);
|
||||||
|
next_dist = decode_next_small(state, &state->dist_huff_code);
|
||||||
|
|
||||||
|
if (next_dist >= DIST_LEN)
|
||||||
|
return ISAL_INVALID_SYMBOL;
|
||||||
|
|
||||||
|
look_back_dist = rfc_lookup_table.dist_start[next_dist] +
|
||||||
|
inflate_in_read_bits(state,
|
||||||
|
rfc_lookup_table.dist_extra_bit_count
|
||||||
|
[next_dist]);
|
||||||
|
|
||||||
|
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;
|
||||||
|
state->next_out = next_out_tmp;
|
||||||
|
state->avail_out = avail_out_tmp;
|
||||||
|
state->total_out = total_out_tmp;
|
||||||
|
state->write_overflow_lits = 0;
|
||||||
|
state->write_overflow_len = 0;
|
||||||
|
return ISAL_END_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (look_back_dist > state->total_out + state->dict_length)
|
||||||
|
return ISAL_INVALID_LOOKBACK;
|
||||||
|
|
||||||
|
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)
|
||||||
|
memcpy(state->next_out,
|
||||||
|
state->next_out - look_back_dist,
|
||||||
|
repeat_length);
|
||||||
|
else
|
||||||
|
byte_copy(state->next_out, look_back_dist,
|
||||||
|
repeat_length);
|
||||||
|
|
||||||
|
state->next_out += repeat_length;
|
||||||
|
state->avail_out -= repeat_length;
|
||||||
|
state->total_out += repeat_length;
|
||||||
|
|
||||||
|
if (state->copy_overflow_length > 0)
|
||||||
|
return ISAL_OUT_OVERFLOW;
|
||||||
|
} else
|
||||||
|
/* Else the read in bits do not
|
||||||
|
* correspond to any valid symbol */
|
||||||
return ISAL_INVALID_SYMBOL;
|
return ISAL_INVALID_SYMBOL;
|
||||||
|
|
||||||
look_back_dist = rfc_lookup_table.dist_start[next_dist] +
|
next_lits >>= 8;
|
||||||
inflate_in_read_bits(state,
|
sym_count--;
|
||||||
rfc_lookup_table.dist_extra_bit_count
|
}
|
||||||
[next_dist]);
|
|
||||||
|
|
||||||
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 ISAL_END_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (look_back_dist > state->total_out + state->dict_length)
|
|
||||||
return ISAL_INVALID_LOOKBACK;
|
|
||||||
|
|
||||||
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)
|
|
||||||
memcpy(state->next_out,
|
|
||||||
state->next_out - look_back_dist, repeat_length);
|
|
||||||
else
|
|
||||||
byte_copy(state->next_out, look_back_dist, repeat_length);
|
|
||||||
|
|
||||||
state->next_out += repeat_length;
|
|
||||||
state->avail_out -= repeat_length;
|
|
||||||
state->total_out += repeat_length;
|
|
||||||
|
|
||||||
if (state->copy_overflow_length > 0)
|
|
||||||
return ISAL_OUT_OVERFLOW;
|
|
||||||
} else
|
|
||||||
/* Else the read in bits do not
|
|
||||||
* correspond to any valid symbol */
|
|
||||||
return ISAL_INVALID_SYMBOL;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1115,6 +1196,8 @@ void isal_inflate_init(struct inflate_state *state)
|
|||||||
state->crc_flag = 0;
|
state->crc_flag = 0;
|
||||||
state->crc = 0;
|
state->crc = 0;
|
||||||
state->type0_block_len = 0;
|
state->type0_block_len = 0;
|
||||||
|
state->write_overflow_lits = 0;
|
||||||
|
state->write_overflow_len = 0;
|
||||||
state->copy_overflow_length = 0;
|
state->copy_overflow_length = 0;
|
||||||
state->copy_overflow_distance = 0;
|
state->copy_overflow_distance = 0;
|
||||||
state->tmp_in_size = 0;
|
state->tmp_in_size = 0;
|
||||||
@@ -1132,6 +1215,8 @@ void isal_inflate_reset(struct inflate_state *state)
|
|||||||
state->bfinal = 0;
|
state->bfinal = 0;
|
||||||
state->crc = 0;
|
state->crc = 0;
|
||||||
state->type0_block_len = 0;
|
state->type0_block_len = 0;
|
||||||
|
state->write_overflow_lits = 0;
|
||||||
|
state->write_overflow_len = 0;
|
||||||
state->copy_overflow_length = 0;
|
state->copy_overflow_length = 0;
|
||||||
state->copy_overflow_distance = 0;
|
state->copy_overflow_distance = 0;
|
||||||
state->tmp_in_size = 0;
|
state->tmp_in_size = 0;
|
||||||
@@ -1187,7 +1272,7 @@ int isal_inflate_stateless(struct inflate_state *state)
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
if (state->bfinal != 0 && state->block_state == ISAL_BLOCK_NEW_HDR)
|
if (state->block_state == ISAL_BLOCK_INPUT_DONE)
|
||||||
state->block_state = ISAL_BLOCK_FINISH;
|
state->block_state = ISAL_BLOCK_FINISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,13 +1327,17 @@ int isal_inflate(struct inflate_state *state)
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
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 */
|
/* Copy valid data from internal buffer into out_buffer */
|
||||||
|
if (state->write_overflow_len != 0) {
|
||||||
|
*(uint32_t *) state->next_out = state->write_overflow_lits;
|
||||||
|
state->next_out += state->write_overflow_len;
|
||||||
|
state->total_out += state->write_overflow_len;
|
||||||
|
state->write_overflow_lits = 0;
|
||||||
|
state->write_overflow_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (state->copy_overflow_length != 0) {
|
if (state->copy_overflow_length != 0) {
|
||||||
byte_copy(state->next_out, state->copy_overflow_distance,
|
byte_copy(state->next_out, state->copy_overflow_distance,
|
||||||
state->copy_overflow_length);
|
state->copy_overflow_length);
|
||||||
@@ -1304,16 +1393,15 @@ int isal_inflate(struct inflate_state *state)
|
|||||||
ret = decode_huffman_code_block_stateless(state);
|
ret = decode_huffman_code_block_stateless(state);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
if (state->bfinal != 0
|
|
||||||
&& state->block_state == ISAL_BLOCK_NEW_HDR)
|
|
||||||
state->block_state = ISAL_BLOCK_INPUT_DONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->crc_flag)
|
if (state->crc_flag)
|
||||||
update_checksum(state, start_out, state->next_out - start_out);
|
update_checksum(state, start_out, state->next_out - start_out);
|
||||||
|
|
||||||
if (state->block_state != ISAL_BLOCK_INPUT_DONE) {
|
if (state->block_state != ISAL_BLOCK_INPUT_DONE
|
||||||
|
|| state->copy_overflow_length + state->write_overflow_len +
|
||||||
|
state->tmp_out_valid > sizeof(state->tmp_out_buffer)) {
|
||||||
/* Save decompression history in tmp_out buffer */
|
/* Save decompression history in tmp_out buffer */
|
||||||
if (state->tmp_out_valid == state->tmp_out_processed
|
if (state->tmp_out_valid == state->tmp_out_processed
|
||||||
&& avail_out - state->avail_out >= ISAL_DEF_HIST_SIZE) {
|
&& avail_out - state->avail_out >= ISAL_DEF_HIST_SIZE) {
|
||||||
@@ -1335,25 +1423,35 @@ int isal_inflate(struct inflate_state *state)
|
|||||||
state->tmp_out_processed -= shift_size;
|
state->tmp_out_processed -= shift_size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (state->copy_overflow_length != 0) {
|
/* Write overflow data into tmp buffer */
|
||||||
byte_copy(&state->tmp_out_buffer[state->tmp_out_valid],
|
if (state->write_overflow_len != 0) {
|
||||||
state->copy_overflow_distance,
|
*(uint32_t *) & state->tmp_out_buffer[state->tmp_out_valid] =
|
||||||
state->copy_overflow_length);
|
state->write_overflow_lits;
|
||||||
state->tmp_out_valid += state->copy_overflow_length;
|
state->tmp_out_valid += state->write_overflow_len;
|
||||||
state->total_out += state->copy_overflow_length;
|
state->total_out += state->write_overflow_len;
|
||||||
state->copy_overflow_distance = 0;
|
state->write_overflow_lits = 0;
|
||||||
state->copy_overflow_length = 0;
|
state->write_overflow_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == ISAL_INVALID_LOOKBACK || ret == ISAL_INVALID_BLOCK
|
if (state->copy_overflow_length != 0) {
|
||||||
|| ret == ISAL_INVALID_SYMBOL) {
|
byte_copy(&state->tmp_out_buffer[state->tmp_out_valid],
|
||||||
state->total_out -=
|
state->copy_overflow_distance, state->copy_overflow_length);
|
||||||
state->tmp_out_valid - state->tmp_out_processed;
|
state->tmp_out_valid += state->copy_overflow_length;
|
||||||
return ret;
|
state->total_out += state->copy_overflow_length;
|
||||||
}
|
state->copy_overflow_distance = 0;
|
||||||
|
state->copy_overflow_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (state->tmp_out_valid == state->tmp_out_processed) {
|
if (ret == ISAL_INVALID_LOOKBACK || ret == ISAL_INVALID_BLOCK
|
||||||
|
|| ret == ISAL_INVALID_SYMBOL) {
|
||||||
|
state->total_out -= state->tmp_out_valid - state->tmp_out_processed;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->block_state == ISAL_BLOCK_INPUT_DONE
|
||||||
|
&& state->tmp_out_valid == state->tmp_out_processed) {
|
||||||
state->block_state = ISAL_BLOCK_FINISH;
|
state->block_state = ISAL_BLOCK_FINISH;
|
||||||
if (state->crc_flag == ISAL_ZLIB
|
if (state->crc_flag == ISAL_ZLIB
|
||||||
|| state->crc_flag == ISAL_ZLIB_NO_HDR)
|
|| state->crc_flag == ISAL_ZLIB_NO_HDR)
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ FIELD _bfinal, 4, 4
|
|||||||
FIELD _crc_flag, 4, 4
|
FIELD _crc_flag, 4, 4
|
||||||
FIELD _crc, 4, 4
|
FIELD _crc, 4, 4
|
||||||
FIELD _type0_block_len, 4, 4
|
FIELD _type0_block_len, 4, 4
|
||||||
|
FIELD _write_overflow_lits, 4, 4
|
||||||
|
FIELD _write_overflow_len, 4, 4
|
||||||
FIELD _copy_overflow_len, 4, 4
|
FIELD _copy_overflow_len, 4, 4
|
||||||
FIELD _copy_overflow_dist, 4, 4
|
FIELD _copy_overflow_dist, 4, 4
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ ISAL_BLOCK_NEW_HDR equ 0
|
|||||||
ISAL_BLOCK_HDR equ 1
|
ISAL_BLOCK_HDR equ 1
|
||||||
ISAL_BLOCK_TYPE0 equ 2
|
ISAL_BLOCK_TYPE0 equ 2
|
||||||
ISAL_BLOCK_CODED equ 3
|
ISAL_BLOCK_CODED equ 3
|
||||||
ISAL_BLOCK_END equ 4
|
ISAL_BLOCK_INPUT_DONE equ 4
|
||||||
ISAL_BLOCK_FINISH equ 5
|
ISAL_BLOCK_FINISH equ 5
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
@@ -472,6 +472,8 @@ struct inflate_state {
|
|||||||
uint32_t crc_flag; //!< Flag identifying whether to track of crc
|
uint32_t crc_flag; //!< Flag identifying whether to track of crc
|
||||||
uint32_t crc; //!< Contains crc of output if crc_flag is set
|
uint32_t crc; //!< Contains crc of output if crc_flag is set
|
||||||
int32_t type0_block_len; //!< Length left to read of type 0 block when outbuffer overflow occured
|
int32_t type0_block_len; //!< Length left to read of type 0 block when outbuffer overflow occured
|
||||||
|
int32_t write_overflow_lits;
|
||||||
|
int32_t write_overflow_len;
|
||||||
int32_t copy_overflow_length; //!< Length left to copy when outbuffer overflow occured
|
int32_t copy_overflow_length; //!< Length left to copy when outbuffer overflow occured
|
||||||
int32_t copy_overflow_distance; //!< Lookback distance when outbuffer overlow occured
|
int32_t copy_overflow_distance; //!< Lookback distance when outbuffer overlow occured
|
||||||
int32_t tmp_in_size; //!< Number of bytes in tmp_in_buffer
|
int32_t tmp_in_size; //!< Number of bytes in tmp_in_buffer
|
||||||
|
|||||||
Reference in New Issue
Block a user