summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2012-07-19 07:05:59 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2012-07-19 07:05:59 +0000
commit86757b7e62ce6e3a30c66eda2f2aeacbfe2450d6 (patch)
treed688c5004cd16e8b305127e4d5d5d659f231c7b9
parent9376393d3c0c1ce7280b91c4747b0eb1c98a943a (diff)
Add support for lzma secondary compression (-S lzma)
-rw-r--r--xdelta3/config.h.in6
-rw-r--r--xdelta3/configure.ac2
l---------xdelta3/ltmain.sh2
l---------xdelta3/m4/ltversion.m42
-rw-r--r--xdelta3/xdelta3-decode.h2
-rw-r--r--xdelta3/xdelta3-djw.h9
-rw-r--r--xdelta3/xdelta3-fgk.h8
-rw-r--r--xdelta3/xdelta3-lzma.h185
-rw-r--r--xdelta3/xdelta3-main.h4
-rw-r--r--xdelta3/xdelta3-second.h38
-rw-r--r--xdelta3/xdelta3-test.h10
-rw-r--r--xdelta3/xdelta3.c59
-rw-r--r--xdelta3/xdelta3.h8
13 files changed, 292 insertions, 43 deletions
diff --git a/xdelta3/config.h.in b/xdelta3/config.h.in
index 19266b3..50345b3 100644
--- a/xdelta3/config.h.in
+++ b/xdelta3/config.h.in
@@ -6,6 +6,12 @@
6/* Define to 1 if you have the <inttypes.h> header file. */ 6/* Define to 1 if you have the <inttypes.h> header file. */
7#undef HAVE_INTTYPES_H 7#undef HAVE_INTTYPES_H
8 8
9/* Define to 1 if you have the `lzma' library (-llzma). */
10#undef HAVE_LIBLZMA
11
12/* Define to 1 if you have the <lzma.h> header file. */
13#undef HAVE_LZMA_H
14
9/* Define to 1 if you have the <memory.h> header file. */ 15/* Define to 1 if you have the <memory.h> header file. */
10#undef HAVE_MEMORY_H 16#undef HAVE_MEMORY_H
11 17
diff --git a/xdelta3/configure.ac b/xdelta3/configure.ac
index 8d1707f..70b733a 100644
--- a/xdelta3/configure.ac
+++ b/xdelta3/configure.ac
@@ -7,6 +7,8 @@ AM_INIT_AUTOMAKE([1.9 no-define foreign tar-ustar])
7AC_DISABLE_STATIC 7AC_DISABLE_STATIC
8AC_PROG_CC 8AC_PROG_CC
9AC_PROG_CXX 9AC_PROG_CXX
10AC_CHECK_HEADERS([lzma.h])
11AC_CHECK_LIB(lzma, lzma_easy_buffer_encode)
10#AM_PATH_PYTHON(,, [:]) 12#AM_PATH_PYTHON(,, [:])
11#AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) 13#AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
12#AX_PYTHON_DEVEL() 14#AX_PYTHON_DEVEL()
diff --git a/xdelta3/ltmain.sh b/xdelta3/ltmain.sh
index 4159958..377d47b 120000
--- a/xdelta3/ltmain.sh
+++ b/xdelta3/ltmain.sh
@@ -1 +1 @@
/usr/share/libtool/config/ltmain.sh \ No newline at end of file /usr/local/share/libtool/config/ltmain.sh \ No newline at end of file
diff --git a/xdelta3/m4/ltversion.m4 b/xdelta3/m4/ltversion.m4
index 5eb474f..f5bd471 120000
--- a/xdelta3/m4/ltversion.m4
+++ b/xdelta3/m4/ltversion.m4
@@ -1 +1 @@
/usr/share/aclocal/ltversion.m4 \ No newline at end of file /usr/local/share/aclocal/ltversion.m4 \ No newline at end of file
diff --git a/xdelta3/xdelta3-decode.h b/xdelta3/xdelta3-decode.h
index d33a79e..c0cb578 100644
--- a/xdelta3/xdelta3-decode.h
+++ b/xdelta3/xdelta3-decode.h
@@ -807,6 +807,8 @@ xd3_decode_input (xd3_stream *stream)
807 FGK_CASE (stream); 807 FGK_CASE (stream);
808 case VCD_DJW_ID: 808 case VCD_DJW_ID:
809 DJW_CASE (stream); 809 DJW_CASE (stream);
810 case VCD_LZMA_ID:
811 LZMA_CASE (stream);
810 default: 812 default:
811 stream->msg = "unknown secondary compressor ID"; 813 stream->msg = "unknown secondary compressor ID";
812 return XD3_INVALID_INPUT; 814 return XD3_INVALID_INPUT;
diff --git a/xdelta3/xdelta3-djw.h b/xdelta3/xdelta3-djw.h
index be9cbf2..d6e2881 100644
--- a/xdelta3/xdelta3-djw.h
+++ b/xdelta3/xdelta3-djw.h
@@ -200,7 +200,9 @@ static const uint8_t djw_encode_12basic[DJW_BASIC_CODES] =
200/*********************************************************************/ 200/*********************************************************************/
201 201
202static djw_stream* djw_alloc (xd3_stream *stream); 202static djw_stream* djw_alloc (xd3_stream *stream);
203static void djw_init (djw_stream *h); 203static int djw_init (xd3_stream *stream,
204 djw_stream *h,
205 int is_encode);
204static void djw_destroy (xd3_stream *stream, 206static void djw_destroy (xd3_stream *stream,
205 djw_stream *h); 207 djw_stream *h);
206 208
@@ -229,10 +231,11 @@ djw_alloc (xd3_stream *stream)
229 return (djw_stream*) xd3_alloc (stream, sizeof (djw_stream), 1); 231 return (djw_stream*) xd3_alloc (stream, sizeof (djw_stream), 1);
230} 232}
231 233
232static void 234static int
233djw_init (djw_stream *h) 235djw_init (xd3_stream *stream, djw_stream *h, int is_encode)
234{ 236{
235 /* Fields are initialized prior to use. */ 237 /* Fields are initialized prior to use. */
238 return 0;
236} 239}
237 240
238static void 241static void
diff --git a/xdelta3/xdelta3-fgk.h b/xdelta3/xdelta3-fgk.h
index 6c61a96..7011500 100644
--- a/xdelta3/xdelta3-fgk.h
+++ b/xdelta3/xdelta3-fgk.h
@@ -106,7 +106,9 @@ struct _fgk_stream
106/*********************************************************************/ 106/*********************************************************************/
107 107
108static fgk_stream* fgk_alloc (xd3_stream *stream /*, usize_t alphabet_size */); 108static fgk_stream* fgk_alloc (xd3_stream *stream /*, usize_t alphabet_size */);
109static void fgk_init (fgk_stream *h); 109static int fgk_init (xd3_stream *stream,
110 fgk_stream *h,
111 int is_encode);
110static int fgk_encode_data (fgk_stream *h, 112static int fgk_encode_data (fgk_stream *h,
111 usize_t n); 113 usize_t n);
112static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h); 114static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h);
@@ -186,7 +188,7 @@ static fgk_stream* fgk_alloc (xd3_stream *stream /*, int alphabet_size0 */)
186 return h; 188 return h;
187} 189}
188 190
189static void fgk_init (fgk_stream *h) 191static int fgk_init (xd3_stream *stream, fgk_stream *h, int is_encode)
190{ 192{
191 usize_t ui; 193 usize_t ui;
192 ssize_t si; 194 ssize_t si;
@@ -219,6 +221,8 @@ static void fgk_init (fgk_stream *h)
219 { 221 {
220 fgk_init_node (h->alphabet + si, (usize_t) si, h->alphabet_size); 222 fgk_init_node (h->alphabet + si, (usize_t) si, h->alphabet_size);
221 } 223 }
224
225 return 0;
222} 226}
223 227
224static void fgk_swap_ptrs(fgk_node **one, fgk_node **two) 228static void fgk_swap_ptrs(fgk_node **one, fgk_node **two)
diff --git a/xdelta3/xdelta3-lzma.h b/xdelta3/xdelta3-lzma.h
new file mode 100644
index 0000000..aa48e84
--- /dev/null
+++ b/xdelta3/xdelta3-lzma.h
@@ -0,0 +1,185 @@
1/* xdelta 3 - delta compression tools and library
2 * Copyright (C) 2012. Joshua P. MacDonald
3 *
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.
8 *
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.
13 *
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
17 */
18
19/* Note: The use of the _easy_ decoder means we're not calling the
20 * xd3_stream malloc hooks. TODO(jmacd) Fix if anyone cares. */
21
22#ifndef _XDELTA3_LZMA_H_
23#define _XDELTA3_LZMA_H_
24
25#include <lzma.h>
26
27typedef struct _xd3_lzma_stream xd3_lzma_stream;
28
29struct _xd3_lzma_stream {
30 lzma_stream lzma;
31};
32
33xd3_sec_stream*
34xd3_lzma_alloc (xd3_stream *stream)
35{
36 return (xd3_sec_stream*) xd3_alloc (stream, sizeof (xd3_lzma_stream), 1);
37}
38
39void
40xd3_lzma_destroy (xd3_stream *stream, xd3_sec_stream *sec_stream)
41{
42 xd3_lzma_stream *ls = (xd3_lzma_stream*) sec_stream;
43 lzma_end (&ls->lzma);
44 xd3_free (stream, ls);
45}
46
47int
48xd3_lzma_init (xd3_stream *stream, xd3_lzma_stream *sec, int is_encode)
49{
50 int ret;
51
52 memset (&sec->lzma, 0, sizeof(sec->lzma));
53
54 if (is_encode)
55 {
56 int level = (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT;
57
58 ret = lzma_easy_encoder (&sec->lzma, level, LZMA_CHECK_CRC32);
59 }
60 else
61 {
62 ret = lzma_stream_decoder (&sec->lzma, UINT64_MAX, 0);
63 }
64
65 if (ret != LZMA_OK)
66 {
67 stream->msg = "lzma stream init failed";
68 return XD3_INTERNAL;
69 }
70
71 return 0;
72}
73
74int xd3_decode_lzma (xd3_stream *stream, xd3_lzma_stream *sec,
75 const uint8_t **input_pos,
76 const uint8_t *const input_end,
77 uint8_t **output_pos,
78 const uint8_t *const output_end)
79{
80 uint8_t *output = *output_pos;
81 const uint8_t *input = *input_pos;
82 size_t avail_in = input_end - input;
83 size_t avail_out = output_end - output;
84
85 sec->lzma.avail_in = avail_in;
86 sec->lzma.next_in = input;
87 sec->lzma.avail_out = avail_out;
88 sec->lzma.next_out = output;
89
90 while (sec->lzma.avail_in != 0 || sec->lzma.avail_out != 0)
91 {
92 int lret = lzma_code (&sec->lzma, LZMA_FINISH);
93
94 if (sec->lzma.avail_out == 0 || lret == LZMA_STREAM_END)
95 {
96 (*output_pos) = sec->lzma.next_out;
97 (*input_pos) = sec->lzma.next_in;
98 }
99
100 switch (lret)
101 {
102 case LZMA_STREAM_END:
103 return 0;
104 case LZMA_OK:
105 break;
106
107 default:
108 stream->msg = "lzma decoding error";
109 return XD3_INTERNAL;
110 }
111 }
112
113 return 0;
114}
115
116#if XD3_ENCODER
117
118int xd3_encode_lzma (xd3_stream *stream,
119 xd3_lzma_stream *sec,
120 xd3_output *input,
121 xd3_output *output,
122 xd3_sec_cfg *cfg)
123
124{
125 lzma_action action = LZMA_RUN;
126
127 sec->lzma.next_in = NULL;
128 sec->lzma.avail_in = 0;
129 sec->lzma.next_out = (output->base + output->next);
130 sec->lzma.avail_out = (output->avail - output->next);
131
132 while (1)
133 {
134 int lret;
135
136 if (sec->lzma.avail_in == 0 && input != NULL)
137 {
138 sec->lzma.avail_in = input->next;
139 sec->lzma.next_in = input->base;
140
141 if ((input = input->next_page) == NULL)
142 {
143 action = LZMA_SYNC_FLUSH;
144 }
145 }
146
147 lret = lzma_code (&sec->lzma, action);
148
149 if (sec->lzma.avail_out == 0 || lret == LZMA_STREAM_END)
150 {
151 size_t nwrite = (output->avail - output->next) - sec->lzma.avail_out;
152 output->next += nwrite;
153
154 if (output->next == output->avail)
155 {
156 if ((output = xd3_alloc_output (stream, output)) == NULL)
157 {
158 return ENOMEM;
159 }
160
161 sec->lzma.next_out = output->base;
162 sec->lzma.avail_out = output->avail;
163 }
164 }
165
166 switch (lret)
167 {
168 case LZMA_OK:
169 break;
170
171 case LZMA_STREAM_END:
172 return 0;
173
174 default:
175 stream->msg = "lzma encoding error";
176 return XD3_INTERNAL;
177 }
178 }
179
180 return 0;
181}
182
183#endif /* XD3_ENCODER */
184
185#endif /* _XDELTA3_LZMA_H_ */
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index d68aa98..d2058c2 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -1161,6 +1161,10 @@ main_set_secondary_flags (xd3_config *config)
1161 { 1161 {
1162 config->flags |= XD3_SEC_FGK; 1162 config->flags |= XD3_SEC_FGK;
1163 } 1163 }
1164 else if (strcmp (option_secondary, "lzma") == 0 && HAVE_LZMA_H)
1165 {
1166 config->flags |= XD3_SEC_LZMA;
1167 }
1164 else if (strncmp (option_secondary, "djw", 3) == 0 && SECONDARY_DJW) 1168 else if (strncmp (option_secondary, "djw", 3) == 0 && SECONDARY_DJW)
1165 { 1169 {
1166 usize_t level = XD3_DEFAULT_SECONDARY_LEVEL; 1170 usize_t level = XD3_DEFAULT_SECONDARY_LEVEL;
diff --git a/xdelta3/xdelta3-second.h b/xdelta3/xdelta3-second.h
index f72ed9b..b9830ab 100644
--- a/xdelta3/xdelta3-second.h
+++ b/xdelta3/xdelta3-second.h
@@ -94,25 +94,27 @@ xd3_test_clean_bits (xd3_stream *stream, bit_state *bits)
94} 94}
95#endif 95#endif
96 96
97static xd3_sec_stream* 97static int
98xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp) 98xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp,
99 int is_encode)
99{ 100{
100 xd3_sec_stream *sec_stream; 101 if (*sec_streamp == NULL)
101
102 if ((sec_stream = *sec_streamp) == NULL)
103 { 102 {
103 int ret;
104
104 if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL) 105 if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL)
105 { 106 {
106 return NULL; 107 stream->msg = "error initializing secondary stream";
108 return XD3_INVALID;
107 } 109 }
108 110
109 sec_stream = *sec_streamp; 111 if ((ret = stream->sec_type->init (stream, *sec_streamp, is_encode)) != 0)
110 112 {
111 /* If cuumulative stats, init once. */ 113 return ret;
112 stream->sec_type->init (sec_stream); 114 }
113 } 115 }
114 116
115 return sec_stream; 117 return 0;
116} 118}
117 119
118static int 120static int
@@ -120,14 +122,13 @@ xd3_decode_secondary (xd3_stream *stream,
120 xd3_desect *sect, 122 xd3_desect *sect,
121 xd3_sec_stream **sec_streamp) 123 xd3_sec_stream **sec_streamp)
122{ 124{
123 xd3_sec_stream *sec_stream;
124 uint32_t dec_size; 125 uint32_t dec_size;
125 uint8_t *out_used; 126 uint8_t *out_used;
126 int ret; 127 int ret;
127 128
128 if ((sec_stream = xd3_get_secondary (stream, sec_streamp)) == NULL) 129 if ((ret = xd3_get_secondary (stream, sec_streamp, 0)) != 0)
129 { 130 {
130 return ENOMEM; 131 return ret;
131 } 132 }
132 133
133 /* Decode the size, allocate the buffer. */ 134 /* Decode the size, allocate the buffer. */
@@ -141,7 +142,7 @@ xd3_decode_secondary (xd3_stream *stream,
141 142
142 out_used = sect->copied2; 143 out_used = sect->copied2;
143 144
144 if ((ret = stream->sec_type->decode (stream, sec_stream, 145 if ((ret = stream->sec_type->decode (stream, *sec_streamp,
145 & sect->buf, sect->buf_max, 146 & sect->buf, sect->buf_max,
146 & out_used, out_used + dec_size))) 147 & out_used, out_used + dec_size)))
147 { 148 {
@@ -244,7 +245,6 @@ xd3_encode_secondary (xd3_stream *stream,
244 xd3_sec_cfg *cfg, 245 xd3_sec_cfg *cfg,
245 int *did_it) 246 int *did_it)
246{ 247{
247 xd3_sec_stream *sec_stream;
248 xd3_output *tmp_head; 248 xd3_output *tmp_head;
249 xd3_output *tmp_tail; 249 xd3_output *tmp_tail;
250 250
@@ -257,9 +257,9 @@ xd3_encode_secondary (xd3_stream *stream,
257 257
258 if (orig_size < SECONDARY_MIN_INPUT) { return 0; } 258 if (orig_size < SECONDARY_MIN_INPUT) { return 0; }
259 259
260 if ((sec_stream = xd3_get_secondary (stream, sec_streamp)) == NULL) 260 if ((ret = xd3_get_secondary (stream, sec_streamp, 1)) != 0)
261 { 261 {
262 return ENOMEM; 262 return ret;
263 } 263 }
264 264
265 tmp_head = xd3_alloc_output (stream, NULL); 265 tmp_head = xd3_alloc_output (stream, NULL);
@@ -268,7 +268,7 @@ xd3_encode_secondary (xd3_stream *stream,
268 * simpler, but is a little gross. Should not need the entire 268 * simpler, but is a little gross. Should not need the entire
269 * section in contiguous memory, but it is much easier this way. */ 269 * section in contiguous memory, but it is much easier this way. */
270 if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) || 270 if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) ||
271 (ret = stream->sec_type->encode (stream, sec_stream, *head, 271 (ret = stream->sec_type->encode (stream, *sec_streamp, *head,
272 tmp_head, cfg))) 272 tmp_head, cfg)))
273 { 273 {
274 goto getout; 274 goto getout;
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h
index bd04f56..7464c4f 100644
--- a/xdelta3/xdelta3-test.h
+++ b/xdelta3/xdelta3-test.h
@@ -1185,7 +1185,7 @@ static int
1185sec_dist_func7 (xd3_stream *stream, xd3_output *data) 1185sec_dist_func7 (xd3_stream *stream, xd3_output *data)
1186{ 1186{
1187 int i, ret, x; 1187 int i, ret, x;
1188 for (i = 0; i < ALPHABET_SIZE*20; i += 1) 1188 for (i = 0; i < ALPHABET_SIZE*200; i += 1)
1189 { 1189 {
1190 x = mt_random (&static_mtrand) % ALPHABET_SIZE; 1190 x = mt_random (&static_mtrand) % ALPHABET_SIZE;
1191 if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } 1191 if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; }
@@ -1305,7 +1305,7 @@ test_secondary_decode (xd3_stream *stream,
1305 1305
1306 if ((dec_stream = sec->alloc (stream)) == NULL) { return ENOMEM; } 1306 if ((dec_stream = sec->alloc (stream)) == NULL) { return ENOMEM; }
1307 1307
1308 sec->init (dec_stream); 1308 if ((ret = sec->init (stream, dec_stream, 0)) != 0) { goto fail; }
1309 1309
1310 dec_input_used = dec_input; 1310 dec_input_used = dec_input;
1311 dec_input_end = dec_input + compress_size; 1311 dec_input_end = dec_input + compress_size;
@@ -1382,7 +1382,7 @@ test_secondary (xd3_stream *stream, const xd3_sec_type *sec, usize_t groups)
1382 1382
1383 if ((ret = sec_dists[test_i] (stream, in_head))) { goto fail; } 1383 if ((ret = sec_dists[test_i] (stream, in_head))) { goto fail; }
1384 1384
1385 sec->init (enc_stream); 1385 if ((ret = sec->init (stream, enc_stream, 1)) != 0) { goto fail; }
1386 1386
1387 /* Encode data */ 1387 /* Encode data */
1388 if ((ret = sec->encode (stream, enc_stream, 1388 if ((ret = sec->encode (stream, enc_stream,
@@ -1482,6 +1482,8 @@ IF_FGK (static int test_secondary_fgk (xd3_stream *stream, usize_t gp)
1482 { return test_secondary (stream, & fgk_sec_type, gp); }) 1482 { return test_secondary (stream, & fgk_sec_type, gp); })
1483IF_DJW (static int test_secondary_huff (xd3_stream *stream, usize_t gp) 1483IF_DJW (static int test_secondary_huff (xd3_stream *stream, usize_t gp)
1484 { return test_secondary (stream, & djw_sec_type, gp); }) 1484 { return test_secondary (stream, & djw_sec_type, gp); })
1485IF_LZMA (static int test_secondary_lzma (xd3_stream *stream, usize_t gp)
1486 { return test_secondary (stream, & lzma_sec_type, gp); })
1485#endif 1487#endif
1486 1488
1487/*********************************************************************** 1489/***********************************************************************
@@ -2818,6 +2820,7 @@ xd3_selftest (void)
2818 DO_TEST (decompress_single_bit_error, 0, 3); 2820 DO_TEST (decompress_single_bit_error, 0, 3);
2819 DO_TEST (decompress_single_bit_error, XD3_ADLER32, 3); 2821 DO_TEST (decompress_single_bit_error, XD3_ADLER32, 3);
2820 2822
2823 IF_LZMA (DO_TEST (decompress_single_bit_error, XD3_SEC_LZMA, 3));
2821 IF_FGK (DO_TEST (decompress_single_bit_error, XD3_SEC_FGK, 3)); 2824 IF_FGK (DO_TEST (decompress_single_bit_error, XD3_SEC_FGK, 3));
2822 IF_DJW (DO_TEST (decompress_single_bit_error, XD3_SEC_DJW, 8)); 2825 IF_DJW (DO_TEST (decompress_single_bit_error, XD3_SEC_DJW, 8));
2823 2826
@@ -2840,6 +2843,7 @@ xd3_selftest (void)
2840 DO_TEST (recode_command, 0, 0); 2843 DO_TEST (recode_command, 0, 0);
2841#endif 2844#endif
2842 2845
2846 IF_LZMA (DO_TEST (secondary_lzma, 0, 1));
2843 IF_DJW (DO_TEST (secondary_huff, 0, DJW_MAX_GROUPS)); 2847 IF_DJW (DO_TEST (secondary_huff, 0, DJW_MAX_GROUPS));
2844 IF_FGK (DO_TEST (secondary_fgk, 0, 1)); 2848 IF_FGK (DO_TEST (secondary_fgk, 0, 1));
2845 2849
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 9d9e52c..cb6bde6 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -278,17 +278,17 @@
278#define VCDIFF_TOOLS XD3_MAIN 278#define VCDIFF_TOOLS XD3_MAIN
279#endif 279#endif
280 280
281#ifndef SECONDARY_FGK /* one from the algorithm preservation department: */ 281#ifndef SECONDARY_FGK /* one from the algorithm preservation department: */
282#define SECONDARY_FGK 0 /* adaptive Huffman routines */ 282#define SECONDARY_FGK 0 /* adaptive Huffman routines */
283#endif 283#endif
284 284
285#ifndef SECONDARY_DJW /* semi-adaptive/static Huffman for the eventual */ 285#ifndef SECONDARY_DJW /* semi-adaptive/static Huffman for the eventual */
286#define SECONDARY_DJW 0 /* standardization, off by default until such time. */ 286#define SECONDARY_DJW 0 /* standardization, off by default until such time. */
287#endif 287#endif
288 288
289#ifndef GENERIC_ENCODE_TABLES /* These three are the RFC-spec'd app-specific */ 289#ifndef GENERIC_ENCODE_TABLES /* These three are the RFC-spec app-specific */
290#define GENERIC_ENCODE_TABLES 0 /* code features. This is tested but not recommended */ 290#define GENERIC_ENCODE_TABLES 0 /* code features. This is tested but not */
291#endif /* unless there's a real application. */ 291#endif /* recommended unless there's a real use. */
292#ifndef GENERIC_ENCODE_TABLES_COMPUTE 292#ifndef GENERIC_ENCODE_TABLES_COMPUTE
293#define GENERIC_ENCODE_TABLES_COMPUTE 0 293#define GENERIC_ENCODE_TABLES_COMPUTE 0
294#endif 294#endif
@@ -326,6 +326,7 @@
326 326
327typedef enum { 327typedef enum {
328 VCD_DJW_ID = 1, 328 VCD_DJW_ID = 1,
329 VCD_LZMA_ID = 2,
329 VCD_FGK_ID = 16 /* Note: these are not standard IANA-allocated IDs! */ 330 VCD_FGK_ID = 16 /* Note: these are not standard IANA-allocated IDs! */
330} xd3_secondary_ids; 331} xd3_secondary_ids;
331 332
@@ -371,7 +372,7 @@ XD3_MAKELIST(xd3_rlist, xd3_rinst, link);
371#define CODE_TABLE_VCDIFF_SIZE (6 * 256) /* Should fit a compressed code 372#define CODE_TABLE_VCDIFF_SIZE (6 * 256) /* Should fit a compressed code
372 * table string */ 373 * table string */
373 374
374#define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK) 375#define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK || HAVE_LZMA_H)
375 376
376#define ALPHABET_SIZE 256 /* Used in test code--size of the secondary 377#define ALPHABET_SIZE 256 /* Used in test code--size of the secondary
377 * compressor alphabet. */ 378 * compressor alphabet. */
@@ -630,7 +631,9 @@ struct _xd3_sec_type
630 xd3_sec_stream* (*alloc) (xd3_stream *stream); 631 xd3_sec_stream* (*alloc) (xd3_stream *stream);
631 void (*destroy) (xd3_stream *stream, 632 void (*destroy) (xd3_stream *stream,
632 xd3_sec_stream *sec); 633 xd3_sec_stream *sec);
633 void (*init) (xd3_sec_stream *sec); 634 int (*init) (xd3_stream *stream,
635 xd3_sec_stream *sec_stream,
636 int is_encode);
634 int (*decode) (xd3_stream *stream, 637 int (*decode) (xd3_stream *stream,
635 xd3_sec_stream *sec_stream, 638 xd3_sec_stream *sec_stream,
636 const uint8_t **input, 639 const uint8_t **input,
@@ -703,6 +706,19 @@ extern const xd3_sec_type djw_sec_type;
703 return XD3_INTERNAL; 706 return XD3_INTERNAL;
704#endif 707#endif
705 708
709#if HAVE_LZMA_H
710extern const xd3_sec_type lzma_sec_type;
711#define IF_LZMA(x) x
712#define LZMA_CASE(s) \
713 s->sec_type = & lzma_sec_type; \
714 break;
715#else
716#define IF_LZMA(x)
717#define LZMA_CASE(s) \
718 s->msg = "unavailable secondary compressor: LZMA"; \
719 return XD3_INTERNAL;
720#endif
721
706/***********************************************************************/ 722/***********************************************************************/
707 723
708#include "xdelta3-hash.h" 724#include "xdelta3-hash.h"
@@ -731,7 +747,7 @@ const xd3_sec_type fgk_sec_type =
731 SEC_NOFLAGS, 747 SEC_NOFLAGS,
732 (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc, 748 (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc,
733 (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy, 749 (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy,
734 (void (*)(xd3_sec_stream*)) fgk_init, 750 (int (*)(xd3_stream*, xd3_sec_stream*, int)) fgk_init,
735 (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, 751 (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*,
736 uint8_t**, const uint8_t*)) xd3_decode_fgk, 752 uint8_t**, const uint8_t*)) xd3_decode_fgk,
737 IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, 753 IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*,
@@ -748,7 +764,7 @@ const xd3_sec_type djw_sec_type =
748 SEC_COUNT_FREQS, 764 SEC_COUNT_FREQS,
749 (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc, 765 (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc,
750 (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy, 766 (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy,
751 (void (*)(xd3_sec_stream*)) djw_init, 767 (int (*)(xd3_stream*, xd3_sec_stream*, int)) djw_init,
752 (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, 768 (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*,
753 uint8_t**, const uint8_t*)) xd3_decode_huff, 769 uint8_t**, const uint8_t*)) xd3_decode_huff,
754 IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, 770 IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*,
@@ -756,6 +772,23 @@ const xd3_sec_type djw_sec_type =
756}; 772};
757#endif 773#endif
758 774
775#if HAVE_LZMA_H
776#include "xdelta3-lzma.h"
777const xd3_sec_type lzma_sec_type =
778{
779 VCD_LZMA_ID,
780 "lzma",
781 SEC_NOFLAGS,
782 (xd3_sec_stream* (*)(xd3_stream*)) xd3_lzma_alloc,
783 (void (*)(xd3_stream*, xd3_sec_stream*)) xd3_lzma_destroy,
784 (int (*)(xd3_stream*, xd3_sec_stream*, int)) xd3_lzma_init,
785 (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*,
786 uint8_t**, const uint8_t*)) xd3_decode_lzma,
787 IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*,
788 xd3_output*, xd3_sec_cfg*)) xd3_encode_lzma)
789};
790#endif
791
759#if XD3_MAIN || PYTHON_MODULE || SWIG_MODULE || NOT_MAIN 792#if XD3_MAIN || PYTHON_MODULE || SWIG_MODULE || NOT_MAIN
760#include "xdelta3-main.h" 793#include "xdelta3-main.h"
761#endif 794#endif
@@ -1678,7 +1711,7 @@ static inline int
1678xd3_emit_bytes (xd3_stream *stream, 1711xd3_emit_bytes (xd3_stream *stream,
1679 xd3_output **outputp, 1712 xd3_output **outputp,
1680 const uint8_t *base, 1713 const uint8_t *base,
1681 usize_t size) 1714 usize_t size)
1682{ 1715{
1683 xd3_output *output = (*outputp); 1716 xd3_output *output = (*outputp);
1684 1717
@@ -2381,6 +2414,8 @@ xd3_config_stream(xd3_stream *stream,
2381 FGK_CASE (stream); 2414 FGK_CASE (stream);
2382 case XD3_SEC_DJW: 2415 case XD3_SEC_DJW:
2383 DJW_CASE (stream); 2416 DJW_CASE (stream);
2417 case XD3_SEC_LZMA:
2418 LZMA_CASE (stream);
2384 default: 2419 default:
2385 stream->msg = "too many secondary compressor types set"; 2420 stream->msg = "too many secondary compressor types set";
2386 return XD3_INTERNAL; 2421 return XD3_INTERNAL;
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index 5c1e5a5..8a94729 100644
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -29,6 +29,8 @@
29#define _ISOC99_SOURCE 29#define _ISOC99_SOURCE
30#define _C99_SOURCE 30#define _C99_SOURCE
31 31
32#include "config.h"
33
32#include <errno.h> 34#include <errno.h>
33#include <stdarg.h> 35#include <stdarg.h>
34#include <stddef.h> 36#include <stddef.h>
@@ -358,7 +360,9 @@ typedef enum
358 360
359 XD3_SEC_DJW = (1 << 5), /* use DJW static huffman */ 361 XD3_SEC_DJW = (1 << 5), /* use DJW static huffman */
360 XD3_SEC_FGK = (1 << 6), /* use FGK adaptive huffman */ 362 XD3_SEC_FGK = (1 << 6), /* use FGK adaptive huffman */
361 XD3_SEC_TYPE = (XD3_SEC_DJW | XD3_SEC_FGK), 363 XD3_SEC_LZMA = (1 << 24), /* use LZMA secondary */
364
365 XD3_SEC_TYPE = (XD3_SEC_DJW | XD3_SEC_FGK | XD3_SEC_LZMA),
362 366
363 XD3_SEC_NODATA = (1 << 7), /* disable secondary compression of 367 XD3_SEC_NODATA = (1 << 7), /* disable secondary compression of
364 the data section. */ 368 the data section. */
@@ -391,7 +395,7 @@ typedef enum
391 * and is independent of compression level). This is for 395 * and is independent of compression level). This is for
392 * convenience, especially with xd3_encode_memory(). */ 396 * convenience, especially with xd3_encode_memory(). */
393 397
394 XD3_COMPLEVEL_SHIFT = 20, /* 20 - 24 */ 398 XD3_COMPLEVEL_SHIFT = 20, /* 20 - 23 */
395 XD3_COMPLEVEL_MASK = (0xF << XD3_COMPLEVEL_SHIFT), 399 XD3_COMPLEVEL_MASK = (0xF << XD3_COMPLEVEL_SHIFT),
396 XD3_COMPLEVEL_1 = (1 << XD3_COMPLEVEL_SHIFT), 400 XD3_COMPLEVEL_1 = (1 << XD3_COMPLEVEL_SHIFT),
397 XD3_COMPLEVEL_2 = (2 << XD3_COMPLEVEL_SHIFT), 401 XD3_COMPLEVEL_2 = (2 << XD3_COMPLEVEL_SHIFT),