xref: /dflybsd-src/contrib/xz/src/liblzma/delta/delta_encoder.c (revision 46a2189dd86b644c3a76ac281d84b4182fd66b95)
12940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
22940b44dSPeter Avalos //
32940b44dSPeter Avalos /// \file       delta_encoder.c
42940b44dSPeter Avalos /// \brief      Delta filter encoder
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_encoder.h"
142940b44dSPeter Avalos #include "delta_private.h"
152940b44dSPeter Avalos 
162940b44dSPeter Avalos 
172940b44dSPeter Avalos /// Copies and encodes the data at the same time. This is used when Delta
182940b44dSPeter Avalos /// is the first filter in the chain (and thus the last filter in the
192940b44dSPeter Avalos /// encoder's filter stack).
202940b44dSPeter Avalos static void
copy_and_encode(lzma_delta_coder * coder,const uint8_t * restrict in,uint8_t * restrict out,size_t size)21*46a2189dSzrj copy_and_encode(lzma_delta_coder *coder,
222940b44dSPeter Avalos 		const uint8_t *restrict in, uint8_t *restrict out, size_t size)
232940b44dSPeter Avalos {
242940b44dSPeter Avalos 	const size_t distance = coder->distance;
252940b44dSPeter Avalos 
262940b44dSPeter Avalos 	for (size_t i = 0; i < size; ++i) {
272940b44dSPeter Avalos 		const uint8_t tmp = coder->history[
282940b44dSPeter Avalos 				(distance + coder->pos) & 0xFF];
292940b44dSPeter Avalos 		coder->history[coder->pos-- & 0xFF] = in[i];
302940b44dSPeter Avalos 		out[i] = in[i] - tmp;
312940b44dSPeter Avalos 	}
322940b44dSPeter Avalos }
332940b44dSPeter Avalos 
342940b44dSPeter Avalos 
352940b44dSPeter Avalos /// Encodes the data in place. This is used when we are the last filter
362940b44dSPeter Avalos /// in the chain (and thus non-last filter in the encoder's filter stack).
372940b44dSPeter Avalos static void
encode_in_place(lzma_delta_coder * coder,uint8_t * buffer,size_t size)38*46a2189dSzrj encode_in_place(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
392940b44dSPeter Avalos {
402940b44dSPeter Avalos 	const size_t distance = coder->distance;
412940b44dSPeter Avalos 
422940b44dSPeter Avalos 	for (size_t i = 0; i < size; ++i) {
432940b44dSPeter Avalos 		const uint8_t tmp = coder->history[
442940b44dSPeter Avalos 				(distance + coder->pos) & 0xFF];
452940b44dSPeter Avalos 		coder->history[coder->pos-- & 0xFF] = buffer[i];
462940b44dSPeter Avalos 		buffer[i] -= tmp;
472940b44dSPeter Avalos 	}
482940b44dSPeter Avalos }
492940b44dSPeter Avalos 
502940b44dSPeter Avalos 
512940b44dSPeter Avalos static lzma_ret
delta_encode(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)52*46a2189dSzrj delta_encode(void *coder_ptr, const lzma_allocator *allocator,
532940b44dSPeter Avalos 		const uint8_t *restrict in, size_t *restrict in_pos,
542940b44dSPeter Avalos 		size_t in_size, uint8_t *restrict out,
552940b44dSPeter Avalos 		size_t *restrict out_pos, size_t out_size, lzma_action action)
562940b44dSPeter Avalos {
57*46a2189dSzrj 	lzma_delta_coder *coder = coder_ptr;
58*46a2189dSzrj 
592940b44dSPeter Avalos 	lzma_ret ret;
602940b44dSPeter Avalos 
612940b44dSPeter Avalos 	if (coder->next.code == NULL) {
622940b44dSPeter Avalos 		const size_t in_avail = in_size - *in_pos;
632940b44dSPeter Avalos 		const size_t out_avail = out_size - *out_pos;
642940b44dSPeter Avalos 		const size_t size = my_min(in_avail, out_avail);
652940b44dSPeter Avalos 
662940b44dSPeter Avalos 		copy_and_encode(coder, in + *in_pos, out + *out_pos, size);
672940b44dSPeter Avalos 
682940b44dSPeter Avalos 		*in_pos += size;
692940b44dSPeter Avalos 		*out_pos += size;
702940b44dSPeter Avalos 
712940b44dSPeter Avalos 		ret = action != LZMA_RUN && *in_pos == in_size
722940b44dSPeter Avalos 				? LZMA_STREAM_END : LZMA_OK;
732940b44dSPeter Avalos 
742940b44dSPeter Avalos 	} else {
752940b44dSPeter Avalos 		const size_t out_start = *out_pos;
762940b44dSPeter Avalos 
772940b44dSPeter Avalos 		ret = coder->next.code(coder->next.coder, allocator,
782940b44dSPeter Avalos 				in, in_pos, in_size, out, out_pos, out_size,
792940b44dSPeter Avalos 				action);
802940b44dSPeter Avalos 
812940b44dSPeter Avalos 		encode_in_place(coder, out + out_start, *out_pos - out_start);
822940b44dSPeter Avalos 	}
832940b44dSPeter Avalos 
842940b44dSPeter Avalos 	return ret;
852940b44dSPeter Avalos }
862940b44dSPeter Avalos 
872940b44dSPeter Avalos 
882940b44dSPeter Avalos static lzma_ret
delta_encoder_update(void * coder_ptr,const lzma_allocator * allocator,const lzma_filter * filters_null lzma_attribute ((__unused__)),const lzma_filter * reversed_filters)89*46a2189dSzrj delta_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
90114db65bSPeter Avalos 		const lzma_filter *filters_null lzma_attribute((__unused__)),
912940b44dSPeter Avalos 		const lzma_filter *reversed_filters)
922940b44dSPeter Avalos {
93*46a2189dSzrj 	lzma_delta_coder *coder = coder_ptr;
94*46a2189dSzrj 
952940b44dSPeter Avalos 	// Delta doesn't and will never support changing the options in
962940b44dSPeter Avalos 	// the middle of encoding. If the app tries to change them, we
972940b44dSPeter Avalos 	// simply ignore them.
982940b44dSPeter Avalos 	return lzma_next_filter_update(
992940b44dSPeter Avalos 			&coder->next, allocator, reversed_filters + 1);
1002940b44dSPeter Avalos }
1012940b44dSPeter Avalos 
1022940b44dSPeter Avalos 
1032940b44dSPeter Avalos extern lzma_ret
lzma_delta_encoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)10415ab8c86SJohn Marino lzma_delta_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
1052940b44dSPeter Avalos 		const lzma_filter_info *filters)
1062940b44dSPeter Avalos {
1072940b44dSPeter Avalos 	next->code = &delta_encode;
1082940b44dSPeter Avalos 	next->update = &delta_encoder_update;
1092940b44dSPeter Avalos 	return lzma_delta_coder_init(next, allocator, filters);
1102940b44dSPeter Avalos }
1112940b44dSPeter Avalos 
1122940b44dSPeter Avalos 
1132940b44dSPeter Avalos extern lzma_ret
lzma_delta_props_encode(const void * options,uint8_t * out)1142940b44dSPeter Avalos lzma_delta_props_encode(const void *options, uint8_t *out)
1152940b44dSPeter Avalos {
1162940b44dSPeter Avalos 	// The caller must have already validated the options, so it's
1172940b44dSPeter Avalos 	// LZMA_PROG_ERROR if they are invalid.
1182940b44dSPeter Avalos 	if (lzma_delta_coder_memusage(options) == UINT64_MAX)
1192940b44dSPeter Avalos 		return LZMA_PROG_ERROR;
1202940b44dSPeter Avalos 
1212940b44dSPeter Avalos 	const lzma_options_delta *opt = options;
1222940b44dSPeter Avalos 	out[0] = opt->dist - LZMA_DELTA_DIST_MIN;
1232940b44dSPeter Avalos 
1242940b44dSPeter Avalos 	return LZMA_OK;
1252940b44dSPeter Avalos }
126