delta_encoder.c revision 213700
1178825Sdfr/////////////////////////////////////////////////////////////////////////////// 2233294Sstas// 3233294Sstas/// \file delta_encoder.c 4233294Sstas/// \brief Delta filter encoder 5178825Sdfr// 6233294Sstas// Author: Lasse Collin 7233294Sstas// 8233294Sstas// This file has been put into the public domain. 9178825Sdfr// You can do whatever you want with this file. 10233294Sstas// 11233294Sstas/////////////////////////////////////////////////////////////////////////////// 12178825Sdfr 13233294Sstas#include "delta_encoder.h" 14233294Sstas#include "delta_private.h" 15233294Sstas 16178825Sdfr 17233294Sstas/// Copies and encodes the data at the same time. This is used when Delta 18233294Sstas/// is the first filter in the chain (and thus the last filter in the 19233294Sstas/// encoder's filter stack). 20178825Sdfrstatic void 21233294Sstascopy_and_encode(lzma_coder *coder, 22233294Sstas const uint8_t *restrict in, uint8_t *restrict out, size_t size) 23233294Sstas{ 24233294Sstas const size_t distance = coder->distance; 25233294Sstas 26233294Sstas for (size_t i = 0; i < size; ++i) { 27233294Sstas const uint8_t tmp = coder->history[ 28233294Sstas (distance + coder->pos) & 0xFF]; 29233294Sstas coder->history[coder->pos-- & 0xFF] = in[i]; 30233294Sstas out[i] = in[i] - tmp; 31233294Sstas } 32178825Sdfr} 33178825Sdfr 34233294Sstas 35233294Sstas/// Encodes the data in place. This is used when we are the last filter 36178825Sdfr/// in the chain (and thus non-last filter in the encoder's filter stack). 37178825Sdfrstatic void 38178825Sdfrencode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size) 39178825Sdfr{ 40178825Sdfr const size_t distance = coder->distance; 41178825Sdfr 42178825Sdfr for (size_t i = 0; i < size; ++i) { 43233294Sstas const uint8_t tmp = coder->history[ 44233294Sstas (distance + coder->pos) & 0xFF]; 45233294Sstas coder->history[coder->pos-- & 0xFF] = buffer[i]; 46233294Sstas buffer[i] -= tmp; 47178825Sdfr } 48233294Sstas} 49233294Sstas 50233294Sstas 51233294Sstasstatic lzma_ret 52178825Sdfrdelta_encode(lzma_coder *coder, lzma_allocator *allocator, 53178825Sdfr const uint8_t *restrict in, size_t *restrict in_pos, 54178825Sdfr size_t in_size, uint8_t *restrict out, 55178825Sdfr size_t *restrict out_pos, size_t out_size, lzma_action action) 56178825Sdfr{ 57178825Sdfr lzma_ret ret; 58178825Sdfr 59178825Sdfr if (coder->next.code == NULL) { 60178825Sdfr const size_t in_avail = in_size - *in_pos; 61178825Sdfr const size_t out_avail = out_size - *out_pos; 62178825Sdfr const size_t size = my_min(in_avail, out_avail); 63178825Sdfr 64178825Sdfr copy_and_encode(coder, in + *in_pos, out + *out_pos, size); 65178825Sdfr 66178825Sdfr *in_pos += size; 67178825Sdfr *out_pos += size; 68178825Sdfr 69178825Sdfr ret = action != LZMA_RUN && *in_pos == in_size 70178825Sdfr ? LZMA_STREAM_END : LZMA_OK; 71178825Sdfr 72178825Sdfr } else { 73178825Sdfr const size_t out_start = *out_pos; 74178825Sdfr 75178825Sdfr ret = coder->next.code(coder->next.coder, allocator, 76178825Sdfr in, in_pos, in_size, out, out_pos, out_size, 77178825Sdfr action); 78178825Sdfr 79178825Sdfr encode_in_place(coder, out + out_start, *out_pos - out_start); 80178825Sdfr } 81178825Sdfr 82178825Sdfr return ret; 83178825Sdfr} 84178825Sdfr 85178825Sdfr 86178825Sdfrstatic lzma_ret 87178825Sdfrdelta_encoder_update(lzma_coder *coder, lzma_allocator *allocator, 88178825Sdfr const lzma_filter *filters_null lzma_attribute((unused)), 89178825Sdfr const lzma_filter *reversed_filters) 90178825Sdfr{ 91178825Sdfr // Delta doesn't and will never support changing the options in 92178825Sdfr // the middle of encoding. If the app tries to change them, we 93178825Sdfr // simply ignore them. 94178825Sdfr return lzma_next_filter_update( 95178825Sdfr &coder->next, allocator, reversed_filters + 1); 96178825Sdfr} 97178825Sdfr 98178825Sdfr 99178825Sdfrextern lzma_ret 100178825Sdfrlzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator, 101178825Sdfr const lzma_filter_info *filters) 102178825Sdfr{ 103178825Sdfr next->code = &delta_encode; 104178825Sdfr next->update = &delta_encoder_update; 105178825Sdfr return lzma_delta_coder_init(next, allocator, filters); 106178825Sdfr} 107178825Sdfr 108178825Sdfr 109178825Sdfrextern lzma_ret 110178825Sdfrlzma_delta_props_encode(const void *options, uint8_t *out) 111178825Sdfr{ 112178825Sdfr // The caller must have already validated the options, so it's 113178825Sdfr // LZMA_PROG_ERROR if they are invalid. 114178825Sdfr if (lzma_delta_coder_memusage(options) == UINT64_MAX) 115178825Sdfr return LZMA_PROG_ERROR; 116178825Sdfr 117178825Sdfr const lzma_options_delta *opt = options; 118178825Sdfr out[0] = opt->dist - LZMA_DELTA_DIST_MIN; 119178825Sdfr 120178825Sdfr return LZMA_OK; 121178825Sdfr} 122178825Sdfr