summaryrefslogtreecommitdiff
path: root/xdelta3/xdelta3-merge.h
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3/xdelta3-merge.h')
-rw-r--r--xdelta3/xdelta3-merge.h84
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
136static int 141static int
142xd3_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
162static int
137xd3_whole_append_inst (xd3_stream *stream, 163xd3_whole_append_inst (xd3_stream *stream,
138 xd3_hinst *inst) 164 xd3_hinst *inst)
139{ 165{
@@ -197,8 +223,13 @@ int
197xd3_whole_append_window (xd3_stream *stream) 223xd3_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,
381static int 411static int
382xd3_merge_source_copy (xd3_stream *stream, 412xd3_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, &copysize))) { 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 }