1 /* xdelta 3 - delta compression tools and library
2 * Copyright (C) 2002, 2003, 2006, 2007, 2013. Joshua P. MacDonald
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef _XDELTA3_SECOND_H_
20 #define _XDELTA3_SECOND_H_
22 static inline void xd3_bit_state_encode_init (bit_state *bits)
28 static inline int xd3_decode_bits (xd3_stream *stream,
30 const uint8_t **input,
31 const uint8_t *input_max,
36 usize_t vmask = 1 << nbits;
38 if (bits->cur_mask == 0x100) { goto next_byte; }
46 if (bits->cur_byte & bits->cur_mask)
53 if (vmask == 1) { goto done; }
55 while (bits->cur_mask != 0x100);
59 if (*input == input_max)
61 stream->msg = "secondary decoder end of input";
65 bits->cur_byte = *(*input)++;
71 IF_DEBUG2 (DP(RINT "(d) %u ", value));
78 /* There may be extra bits at the end of secondary decompression, this macro
79 * checks for non-zero bits. This is overly strict, but helps pass the
80 * single-bit-error regression test. */
82 xd3_test_clean_bits (xd3_stream *stream, bit_state *bits)
84 for (; bits->cur_mask != 0x100; bits->cur_mask <<= 1)
86 if (bits->cur_byte & bits->cur_mask)
88 stream->msg = "secondary decoder garbage";
98 xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp,
101 if (*sec_streamp == NULL)
105 if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL)
107 stream->msg = "error initializing secondary stream";
111 if ((ret = stream->sec_type->init (stream, *sec_streamp, is_encode)) != 0)
121 xd3_decode_secondary (xd3_stream *stream,
123 xd3_sec_stream **sec_streamp)
129 if ((ret = xd3_get_secondary (stream, sec_streamp, 0)) != 0)
134 /* Decode the size, allocate the buffer. */
135 if ((ret = xd3_read_size (stream, & sect->buf,
136 sect->buf_max, & dec_size)) ||
137 (ret = xd3_decode_allocate (stream, dec_size,
138 & sect->copied2, & sect->alloc2)))
143 out_used = sect->copied2;
145 if ((ret = stream->sec_type->decode (stream, *sec_streamp,
146 & sect->buf, sect->buf_max,
147 & out_used, out_used + dec_size)))
152 if (sect->buf != sect->buf_max)
154 stream->msg = "secondary decoder finished with unused input";
158 if (out_used != sect->copied2 + dec_size)
160 stream->msg = "secondary decoder short output";
164 sect->buf = sect->copied2;
165 sect->buf_max = sect->copied2 + dec_size;
166 sect->size = dec_size;
172 static inline int xd3_encode_bit (xd3_stream *stream,
181 bits->cur_byte |= bits->cur_mask;
184 /* OPT: Might help to buffer more than 8 bits at once. */
185 if (bits->cur_mask == 0x80)
187 if ((ret = xd3_emit_byte (stream, output, bits->cur_byte)) != 0)
197 bits->cur_mask <<= 1;
203 static inline int xd3_flush_bits (xd3_stream *stream,
207 return (bits->cur_mask == 1) ? 0 :
208 xd3_emit_byte (stream, output, bits->cur_byte);
211 static inline int xd3_encode_bits (xd3_stream *stream,
218 usize_t mask = 1 << nbits;
220 XD3_ASSERT (nbits > 0);
221 XD3_ASSERT (nbits < sizeof (usize_t) * 8);
222 XD3_ASSERT (value < mask);
228 if ((ret = xd3_encode_bit (stream, output, bits, value & mask)))
235 IF_DEBUG2 (DP(RINT "(e) %u ", value));
241 xd3_encode_secondary (xd3_stream *stream,
244 xd3_sec_stream **sec_streamp,
248 xd3_output *tmp_head;
249 xd3_output *tmp_tail;
256 orig_size = xd3_sizeof_output (*head);
258 if (orig_size < SECONDARY_MIN_INPUT) { return 0; }
260 if ((ret = xd3_get_secondary (stream, sec_streamp, 1)) != 0)
265 tmp_head = xd3_alloc_output (stream, NULL);
267 /* Encode the size, encode the data. Encoding the size makes it
268 * simpler, but is a little gross. Should not need the entire
269 * section in contiguous memory, but it is much easier this way. */
270 if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) ||
271 (ret = stream->sec_type->encode (stream, *sec_streamp, *head,
277 /* If the secondary compressor determines it's no good, it returns
280 /* Setup tmp_tail, comp_size */
282 comp_size = tmp_head->next;
284 while (tmp_tail->next_page != NULL)
286 tmp_tail = tmp_tail->next_page;
287 comp_size += tmp_tail->next;
290 XD3_ASSERT (comp_size == xd3_sizeof_output (tmp_head));
291 XD3_ASSERT (tmp_tail != NULL);
293 if (comp_size < (orig_size - SECONDARY_MIN_SAVINGS) || cfg->inefficient)
295 IF_DEBUG1(DP(RINT "secondary saved %u bytes: %u -> %u (%0.2f%%)\n",
296 orig_size - comp_size, orig_size, comp_size,
297 100.0 * (double) comp_size / (double) orig_size));
299 xd3_free_output (stream, *head);
308 if (ret == XD3_NOSECOND) { ret = 0; }
309 xd3_free_output (stream, tmp_head);
314 #endif /* XD3_ENCODER */
315 #endif /* _XDELTA3_SECOND_H_ */