delta_decoder.c revision 292588
1114402Sru///////////////////////////////////////////////////////////////////////////////
2114402Sru//
3114402Sru/// \file       delta_decoder.c
4114402Sru/// \brief      Delta filter decoder
5114402Sru//
6114402Sru//  Author:     Lasse Collin
7114402Sru//
8114402Sru//  This file has been put into the public domain.
9114402Sru//  You can do whatever you want with this file.
10114402Sru//
11114402Sru///////////////////////////////////////////////////////////////////////////////
12114402Sru
13114402Sru#include "delta_decoder.h"
14114402Sru#include "delta_private.h"
15114402Sru
16114402Sru
17114402Srustatic void
18151503Srudecode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
19114402Sru{
20114411Sru	const size_t distance = coder->distance;
21114411Sru
22114402Sru	for (size_t i = 0; i < size; ++i) {
23114402Sru		buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
24114402Sru		coder->history[coder->pos-- & 0xFF] = buffer[i];
25114402Sru	}
26114402Sru}
27114402Sru
28114402Sru
29114402Srustatic lzma_ret
30114402Srudelta_decode(lzma_coder *coder, const lzma_allocator *allocator,
31114402Sru		const uint8_t *restrict in, size_t *restrict in_pos,
32114402Sru		size_t in_size, uint8_t *restrict out,
33114402Sru		size_t *restrict out_pos, size_t out_size, lzma_action action)
34114402Sru{
35114402Sru	assert(coder->next.code != NULL);
36114411Sru
37114402Sru	const size_t out_start = *out_pos;
38114402Sru
39114402Sru	const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
40114402Sru			in, in_pos, in_size, out, out_pos, out_size,
41114402Sru			action);
42114402Sru
43114411Sru	decode_buffer(coder, out + out_start, *out_pos - out_start);
44114402Sru
45114402Sru	return ret;
46114402Sru}
47114402Sru
48114402Sru
49114402Sruextern lzma_ret
50114402Srulzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
51114402Sru		const lzma_filter_info *filters)
52114402Sru{
53114402Sru	next->code = &delta_decode;
54114402Sru	return lzma_delta_coder_init(next, allocator, filters);
55114402Sru}
56114402Sru
57114402Sru
58114402Sruextern lzma_ret
59114402Srulzma_delta_props_decode(void **options, const lzma_allocator *allocator,
60114402Sru		const uint8_t *props, size_t props_size)
61114402Sru{
62114402Sru	if (props_size != 1)
63		return LZMA_OPTIONS_ERROR;
64
65	lzma_options_delta *opt
66			= lzma_alloc(sizeof(lzma_options_delta), allocator);
67	if (opt == NULL)
68		return LZMA_MEM_ERROR;
69
70	opt->type = LZMA_DELTA_TYPE_BYTE;
71	opt->dist = props[0] + 1;
72
73	*options = opt;
74
75	return LZMA_OK;
76}
77