1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file delta_encoder.c
4 /// \brief Delta filter encoder
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "delta_encoder.h"
14 #include "delta_private.h"
17 /// Copies and encodes the data at the same time. This is used when Delta
18 /// is the first filter in the chain (and thus the last filter in the
19 /// encoder's filter stack).
21 copy_and_encode(lzma_delta_coder
*coder
,
22 const uint8_t *restrict in
, uint8_t *restrict out
, size_t size
)
24 const size_t distance
= coder
->distance
;
26 for (size_t i
= 0; i
< size
; ++i
) {
27 const uint8_t tmp
= coder
->history
[
28 (distance
+ coder
->pos
) & 0xFF];
29 coder
->history
[coder
->pos
-- & 0xFF] = in
[i
];
35 /// Encodes the data in place. This is used when we are the last filter
36 /// in the chain (and thus non-last filter in the encoder's filter stack).
38 encode_in_place(lzma_delta_coder
*coder
, uint8_t *buffer
, size_t size
)
40 const size_t distance
= coder
->distance
;
42 for (size_t i
= 0; i
< size
; ++i
) {
43 const uint8_t tmp
= coder
->history
[
44 (distance
+ coder
->pos
) & 0xFF];
45 coder
->history
[coder
->pos
-- & 0xFF] = buffer
[i
];
52 delta_encode(void *coder_ptr
, const lzma_allocator
*allocator
,
53 const uint8_t *restrict in
, size_t *restrict in_pos
,
54 size_t in_size
, uint8_t *restrict out
,
55 size_t *restrict out_pos
, size_t out_size
, lzma_action action
)
57 lzma_delta_coder
*coder
= coder_ptr
;
61 if (coder
->next
.code
== NULL
) {
62 const size_t in_avail
= in_size
- *in_pos
;
63 const size_t out_avail
= out_size
- *out_pos
;
64 const size_t size
= my_min(in_avail
, out_avail
);
66 copy_and_encode(coder
, in
+ *in_pos
, out
+ *out_pos
, size
);
71 ret
= action
!= LZMA_RUN
&& *in_pos
== in_size
72 ? LZMA_STREAM_END
: LZMA_OK
;
75 const size_t out_start
= *out_pos
;
77 ret
= coder
->next
.code(coder
->next
.coder
, allocator
,
78 in
, in_pos
, in_size
, out
, out_pos
, out_size
,
81 encode_in_place(coder
, out
+ out_start
, *out_pos
- out_start
);
89 delta_encoder_update(void *coder_ptr
, const lzma_allocator
*allocator
,
90 const lzma_filter
*filters_null
lzma_attribute((__unused__
)),
91 const lzma_filter
*reversed_filters
)
93 lzma_delta_coder
*coder
= coder_ptr
;
95 // Delta doesn't and will never support changing the options in
96 // the middle of encoding. If the app tries to change them, we
97 // simply ignore them.
98 return lzma_next_filter_update(
99 &coder
->next
, allocator
, reversed_filters
+ 1);
104 lzma_delta_encoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
105 const lzma_filter_info
*filters
)
107 next
->code
= &delta_encode
;
108 next
->update
= &delta_encoder_update
;
109 return lzma_delta_coder_init(next
, allocator
, filters
);
114 lzma_delta_props_encode(const void *options
, uint8_t *out
)
116 // The caller must have already validated the options, so it's
117 // LZMA_PROG_ERROR if they are invalid.
118 if (lzma_delta_coder_memusage(options
) == UINT64_MAX
)
119 return LZMA_PROG_ERROR
;
121 const lzma_options_delta
*opt
= options
;
122 out
[0] = opt
->dist
- LZMA_DELTA_DIST_MIN
;