(root)/
xz-5.4.5/
src/
liblzma/
delta/
delta_decoder.c
       1  ///////////////////////////////////////////////////////////////////////////////
       2  //
       3  /// \file       delta_decoder.c
       4  /// \brief      Delta filter decoder
       5  //
       6  //  Author:     Lasse Collin
       7  //
       8  //  This file has been put into the public domain.
       9  //  You can do whatever you want with this file.
      10  //
      11  ///////////////////////////////////////////////////////////////////////////////
      12  
      13  #include "delta_decoder.h"
      14  #include "delta_private.h"
      15  
      16  
      17  static void
      18  decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
      19  {
      20  	const size_t distance = coder->distance;
      21  
      22  	for (size_t i = 0; i < size; ++i) {
      23  		buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
      24  		coder->history[coder->pos-- & 0xFF] = buffer[i];
      25  	}
      26  }
      27  
      28  
      29  static lzma_ret
      30  delta_decode(void *coder_ptr, const lzma_allocator *allocator,
      31  		const uint8_t *restrict in, size_t *restrict in_pos,
      32  		size_t in_size, uint8_t *restrict out,
      33  		size_t *restrict out_pos, size_t out_size, lzma_action action)
      34  {
      35  	lzma_delta_coder *coder = coder_ptr;
      36  
      37  	assert(coder->next.code != NULL);
      38  
      39  	const size_t out_start = *out_pos;
      40  
      41  	const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
      42  			in, in_pos, in_size, out, out_pos, out_size,
      43  			action);
      44  
      45  	// out might be NULL. In that case size == 0. Null pointer + 0 is
      46  	// undefined behavior so skip the call in that case as it would
      47  	// do nothing anyway.
      48  	const size_t size = *out_pos - out_start;
      49  	if (size > 0)
      50  		decode_buffer(coder, out + out_start, size);
      51  
      52  	return ret;
      53  }
      54  
      55  
      56  extern lzma_ret
      57  lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
      58  		const lzma_filter_info *filters)
      59  {
      60  	next->code = &delta_decode;
      61  	return lzma_delta_coder_init(next, allocator, filters);
      62  }
      63  
      64  
      65  extern lzma_ret
      66  lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
      67  		const uint8_t *props, size_t props_size)
      68  {
      69  	if (props_size != 1)
      70  		return LZMA_OPTIONS_ERROR;
      71  
      72  	lzma_options_delta *opt
      73  			= lzma_alloc(sizeof(lzma_options_delta), allocator);
      74  	if (opt == NULL)
      75  		return LZMA_MEM_ERROR;
      76  
      77  	opt->type = LZMA_DELTA_TYPE_BYTE;
      78  	opt->dist = props[0] + 1U;
      79  
      80  	*options = opt;
      81  
      82  	return LZMA_OK;
      83  }