diff options
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/xdelta3-main.h | 22 | ||||
-rw-r--r-- | xdelta3/xdelta3-merge.h | 84 | ||||
-rw-r--r-- | xdelta3/xdelta3.c | 1 | ||||
-rw-r--r-- | xdelta3/xdelta3.h | 6 |
4 files changed, 97 insertions, 16 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index ae6fc19..46b2cfb 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -1265,7 +1265,7 @@ main_print_window (xd3_stream* stream, main_file *xfile) | |||
1265 | { | 1265 | { |
1266 | if (stream->dec_current1.addr >= stream->dec_cpylen) | 1266 | if (stream->dec_current1.addr >= stream->dec_cpylen) |
1267 | { | 1267 | { |
1268 | VC(UT " T@%-6"Q"u", | 1268 | VC(UT " T@%-6u", |
1269 | stream->dec_current1.addr - stream->dec_cpylen)VE; | 1269 | stream->dec_current1.addr - stream->dec_cpylen)VE; |
1270 | } | 1270 | } |
1271 | else | 1271 | else |
@@ -1293,7 +1293,7 @@ main_print_window (xd3_stream* stream, main_file *xfile) | |||
1293 | { | 1293 | { |
1294 | if (stream->dec_current2.addr >= stream->dec_cpylen) | 1294 | if (stream->dec_current2.addr >= stream->dec_cpylen) |
1295 | { | 1295 | { |
1296 | VC(UT " T@%-6"Q"u", | 1296 | VC(UT " T@%-6u", |
1297 | stream->dec_current2.addr - stream->dec_cpylen)VE; | 1297 | stream->dec_current2.addr - stream->dec_cpylen)VE; |
1298 | } | 1298 | } |
1299 | else | 1299 | else |
@@ -1794,6 +1794,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1794 | usize_t inst_pos = 0; | 1794 | usize_t inst_pos = 0; |
1795 | xoff_t output_pos = 0; | 1795 | xoff_t output_pos = 0; |
1796 | xd3_source recode_source; | 1796 | xd3_source recode_source; |
1797 | usize_t window_num = 0; | ||
1797 | int at_least_once = 0; | 1798 | int at_least_once = 0; |
1798 | 1799 | ||
1799 | /* merge_stream is set if there were arguments. this stream's input | 1800 | /* merge_stream is set if there were arguments. this stream's input |
@@ -1821,6 +1822,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1821 | xoff_t window_srcmin = 0; | 1822 | xoff_t window_srcmin = 0; |
1822 | xoff_t window_srcmax = 0; | 1823 | xoff_t window_srcmax = 0; |
1823 | usize_t window_pos = 0; | 1824 | usize_t window_pos = 0; |
1825 | usize_t window_size; | ||
1824 | 1826 | ||
1825 | /* at_least_once ensures that we encode at least one window, | 1827 | /* at_least_once ensures that we encode at least one window, |
1826 | * which handles the 0-byte case. */ | 1828 | * which handles the 0-byte case. */ |
@@ -1834,25 +1836,31 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1834 | return XD3_INVALID; | 1836 | return XD3_INVALID; |
1835 | } | 1837 | } |
1836 | 1838 | ||
1837 | if (main_bsize < stream->dec_tgtlen) | 1839 | /* Window sizes must match from the input to the output, so that |
1840 | * target copies are in-range (and so that checksums carry | ||
1841 | * over). */ | ||
1842 | XD3_ASSERT (window_num < stream->whole_target.winsizeslen); | ||
1843 | window_size = stream->whole_target.winsizes[window_num++]; | ||
1844 | |||
1845 | if (main_bsize < window_size) | ||
1838 | { | 1846 | { |
1839 | main_free (main_bdata); | 1847 | main_free (main_bdata); |
1840 | main_bdata = NULL; | 1848 | main_bdata = NULL; |
1841 | main_bsize = 0; | 1849 | main_bsize = 0; |
1842 | if ((main_bdata = (uint8_t*) | 1850 | if ((main_bdata = (uint8_t*) |
1843 | main_malloc (stream->dec_tgtlen)) == NULL) | 1851 | main_malloc (window_size)) == NULL) |
1844 | { | 1852 | { |
1845 | return ENOMEM; | 1853 | return ENOMEM; |
1846 | } | 1854 | } |
1847 | main_bsize = stream->dec_tgtlen; | 1855 | main_bsize = window_size; |
1848 | } | 1856 | } |
1849 | 1857 | ||
1850 | /* This encodes a single target window. */ | 1858 | /* This encodes a single target window. */ |
1851 | while (window_pos < stream->dec_tgtlen && | 1859 | while (window_pos < window_size && |
1852 | inst_pos < stream->whole_target.instlen) | 1860 | inst_pos < stream->whole_target.instlen) |
1853 | { | 1861 | { |
1854 | xd3_winst *inst = &stream->whole_target.inst[inst_pos]; | 1862 | xd3_winst *inst = &stream->whole_target.inst[inst_pos]; |
1855 | usize_t take = min(inst->size, stream->dec_tgtlen - window_pos); | 1863 | usize_t take = min(inst->size, window_size - window_pos); |
1856 | xoff_t addr; | 1864 | xoff_t addr; |
1857 | 1865 | ||
1858 | switch (inst->type) | 1866 | switch (inst->type) |
diff --git a/xdelta3/xdelta3-merge.h b/xdelta3/xdelta3-merge.h index fefe55d..553fbf0 100644 --- a/xdelta3/xdelta3-merge.h +++ b/xdelta3/xdelta3-merge.h | |||
@@ -28,15 +28,19 @@ xd3_whole_state_init (xd3_stream *stream) | |||
28 | { | 28 | { |
29 | XD3_ASSERT (stream->whole_target.adds == NULL); | 29 | XD3_ASSERT (stream->whole_target.adds == NULL); |
30 | XD3_ASSERT (stream->whole_target.inst == NULL); | 30 | XD3_ASSERT (stream->whole_target.inst == NULL); |
31 | XD3_ASSERT (stream->whole_target.winsizes == NULL); | ||
31 | XD3_ASSERT (stream->whole_target.length == 0); | 32 | XD3_ASSERT (stream->whole_target.length == 0); |
32 | 33 | ||
33 | stream->whole_target.adds_alloc = XD3_ALLOCSIZE; | 34 | stream->whole_target.adds_alloc = XD3_ALLOCSIZE; |
34 | stream->whole_target.inst_alloc = XD3_ALLOCSIZE / sizeof (xd3_winst); | 35 | stream->whole_target.inst_alloc = XD3_ALLOCSIZE; |
36 | stream->whole_target.winsizes_alloc = XD3_ALLOCSIZE; | ||
35 | 37 | ||
36 | if ((stream->whole_target.adds = (uint8_t*) | 38 | if ((stream->whole_target.adds = (uint8_t*) |
37 | xd3_alloc (stream, XD3_ALLOCSIZE, 1)) == NULL || | 39 | xd3_alloc (stream, stream->whole_target.adds_alloc, 1)) == NULL || |
38 | (stream->whole_target.inst = (xd3_winst*) | 40 | (stream->whole_target.inst = (xd3_winst*) |
39 | xd3_alloc (stream, XD3_ALLOCSIZE, sizeof(xd3_winst))) == NULL) | 41 | xd3_alloc (stream, stream->whole_target.inst_alloc, 1)) == NULL || |
42 | (stream->whole_target.winsizes = (usize_t*) | ||
43 | xd3_alloc (stream, stream->whole_target.winsizes_alloc, 1)) == NULL) | ||
40 | { | 44 | { |
41 | return ENOMEM; | 45 | return ENOMEM; |
42 | } | 46 | } |
@@ -50,6 +54,7 @@ xd3_swap_whole_state (xd3_whole_state *a, | |||
50 | xd3_whole_state tmp; | 54 | xd3_whole_state tmp; |
51 | XD3_ASSERT (a->inst != NULL && a->adds != NULL); | 55 | XD3_ASSERT (a->inst != NULL && a->adds != NULL); |
52 | XD3_ASSERT (b->inst != NULL && b->adds != NULL); | 56 | XD3_ASSERT (b->inst != NULL && b->adds != NULL); |
57 | XD3_ASSERT (b->winsizes != NULL && b->winsizes != NULL); | ||
53 | memcpy (&tmp, a, sizeof (xd3_whole_state)); | 58 | memcpy (&tmp, a, sizeof (xd3_whole_state)); |
54 | memcpy (a, b, sizeof (xd3_whole_state)); | 59 | memcpy (a, b, sizeof (xd3_whole_state)); |
55 | memcpy (b, &tmp, sizeof (xd3_whole_state)); | 60 | memcpy (b, &tmp, sizeof (xd3_whole_state)); |
@@ -134,6 +139,27 @@ xd3_whole_alloc_adds (xd3_stream *stream, | |||
134 | } | 139 | } |
135 | 140 | ||
136 | static int | 141 | static int |
142 | xd3_whole_alloc_winsize (xd3_stream *stream, | ||
143 | usize_t **winsizep) | ||
144 | { | ||
145 | int ret; | ||
146 | |||
147 | if ((ret = xd3_realloc_buffer (stream, | ||
148 | stream->whole_target.winsizeslen, | ||
149 | sizeof (xd3_winst), | ||
150 | 1, | ||
151 | & stream->whole_target.winsizes_alloc, | ||
152 | (void**) & stream->whole_target.winsizes))) | ||
153 | { | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | *winsizep = &stream->whole_target.winsizes[stream->whole_target.winsizeslen++]; | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int | ||
137 | xd3_whole_append_inst (xd3_stream *stream, | 163 | xd3_whole_append_inst (xd3_stream *stream, |
138 | xd3_hinst *inst) | 164 | xd3_hinst *inst) |
139 | { | 165 | { |
@@ -197,8 +223,13 @@ int | |||
197 | xd3_whole_append_window (xd3_stream *stream) | 223 | xd3_whole_append_window (xd3_stream *stream) |
198 | { | 224 | { |
199 | int ret; | 225 | int ret; |
226 | usize_t *winsize; | ||
200 | 227 | ||
201 | stream->whole_target.windows += 1; | 228 | stream->whole_target.windows += 1; |
229 | |||
230 | if ((ret = xd3_whole_alloc_winsize (stream, &winsize))) { return ret; } | ||
231 | |||
232 | *winsize = stream->dec_tgtlen; | ||
202 | 233 | ||
203 | while (stream->inst_sect.buf < stream->inst_sect.buf_max) | 234 | while (stream->inst_sect.buf < stream->inst_sect.buf_max) |
204 | { | 235 | { |
@@ -325,7 +356,6 @@ xd3_merge_target_copy (xd3_stream *stream, | |||
325 | } | 356 | } |
326 | 357 | ||
327 | XD3_ASSERT (stream->whole_target.length == iinst->position); | 358 | XD3_ASSERT (stream->whole_target.length == iinst->position); |
328 | stream->whole_target.length += iinst->size; | ||
329 | 359 | ||
330 | memcpy (oinst, iinst, sizeof (*oinst)); | 360 | memcpy (oinst, iinst, sizeof (*oinst)); |
331 | return 0; | 361 | return 0; |
@@ -381,7 +411,7 @@ xd3_merge_find_position (xd3_stream *stream, | |||
381 | static int | 411 | static int |
382 | xd3_merge_source_copy (xd3_stream *stream, | 412 | xd3_merge_source_copy (xd3_stream *stream, |
383 | xd3_whole_state *source, | 413 | xd3_whole_state *source, |
384 | xd3_winst *iinst_orig) | 414 | const xd3_winst *iinst_orig) |
385 | { | 415 | { |
386 | int ret; | 416 | int ret; |
387 | xd3_winst iinst; | 417 | xd3_winst iinst; |
@@ -455,12 +485,35 @@ xd3_merge_source_copy (xd3_stream *stream, | |||
455 | stream->whole_target.addslen += this_take; | 485 | stream->whole_target.addslen += this_take; |
456 | break; | 486 | break; |
457 | default: | 487 | default: |
458 | minst->mode = sinst->mode; | 488 | if (sinst->mode != 0) |
459 | minst->addr = sinst->addr + sinst_offset; | 489 | { |
490 | minst->mode = sinst->mode; | ||
491 | minst->addr = sinst->addr + sinst_offset; | ||
492 | } | ||
493 | else | ||
494 | { | ||
495 | // TODO: this is slow because of the recursion, which | ||
496 | // could reach a depth equal to the number of target | ||
497 | // copies, and this is compression-inefficient because | ||
498 | // it can produce duplicate adds. | ||
499 | xd3_winst tinst; | ||
500 | tinst.type = XD3_CPY; | ||
501 | tinst.mode = iinst.mode; | ||
502 | tinst.addr = sinst->addr + sinst_offset; | ||
503 | tinst.size = this_take; | ||
504 | tinst.position = iinst.position; | ||
505 | |||
506 | // The instruction allocated in this frame will not be used. | ||
507 | stream->whole_target.instlen -= 1; | ||
508 | |||
509 | if ((ret = xd3_merge_source_copy (stream, source, &tinst))) | ||
510 | { | ||
511 | return ret; | ||
512 | } | ||
513 | } | ||
460 | break; | 514 | break; |
461 | } | 515 | } |
462 | 516 | ||
463 | stream->whole_target.length += this_take; | ||
464 | iinst.position += this_take; | 517 | iinst.position += this_take; |
465 | iinst.addr += this_take; | 518 | iinst.addr += this_take; |
466 | iinst.size -= this_take; | 519 | iinst.size -= this_take; |
@@ -477,8 +530,17 @@ int xd3_merge_inputs (xd3_stream *stream, | |||
477 | xd3_whole_state *input) | 530 | xd3_whole_state *input) |
478 | { | 531 | { |
479 | int ret = 0; | 532 | int ret = 0; |
533 | usize_t i; | ||
480 | size_t input_i; | 534 | size_t input_i; |
481 | 535 | ||
536 | for (i = 0; i < input->winsizeslen; ++i) { | ||
537 | usize_t *copysize; | ||
538 | |||
539 | if ((ret = xd3_whole_alloc_winsize (stream, ©size))) { return ret; } | ||
540 | |||
541 | *copysize = input->winsizes[i]; | ||
542 | } | ||
543 | |||
482 | /* iterate over each instruction. */ | 544 | /* iterate over each instruction. */ |
483 | for (input_i = 0; ret == 0 && input_i < input->instlen; ++input_i) | 545 | for (input_i = 0; ret == 0 && input_i < input->instlen; ++input_i) |
484 | { | 546 | { |
@@ -493,7 +555,7 @@ int xd3_merge_inputs (xd3_stream *stream, | |||
493 | ret = xd3_merge_add (stream, input, iinst); | 555 | ret = xd3_merge_add (stream, input, iinst); |
494 | break; | 556 | break; |
495 | default: | 557 | default: |
496 | /* Note: VCD_TARGET support is completely untested all | 558 | /* TODO: VCD_TARGET support is completely untested all |
497 | * throughout. */ | 559 | * throughout. */ |
498 | if (iinst->mode == 0 || iinst->mode == VCD_TARGET) | 560 | if (iinst->mode == 0 || iinst->mode == VCD_TARGET) |
499 | { | 561 | { |
@@ -503,6 +565,10 @@ int xd3_merge_inputs (xd3_stream *stream, | |||
503 | { | 565 | { |
504 | ret = xd3_merge_source_copy (stream, source, iinst); | 566 | ret = xd3_merge_source_copy (stream, source, iinst); |
505 | } | 567 | } |
568 | |||
569 | /* The whole_target.length is not updated in the xd3_merge*copy | ||
570 | * routine because of recursion in xd3_merge_source_copy. */ | ||
571 | stream->whole_target.length += iinst->size; | ||
506 | break; | 572 | break; |
507 | } | 573 | } |
508 | } | 574 | } |
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index bdf02af..7921556 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -2295,6 +2295,7 @@ xd3_free_stream (xd3_stream *stream) | |||
2295 | 2295 | ||
2296 | xd3_free (stream, stream->whole_target.adds); | 2296 | xd3_free (stream, stream->whole_target.adds); |
2297 | xd3_free (stream, stream->whole_target.inst); | 2297 | xd3_free (stream, stream->whole_target.inst); |
2298 | xd3_free (stream, stream->whole_target.winsizes); | ||
2298 | 2299 | ||
2299 | XD3_ASSERT (stream->alloc_cnt == stream->free_cnt); | 2300 | XD3_ASSERT (stream->alloc_cnt == stream->free_cnt); |
2300 | 2301 | ||
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index fc3316a..1e6d4af 100644 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -643,9 +643,15 @@ struct _xd3_whole_state { | |||
643 | usize_t addslen; | 643 | usize_t addslen; |
644 | uint8_t *adds; | 644 | uint8_t *adds; |
645 | usize_t adds_alloc; | 645 | usize_t adds_alloc; |
646 | |||
646 | usize_t instlen; | 647 | usize_t instlen; |
647 | xd3_winst *inst; | 648 | xd3_winst *inst; |
648 | usize_t inst_alloc; | 649 | usize_t inst_alloc; |
650 | |||
651 | usize_t winsizeslen; | ||
652 | usize_t *winsizes; | ||
653 | usize_t winsizes_alloc; | ||
654 | |||
649 | xoff_t length; | 655 | xoff_t length; |
650 | xoff_t windows; | 656 | xoff_t windows; |
651 | }; | 657 | }; |