delta_encoder.c revision 292588
133965Sjdp/////////////////////////////////////////////////////////////////////////////// 260484Sobrien// 338889Sjdp/// \file delta_encoder.c 433965Sjdp/// \brief Delta filter encoder 533965Sjdp// 633965Sjdp// Author: Lasse Collin 733965Sjdp// 833965Sjdp// This file has been put into the public domain. 933965Sjdp// You can do whatever you want with this file. 1033965Sjdp// 1133965Sjdp/////////////////////////////////////////////////////////////////////////////// 1233965Sjdp 1333965Sjdp#include "delta_encoder.h" 1433965Sjdp#include "delta_private.h" 1533965Sjdp 1633965Sjdp 1733965Sjdp/// Copies and encodes the data at the same time. This is used when Delta 1833965Sjdp/// is the first filter in the chain (and thus the last filter in the 1933965Sjdp/// encoder's filter stack). 2033965Sjdpstatic void 2133965Sjdpcopy_and_encode(lzma_coder *coder, 2233965Sjdp const uint8_t *restrict in, uint8_t *restrict out, size_t size) 2333965Sjdp{ 2433965Sjdp const size_t distance = coder->distance; 2533965Sjdp 2633965Sjdp for (size_t i = 0; i < size; ++i) { 2733965Sjdp const uint8_t tmp = coder->history[ 2833965Sjdp (distance + coder->pos) & 0xFF]; 2933965Sjdp coder->history[coder->pos-- & 0xFF] = in[i]; 3033965Sjdp out[i] = in[i] - tmp; 3133965Sjdp } 3233965Sjdp} 3333965Sjdp 3433965Sjdp 3533965Sjdp/// Encodes the data in place. This is used when we are the last filter 3633965Sjdp/// in the chain (and thus non-last filter in the encoder's filter stack). 3733965Sjdpstatic void 3833965Sjdpencode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size) 3933965Sjdp{ 4033965Sjdp const size_t distance = coder->distance; 4133965Sjdp 4233965Sjdp for (size_t i = 0; i < size; ++i) { 4333965Sjdp const uint8_t tmp = coder->history[ 4433965Sjdp (distance + coder->pos) & 0xFF]; 4533965Sjdp coder->history[coder->pos-- & 0xFF] = buffer[i]; 4633965Sjdp buffer[i] -= tmp; 4733965Sjdp } 4833965Sjdp} 4933965Sjdp 5033965Sjdp 5133965Sjdpstatic lzma_ret 5233965Sjdpdelta_encode(lzma_coder *coder, const lzma_allocator *allocator, 5333965Sjdp const uint8_t *restrict in, size_t *restrict in_pos, 5433965Sjdp size_t in_size, uint8_t *restrict out, 5533965Sjdp size_t *restrict out_pos, size_t out_size, lzma_action action) 5633965Sjdp{ 5733965Sjdp lzma_ret ret; 5833965Sjdp 5933965Sjdp if (coder->next.code == NULL) { 6033965Sjdp const size_t in_avail = in_size - *in_pos; 6133965Sjdp const size_t out_avail = out_size - *out_pos; 6233965Sjdp const size_t size = my_min(in_avail, out_avail); 6377298Sobrien 6433965Sjdp copy_and_encode(coder, in + *in_pos, out + *out_pos, size); 6533965Sjdp 6638889Sjdp *in_pos += size; 6733965Sjdp *out_pos += size; 6833965Sjdp 6933965Sjdp ret = action != LZMA_RUN && *in_pos == in_size 7033965Sjdp ? LZMA_STREAM_END : LZMA_OK; 7133965Sjdp 7233965Sjdp } else { 7333965Sjdp const size_t out_start = *out_pos; 7433965Sjdp 7533965Sjdp ret = coder->next.code(coder->next.coder, allocator, 7633965Sjdp in, in_pos, in_size, out, out_pos, out_size, 7733965Sjdp action); 7833965Sjdp 7933965Sjdp encode_in_place(coder, out + out_start, *out_pos - out_start); 8033965Sjdp } 8133965Sjdp 8233965Sjdp return ret; 8333965Sjdp} 8433965Sjdp 8533965Sjdp 8633965Sjdpstatic lzma_ret 8733965Sjdpdelta_encoder_update(lzma_coder *coder, const lzma_allocator *allocator, 8833965Sjdp const lzma_filter *filters_null lzma_attribute((__unused__)), 8933965Sjdp const lzma_filter *reversed_filters) 9033965Sjdp{ 9133965Sjdp // Delta doesn't and will never support changing the options in 9233965Sjdp // the middle of encoding. If the app tries to change them, we 9333965Sjdp // simply ignore them. 9433965Sjdp return lzma_next_filter_update( 9533965Sjdp &coder->next, allocator, reversed_filters + 1); 9633965Sjdp} 9733965Sjdp 9833965Sjdp 9933965Sjdpextern lzma_ret 10033965Sjdplzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 10133965Sjdp const lzma_filter_info *filters) 10233965Sjdp{ 10333965Sjdp next->code = &delta_encode; 10433965Sjdp next->update = &delta_encoder_update; 10533965Sjdp return lzma_delta_coder_init(next, allocator, filters); 10633965Sjdp} 10733965Sjdp 10833965Sjdp 10933965Sjdpextern lzma_ret 11033965Sjdplzma_delta_props_encode(const void *options, uint8_t *out) 11133965Sjdp{ 11233965Sjdp // The caller must have already validated the options, so it's 11333965Sjdp // LZMA_PROG_ERROR if they are invalid. 11433965Sjdp if (lzma_delta_coder_memusage(options) == UINT64_MAX) 11533965Sjdp return LZMA_PROG_ERROR; 11633965Sjdp 11733965Sjdp const lzma_options_delta *opt = options; 11833965Sjdp out[0] = opt->dist - LZMA_DELTA_DIST_MIN; 11933965Sjdp 12033965Sjdp return LZMA_OK; 12133965Sjdp} 12233965Sjdp