12940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
22940b44dSPeter Avalos //
32940b44dSPeter Avalos /// \file       delta_decoder.c
42940b44dSPeter Avalos /// \brief      Delta filter decoder
52940b44dSPeter Avalos //
62940b44dSPeter Avalos //  Author:     Lasse Collin
72940b44dSPeter Avalos //
82940b44dSPeter Avalos //  This file has been put into the public domain.
92940b44dSPeter Avalos //  You can do whatever you want with this file.
102940b44dSPeter Avalos //
112940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
122940b44dSPeter Avalos 
132940b44dSPeter Avalos #include "delta_decoder.h"
142940b44dSPeter Avalos #include "delta_private.h"
152940b44dSPeter Avalos 
162940b44dSPeter Avalos 
172940b44dSPeter Avalos static void
decode_buffer(lzma_delta_coder * coder,uint8_t * buffer,size_t size)1846a2189dSzrj decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
192940b44dSPeter Avalos {
202940b44dSPeter Avalos 	const size_t distance = coder->distance;
212940b44dSPeter Avalos 
222940b44dSPeter Avalos 	for (size_t i = 0; i < size; ++i) {
232940b44dSPeter Avalos 		buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
242940b44dSPeter Avalos 		coder->history[coder->pos-- & 0xFF] = buffer[i];
252940b44dSPeter Avalos 	}
262940b44dSPeter Avalos }
272940b44dSPeter Avalos 
282940b44dSPeter Avalos 
292940b44dSPeter Avalos static lzma_ret
delta_decode(void * coder_ptr,const lzma_allocator * allocator,const uint8_t * restrict in,size_t * restrict in_pos,size_t in_size,uint8_t * restrict out,size_t * restrict out_pos,size_t out_size,lzma_action action)3046a2189dSzrj delta_decode(void *coder_ptr, const lzma_allocator *allocator,
312940b44dSPeter Avalos 		const uint8_t *restrict in, size_t *restrict in_pos,
322940b44dSPeter Avalos 		size_t in_size, uint8_t *restrict out,
332940b44dSPeter Avalos 		size_t *restrict out_pos, size_t out_size, lzma_action action)
342940b44dSPeter Avalos {
3546a2189dSzrj 	lzma_delta_coder *coder = coder_ptr;
3646a2189dSzrj 
372940b44dSPeter Avalos 	assert(coder->next.code != NULL);
382940b44dSPeter Avalos 
392940b44dSPeter Avalos 	const size_t out_start = *out_pos;
402940b44dSPeter Avalos 
412940b44dSPeter Avalos 	const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
422940b44dSPeter Avalos 			in, in_pos, in_size, out, out_pos, out_size,
432940b44dSPeter Avalos 			action);
442940b44dSPeter Avalos 
452940b44dSPeter Avalos 	decode_buffer(coder, out + out_start, *out_pos - out_start);
462940b44dSPeter Avalos 
472940b44dSPeter Avalos 	return ret;
482940b44dSPeter Avalos }
492940b44dSPeter Avalos 
502940b44dSPeter Avalos 
512940b44dSPeter Avalos extern lzma_ret
lzma_delta_decoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)5215ab8c86SJohn Marino lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
532940b44dSPeter Avalos 		const lzma_filter_info *filters)
542940b44dSPeter Avalos {
552940b44dSPeter Avalos 	next->code = &delta_decode;
562940b44dSPeter Avalos 	return lzma_delta_coder_init(next, allocator, filters);
572940b44dSPeter Avalos }
582940b44dSPeter Avalos 
592940b44dSPeter Avalos 
602940b44dSPeter Avalos extern lzma_ret
lzma_delta_props_decode(void ** options,const lzma_allocator * allocator,const uint8_t * props,size_t props_size)6115ab8c86SJohn Marino lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
622940b44dSPeter Avalos 		const uint8_t *props, size_t props_size)
632940b44dSPeter Avalos {
642940b44dSPeter Avalos 	if (props_size != 1)
652940b44dSPeter Avalos 		return LZMA_OPTIONS_ERROR;
662940b44dSPeter Avalos 
672940b44dSPeter Avalos 	lzma_options_delta *opt
682940b44dSPeter Avalos 			= lzma_alloc(sizeof(lzma_options_delta), allocator);
692940b44dSPeter Avalos 	if (opt == NULL)
702940b44dSPeter Avalos 		return LZMA_MEM_ERROR;
712940b44dSPeter Avalos 
722940b44dSPeter Avalos 	opt->type = LZMA_DELTA_TYPE_BYTE;
73*e151908bSDaniel Fojt 	opt->dist = props[0] + 1U;
742940b44dSPeter Avalos 
752940b44dSPeter Avalos 	*options = opt;
762940b44dSPeter Avalos 
772940b44dSPeter Avalos 	return LZMA_OK;
782940b44dSPeter Avalos }
79