diff options
Diffstat (limited to 'fast_encoder.cc')
-rw-r--r-- | fast_encoder.cc | 119 |
1 files changed, 41 insertions, 78 deletions
diff --git a/fast_encoder.cc b/fast_encoder.cc index dfbb429..f87fdec 100644 --- a/fast_encoder.cc +++ b/fast_encoder.cc @@ -1,5 +1,6 @@ /* Lzip - LZMA lossless data compressor - Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz. + Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,37 +33,35 @@ int Fmatchfinder::longest_match_len( int * const distance ) { - int len_limit = match_len_limit_; - if( len_limit > available_bytes() ) - { - len_limit = available_bytes(); - if( len_limit < 4 ) return 0; - } + if( len_limit > available_bytes() ) return 0; - key4 = ( ( key4 << 4 ) ^ buffer[pos+3] ) & key4_mask; + const uint8_t * const data = buffer + pos; + key4 = ( ( key4 << 4 ) ^ data[3] ) & key4_mask; + const int pos1 = pos + 1; int newpos = prev_positions[key4]; - prev_positions[key4] = pos; + prev_positions[key4] = pos1; int32_t * ptr0 = pos_array + cyclic_pos; int maxlen = 0; for( int count = 4; ; ) { - const int delta = pos - newpos; - if( delta > dictionary_size_ || newpos < 0 || --count < 0 ) - { *ptr0 = -1; break; } - int len = 0; - if( buffer[maxlen+newpos] == buffer[maxlen+pos] ) - while( len < len_limit && buffer[len+newpos] == buffer[len+pos] ) ++len; - - if( maxlen < len ) { maxlen = len; *distance = delta - 1; } - + if( --count < 0 || newpos <= 0 ) { *ptr0 = 0; break; } + const int delta = pos1 - newpos; + if( delta > dictionary_size_ ) { *ptr0 = 0; break; } int32_t * const newptr = pos_array + ( cyclic_pos - delta + ( ( cyclic_pos >= delta ) ? 0 : dictionary_size_ + 1 ) ); - if( len < len_limit ) + if( data[maxlen-delta] == data[maxlen] ) + { + int len = 0; + while( len < len_limit && data[len-delta] == data[len] ) ++len; + if( maxlen < len ) { maxlen = len; *distance = delta - 1; } + } + + if( maxlen < len_limit ) { *ptr0 = newpos; ptr0 = newptr; @@ -71,54 +70,19 @@ int Fmatchfinder::longest_match_len( int * const distance ) else { *ptr0 = *newptr; + maxlen += true_match_len( maxlen, *distance + 1, max_match_len - maxlen ); break; } } - if( maxlen == match_len_limit_ && maxlen < max_match_len ) - maxlen += true_match_len( maxlen, *distance + 1, max_match_len - maxlen ); return maxlen; } -void Fmatchfinder::longest_match_len( int n ) - { - while( --n >= 0 ) - { - int len_limit = match_len_limit_ - 1; // len_limit - 1 - if( len_limit >= available_bytes() ) - { - len_limit = available_bytes() - 1; - if( len_limit < 3 ) { move_pos(); continue; } - } - - key4 = ( ( key4 << 4 ) ^ buffer[pos+3] ) & key4_mask; - - const int newpos = prev_positions[key4]; - prev_positions[key4] = pos; - - int32_t * const ptr0 = pos_array + cyclic_pos; - - if( pos - newpos > dictionary_size_ || newpos < 0 ) - *ptr0 = -1; - else if( buffer[len_limit+newpos] != buffer[len_limit+pos] || - std::memcmp( buffer + newpos, buffer + pos, len_limit ) != 0 ) - *ptr0 = newpos; - else - { - int idx = cyclic_pos - pos + newpos; - if( idx < 0 ) idx += dictionary_size_ + 1; - *ptr0 = pos_array[idx]; - } - move_pos(); - } - } - - bool FLZ_encoder::encode_member( const unsigned long long member_size ) { const unsigned long long member_size_limit = member_size - File_trailer::size() - max_marker_size; - int dis = 0; + int rep = 0; int reps[num_rep_distances]; State state; for( int i = 0; i < num_rep_distances; ++i ) reps[i] = 0; @@ -134,7 +98,7 @@ bool FLZ_encoder::encode_member( const unsigned long long member_size ) renc.encode_bit( bm_match[state()][0], 0 ); encode_literal( prev_byte, cur_byte ); crc32.update_byte( crc_, cur_byte ); - fmatchfinder.longest_match_len( 1 ); + fmatchfinder.update_and_move( 1 ); } while( !fmatchfinder.finished() && @@ -149,52 +113,51 @@ bool FLZ_encoder::encode_member( const unsigned long long member_size ) { const int tlen = fmatchfinder.true_match_len( 0, reps[i] + 1, max_match_len ); - if( tlen > len ) { len = tlen; dis = i; } + if( tlen > len ) { len = tlen; rep = i; } } - if( len > min_match_len && len + 4 > main_len ) + if( len > min_match_len && len + 3 > main_len ) { crc32.update_buf( crc_, fmatchfinder.ptr_to_current_pos(), len ); renc.encode_bit( bm_match[state()][pos_state], 1 ); renc.encode_bit( bm_rep[state()], 1 ); - const bool bit = ( dis == 0 ); - renc.encode_bit( bm_rep0[state()], !bit ); - if( bit ) + renc.encode_bit( bm_rep0[state()], rep != 0 ); + if( rep == 0 ) renc.encode_bit( bm_len[state()][pos_state], 1 ); else { - const int distance = reps[dis]; - for( int i = dis; i > 0; --i ) reps[i] = reps[i-1]; + renc.encode_bit( bm_rep1[state()], rep > 1 ); + if( rep > 1 ) + renc.encode_bit( bm_rep2[state()], rep > 2 ); + const int distance = reps[rep]; + for( int i = rep; i > 0; --i ) reps[i] = reps[i-1]; reps[0] = distance; - renc.encode_bit( bm_rep1[state()], dis > 1 ); - if( dis > 1 ) - renc.encode_bit( bm_rep2[state()], dis > 2 ); } - rep_len_encoder.encode( renc, len, pos_state ); state.set_rep(); - move_pos( len ); + rep_len_encoder.encode( renc, len, pos_state ); + fmatchfinder.move_pos(); + fmatchfinder.update_and_move( len - 1 ); continue; } - if( main_len > min_match_len || - ( main_len == min_match_len && match_distance < modeled_distances ) ) + if( main_len > min_match_len ) { crc32.update_buf( crc_, fmatchfinder.ptr_to_current_pos(), main_len ); - dis = match_distance; renc.encode_bit( bm_match[state()][pos_state], 1 ); renc.encode_bit( bm_rep[state()], 0 ); - encode_pair( dis, main_len, pos_state ); state.set_match(); - move_pos( main_len ); for( int i = num_rep_distances - 1; i > 0; --i ) reps[i] = reps[i-1]; - reps[0] = dis; + reps[0] = match_distance; + encode_pair( match_distance, main_len, pos_state ); + fmatchfinder.move_pos(); + fmatchfinder.update_and_move( main_len - 1 ); continue; } - const uint8_t prev_byte = fmatchfinder[-1]; + const uint8_t prev_byte = fmatchfinder[1]; const uint8_t cur_byte = fmatchfinder[0]; - const uint8_t match_byte = fmatchfinder[-reps[0]-1]; - crc32.update_byte( crc_, cur_byte ); + const uint8_t match_byte = fmatchfinder[reps[0]+1]; fmatchfinder.move_pos(); + crc32.update_byte( crc_, cur_byte ); if( match_byte == cur_byte ) { |