diff options
Diffstat (limited to 'xdelta3/xdelta3-merge.h')
-rw-r--r-- | xdelta3/xdelta3-merge.h | 84 |
1 files changed, 75 insertions, 9 deletions
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 | } |