mirror of
https://git.tukaani.org/xz.git
synced 2025-09-27 12:58:23 +00:00
Originally the idea was that using LZMA_FULL_FLUSH with Stream encoder would read the filter chain from the same array that was used to intialize the Stream encoder. Since most apps wouldn't use LZMA_FULL_FLUSH, most apps wouldn't need to keep the filter chain available after initializing the Stream encoder. However, due to my mistake, it actually required keeping the array always available. Since setting the new filter chain via the array used at initialization time is not a nice way to do it for a couple of reasons, this commit ditches it and introduces lzma_filters_update(). This new function replaces also the "persistent" flag used by LZMA2 (and to-be-designed Subblock filter), which was also an ugly thing to do. Thanks to Alexey Tourbin for reminding me about the problem that Stream encoder used to require keeping the filter chain allocated.
77 lines
1.8 KiB
C
77 lines
1.8 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
/// \file delta_decoder.c
|
|
/// \brief Delta filter decoder
|
|
//
|
|
// Author: Lasse Collin
|
|
//
|
|
// This file has been put into the public domain.
|
|
// You can do whatever you want with this file.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "delta_decoder.h"
|
|
#include "delta_private.h"
|
|
|
|
|
|
static void
|
|
decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
|
|
{
|
|
const size_t distance = coder->distance;
|
|
|
|
for (size_t i = 0; i < size; ++i) {
|
|
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
|
|
coder->history[coder->pos-- & 0xFF] = buffer[i];
|
|
}
|
|
}
|
|
|
|
|
|
static lzma_ret
|
|
delta_decode(lzma_coder *coder, 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)
|
|
{
|
|
assert(coder->next.code != NULL);
|
|
|
|
const size_t out_start = *out_pos;
|
|
|
|
const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
|
|
in, in_pos, in_size, out, out_pos, out_size,
|
|
action);
|
|
|
|
decode_buffer(coder, out + out_start, *out_pos - out_start);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
extern lzma_ret
|
|
lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
|
const lzma_filter_info *filters)
|
|
{
|
|
next->code = &delta_decode;
|
|
return lzma_delta_coder_init(next, allocator, filters);
|
|
}
|
|
|
|
|
|
extern lzma_ret
|
|
lzma_delta_props_decode(void **options, lzma_allocator *allocator,
|
|
const uint8_t *props, size_t props_size)
|
|
{
|
|
if (props_size != 1)
|
|
return LZMA_OPTIONS_ERROR;
|
|
|
|
lzma_options_delta *opt
|
|
= lzma_alloc(sizeof(lzma_options_delta), allocator);
|
|
if (opt == NULL)
|
|
return LZMA_MEM_ERROR;
|
|
|
|
opt->type = LZMA_DELTA_TYPE_BYTE;
|
|
opt->dist = props[0] + 1;
|
|
|
|
*options = opt;
|
|
|
|
return LZMA_OK;
|
|
}
|