Exemplo n.º 1
0
/* 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;
  }
Exemplo n.º 2
0
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;
  }