mirror of
https://github.com/intel/isa-l.git
synced 2024-12-13 09:52:56 +01:00
igzip: Rearrange inflate_state
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
5a7c97a930
commit
456be4cfc1
@ -306,11 +306,11 @@ uint32_t check_gzip_trl(struct inflate_state * gstream)
|
||||
uint8_t *index = NULL;
|
||||
uint32_t crc, ret = 0;
|
||||
|
||||
index = gstream->out_buffer.next_out - gstream->out_buffer.total_out;
|
||||
crc = find_crc(index, gstream->out_buffer.total_out);
|
||||
index = gstream->next_out - gstream->total_out;
|
||||
crc = find_crc(index, gstream->total_out);
|
||||
|
||||
if (gstream->out_buffer.total_out != *(uint32_t *) (gstream->in_buffer.next_in + 4) ||
|
||||
crc != *(uint32_t *) gstream->in_buffer.next_in)
|
||||
if (gstream->total_out != *(uint32_t *) (gstream->next_in + 4) ||
|
||||
crc != *(uint32_t *) gstream->next_in)
|
||||
ret = INCORRECT_GZIP_TRAILER;
|
||||
|
||||
return ret;
|
||||
@ -367,8 +367,8 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
||||
|
||||
#ifndef DEFLATE
|
||||
gzip_trl_result = check_gzip_trl(&gstream);
|
||||
gstream.in_buffer.avail_in -= gzip_trl_bytes;
|
||||
gstream.in_buffer.next_in += gzip_trl_bytes;
|
||||
gstream.avail_in -= gzip_trl_bytes;
|
||||
gstream.next_in += gzip_trl_bytes;
|
||||
#endif
|
||||
|
||||
if (test_buf != NULL)
|
||||
@ -400,10 +400,10 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gstream.in_buffer.avail_in != 0)
|
||||
if (gstream.avail_in != 0)
|
||||
return INFLATE_LEFTOVER_INPUT;
|
||||
|
||||
if (gstream.out_buffer.total_out != in_size)
|
||||
if (gstream.total_out != in_size)
|
||||
return INFLATE_INCORRECT_OUTPUT_SIZE;
|
||||
|
||||
if (mem_result)
|
||||
|
@ -41,9 +41,9 @@
|
||||
# define RUN_MEM_SIZE 2000000000
|
||||
#endif
|
||||
|
||||
extern uint64_t inflate_in_read_bits(struct inflate_in_buffer *, uint8_t);
|
||||
extern uint64_t inflate_in_read_bits(struct inflate_state *, uint8_t);
|
||||
extern int read_header(struct inflate_state *);
|
||||
extern uint16_t decode_next(struct inflate_in_buffer *, struct inflate_huff_code *);
|
||||
extern uint16_t decode_next(struct inflate_state *, struct inflate_huff_code *);
|
||||
|
||||
/* Inflates and fills a histogram of lit, len, and dist codes seen in non-type 0 blocks.*/
|
||||
int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *histogram)
|
||||
@ -92,28 +92,28 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
||||
|
||||
if (state->btype == 0) {
|
||||
/* If the block is uncompressed, update state data accordingly */
|
||||
if (state->in_buffer.avail_in < 4)
|
||||
if (state->avail_in < 4)
|
||||
return END_OF_INPUT;
|
||||
|
||||
len = *(uint16_t *) state->in_buffer.next_in;
|
||||
state->in_buffer.next_in += 2;
|
||||
nlen = *(uint16_t *) state->in_buffer.next_in;
|
||||
state->in_buffer.next_in += 2;
|
||||
len = *(uint16_t *) state->next_in;
|
||||
state->next_in += 2;
|
||||
nlen = *(uint16_t *) state->next_in;
|
||||
state->next_in += 2;
|
||||
|
||||
/* Check if len and nlen match */
|
||||
if (len != (~nlen & 0xffff))
|
||||
return INVALID_NON_COMPRESSED_BLOCK_LENGTH;
|
||||
|
||||
if (state->in_buffer.avail_in < len)
|
||||
len = state->in_buffer.avail_in;
|
||||
if (state->avail_in < len)
|
||||
len = state->avail_in;
|
||||
else
|
||||
state->new_block = 1;
|
||||
|
||||
state->out_buffer.total_out += len;
|
||||
state->in_buffer.next_in += len;
|
||||
state->in_buffer.avail_in -= len + 4;
|
||||
state->total_out += len;
|
||||
state->next_in += len;
|
||||
state->avail_in -= len + 4;
|
||||
|
||||
if (state->in_buffer.avail_in == 0 && state->new_block == 0)
|
||||
if (state->avail_in == 0 && state->new_block == 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
} else {
|
||||
@ -122,16 +122,16 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
||||
/* While not at the end of block, decode the next
|
||||
* symbol */
|
||||
next_lit =
|
||||
decode_next(&state->in_buffer, &state->lit_huff_code);
|
||||
decode_next(state, &state->lit_huff_code);
|
||||
|
||||
histogram->lit_len_histogram[next_lit] += 1;
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (next_lit < 256)
|
||||
/* Next symbol is a literal */
|
||||
state->out_buffer.total_out++;
|
||||
state->total_out++;
|
||||
|
||||
else if (next_lit == 256)
|
||||
/* Next symbol is end of block */
|
||||
@ -142,35 +142,35 @@ int isal_inflate_hist(struct inflate_state *state, struct isal_huff_histogram *h
|
||||
lookback distance */
|
||||
repeat_length =
|
||||
len_start[next_lit - 257] +
|
||||
inflate_in_read_bits(&state->in_buffer,
|
||||
inflate_in_read_bits(state,
|
||||
len_extra_bit_count[next_lit -
|
||||
257]);
|
||||
|
||||
next_dist = decode_next(&state->in_buffer,
|
||||
next_dist = decode_next(state,
|
||||
&state->dist_huff_code);
|
||||
|
||||
histogram->dist_histogram[next_dist] += 1;
|
||||
|
||||
look_back_dist = dist_start[next_dist] +
|
||||
inflate_in_read_bits(&state->in_buffer,
|
||||
inflate_in_read_bits(state,
|
||||
dist_extra_bit_count
|
||||
[next_dist]);
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (look_back_dist > state->out_buffer.total_out)
|
||||
if (look_back_dist > state->total_out)
|
||||
return INVALID_LOOK_BACK_DISTANCE;
|
||||
|
||||
state->out_buffer.total_out += repeat_length;
|
||||
state->total_out += repeat_length;
|
||||
|
||||
} else
|
||||
return INVALID_SYMBOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
state->in_buffer.next_in -= state->in_buffer.read_in_length / 8;
|
||||
state->in_buffer.avail_in += state->in_buffer.read_in_length / 8;
|
||||
state->next_in -= state->read_in_length / 8;
|
||||
state->avail_in += state->read_in_length / 8;
|
||||
|
||||
return DECOMPRESSION_FINISHED;
|
||||
}
|
||||
|
@ -81,6 +81,9 @@ extern rfc1951_lookup_table
|
||||
;; r15 ; Saved
|
||||
%define rfc_lookup r15
|
||||
|
||||
start_out_mem_offset equ 0
|
||||
stack_size equ 8
|
||||
|
||||
%define _dist_extra_bit_count 264
|
||||
%define _dist_start _dist_extra_bit_count + 1*32
|
||||
%define _len_extra_bit_count _dist_start + 4*32
|
||||
@ -264,18 +267,26 @@ decode_huffman_code_block_stateless_ %+ ARCH %+ :
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, stack_size
|
||||
|
||||
mov state, rdi
|
||||
lea rfc_lookup, [rfc1951_lookup_table]
|
||||
|
||||
mov read_in,[state + _in_buffer_read_in]
|
||||
mov read_in_length %+ d, dword [state + _in_buffer_read_in_length]
|
||||
mov next_out, [state + _out_buffer_next_out]
|
||||
mov end_out %+ d, dword [state + _out_buffer_avail_out]
|
||||
mov read_in,[state + _read_in]
|
||||
mov read_in_length %+ d, dword [state + _read_in_length]
|
||||
mov next_out, [state + _next_out]
|
||||
mov end_out %+ d, dword [state + _avail_out]
|
||||
add end_out, next_out
|
||||
mov next_in, [state + _in_buffer_next_in]
|
||||
mov end_in %+ d, dword [state + _in_buffer_avail_in]
|
||||
mov next_in, [state + _next_in]
|
||||
mov end_in %+ d, dword [state + _avail_in]
|
||||
add end_in, next_in
|
||||
|
||||
mov tmp3 %+ d, dword [state + _total_out]
|
||||
sub tmp3, next_out
|
||||
neg tmp3
|
||||
|
||||
mov [rsp + start_out_mem_offset], tmp3
|
||||
|
||||
sub end_out, OUT_BUFFER_SLOP
|
||||
sub end_in, IN_BUFFER_SLOP
|
||||
|
||||
@ -386,7 +397,7 @@ decode_len_dist:
|
||||
sub copy_start, look_back_dist2
|
||||
|
||||
;; ;; Check if a valid look back distances was decoded
|
||||
cmp copy_start, [state + _out_buffer_start_out]
|
||||
cmp copy_start, [rsp + start_out_mem_offset]
|
||||
jl invalid_look_back_distance
|
||||
vmovdqu xmm1, [copy_start]
|
||||
|
||||
@ -490,7 +501,7 @@ decode_len_dist_2:
|
||||
jg out_buffer_overflow
|
||||
|
||||
;; Check if a valid look back distance was decoded
|
||||
cmp rsi, [state + _out_buffer_start_out]
|
||||
cmp rsi, [rsp + start_out_mem_offset]
|
||||
jl invalid_look_back_distance
|
||||
|
||||
rep movsb
|
||||
@ -527,17 +538,18 @@ end_symbol:
|
||||
xor rax, rax
|
||||
end:
|
||||
;; Save current buffer states
|
||||
mov [state + _in_buffer_read_in], read_in
|
||||
mov [state + _in_buffer_read_in_length], read_in_length %+ d
|
||||
mov [state + _out_buffer_next_out], next_out
|
||||
mov [state + _read_in], read_in
|
||||
mov [state + _read_in_length], read_in_length %+ d
|
||||
mov [state + _next_out], next_out
|
||||
sub end_out, next_out
|
||||
mov dword [state + _out_buffer_avail_out], end_out %+ d
|
||||
sub next_out, [state + _out_buffer_start_out]
|
||||
mov [state + _out_buffer_total_out], next_out %+ d
|
||||
mov [state + _in_buffer_next_in], next_in
|
||||
mov dword [state + _avail_out], end_out %+ d
|
||||
sub next_out, [rsp + start_out_mem_offset]
|
||||
mov [state + _total_out], next_out %+ d
|
||||
mov [state + _next_in], next_in
|
||||
sub end_in, next_in
|
||||
mov [state + _in_buffer_avail_in], end_in %+ d
|
||||
mov [state + _avail_in], end_in %+ d
|
||||
|
||||
add rsp, stack_size
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
|
@ -66,110 +66,53 @@ uint16_t inline bit_reverse2(uint16_t bits, uint8_t length)
|
||||
return bits >> (16 - length);
|
||||
}
|
||||
|
||||
/* Initialize a struct in_buffer for use */
|
||||
void inline init_inflate_in_buffer(struct inflate_in_buffer *inflate_in)
|
||||
{
|
||||
inflate_in->read_in = 0;
|
||||
inflate_in->read_in_length = 0;
|
||||
}
|
||||
|
||||
/* Set up the in_stream used for the in_buffer*/
|
||||
void inline set_inflate_in_buffer(struct inflate_in_buffer *inflate_in, uint8_t * in_stream,
|
||||
uint32_t in_size)
|
||||
{
|
||||
inflate_in->next_in = inflate_in->start = in_stream;
|
||||
inflate_in->avail_in = in_size;
|
||||
}
|
||||
|
||||
/* Set up the out_stream used for the out_buffer */
|
||||
void inline set_inflate_out_buffer(struct inflate_out_buffer *inflate_out,
|
||||
uint8_t * out_stream, uint32_t out_size)
|
||||
{
|
||||
inflate_out->start_out = out_stream;
|
||||
inflate_out->next_out = out_stream;
|
||||
inflate_out->avail_out = out_size;
|
||||
inflate_out->total_out = 0;
|
||||
}
|
||||
|
||||
|
||||
void inline inflate_in_clear_bits(struct inflate_in_buffer *inflate_in)
|
||||
{
|
||||
uint8_t bytes;
|
||||
|
||||
bytes = inflate_in->read_in_length / 8;
|
||||
|
||||
inflate_in->read_in = 0;
|
||||
inflate_in->read_in_length = 0;
|
||||
inflate_in->next_in -= bytes;
|
||||
inflate_in->avail_in += bytes;
|
||||
}
|
||||
|
||||
/* Load data from the in_stream into a buffer to allow for handling unaligned data*/
|
||||
void inline inflate_in_load(struct inflate_in_buffer *inflate_in, int min_required)
|
||||
void inline inflate_in_load(struct inflate_state *state, int min_required)
|
||||
{
|
||||
uint64_t temp = 0;
|
||||
uint8_t new_bytes;
|
||||
|
||||
if (inflate_in->avail_in >= 8) {
|
||||
if (state->avail_in >= 8) {
|
||||
/* If there is enough space to load a 64 bits, load the data and use
|
||||
* that to fill read_in */
|
||||
new_bytes = 8 - (inflate_in->read_in_length + 7) / 8;
|
||||
temp = *(uint64_t *) inflate_in->next_in;
|
||||
new_bytes = 8 - (state->read_in_length + 7) / 8;
|
||||
temp = *(uint64_t *) state->next_in;
|
||||
|
||||
inflate_in->read_in |= temp << inflate_in->read_in_length;
|
||||
inflate_in->next_in += new_bytes;
|
||||
inflate_in->avail_in -= new_bytes;
|
||||
inflate_in->read_in_length += new_bytes * 8;
|
||||
state->read_in |= temp << state->read_in_length;
|
||||
state->next_in += new_bytes;
|
||||
state->avail_in -= new_bytes;
|
||||
state->read_in_length += new_bytes * 8;
|
||||
|
||||
} else {
|
||||
/* Else fill the read_in buffer 1 byte at a time */
|
||||
while (inflate_in->read_in_length < 57 && inflate_in->avail_in > 0) {
|
||||
temp = *inflate_in->next_in;
|
||||
inflate_in->read_in |= temp << inflate_in->read_in_length;
|
||||
inflate_in->next_in++;
|
||||
inflate_in->avail_in--;
|
||||
inflate_in->read_in_length += 8;
|
||||
while (state->read_in_length < 57 && state->avail_in > 0) {
|
||||
temp = *state->next_in;
|
||||
state->read_in |= temp << state->read_in_length;
|
||||
state->next_in++;
|
||||
state->avail_in--;
|
||||
state->read_in_length += 8;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Returns the next bit_count bits from the in stream*/
|
||||
uint64_t inline inflate_in_peek_bits(struct inflate_in_buffer *inflate_in, uint8_t bit_count)
|
||||
{
|
||||
assert(bit_count < 57);
|
||||
|
||||
/* Load inflate_in if not enough data is in the read_in buffer */
|
||||
if (inflate_in->read_in_length < bit_count)
|
||||
inflate_in_load(inflate_in, 0);
|
||||
|
||||
return (inflate_in->read_in) & ((1 << bit_count) - 1);
|
||||
}
|
||||
|
||||
/* Shifts the in stream over by bit-count bits */
|
||||
void inline inflate_in_shift_bits(struct inflate_in_buffer *inflate_in, uint8_t bit_count)
|
||||
{
|
||||
|
||||
inflate_in->read_in >>= bit_count;
|
||||
inflate_in->read_in_length -= bit_count;
|
||||
}
|
||||
|
||||
/* Returns the next bit_count bits from the in stream and shifts the stream over
|
||||
* by bit-count bits */
|
||||
uint64_t inflate_in_read_bits(struct inflate_in_buffer *inflate_in, uint8_t bit_count);
|
||||
uint64_t inline inflate_in_read_bits(struct inflate_in_buffer *inflate_in, uint8_t bit_count)
|
||||
uint64_t inflate_in_read_bits(struct inflate_state *state, uint8_t bit_count);
|
||||
uint64_t inline inflate_in_read_bits(struct inflate_state *state, uint8_t bit_count)
|
||||
{
|
||||
uint64_t ret;
|
||||
assert(bit_count < 57);
|
||||
|
||||
/* Load inflate_in if not enough data is in the read_in buffer */
|
||||
if (inflate_in->read_in_length < bit_count)
|
||||
inflate_in_load(inflate_in, bit_count);
|
||||
if (state->read_in_length < bit_count)
|
||||
inflate_in_load(state, bit_count);
|
||||
|
||||
ret = (inflate_in->read_in) & ((1 << bit_count) - 1);
|
||||
inflate_in->read_in >>= bit_count;
|
||||
inflate_in->read_in_length -= bit_count;
|
||||
ret = (state->read_in) & ((1 << bit_count) - 1);
|
||||
state->read_in >>= bit_count;
|
||||
state->read_in_length -= bit_count;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -323,14 +266,19 @@ int inline setup_static_header(struct inflate_state *state)
|
||||
|
||||
/* Decodes the next symbol symbol in in_buffer using the huff code defined by
|
||||
* huff_code */
|
||||
uint16_t decode_next(struct inflate_in_buffer *in_buffer, struct inflate_huff_code *huff_code);
|
||||
uint16_t inline decode_next(struct inflate_in_buffer *in_buffer,
|
||||
uint16_t decode_next(struct inflate_state *state, struct inflate_huff_code *huff_code);
|
||||
uint16_t inline decode_next(struct inflate_state *state,
|
||||
struct inflate_huff_code *huff_code)
|
||||
{
|
||||
uint16_t next_bits;
|
||||
uint16_t next_sym;
|
||||
uint32_t bit_count;
|
||||
uint32_t bit_mask;
|
||||
|
||||
next_bits = inflate_in_peek_bits(in_buffer, DECODE_LOOKUP_SIZE);
|
||||
if (state->read_in_length <= DEFLATE_CODE_MAX_LENGTH)
|
||||
inflate_in_load(state, 0);
|
||||
|
||||
next_bits = state->read_in & ((1 << DECODE_LOOKUP_SIZE) - 1);
|
||||
|
||||
/* next_sym is a possible symbol decoded from next_bits. If bit 15 is 0,
|
||||
* next_code is a symbol. Bits 9:0 represent the symbol, and bits 14:10
|
||||
@ -343,18 +291,24 @@ uint16_t inline decode_next(struct inflate_in_buffer *in_buffer,
|
||||
if (next_sym < 0x8000) {
|
||||
/* Return symbol found if next_code is a complete huffman code
|
||||
* and shift in buffer over by the length of the next_code */
|
||||
inflate_in_shift_bits(in_buffer, next_sym >> 9);
|
||||
bit_count = next_sym >> 9;
|
||||
state->read_in >>= bit_count;
|
||||
state->read_in_length -= bit_count;
|
||||
|
||||
return next_sym & 0x1FF;
|
||||
|
||||
} else {
|
||||
/* If a symbol is not found, perform a linear search of the long code
|
||||
* list starting from the hint in next_sym */
|
||||
next_bits = inflate_in_peek_bits(in_buffer, (next_sym - 0x8000) >> 9);
|
||||
bit_mask = (next_sym - 0x8000) >> 9;
|
||||
bit_mask = (1 << bit_mask) - 1;
|
||||
next_bits = state->read_in & bit_mask;
|
||||
next_sym =
|
||||
huff_code->long_code_lookup[(next_sym & 0x1FF) +
|
||||
(next_bits >> DECODE_LOOKUP_SIZE)];
|
||||
inflate_in_shift_bits(in_buffer, next_sym >> 9);
|
||||
bit_count = next_sym >> 9;
|
||||
state->read_in >>= bit_count;
|
||||
state->read_in_length -= bit_count;
|
||||
return next_sym & 0x1FF;
|
||||
|
||||
}
|
||||
@ -388,19 +342,19 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
memset(lit_and_dist_huff, 0, sizeof(lit_and_dist_huff));
|
||||
|
||||
/* These variables are defined in the deflate standard, RFC 1951 */
|
||||
hlit = inflate_in_read_bits(&state->in_buffer, 5);
|
||||
hdist = inflate_in_read_bits(&state->in_buffer, 5);
|
||||
hclen = inflate_in_read_bits(&state->in_buffer, 4);
|
||||
hlit = inflate_in_read_bits(state, 5);
|
||||
hdist = inflate_in_read_bits(state, 5);
|
||||
hclen = inflate_in_read_bits(state, 4);
|
||||
|
||||
/* Create the code huffman code for decoding the lit/len and dist huffman codes */
|
||||
for (i = 0; i < hclen + 4; i++) {
|
||||
code_huff[code_length_code_order[i]].length =
|
||||
inflate_in_read_bits(&state->in_buffer, 3);
|
||||
inflate_in_read_bits(state, 3);
|
||||
|
||||
code_count[code_huff[code_length_code_order[i]].length] += 1;
|
||||
}
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
make_inflate_huff_code(&inflate_code_huff, code_huff, CODE_LEN_CODES, code_count);
|
||||
@ -420,9 +374,9 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
if (current == lit_and_dist_huff + LIT_LEN)
|
||||
count = dist_count;
|
||||
|
||||
symbol = decode_next(&state->in_buffer, &inflate_code_huff);
|
||||
symbol = decode_next(state, &inflate_code_huff);
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (symbol < 16) {
|
||||
@ -440,7 +394,7 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
if (previous == NULL) /* No elements available to be repeated */
|
||||
return INVALID_BLOCK_HEADER;
|
||||
|
||||
i = 3 + inflate_in_read_bits(&state->in_buffer, 2);
|
||||
i = 3 + inflate_in_read_bits(state, 2);
|
||||
for (j = 0; j < i; j++) {
|
||||
*current = *previous;
|
||||
count[current->length]++;
|
||||
@ -458,7 +412,7 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
/* If a repeat zeroes if found, update then next
|
||||
* repeated zeroes length lit/len/dist elements to have
|
||||
* length 0. */
|
||||
i = 3 + inflate_in_read_bits(&state->in_buffer, 3);
|
||||
i = 3 + inflate_in_read_bits(state, 3);
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
previous = current;
|
||||
@ -475,7 +429,7 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
/* If a repeat zeroes if found, update then next
|
||||
* repeated zeroes length lit/len/dist elements to have
|
||||
* length 0. */
|
||||
i = 11 + inflate_in_read_bits(&state->in_buffer, 7);
|
||||
i = 11 + inflate_in_read_bits(state, 7);
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
previous = current;
|
||||
@ -492,7 +446,7 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
|
||||
}
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
make_inflate_huff_code(&state->lit_huff_code, lit_and_dist_huff, LIT_LEN, lit_count);
|
||||
@ -506,19 +460,26 @@ int inline setup_dynamic_header(struct inflate_state *state)
|
||||
* header information*/
|
||||
int read_header(struct inflate_state *state)
|
||||
{
|
||||
uint8_t bytes;
|
||||
|
||||
state->new_block = 0;
|
||||
|
||||
/* btype and bfinal are defined in RFC 1951, bfinal represents whether
|
||||
* the current block is the end of block, and btype represents the
|
||||
* encoding method on the current block. */
|
||||
state->bfinal = inflate_in_read_bits(&state->in_buffer, 1);
|
||||
state->btype = inflate_in_read_bits(&state->in_buffer, 2);
|
||||
state->bfinal = inflate_in_read_bits(state, 1);
|
||||
state->btype = inflate_in_read_bits(state, 2);
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (state->btype == 0) {
|
||||
inflate_in_clear_bits(&state->in_buffer);
|
||||
bytes = state->read_in_length / 8;
|
||||
|
||||
state->read_in = 0;
|
||||
state->read_in_length = 0;
|
||||
state->next_in -= bytes;
|
||||
state->avail_in += bytes;
|
||||
return 0;
|
||||
|
||||
} else if (state->btype == 1)
|
||||
@ -535,36 +496,36 @@ int inline decode_literal_block(struct inflate_state *state)
|
||||
uint16_t len, nlen;
|
||||
/* If the block is uncompressed, perform a memcopy while
|
||||
* updating state data */
|
||||
if (state->in_buffer.avail_in < 4)
|
||||
if (state->avail_in < 4)
|
||||
return END_OF_INPUT;
|
||||
|
||||
len = *(uint16_t *) state->in_buffer.next_in;
|
||||
state->in_buffer.next_in += 2;
|
||||
nlen = *(uint16_t *) state->in_buffer.next_in;
|
||||
state->in_buffer.next_in += 2;
|
||||
len = *(uint16_t *) state->next_in;
|
||||
state->next_in += 2;
|
||||
nlen = *(uint16_t *) state->next_in;
|
||||
state->next_in += 2;
|
||||
|
||||
/* Check if len and nlen match */
|
||||
if (len != (~nlen & 0xffff))
|
||||
return INVALID_NON_COMPRESSED_BLOCK_LENGTH;
|
||||
|
||||
if (state->out_buffer.avail_out < len)
|
||||
if (state->avail_out < len)
|
||||
return OUT_BUFFER_OVERFLOW;
|
||||
|
||||
if (state->in_buffer.avail_in < len)
|
||||
len = state->in_buffer.avail_in;
|
||||
if (state->avail_in < len)
|
||||
len = state->avail_in;
|
||||
|
||||
else
|
||||
state->new_block = 1;
|
||||
|
||||
memcpy(state->out_buffer.next_out, state->in_buffer.next_in, len);
|
||||
memcpy(state->next_out, state->next_in, len);
|
||||
|
||||
state->out_buffer.next_out += len;
|
||||
state->out_buffer.avail_out -= len;
|
||||
state->out_buffer.total_out += len;
|
||||
state->in_buffer.next_in += len;
|
||||
state->in_buffer.avail_in -= len + 4;
|
||||
state->next_out += len;
|
||||
state->avail_out -= len;
|
||||
state->total_out += len;
|
||||
state->next_in += len;
|
||||
state->avail_in -= len + 4;
|
||||
|
||||
if (state->in_buffer.avail_in == 0 && state->new_block == 0)
|
||||
if (state->avail_in == 0 && state->new_block == 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
return 0;
|
||||
@ -583,22 +544,22 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
||||
/* While not at the end of block, decode the next
|
||||
* symbol */
|
||||
|
||||
next_lit = decode_next(&state->in_buffer, &state->lit_huff_code);
|
||||
next_lit = decode_next(state, &state->lit_huff_code);
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (next_lit < 256) {
|
||||
/* If the next symbol is a literal,
|
||||
* write out the symbol and update state
|
||||
* data accordingly. */
|
||||
if (state->out_buffer.avail_out < 1)
|
||||
if (state->avail_out < 1)
|
||||
return OUT_BUFFER_OVERFLOW;
|
||||
|
||||
*state->out_buffer.next_out = next_lit;
|
||||
state->out_buffer.next_out++;
|
||||
state->out_buffer.avail_out--;
|
||||
state->out_buffer.total_out++;
|
||||
*state->next_out = next_lit;
|
||||
state->next_out++;
|
||||
state->avail_out--;
|
||||
state->total_out++;
|
||||
|
||||
} else if (next_lit == 256) {
|
||||
/* If the next symbol is the end of
|
||||
@ -615,37 +576,37 @@ int decode_huffman_code_block_stateless_base(struct inflate_state *state)
|
||||
* state data accordingly*/
|
||||
repeat_length =
|
||||
rfc_lookup_table.len_start[next_lit - 257] +
|
||||
inflate_in_read_bits(&state->in_buffer,
|
||||
inflate_in_read_bits(state,
|
||||
rfc_lookup_table.
|
||||
len_extra_bit_count[next_lit - 257]);
|
||||
|
||||
if (state->out_buffer.avail_out < repeat_length)
|
||||
if (state->avail_out < repeat_length)
|
||||
return OUT_BUFFER_OVERFLOW;
|
||||
|
||||
next_dist = decode_next(&state->in_buffer, &state->dist_huff_code);
|
||||
next_dist = decode_next(state, &state->dist_huff_code);
|
||||
|
||||
look_back_dist = rfc_lookup_table.dist_start[next_dist] +
|
||||
inflate_in_read_bits(&state->in_buffer,
|
||||
inflate_in_read_bits(state,
|
||||
rfc_lookup_table.
|
||||
dist_extra_bit_count[next_dist]);
|
||||
|
||||
if (state->in_buffer.read_in_length < 0)
|
||||
if (state->read_in_length < 0)
|
||||
return END_OF_INPUT;
|
||||
|
||||
if (look_back_dist > state->out_buffer.total_out)
|
||||
if (look_back_dist > state->total_out)
|
||||
return INVALID_LOOK_BACK_DISTANCE;
|
||||
|
||||
if (look_back_dist > repeat_length)
|
||||
memcpy(state->out_buffer.next_out,
|
||||
state->out_buffer.next_out -
|
||||
memcpy(state->next_out,
|
||||
state->next_out -
|
||||
look_back_dist, repeat_length);
|
||||
else
|
||||
byte_copy(state->out_buffer.next_out,
|
||||
byte_copy(state->next_out,
|
||||
look_back_dist, repeat_length);
|
||||
|
||||
state->out_buffer.next_out += repeat_length;
|
||||
state->out_buffer.avail_out -= repeat_length;
|
||||
state->out_buffer.total_out += repeat_length;
|
||||
state->next_out += repeat_length;
|
||||
state->avail_out -= repeat_length;
|
||||
state->total_out += repeat_length;
|
||||
} else
|
||||
/* Else the read in bits do not
|
||||
* correspond to any valid symbol */
|
||||
@ -658,11 +619,14 @@ void isal_inflate_init(struct inflate_state *state, uint8_t * in_stream, uint32_
|
||||
uint8_t * out_stream, uint64_t out_size)
|
||||
{
|
||||
|
||||
init_inflate_in_buffer(&state->in_buffer);
|
||||
|
||||
set_inflate_in_buffer(&state->in_buffer, in_stream, in_size);
|
||||
set_inflate_out_buffer(&state->out_buffer, out_stream, out_size);
|
||||
|
||||
state->read_in = 0;
|
||||
state->read_in_length = 0;
|
||||
state->next_in = in_stream;
|
||||
state->avail_in = in_size;
|
||||
state->next_out = out_stream;
|
||||
state->avail_out = out_size;
|
||||
state->total_out = 0;
|
||||
state->new_block = 1;
|
||||
state->bfinal = 0;
|
||||
}
|
||||
@ -689,8 +653,8 @@ int isal_inflate_stateless(struct inflate_state *state)
|
||||
}
|
||||
|
||||
/* Undo count stuff of bytes read into the read buffer */
|
||||
state->in_buffer.next_in -= state->in_buffer.read_in_length / 8;
|
||||
state->in_buffer.avail_in += state->in_buffer.read_in_length / 8;
|
||||
state->next_in -= state->read_in_length / 8;
|
||||
state->avail_in += state->read_in_length / 8;
|
||||
|
||||
return DECOMPRESSION_FINISHED;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
perf_stop(&stop);
|
||||
printf(" file %s - in_size=%d out_size=%d iter=%d\n", argv[1],
|
||||
infile_size, state.out_buffer.total_out, i);
|
||||
infile_size, state.total_out, i);
|
||||
|
||||
printf("igzip_file: ");
|
||||
perf_print(stop, start, (long long)infile_size * i);
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include "inflate.h"
|
||||
#include "huff_codes.h"
|
||||
|
||||
#define OUT_BUFFER_SLOP 16
|
||||
|
||||
/*Don't use file larger memory can support because compression and decompression
|
||||
* are done in a stateless manner. */
|
||||
#define MAX_INPUT_FILE_SIZE 2L*1024L*1024L*1024L
|
||||
@ -90,9 +88,9 @@ int test(uint8_t * compressed_stream, uint64_t * compressed_length,
|
||||
break;
|
||||
}
|
||||
|
||||
if (state.out_buffer.total_out != uncompressed_length) {
|
||||
if (state.total_out != uncompressed_length) {
|
||||
printf("incorrect amount of data was decompressed from compressed data\n");
|
||||
printf("%d decompressed of %d compressed", state.out_buffer.total_out,
|
||||
printf("%d decompressed of %d compressed", state.total_out,
|
||||
uncompressed_length);
|
||||
return -1;
|
||||
}
|
||||
@ -164,7 +162,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
uncompressed_length = fread(uncompressed_stream, 1, file_length, file);
|
||||
uncompressed_test_stream_length = uncompressed_length + OUT_BUFFER_SLOP;
|
||||
uncompressed_test_stream_length = uncompressed_length;
|
||||
|
||||
ret =
|
||||
test(compressed_stream, &compressed_length, uncompressed_stream,
|
||||
|
@ -311,11 +311,11 @@ uint32_t check_gzip_trl(struct inflate_state * gstream)
|
||||
uint8_t *index = NULL;
|
||||
uint32_t crc, ret = 0;
|
||||
|
||||
index = gstream->out_buffer.next_out - gstream->out_buffer.total_out;
|
||||
crc = find_crc(index, gstream->out_buffer.total_out);
|
||||
index = gstream->next_out - gstream->total_out;
|
||||
crc = find_crc(index, gstream->total_out);
|
||||
|
||||
if (gstream->out_buffer.total_out != *(uint32_t *) (gstream->in_buffer.next_in + 4) ||
|
||||
crc != *(uint32_t *) gstream->in_buffer.next_in)
|
||||
if (gstream->total_out != *(uint32_t *) (gstream->next_in + 4) ||
|
||||
crc != *(uint32_t *) gstream->next_in)
|
||||
ret = INCORRECT_GZIP_TRAILER;
|
||||
|
||||
return ret;
|
||||
@ -371,8 +371,8 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
||||
|
||||
#ifndef DEFLATE
|
||||
gzip_trl_result = check_gzip_trl(&gstream);
|
||||
gstream.in_buffer.avail_in -= gzip_trl_bytes;
|
||||
gstream.in_buffer.next_in += gzip_trl_bytes;
|
||||
gstream.avail_in -= gzip_trl_bytes;
|
||||
gstream.next_in += gzip_trl_bytes;
|
||||
#endif
|
||||
|
||||
if (test_buf != NULL)
|
||||
@ -404,10 +404,10 @@ int inflate_check(uint8_t * z_buf, int z_size, uint8_t * in_buf, int in_size)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gstream.in_buffer.avail_in != 0)
|
||||
if (gstream.avail_in != 0)
|
||||
return INFLATE_LEFTOVER_INPUT;
|
||||
|
||||
if (gstream.out_buffer.total_out != in_size)
|
||||
if (gstream.total_out != in_size)
|
||||
return INFLATE_INCORRECT_OUTPUT_SIZE;
|
||||
|
||||
if (mem_result)
|
||||
|
@ -24,41 +24,10 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
START_FIELDS ;; inflate out buffer
|
||||
|
||||
;; name size align
|
||||
FIELD _start_out, 8, 8
|
||||
FIELD _next_out, 8, 8
|
||||
FIELD _avail_out, 4, 4
|
||||
FIELD _total_out, 4, 4
|
||||
|
||||
%assign _inflate_out_buffer_size _FIELD_OFFSET
|
||||
%assign _inflate_out_buffer_align _STRUCT_ALIGN
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
START_FIELDS ;; inflate in buffer
|
||||
|
||||
;; name size align
|
||||
FIELD _start_in, 8, 8
|
||||
FIELD _next_in, 8, 8
|
||||
FIELD _avail_in, 4, 4
|
||||
FIELD _read_in, 8, 8
|
||||
FIELD _read_in_length,4, 4
|
||||
|
||||
%assign _inflate_in_buffer_size _FIELD_OFFSET
|
||||
%assign _inflate_in_buffer_align _STRUCT_ALIGN
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
START_FIELDS ;; inflate huff code
|
||||
|
||||
;; name size align
|
||||
FIELD _small_code_lookup, 2 * (1 << (DECODE_LOOKUP_SIZE)), 8
|
||||
FIELD _small_code_lookup, 2 * (1 << (DECODE_LOOKUP_SIZE)), 2
|
||||
FIELD _long_code_lookup, 2 * MAX_LONG_CODE, 2
|
||||
|
||||
%assign _inflate_huff_code_size _FIELD_OFFSET
|
||||
@ -71,8 +40,13 @@ FIELD _long_code_lookup, 2 * MAX_LONG_CODE, 2
|
||||
START_FIELDS ;; inflate state
|
||||
|
||||
;; name size align
|
||||
FIELD _out_buffer, _inflate_out_buffer_size, _inflate_out_buffer_align
|
||||
FIELD _in_buffer, _inflate_in_buffer_size, _inflate_in_buffer_align
|
||||
FIELD _next_out, 8, 8
|
||||
FIELD _avail_out, 4, 4
|
||||
FIELD _total_out, 4, 4
|
||||
FIELD _next_in, 8, 8
|
||||
FIELD _read_in, 8, 8
|
||||
FIELD _avail_in, 4, 4
|
||||
FIELD _read_in_length,4, 4
|
||||
FIELD _lit_huff_code, _inflate_huff_code_size, _inflate_huff_code_align
|
||||
FIELD _dist_huff_code,_inflate_huff_code_size, _inflate_huff_code_align
|
||||
FIELD _new_block, 1, 1
|
||||
@ -82,17 +56,6 @@ FIELD _btype, 1, 1
|
||||
%assign _inflate_state_size _FIELD_OFFSET
|
||||
%assign _inflate_state_align _STRUCT_ALIGN
|
||||
|
||||
_out_buffer_start_out equ _out_buffer+_start_out
|
||||
_out_buffer_next_out equ _out_buffer+_next_out
|
||||
_out_buffer_avail_out equ _out_buffer+_avail_out
|
||||
_out_buffer_total_out equ _out_buffer+_total_out
|
||||
|
||||
_in_buffer_start equ _in_buffer+_start_in
|
||||
_in_buffer_next_in equ _in_buffer+_next_in
|
||||
_in_buffer_avail_in equ _in_buffer+_avail_in
|
||||
_in_buffer_read_in equ _in_buffer+_read_in
|
||||
_in_buffer_read_in_length equ _in_buffer+_read_in_length
|
||||
|
||||
_lit_huff_code_small_code_lookup equ _lit_huff_code+_small_code_lookup
|
||||
_lit_huff_code_long_code_lookup equ _lit_huff_code+_long_code_lookup
|
||||
|
||||
|
@ -13,28 +13,12 @@
|
||||
|
||||
#define DECODE_LOOKUP_SIZE 12
|
||||
|
||||
#if DECODE_LOOKUP_SIZE > 15
|
||||
#define DEFLATE_CODE_MAX_LENGTH 15
|
||||
#if DECODE_LOOKUP_SIZE > DEFLATE_CODE_MAX_LENGTH
|
||||
# undef DECODE_LOOKUP_SIZE
|
||||
# define DECODE_LOOKUP_SIZE 15
|
||||
# define DECODE_LOOKUP_SIZE DEFLATE_CODE_MAX_LENGTH
|
||||
#endif
|
||||
|
||||
/* Buffer used to manage decompressed output */
|
||||
struct inflate_out_buffer{
|
||||
uint8_t *start_out;
|
||||
uint8_t *next_out;
|
||||
uint32_t avail_out;
|
||||
uint32_t total_out;
|
||||
};
|
||||
|
||||
/* Buffer used to manager compressed input */
|
||||
struct inflate_in_buffer{
|
||||
uint8_t *start;
|
||||
uint8_t *next_in;
|
||||
uint32_t avail_in;
|
||||
uint64_t read_in;
|
||||
int32_t read_in_length;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -80,6 +64,7 @@ struct inflate_in_buffer{
|
||||
* small_lookup_code is 9 bits long because the increasing relationship between
|
||||
* code length and code value forces the maximum offset to be less than 288.
|
||||
*/
|
||||
|
||||
struct inflate_huff_code{
|
||||
uint16_t small_code_lookup[ 1 << (DECODE_LOOKUP_SIZE)];
|
||||
uint16_t long_code_lookup[288 + (1 << (15 - DECODE_LOOKUP_SIZE))];
|
||||
@ -87,8 +72,13 @@ struct inflate_huff_code{
|
||||
|
||||
/* Structure contained current state of decompression of data */
|
||||
struct inflate_state {
|
||||
struct inflate_out_buffer out_buffer;
|
||||
struct inflate_in_buffer in_buffer;
|
||||
uint8_t *next_out;
|
||||
uint32_t avail_out;
|
||||
uint32_t total_out;
|
||||
uint8_t *next_in;
|
||||
uint64_t read_in;
|
||||
uint32_t avail_in;
|
||||
int32_t read_in_length;
|
||||
struct inflate_huff_code lit_huff_code;
|
||||
struct inflate_huff_code dist_huff_code;
|
||||
uint8_t new_block;
|
||||
|
Loading…
Reference in New Issue
Block a user