fast_encoder.c (lzlib-1.12.tar.lz) | : | fast_encoder.c (lzlib-1.13.tar.lz) | ||
---|---|---|---|---|
/* Lzlib - Compression library for the lzip format | /* Lzlib - Compression library for the lzip format | |||
Copyright (C) 2009-2021 Antonio Diaz Diaz. | Copyright (C) 2009-2022 Antonio Diaz Diaz. | |||
This library is free software. Redistribution and use in source and | This library is free software. Redistribution and use in source and | |||
binary forms, with or without modification, are permitted provided | binary forms, with or without modification, are permitted provided | |||
that the following conditions are met: | that the following conditions are met: | |||
1. Redistributions of source code must retain the above copyright | 1. Redistributions of source code must retain the above copyright | |||
notice, this list of conditions, and the following disclaimer. | notice, this list of conditions, and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright | 2. Redistributions in binary form must reproduce the above copyright | |||
notice, this list of conditions, and the following disclaimer in the | notice, this list of conditions, and the following disclaimer in the | |||
documentation and/or other materials provided with the distribution. | documentation and/or other materials provided with the distribution. | |||
This library is distributed in the hope that it will be useful, | This library is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |||
*/ | */ | |||
static int FLZe_longest_match_len( struct FLZ_encoder * const fe, int * const di stance ) | static int FLZe_longest_match_len( struct FLZ_encoder * const fe, int * const di stance ) | |||
{ | { | |||
enum { len_limit = 16 }; | enum { len_limit = 16 }; | |||
const uint8_t * const data = Mb_ptr_to_current_pos( &fe->eb.mb ); | ||||
int32_t * ptr0 = fe->eb.mb.pos_array + fe->eb.mb.cyclic_pos; | int32_t * ptr0 = fe->eb.mb.pos_array + fe->eb.mb.cyclic_pos; | |||
const int pos1 = fe->eb.mb.pos + 1; | ||||
int maxlen = 0, newpos1, count; | ||||
const int available = min( Mb_available_bytes( &fe->eb.mb ), max_match_len ); | const int available = min( Mb_available_bytes( &fe->eb.mb ), max_match_len ); | |||
if( available < len_limit ) { *ptr0 = 0; return 0; } | if( available < len_limit ) { *ptr0 = 0; return 0; } | |||
const uint8_t * const data = Mb_ptr_to_current_pos( &fe->eb.mb ); | ||||
fe->key4 = ( ( fe->key4 << 4 ) ^ data[3] ) & fe->eb.mb.key4_mask; | fe->key4 = ( ( fe->key4 << 4 ) ^ data[3] ) & fe->eb.mb.key4_mask; | |||
newpos1 = fe->eb.mb.prev_positions[fe->key4]; | const int pos1 = fe->eb.mb.pos + 1; | |||
int newpos1 = fe->eb.mb.prev_positions[fe->key4]; | ||||
fe->eb.mb.prev_positions[fe->key4] = pos1; | fe->eb.mb.prev_positions[fe->key4] = pos1; | |||
int maxlen = 0, count; | ||||
for( count = 4; ; ) | for( count = 4; ; ) | |||
{ | { | |||
int32_t * newptr; | ||||
int delta; | int delta; | |||
if( newpos1 <= 0 || --count < 0 || | if( newpos1 <= 0 || --count < 0 || | |||
( delta = pos1 - newpos1 ) > fe->eb.mb.dictionary_size ) | ( delta = pos1 - newpos1 ) > fe->eb.mb.dictionary_size ) | |||
{ *ptr0 = 0; break; } | { *ptr0 = 0; break; } | |||
newptr = fe->eb.mb.pos_array + | int32_t * const newptr = fe->eb.mb.pos_array + | |||
( fe->eb.mb.cyclic_pos - delta + | ( fe->eb.mb.cyclic_pos - delta + | |||
( ( fe->eb.mb.cyclic_pos >= delta ) ? 0 : fe->eb.mb.dictionary_size + 1 ) ); | ( ( fe->eb.mb.cyclic_pos >= delta ) ? 0 : fe->eb.mb.dictionary_size + 1 ) ); | |||
if( data[maxlen-delta] == data[maxlen] ) | if( data[maxlen-delta] == data[maxlen] ) | |||
{ | { | |||
int len = 0; | int len = 0; | |||
while( len < available && data[len-delta] == data[len] ) ++len; | while( len < available && data[len-delta] == data[len] ) ++len; | |||
if( maxlen < len ) | if( maxlen < len ) | |||
{ maxlen = len; *distance = delta - 1; | { maxlen = len; *distance = delta - 1; | |||
if( maxlen >= len_limit ) { *ptr0 = *newptr; break; } } | if( maxlen >= len_limit ) { *ptr0 = *newptr; break; } } | |||
skipping to change at line 73 | skipping to change at line 72 | |||
int rep = 0, i; | int rep = 0, i; | |||
State * const state = &fe->eb.state; | State * const state = &fe->eb.state; | |||
if( fe->eb.member_finished ) return true; | if( fe->eb.member_finished ) return true; | |||
if( Re_member_position( &fe->eb.renc ) >= fe->eb.member_size_limit ) | if( Re_member_position( &fe->eb.renc ) >= fe->eb.member_size_limit ) | |||
{ LZeb_try_full_flush( &fe->eb ); return true; } | { LZeb_try_full_flush( &fe->eb ); return true; } | |||
if( Mb_data_position( &fe->eb.mb ) == 0 && | if( Mb_data_position( &fe->eb.mb ) == 0 && | |||
!Mb_data_finished( &fe->eb.mb ) ) /* encode first byte */ | !Mb_data_finished( &fe->eb.mb ) ) /* encode first byte */ | |||
{ | { | |||
const uint8_t prev_byte = 0; | ||||
uint8_t cur_byte; | ||||
if( !Mb_enough_available_bytes( &fe->eb.mb ) || | if( !Mb_enough_available_bytes( &fe->eb.mb ) || | |||
!Re_enough_free_bytes( &fe->eb.renc ) ) return true; | !Re_enough_free_bytes( &fe->eb.renc ) ) return true; | |||
cur_byte = Mb_peek( &fe->eb.mb, 0 ); | const uint8_t prev_byte = 0; | |||
const uint8_t cur_byte = Mb_peek( &fe->eb.mb, 0 ); | ||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][0], 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][0], 0 ); | |||
LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); | LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); | |||
CRC32_update_byte( &fe->eb.crc, cur_byte ); | CRC32_update_byte( &fe->eb.crc, cur_byte ); | |||
FLZe_reset_key4( fe ); | FLZe_reset_key4( fe ); | |||
if( !FLZe_update_and_move( fe, 1 ) ) return false; | if( !FLZe_update_and_move( fe, 1 ) ) return false; | |||
} | } | |||
while( !Mb_data_finished( &fe->eb.mb ) && | while( !Mb_data_finished( &fe->eb.mb ) && | |||
Re_member_position( &fe->eb.renc ) < fe->eb.member_size_limit ) | Re_member_position( &fe->eb.renc ) < fe->eb.member_size_limit ) | |||
{ | { | |||
int match_distance = 0; /* avoid warning from gcc 6.1.0 */ | ||||
int main_len, pos_state; | ||||
int len = 0; | ||||
if( !Mb_enough_available_bytes( &fe->eb.mb ) || | if( !Mb_enough_available_bytes( &fe->eb.mb ) || | |||
!Re_enough_free_bytes( &fe->eb.renc ) ) return true; | !Re_enough_free_bytes( &fe->eb.renc ) ) return true; | |||
main_len = FLZe_longest_match_len( fe, &match_distance ); | int match_distance = 0; /* avoid warning from gcc 6.1.0 */ | |||
pos_state = Mb_data_position( &fe->eb.mb ) & pos_state_mask; | const int main_len = FLZe_longest_match_len( fe, &match_distance ); | |||
const int pos_state = Mb_data_position( &fe->eb.mb ) & pos_state_mask; | ||||
int len = 0; | ||||
for( i = 0; i < num_rep_distances; ++i ) | for( i = 0; i < num_rep_distances; ++i ) | |||
{ | { | |||
const int tlen = Mb_true_match_len( &fe->eb.mb, 0, fe->eb.reps[i] + 1 ); | const int tlen = Mb_true_match_len( &fe->eb.mb, 0, fe->eb.reps[i] + 1 ); | |||
if( tlen > len ) { len = tlen; rep = i; } | if( tlen > len ) { len = tlen; rep = i; } | |||
} | } | |||
if( len > min_match_len && len + 3 > main_len ) | if( len > min_match_len && len + 3 > main_len ) | |||
{ | { | |||
CRC32_update_buf( &fe->eb.crc, Mb_ptr_to_current_pos( &fe->eb.mb ), len ); | CRC32_update_buf( &fe->eb.crc, Mb_ptr_to_current_pos( &fe->eb.mb ), len ); | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 1 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 1 ); | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 ); | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], rep != 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], rep != 0 ); | |||
if( rep == 0 ) | if( rep == 0 ) | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 1 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 1 ); | |||
else | else | |||
{ | { | |||
int distance; | ||||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep1[*state], rep > 1 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep1[*state], rep > 1 ); | |||
if( rep > 1 ) | if( rep > 1 ) | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep2[*state], rep > 2 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep2[*state], rep > 2 ); | |||
distance = fe->eb.reps[rep]; | const int distance = fe->eb.reps[rep]; | |||
for( i = rep; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1]; | for( i = rep; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1]; | |||
fe->eb.reps[0] = distance; | fe->eb.reps[0] = distance; | |||
} | } | |||
*state = St_set_rep( *state ); | *state = St_set_rep( *state ); | |||
Re_encode_len( &fe->eb.renc, &fe->eb.rep_len_model, len, pos_state ); | Re_encode_len( &fe->eb.renc, &fe->eb.rep_len_model, len, pos_state ); | |||
if( !Mb_move_pos( &fe->eb.mb ) ) return false; | if( !Mb_move_pos( &fe->eb.mb ) ) return false; | |||
if( !FLZe_update_and_move( fe, len - 1 ) ) return false; | if( !FLZe_update_and_move( fe, len - 1 ) ) return false; | |||
continue; | continue; | |||
} | } | |||
skipping to change at line 140 | skipping to change at line 136 | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 0 ); | |||
*state = St_set_match( *state ); | *state = St_set_match( *state ); | |||
for( i = num_rep_distances - 1; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[ i-1]; | for( i = num_rep_distances - 1; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[ i-1]; | |||
fe->eb.reps[0] = match_distance; | fe->eb.reps[0] = match_distance; | |||
LZeb_encode_pair( &fe->eb, match_distance, main_len, pos_state ); | LZeb_encode_pair( &fe->eb, match_distance, main_len, pos_state ); | |||
if( !Mb_move_pos( &fe->eb.mb ) ) return false; | if( !Mb_move_pos( &fe->eb.mb ) ) return false; | |||
if( !FLZe_update_and_move( fe, main_len - 1 ) ) return false; | if( !FLZe_update_and_move( fe, main_len - 1 ) ) return false; | |||
continue; | continue; | |||
} | } | |||
{ | ||||
const uint8_t prev_byte = Mb_peek( &fe->eb.mb, 1 ); | const uint8_t prev_byte = Mb_peek( &fe->eb.mb, 1 ); | |||
const uint8_t cur_byte = Mb_peek( &fe->eb.mb, 0 ); | const uint8_t cur_byte = Mb_peek( &fe->eb.mb, 0 ); | |||
const uint8_t match_byte = Mb_peek( &fe->eb.mb, fe->eb.reps[0] + 1 ); | const uint8_t match_byte = Mb_peek( &fe->eb.mb, fe->eb.reps[0] + 1 ); | |||
if( !Mb_move_pos( &fe->eb.mb ) ) return false; | if( !Mb_move_pos( &fe->eb.mb ) ) return false; | |||
CRC32_update_byte( &fe->eb.crc, cur_byte ); | CRC32_update_byte( &fe->eb.crc, cur_byte ); | |||
if( match_byte == cur_byte ) | if( match_byte == cur_byte ) | |||
{ | { | |||
const int short_rep_price = price1( fe->eb.bm_match[*state][pos_state] ) + | const int short_rep_price = price1( fe->eb.bm_match[*state][pos_state] ) + | |||
price1( fe->eb.bm_rep[*state] ) + | price1( fe->eb.bm_rep[*state] ) + | |||
skipping to change at line 171 | skipping to change at line 166 | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep[*state], 1 ); | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], 0 ); | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 0 ); | |||
*state = St_set_short_rep( *state ); | *state = St_set_short_rep( *state ); | |||
continue; | continue; | |||
} | } | |||
} | } | |||
/* literal byte */ | /* literal byte */ | |||
Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 0 ); | Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 0 ); | |||
if( St_is_char( *state ) ) | if( ( *state = St_set_char( *state ) ) < 4 ) | |||
LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); | LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); | |||
else | else | |||
LZeb_encode_matched( &fe->eb, prev_byte, cur_byte, match_byte ); | LZeb_encode_matched( &fe->eb, prev_byte, cur_byte, match_byte ); | |||
*state = St_set_char( *state ); | ||||
} | ||||
} | } | |||
LZeb_try_full_flush( &fe->eb ); | LZeb_try_full_flush( &fe->eb ); | |||
return true; | return true; | |||
} | } | |||
End of changes. 17 change blocks. | ||||
21 lines changed or deleted | 14 lines changed or added |