/* Return value: 0 = OK, 1 = decoder error, 2 = unexpected EOF, 3 = trailer error, 4 = unknown marker found. */ static int LZd_decode_member( struct LZ_decoder * const decoder ) { struct Range_decoder * const rdec = decoder->rdec; State * const state = &decoder->state; if( decoder->member_finished ) return 0; if( !Rd_try_reload( rdec, false ) ) return 0; if( decoder->verify_trailer_pending ) { if( Rd_available_bytes( rdec ) < Ft_size && !rdec->at_stream_end ) return 0; decoder->verify_trailer_pending = false; decoder->member_finished = true; if( LZd_verify_trailer( decoder ) ) return 0; else return 3; } while( !Rd_finished( rdec ) ) { const int pos_state = LZd_data_position( decoder ) & pos_state_mask; if( !Rd_enough_available_bytes( rdec ) || !LZd_enough_free_bytes( decoder ) ) return 0; if( Rd_decode_bit( rdec, &decoder->bm_match[*state][pos_state] ) == 0 ) /* 1st bit */ { const uint8_t prev_byte = LZd_get_prev_byte( decoder ); if( St_is_char( *state ) ) { *state -= ( *state < 4 ) ? *state : 3; LZd_put_byte( decoder, Rd_decode_tree( rdec, decoder->bm_literal[get_lit_state(prev_byte)], 8 ) ); } else { *state -= ( *state < 10 ) ? 3 : 6; LZd_put_byte( decoder, Rd_decode_matched( rdec, decoder->bm_literal[get_lit_state(prev_byte)], LZd_get_byte( decoder, decoder->rep0 ) ) ); } } else { int len; if( Rd_decode_bit( rdec, &decoder->bm_rep[*state] ) != 0 ) /* 2nd bit */ { if( Rd_decode_bit( rdec, &decoder->bm_rep0[*state] ) != 0 ) /* 3rd bit */ { unsigned distance; if( Rd_decode_bit( rdec, &decoder->bm_rep1[*state] ) == 0 ) /* 4th bit */ distance = decoder->rep1; else { if( Rd_decode_bit( rdec, &decoder->bm_rep2[*state] ) == 0 ) /* 5th bit */ distance = decoder->rep2; else { distance = decoder->rep3; decoder->rep3 = decoder->rep2; } decoder->rep2 = decoder->rep1; } decoder->rep1 = decoder->rep0; decoder->rep0 = distance; } else { if( Rd_decode_bit( rdec, &decoder->bm_len[*state][pos_state] ) == 0 ) /* 4th bit */ { *state = St_set_short_rep( *state ); LZd_put_byte( decoder, LZd_get_byte( decoder, decoder->rep0 ) ); continue; } } *state = St_set_rep( *state ); len = min_match_len + Rd_decode_len( rdec, &decoder->rep_len_model, pos_state ); } else { int dis_slot; const unsigned rep0_saved = decoder->rep0; len = min_match_len + Rd_decode_len( rdec, &decoder->match_len_model, pos_state ); dis_slot = Rd_decode_tree6( rdec, decoder->bm_dis_slot[get_len_state(len)] ); if( dis_slot < start_dis_model ) decoder->rep0 = dis_slot; else { const int direct_bits = ( dis_slot >> 1 ) - 1; decoder->rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits; if( dis_slot < end_dis_model ) decoder->rep0 += Rd_decode_tree_reversed( rdec, decoder->bm_dis + decoder->rep0 - dis_slot - 1, direct_bits ); else { decoder->rep0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits; decoder->rep0 += Rd_decode_tree_reversed4( rdec, decoder->bm_align ); if( decoder->rep0 == 0xFFFFFFFFU ) /* Marker found */ { decoder->rep0 = rep0_saved; Rd_normalize( rdec ); if( len == min_match_len ) /* End Of Stream marker */ { if( Rd_available_bytes( rdec ) < Ft_size && !rdec->at_stream_end ) { decoder->verify_trailer_pending = true; return 0; } decoder->member_finished = true; if( LZd_verify_trailer( decoder ) ) return 0; else return 3; } if( len == min_match_len + 1 ) /* Sync Flush marker */ { if( Rd_try_reload( rdec, true ) ) continue; else return 0; } return 4; } } } decoder->rep3 = decoder->rep2; decoder->rep2 = decoder->rep1; decoder->rep1 = rep0_saved; *state = St_set_match( *state ); if( decoder->rep0 >= (unsigned)decoder->dictionary_size || ( decoder->rep0 >= (unsigned)decoder->cb.put && !decoder->partial_data_pos ) ) return 1; } LZd_copy_block( decoder, decoder->rep0, len ); } } return 2; }
bool FLZe_encode_member( struct FLZ_encoder * const fe ) { int rep = 0, i; State * const state = &fe->eb.state; if( fe->eb.member_finished ) return true; if( Re_member_position( &fe->eb.renc ) >= fe->eb.member_size_limit ) { if( LZeb_full_flush( &fe->eb ) ) fe->eb.member_finished = true; return true; } if( Mb_data_position( &fe->eb.mb ) == 0 && !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 ) || !Re_enough_free_bytes( &fe->eb.renc ) ) return true; cur_byte = Mb_peek( &fe->eb.mb, 0 ); Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][0], 0 ); LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); CRC32_update_byte( &fe->eb.crc, cur_byte ); FLZe_reset_key4( fe ); if( !FLZe_update_and_move( fe, 1 ) ) return false; } while( !Mb_data_finished( &fe->eb.mb ) && Re_member_position( &fe->eb.renc ) < fe->eb.member_size_limit ) { int match_distance; int main_len, pos_state, len; if( !Mb_enough_available_bytes( &fe->eb.mb ) || !Re_enough_free_bytes( &fe->eb.renc ) ) return true; main_len = FLZe_longest_match_len( fe, &match_distance ); pos_state = Mb_data_position( &fe->eb.mb ) & pos_state_mask; len = 0; for( i = 0; i < num_rep_distances; ++i ) { const int tlen = Mb_true_match_len( &fe->eb.mb, 0, fe->eb.reps[i] + 1, max_match_len ); if( tlen > len ) { len = tlen; rep = i; } } if( len > min_match_len && len + 3 > main_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_rep[*state], 1 ); Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep0[*state], rep != 0 ); if( rep == 0 ) Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 1 ); else { int distance; Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep1[*state], rep > 1 ); if( rep > 1 ) Re_encode_bit( &fe->eb.renc, &fe->eb.bm_rep2[*state], rep > 2 ); distance = fe->eb.reps[rep]; for( i = rep; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1]; fe->eb.reps[0] = distance; } *state = St_set_rep( *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( !FLZe_update_and_move( fe, len - 1 ) ) return false; continue; } if( main_len > min_match_len ) { CRC32_update_buf( &fe->eb.crc, Mb_ptr_to_current_pos( &fe->eb.mb ), main_len ); 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], 0 ); *state = St_set_match( *state ); for( i = num_rep_distances - 1; i > 0; --i ) fe->eb.reps[i] = fe->eb.reps[i-1]; fe->eb.reps[0] = match_distance; LZeb_encode_pair( &fe->eb, match_distance, main_len, pos_state ); if( !Mb_move_pos( &fe->eb.mb ) ) return false; if( !FLZe_update_and_move( fe, main_len - 1 ) ) return false; continue; } { 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 match_byte = Mb_peek( &fe->eb.mb, fe->eb.reps[0] + 1 ); if( !Mb_move_pos( &fe->eb.mb ) ) return false; CRC32_update_byte( &fe->eb.crc, cur_byte ); if( match_byte == cur_byte ) { const int short_rep_price = price1( fe->eb.bm_match[*state][pos_state] ) + price1( fe->eb.bm_rep[*state] ) + price0( fe->eb.bm_rep0[*state] ) + price0( fe->eb.bm_len[*state][pos_state] ); int price = price0( fe->eb.bm_match[*state][pos_state] ); if( St_is_char( *state ) ) price += LZeb_price_literal( &fe->eb, prev_byte, cur_byte ); else price += LZeb_price_matched( &fe->eb, prev_byte, cur_byte, match_byte ); if( short_rep_price < price ) { 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_rep0[*state], 0 ); Re_encode_bit( &fe->eb.renc, &fe->eb.bm_len[*state][pos_state], 0 ); *state = St_set_short_rep( *state ); continue; } } /* literal byte */ Re_encode_bit( &fe->eb.renc, &fe->eb.bm_match[*state][pos_state], 0 ); if( St_is_char( *state ) ) LZeb_encode_literal( &fe->eb, prev_byte, cur_byte ); else LZeb_encode_matched( &fe->eb, prev_byte, cur_byte, match_byte ); *state = St_set_char( *state ); } } if( LZeb_full_flush( &fe->eb ) ) fe->eb.member_finished = true; return true; }