summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/xdelta3-main.h6
-rw-r--r--xdelta3/xdelta3-merge.h284
-rw-r--r--xdelta3/xdelta3.h2
3 files changed, 272 insertions, 20 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 91c9884..51bd208 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -3519,6 +3519,12 @@ done:
3519 { 3519 {
3520 return EXIT_FAILURE; 3520 return EXIT_FAILURE;
3521 } 3521 }
3522
3523 if (cmd == CMD_MERGE_ARG)
3524 {
3525 xd3_swap_whole_state (& stream.whole_target,
3526 & recode_stream->whole_target);
3527 }
3522#endif /* VCDIFF_TOOLS */ 3528#endif /* VCDIFF_TOOLS */
3523 3529
3524 /* If output file is not open yet because of delayed-open, it means 3530 /* If output file is not open yet because of delayed-open, it means
diff --git a/xdelta3/xdelta3-merge.h b/xdelta3/xdelta3-merge.h
index a7b3329..d917ba5 100644
--- a/xdelta3/xdelta3-merge.h
+++ b/xdelta3/xdelta3-merge.h
@@ -28,6 +28,7 @@ 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.length == 0);
31 32
32 stream->whole_target.adds_alloc = XD3_ALLOCSIZE; 33 stream->whole_target.adds_alloc = XD3_ALLOCSIZE;
33 stream->whole_target.inst_alloc = XD3_ALLOCSIZE / sizeof (xd3_winst); 34 stream->whole_target.inst_alloc = XD3_ALLOCSIZE / sizeof (xd3_winst);
@@ -98,6 +99,40 @@ xd3_realloc_buffer (xd3_stream *stream,
98 return 0; 99 return 0;
99} 100}
100 101
102/* allocate one new output instruction */
103static int
104xd3_whole_alloc_winst (xd3_stream *stream,
105 xd3_winst **winstp)
106{
107 int ret;
108
109 if ((ret = xd3_realloc_buffer (stream,
110 stream->whole_target.instlen,
111 sizeof (xd3_winst),
112 1,
113 & stream->whole_target.inst_alloc,
114 (void**) & stream->whole_target.inst)))
115 {
116 return ret;
117 }
118
119 *winstp = &stream->whole_target.inst[stream->whole_target.instlen++];
120
121 return 0;
122}
123
124static int
125xd3_whole_alloc_adds (xd3_stream *stream,
126 usize_t count)
127{
128 return xd3_realloc_buffer (stream,
129 stream->whole_target.addslen,
130 1,
131 count,
132 & stream->whole_target.adds_alloc,
133 (void**) & stream->whole_target.adds);
134}
135
101static int 136static int
102xd3_whole_append_inst (xd3_stream *stream, 137xd3_whole_append_inst (xd3_stream *stream,
103 xd3_hinst *inst) 138 xd3_hinst *inst)
@@ -105,32 +140,24 @@ xd3_whole_append_inst (xd3_stream *stream,
105 int ret; 140 int ret;
106 xd3_winst *winst; 141 xd3_winst *winst;
107 142
108 if ((ret = xd3_realloc_buffer (stream, 143 if ((ret = xd3_whole_alloc_winst (stream, &winst)))
109 stream->whole_target.instlen,
110 sizeof (xd3_winst),
111 1,
112 & stream->whole_target.inst_alloc,
113 (void**) & stream->whole_target.inst)))
114 { 144 {
115 return ret; 145 return ret;
116 } 146 }
117 147
148 winst->type = inst->type;
149 winst->mode = 0;
150 winst->size = inst->size;
151 winst->position = stream->whole_target.length;
152 stream->whole_target.length += inst->size;
153
118 if ((inst->type <= XD3_ADD) && 154 if ((inst->type <= XD3_ADD) &&
119 (ret = xd3_realloc_buffer (stream, 155 (ret = xd3_whole_alloc_adds (stream,
120 stream->whole_target.addslen, 156 (inst->type == XD3_RUN ? 1 : inst->size))))
121 1,
122 (inst->type == XD3_RUN ? 1 : inst->size),
123 & stream->whole_target.adds_alloc,
124 (void**) & stream->whole_target.adds)))
125 { 157 {
126 return ret; 158 return ret;
127 } 159 }
128 160
129 winst = &stream->whole_target.inst[stream->whole_target.instlen++];
130 winst->type = inst->type;
131 winst->mode = 0;
132 winst->size = inst->size;
133
134 switch (inst->type) 161 switch (inst->type)
135 { 162 {
136 case XD3_RUN: 163 case XD3_RUN:
@@ -220,17 +247,234 @@ int xd3_merge_input_output (xd3_stream *stream,
220 return 0; 247 return 0;
221} 248}
222 249
250static int
251xd3_merge_run (xd3_stream *stream,
252 xd3_whole_state *source,
253 xd3_winst *iinst)
254{
255 int ret;
256 xd3_winst *oinst;
257
258 if ((ret = xd3_whole_alloc_winst (stream, &oinst)) ||
259 (ret = xd3_whole_alloc_adds (stream, 1)))
260 {
261 return ret;
262 }
263
264 oinst->type = iinst->type;
265 oinst->mode = iinst->mode;
266 oinst->size = iinst->size;
267 oinst->addr = stream->whole_target.addslen;
268
269 XD3_ASSERT (stream->whole_target.length == iinst->position);
270 oinst->position = stream->whole_target.length;
271 stream->whole_target.length += iinst->size;
272
273 stream->whole_target.adds[stream->whole_target.addslen++] =
274 source->adds[iinst->addr];
275
276 return 0;
277}
278
279static int
280xd3_merge_add (xd3_stream *stream,
281 xd3_whole_state *source,
282 xd3_winst *iinst)
283{
284 int ret;
285 xd3_winst *oinst;
286
287 if ((ret = xd3_whole_alloc_winst (stream, &oinst)) ||
288 (ret = xd3_whole_alloc_adds (stream, iinst->size)))
289 {
290 return ret;
291 }
292
293 oinst->type = iinst->type;
294 oinst->mode = iinst->mode;
295 oinst->size = iinst->size;
296 oinst->addr = stream->whole_target.addslen;
297
298 XD3_ASSERT (stream->whole_target.length == iinst->position);
299 oinst->position = stream->whole_target.length;
300 stream->whole_target.length += iinst->size;
301
302 memcpy(stream->whole_target.adds,
303 source->adds + iinst->addr,
304 stream->whole_target.addslen);
305
306 stream->whole_target.addslen += iinst->size;
307
308 return 0;
309}
310
311static int
312xd3_merge_target_copy (xd3_stream *stream,
313 xd3_winst *iinst)
314{
315 int ret;
316 xd3_winst *oinst;
317
318 if ((ret = xd3_whole_alloc_winst (stream, &oinst)))
319 {
320 return ret;
321 }
322
323 XD3_ASSERT (stream->whole_target.length == iinst->position);
324 stream->whole_target.length += iinst->size;
325
326 memcpy (oinst, iinst, sizeof (*oinst));
327 return 0;
328}
329
330static int
331xd3_merge_find_position (xd3_stream *stream,
332 xd3_whole_state *source,
333 xoff_t address,
334 usize_t *inst_num)
335{
336 usize_t low;
337 usize_t high;
338
339 if (address >= source->length)
340 {
341 stream->msg = "Invalid copy offset in merge";
342 return XD3_INVALID_INPUT;
343 }
344
345 low = 0;
346 high = source->instlen;
347
348 while (low != high)
349 {
350 xoff_t mid_lpos;
351 xoff_t mid_hpos;
352 usize_t mid = low + (high - low) / 2;
353 mid_lpos = source->inst[mid].position;
354
355 if (address < mid_lpos)
356 {
357 high = mid;
358 continue;
359 }
360
361 mid_hpos = mid_lpos + source->inst[mid].size;
362
363 if (address >= mid_hpos)
364 {
365 low = mid + 1;
366 continue;
367 }
368
369 *inst_num = mid;
370 return 0;
371 }
372
373 stream->msg = "Internal error in merge";
374 return XD3_INTERNAL;
375}
376
377static int
378xd3_merge_source_copy (xd3_stream *stream,
379 xd3_whole_state *source,
380 xd3_winst *iinst_orig)
381{
382 int ret;
383 xd3_winst iinst;
384 usize_t sinst_num;
385
386 memcpy (& iinst, iinst_orig, sizeof (iinst));
387
388 XD3_ASSERT (iinst.mode == VCD_SOURCE);
389
390 if ((ret = xd3_merge_find_position (stream, source,
391 iinst.addr, &sinst_num)))
392 {
393 return ret;
394 }
395
396 while (iinst.size > 0)
397 {
398 xd3_winst *sinst;
399 xd3_winst *minst;
400 usize_t sinst_offset;
401 usize_t sinst_left;
402 usize_t this_take;
403
404 XD3_ASSERT (sinst_num < source->instlen);
405
406 sinst = &source->inst[sinst_num];
407
408 XD3_ASSERT (sinst->position >= iinst.addr);
409
410 sinst_offset = sinst->position - iinst.addr;
411
412 XD3_ASSERT (sinst->size > (sinst->position - iinst.addr));
413
414 sinst_left = sinst->size - sinst_offset;
415 this_take = min (iinst.size, sinst_left);
416
417 XD3_ASSERT (this_take > 0);
418
419 if ((ret = xd3_whole_alloc_winst (stream, &minst)))
420 {
421 return ret;
422 }
423
424 minst->size = this_take;
425 minst->mode = VCD_SOURCE;
426 minst->type = XD3_CPY;
427 minst->addr = sinst->addr + sinst_offset;
428 minst->position = iinst.position;
429
430 stream->whole_target.length += this_take;
431 iinst.position += this_take;
432 iinst.addr += this_take;
433 iinst.size -= this_take;
434 sinst_num += 1;
435 }
436
437 return 0;
438}
439
223/* xd3_merge_inputs() applies *input to *source, returns its result in 440/* xd3_merge_inputs() applies *input to *source, returns its result in
224 * stream. In certain cases, input == stream->whole_target. */ 441 * stream. */
225int xd3_merge_inputs (xd3_stream *stream, 442int xd3_merge_inputs (xd3_stream *stream,
226 xd3_whole_state *source, 443 xd3_whole_state *source,
227 xd3_whole_state *input) 444 xd3_whole_state *input)
228{ 445{
446 int ret = 0;
447 int input_i;
229 448
449 /* iterate over each instruction. */
450 for (input_i = 0; ret == 0 && input_i < input->instlen; ++input_i)
451 {
452 xd3_winst *iinst = &input->inst[input_i];
230 453
231 xd3_swap_whole_state (&stream->whole_target, input); 454 switch (iinst->type)
455 {
456 case XD3_RUN:
457 ret = xd3_merge_run (stream, source, iinst);
458 break;
459 case XD3_ADD:
460 ret = xd3_merge_add (stream, source, iinst);
461 break;
462 default:
463 /* Note: VCD_TARGET support is completely untested all
464 * throughout. */
465 if (iinst->mode == 0 || iinst->mode == VCD_TARGET)
466 {
467 ret = xd3_merge_target_copy (stream, iinst);
468 }
469 else
470 {
471 ret = xd3_merge_source_copy (stream, source, iinst);
472 }
473 break;
474 }
475 }
232 476
233 return 0; 477 return ret;
234} 478}
235 479
236#endif 480#endif
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index d77649f..f8eee7a 100644
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -562,6 +562,7 @@ struct _xd3_winst
562 uint8_t mode; /* 0, VCD_SOURCE, VCD_TARGET */ 562 uint8_t mode; /* 0, VCD_SOURCE, VCD_TARGET */
563 usize_t size; 563 usize_t size;
564 xoff_t addr; 564 xoff_t addr;
565 xoff_t position; /* absolute position of this inst */
565}; 566};
566 567
567/* used by the encoder to buffer output in sections. list of blocks. */ 568/* used by the encoder to buffer output in sections. list of blocks. */
@@ -645,6 +646,7 @@ struct _xd3_whole_state {
645 usize_t instlen; 646 usize_t instlen;
646 xd3_winst *inst; 647 xd3_winst *inst;
647 usize_t inst_alloc; 648 usize_t inst_alloc;
649 xoff_t length;
648}; 650};
649 651
650/******************************************************************** 652/********************************************************************