diff options
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/Makefile | 26 | ||||
-rwxr-xr-x | xdelta3/examples/Makefile | 4 | ||||
-rw-r--r-- | xdelta3/xdelta3-decode.h | 181 | ||||
-rw-r--r-- | xdelta3/xdelta3-djw.h | 5 | ||||
-rw-r--r-- | xdelta3/xdelta3-main.h | 10 | ||||
-rw-r--r-- | xdelta3/xdelta3-test.h | 213 | ||||
-rw-r--r-- | xdelta3/xdelta3.c | 372 | ||||
-rw-r--r-- | xdelta3/xdelta3.h | 153 |
8 files changed, 576 insertions, 388 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile index 40647e8..10f5d33 100644 --- a/xdelta3/Makefile +++ b/xdelta3/Makefile | |||
@@ -125,12 +125,30 @@ xdelta3-32: $(SOURCES) | |||
125 | -DXD3_POSIX=1 | 125 | -DXD3_POSIX=1 |
126 | 126 | ||
127 | xdelta3-debug: $(SOURCES) | 127 | xdelta3-debug: $(SOURCES) |
128 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ | 128 | $(CC) -g -Wall -Wshadow \ |
129 | -DXD3_USE_LARGEFILE64=1 -DXD3_STDIO=1 -DREGRESSION_TEST=1 -DXD3_DEBUG=1 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -lm | 129 | xdelta3.c -o xdelta3-debug \ |
130 | -DXD3_DEBUG=1 \ | ||
131 | -DXD3_MAIN=1 \ | ||
132 | -DXD3_STDIO=1 \ | ||
133 | -DXD3_USE_LARGEFILE64=1 \ | ||
134 | -DGENERIC_ENCODE_TABLES=1 \ | ||
135 | -DREGRESSION_TEST=1 \ | ||
136 | -DSECONDARY_DJW=1 \ | ||
137 | -DSECONDARY_FGK=1 \ | ||
138 | -lm | ||
130 | 139 | ||
131 | xdelta3-debug2: $(SOURCES) | 140 | xdelta3-debug2: $(SOURCES) |
132 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug2 -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ | 141 | $(CC) -g -Wall -Wshadow \ |
133 | -DXD3_USE_LARGEFILE64=1 -DXD3_STDIO=1 -DREGRESSION_TEST=1 -DXD3_DEBUG=2 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -lm | 142 | xdelta3.c -o xdelta3-debug2 \ |
143 | -DXD3_DEBUG=2 \ | ||
144 | -DXD3_MAIN=1 \ | ||
145 | -DXD3_STDIO=1 \ | ||
146 | -DXD3_USE_LARGEFILE64=1 \ | ||
147 | -DGENERIC_ENCODE_TABLES=1 \ | ||
148 | -DREGRESSION_TEST=1 \ | ||
149 | -DSECONDARY_DJW=1 \ | ||
150 | -DSECONDARY_FGK=1 \ | ||
151 | -lm | ||
134 | 152 | ||
135 | xdelta3-debug3: $(SOURCES) | 153 | xdelta3-debug3: $(SOURCES) |
136 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug3 -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ | 154 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug3 -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ |
diff --git a/xdelta3/examples/Makefile b/xdelta3/examples/Makefile index 2a6c966..d171a80 100755 --- a/xdelta3/examples/Makefile +++ b/xdelta3/examples/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | #CFLAGS = -g -Wall -I.. -DXD3_DEBUG=1 | 1 | #CFLAGS = -g -Wall -I.. |
2 | # -DXD3_DEBUG=1 | ||
2 | CFLAGS = -O3 -pg -Wall -I.. -DXD3_DEBUG=0 | 3 | CFLAGS = -O3 -pg -Wall -I.. -DXD3_DEBUG=0 |
4 | # -pg | ||
3 | 5 | ||
4 | SOURCES = small_page_test.c encode_decode_test.c speed_test.c | 6 | SOURCES = small_page_test.c encode_decode_test.c speed_test.c |
5 | 7 | ||
diff --git a/xdelta3/xdelta3-decode.h b/xdelta3/xdelta3-decode.h index bb03c04..5ddf823 100644 --- a/xdelta3/xdelta3-decode.h +++ b/xdelta3/xdelta3-decode.h | |||
@@ -20,19 +20,21 @@ | |||
20 | #define _XDELTA3_DECODE_H_ | 20 | #define _XDELTA3_DECODE_H_ |
21 | 21 | ||
22 | 22 | ||
23 | /* Return true if the caller must provide a source. Theoretically, this has to be checked | 23 | /* Return true if the caller must provide a source. Theoretically, |
24 | * after every window. It could be that the first window requires no source, but the | 24 | * this has to be checked after every window. It could be that the |
25 | * second window does. In practice? */ | 25 | * first window requires no source, but the second window does. In |
26 | * practice? */ | ||
26 | int xd3_decoder_needs_source (xd3_stream *stream) | 27 | int xd3_decoder_needs_source (xd3_stream *stream) |
27 | { | 28 | { |
28 | return stream->dec_win_ind & VCD_SOURCE; | 29 | return stream->dec_win_ind & VCD_SOURCE; |
29 | } | 30 | } |
30 | 31 | ||
31 | /* Initialize the decoder for a new window. The dec_tgtlen value is preserved across | 32 | /* Initialize the decoder for a new window. The dec_tgtlen value is |
32 | * successive window decodings, and the update to dec_winstart is delayed until a new | 33 | * preserved across successive window decodings, and the update to |
33 | * window actually starts. This is to avoid throwing an error due to overflow until the | 34 | * dec_winstart is delayed until a new window actually starts. This |
34 | * last possible moment. This makes it possible to encode exactly 4GB through a 32-bit | 35 | * is to avoid throwing an error due to overflow until the last |
35 | * encoder. */ | 36 | * possible moment. This makes it possible to encode exactly 4GB |
37 | * through a 32-bit encoder. */ | ||
36 | static int | 38 | static int |
37 | xd3_decode_init_window (xd3_stream *stream) | 39 | xd3_decode_init_window (xd3_stream *stream) |
38 | { | 40 | { |
@@ -45,25 +47,28 @@ xd3_decode_init_window (xd3_stream *stream) | |||
45 | return 0; | 47 | return 0; |
46 | } | 48 | } |
47 | 49 | ||
48 | /* Allocates buffer space for the target window and possibly the VCD_TARGET copy-window. | 50 | /* Allocates buffer space for the target window and possibly the |
49 | * Also sets the base of the two copy segments. */ | 51 | * VCD_TARGET copy-window. Also sets the base of the two copy |
52 | * segments. */ | ||
50 | static int | 53 | static int |
51 | xd3_decode_setup_buffers (xd3_stream *stream) | 54 | xd3_decode_setup_buffers (xd3_stream *stream) |
52 | { | 55 | { |
53 | /* If VCD_TARGET is set then the previous buffer may be reused. */ | 56 | /* If VCD_TARGET is set then the previous buffer may be reused. */ |
54 | if (stream->dec_win_ind & VCD_TARGET) | 57 | if (stream->dec_win_ind & VCD_TARGET) |
55 | { | 58 | { |
56 | /* But this implementation only supports copying from the last target window. If the | 59 | /* But this implementation only supports copying from the last |
57 | * offset is outside that range, it can't be done. */ | 60 | * target window. If the offset is outside that range, it can't |
61 | * be done. */ | ||
58 | if (stream->dec_cpyoff < stream->dec_laststart) | 62 | if (stream->dec_cpyoff < stream->dec_laststart) |
59 | { | 63 | { |
60 | stream->msg = "unsupported VCD_TARGET offset"; | 64 | stream->msg = "unsupported VCD_TARGET offset"; |
61 | return XD3_INVALID_INPUT; | 65 | return XD3_INVALID_INPUT; |
62 | } | 66 | } |
63 | 67 | ||
64 | /* See if the two windows are the same. This indicates the first time VCD_TARGET is | 68 | /* See if the two windows are the same. This indicates the |
65 | * used. This causes a second buffer to be allocated, after that the two are | 69 | * first time VCD_TARGET is used. This causes a second buffer |
66 | * swapped in the DEC_FINISH case. */ | 70 | * to be allocated, after that the two are swapped in the |
71 | * DEC_FINISH case. */ | ||
67 | if (stream->dec_lastwin == stream->next_out) | 72 | if (stream->dec_lastwin == stream->next_out) |
68 | { | 73 | { |
69 | stream->next_out = NULL; | 74 | stream->next_out = NULL; |
@@ -88,9 +93,10 @@ xd3_decode_setup_buffers (xd3_stream *stream) | |||
88 | stream->next_out = stream->dec_buffer; | 93 | stream->next_out = stream->dec_buffer; |
89 | } | 94 | } |
90 | 95 | ||
91 | /* dec_tgtaddrbase refers to an invalid base address, but it is always used with a | 96 | /* dec_tgtaddrbase refers to an invalid base address, but it is |
92 | * sufficiently large instruction offset (i.e., beyond the copy window). This condition | 97 | * always used with a sufficiently large instruction offset (i.e., |
93 | * is enforced by xd3_decode_output_halfinst. */ | 98 | * beyond the copy window). This condition is enforced by |
99 | * xd3_decode_output_halfinst. */ | ||
94 | stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; | 100 | stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; |
95 | 101 | ||
96 | return 0; | 102 | return 0; |
@@ -190,9 +196,10 @@ xd3_decode_section (xd3_stream *stream, | |||
190 | return 0; | 196 | return 0; |
191 | } | 197 | } |
192 | 198 | ||
193 | /* Decode the size and address for half of an instruction (i.e., a single opcode). This | 199 | /* Decode the size and address for half of an instruction (i.e., a |
194 | * updates the stream->dec_position, which are bytes already output prior to processing | 200 | * single opcode). This updates the stream->dec_position, which are |
195 | * this instruction. Perform bounds checking for sizes and copy addresses, which uses the | 201 | * bytes already output prior to processing this instruction. Perform |
202 | * bounds checking for sizes and copy addresses, which uses the | ||
196 | * dec_position (which is why these checks are done here). */ | 203 | * dec_position (which is why these checks are done here). */ |
197 | static int | 204 | static int |
198 | xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) | 205 | xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) |
@@ -303,9 +310,10 @@ xd3_decode_instruction (xd3_stream *stream) | |||
303 | stream->dec_current1.size = inst->size1; | 310 | stream->dec_current1.size = inst->size1; |
304 | stream->dec_current2.size = inst->size2; | 311 | stream->dec_current2.size = inst->size2; |
305 | 312 | ||
306 | /* For each instruction with a real operation, decode the corresponding size and | 313 | /* For each instruction with a real operation, decode the |
307 | * addresses if necessary. Assume a code-table may have NOOP in either position, | 314 | * corresponding size and addresses if necessary. Assume a |
308 | * although this is unlikely. */ | 315 | * code-table may have NOOP in either position, although this is |
316 | * unlikely. */ | ||
309 | if (inst->type1 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) | 317 | if (inst->type1 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) |
310 | { | 318 | { |
311 | return ret; | 319 | return ret; |
@@ -317,11 +325,13 @@ xd3_decode_instruction (xd3_stream *stream) | |||
317 | return 0; | 325 | return 0; |
318 | } | 326 | } |
319 | 327 | ||
320 | /* Output the result of a single half-instruction. OPT: This the decoder hotspot. */ | 328 | /* Output the result of a single half-instruction. OPT: This the |
329 | decoder hotspot. */ | ||
321 | static int | 330 | static int |
322 | xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | 331 | xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) |
323 | { | 332 | { |
324 | /* To make this reentrant, set take = min (inst->size, available space)... */ | 333 | /* To make this reentrant, set take = min (inst->size, available |
334 | space)... */ | ||
325 | usize_t take = inst->size; | 335 | usize_t take = inst->size; |
326 | 336 | ||
327 | XD3_ASSERT (inst->type != XD3_NOOP); | 337 | XD3_ASSERT (inst->type != XD3_NOOP); |
@@ -370,14 +380,15 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
370 | const uint8_t *src; | 380 | const uint8_t *src; |
371 | uint8_t *dst; | 381 | uint8_t *dst; |
372 | 382 | ||
373 | /* See if it copies from the VCD_TARGET/VCD_SOURCE window or the target window. | 383 | /* See if it copies from the VCD_TARGET/VCD_SOURCE window or |
374 | * Out-of-bounds checks for the addresses and sizes are performed in | 384 | * the target window. Out-of-bounds checks for the addresses |
375 | * xd3_decode_parse_halfinst. */ | 385 | * and sizes are performed in xd3_decode_parse_halfinst. */ |
376 | if (inst->addr < stream->dec_cpylen) | 386 | if (inst->addr < stream->dec_cpylen) |
377 | { | 387 | { |
378 | if (stream->dec_win_ind & VCD_TARGET) | 388 | if (stream->dec_win_ind & VCD_TARGET) |
379 | { | 389 | { |
380 | /* For VCD_TARGET we know the entire range is in-memory, as established by | 390 | /* For VCD_TARGET we know the entire range is |
391 | * in-memory, as established by | ||
381 | * decode_setup_buffers. */ | 392 | * decode_setup_buffers. */ |
382 | src = stream->dec_cpyaddrbase + inst->addr; | 393 | src = stream->dec_cpyaddrbase + inst->addr; |
383 | inst->type = XD3_NOOP; | 394 | inst->type = XD3_NOOP; |
@@ -385,8 +396,9 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
385 | } | 396 | } |
386 | else | 397 | else |
387 | { | 398 | { |
388 | /* In this case we have to read a source block, which could return control | 399 | /* In this case we have to read a source block, which |
389 | * to the caller. We need to know the first block number needed for this | 400 | * could return control to the caller. We need to |
401 | * know the first block number needed for this | ||
390 | * copy. */ | 402 | * copy. */ |
391 | xd3_source *source; | 403 | xd3_source *source; |
392 | xoff_t block; | 404 | xoff_t block; |
@@ -419,8 +431,8 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
419 | 431 | ||
420 | src = source->curblk + blkoff; | 432 | src = source->curblk + blkoff; |
421 | 433 | ||
422 | /* This block either contains enough data or the source file is | 434 | /* This block either contains enough data or the |
423 | * short. */ | 435 | * source file is short. */ |
424 | if ((source->onblk != blksize) && (blkoff + take > source->onblk)) | 436 | if ((source->onblk != blksize) && (blkoff + take > source->onblk)) |
425 | { | 437 | { |
426 | stream->msg = "source file too short"; | 438 | stream->msg = "source file too short"; |
@@ -437,8 +449,8 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
437 | } | 449 | } |
438 | else | 450 | else |
439 | { | 451 | { |
440 | /* This block doesn't contain all the data, modify the instruction, do | 452 | /* This block doesn't contain all the data, modify |
441 | * not set to XD3_NOOP. */ | 453 | * the instruction, do not set to XD3_NOOP. */ |
442 | take = blksize - blkoff; | 454 | take = blksize - blkoff; |
443 | inst->size -= take; | 455 | inst->size -= take; |
444 | inst->addr += take; | 456 | inst->addr += take; |
@@ -447,9 +459,10 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) | |||
447 | } | 459 | } |
448 | else | 460 | else |
449 | { | 461 | { |
450 | /* For a target-window copy, we know the entire range is in-memory. The | 462 | /* For a target-window copy, we know the entire range is |
451 | * dec_tgtaddrbase is negatively offset by dec_cpylen because the addresses | 463 | * in-memory. The dec_tgtaddrbase is negatively offset by |
452 | * start beyond that point. */ | 464 | * dec_cpylen because the addresses start beyond that |
465 | * point. */ | ||
453 | src = stream->dec_tgtaddrbase + inst->addr; | 466 | src = stream->dec_tgtaddrbase + inst->addr; |
454 | inst->type = XD3_NOOP; | 467 | inst->type = XD3_NOOP; |
455 | inst->size = 0; | 468 | inst->size = 0; |
@@ -587,9 +600,10 @@ xd3_decode_sections (xd3_stream *stream) | |||
587 | return xd3_decode_finish_window (stream); | 600 | return xd3_decode_finish_window (stream); |
588 | } | 601 | } |
589 | 602 | ||
590 | /* OPT: A possible optimization is to avoid allocating memory in decode_setup_buffers | 603 | /* OPT: A possible optimization is to avoid allocating memory in |
591 | * and to avoid a large memcpy when the window consists of a single VCD_SOURCE copy | 604 | * decode_setup_buffers and to avoid a large memcpy when the window |
592 | * instruction. The only potential problem is if the following window is a VCD_TARGET, | 605 | * consists of a single VCD_SOURCE copy instruction. The only |
606 | * potential problem is if the following window is a VCD_TARGET, | ||
593 | * then you need to remember... */ | 607 | * then you need to remember... */ |
594 | if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } | 608 | if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } |
595 | 609 | ||
@@ -601,14 +615,16 @@ xd3_decode_emit (xd3_stream *stream) | |||
601 | { | 615 | { |
602 | int ret; | 616 | int ret; |
603 | 617 | ||
604 | /* Produce output: originally structured to allow reentrant code that fills as much of | 618 | /* Produce output: originally structured to allow reentrant code |
605 | * the output buffer as possible, but VCDIFF semantics allows to copy from anywhere from | 619 | * that fills as much of the output buffer as possible, but VCDIFF |
606 | * the target window, so instead allocate a sufficiently sized buffer after the target | 620 | * semantics allows to copy from anywhere from the target window, so |
621 | * instead allocate a sufficiently sized buffer after the target | ||
607 | * window length is decoded. | 622 | * window length is decoded. |
608 | * | 623 | * |
609 | * This code still needs to be reentrant to allow XD3_GETSRCBLK to return control. This | 624 | * This code still needs to be reentrant to allow XD3_GETSRCBLK to |
610 | * is handled by setting the stream->dec_currentN instruction types to XD3_NOOP after | 625 | * return control. This is handled by setting the |
611 | * they have been processed. */ | 626 | * stream->dec_currentN instruction types to XD3_NOOP after they |
627 | * have been processed. */ | ||
612 | XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); | 628 | XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); |
613 | XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); | 629 | XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); |
614 | 630 | ||
@@ -683,35 +699,39 @@ xd3_decode_input (xd3_stream *stream) | |||
683 | return XD3_INVALID_INPUT; | 699 | return XD3_INVALID_INPUT; |
684 | } | 700 | } |
685 | 701 | ||
686 | #define BYTE_CASE(expr,x,nstate) \ | 702 | #define BYTE_CASE(expr,x,nstate) \ |
687 | do { \ | 703 | do { \ |
688 | if ( (expr) && \ | 704 | if ( (expr) && \ |
689 | ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ | 705 | ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ |
690 | stream->dec_state = (nstate); \ | 706 | stream->dec_state = (nstate); \ |
691 | } while (0) | 707 | } while (0) |
692 | 708 | ||
693 | #define OFFSET_CASE(expr,x,nstate) \ | 709 | #define OFFSET_CASE(expr,x,nstate) \ |
694 | do { \ | 710 | do { \ |
695 | if ( (expr) && \ | 711 | if ( (expr) && \ |
696 | ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ | 712 | ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ |
697 | stream->dec_state = (nstate); \ | 713 | stream->dec_state = (nstate); \ |
698 | } while (0) | 714 | } while (0) |
699 | 715 | ||
700 | #define SIZE_CASE(expr,x,nstate) \ | 716 | #define SIZE_CASE(expr,x,nstate) \ |
701 | do { \ | 717 | do { \ |
702 | if ( (expr) && \ | 718 | if ( (expr) && \ |
703 | ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ | 719 | ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ |
704 | stream->dec_state = (nstate); \ | 720 | stream->dec_state = (nstate); \ |
705 | } while (0) | 721 | } while (0) |
706 | 722 | ||
707 | #define SRCORTGT(x) (((x) & VCD_SRCORTGT) == VCD_SOURCE || \ | 723 | #define SRCORTGT(x) (((x) & VCD_SRCORTGT) == VCD_SOURCE || \ |
708 | ((x) & VCD_SRCORTGT) == VCD_TARGET) | 724 | ((x) & VCD_SRCORTGT) == VCD_TARGET) |
709 | 725 | ||
710 | switch (stream->dec_state) | 726 | switch (stream->dec_state) |
711 | { | 727 | { |
712 | case DEC_VCHEAD: | 728 | case DEC_VCHEAD: |
713 | { | 729 | { |
714 | if ((ret = xd3_decode_bytes (stream, stream->dec_magic, & stream->dec_magicbytes, 4))) { return ret; } | 730 | if ((ret = xd3_decode_bytes (stream, stream->dec_magic, |
731 | & stream->dec_magicbytes, 4))) | ||
732 | { | ||
733 | return ret; | ||
734 | } | ||
715 | 735 | ||
716 | if (stream->dec_magic[0] != VCDIFF_MAGIC1 || | 736 | if (stream->dec_magic[0] != VCDIFF_MAGIC1 || |
717 | stream->dec_magic[1] != VCDIFF_MAGIC2 || | 737 | stream->dec_magic[1] != VCDIFF_MAGIC2 || |
@@ -817,7 +837,8 @@ xd3_decode_input (xd3_stream *stream) | |||
817 | /* Application data */ | 837 | /* Application data */ |
818 | if (stream->dec_hdr_ind & VCD_APPHEADER) | 838 | if (stream->dec_hdr_ind & VCD_APPHEADER) |
819 | { | 839 | { |
820 | /* Note: we add an additional byte for padding, to allow 0-termination. */ | 840 | /* Note: we add an additional byte for padding, to allow |
841 | 0-termination. */ | ||
821 | if ((stream->dec_appheader == NULL) && | 842 | if ((stream->dec_appheader == NULL) && |
822 | (stream->dec_appheader = xd3_alloc (stream, stream->dec_appheadsz+1, 1)) == NULL) { return ENOMEM; } | 843 | (stream->dec_appheader = xd3_alloc (stream, stream->dec_appheadsz+1, 1)) == NULL) { return ENOMEM; } |
823 | 844 | ||
@@ -865,9 +886,10 @@ xd3_decode_input (xd3_stream *stream) | |||
865 | /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ | 886 | /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ |
866 | SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, DEC_CPYOFF); | 887 | SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, DEC_CPYOFF); |
867 | 888 | ||
868 | /* Set the initial, logical decoder position (HERE address) in dec_position. This | 889 | /* Set the initial, logical decoder position (HERE address) in |
869 | * is set to just after the source/copy window, as we are just about to output the | 890 | * dec_position. This is set to just after the source/copy |
870 | * first byte of target window. */ | 891 | * window, as we are just about to output the first byte of |
892 | * target window. */ | ||
871 | stream->dec_position = stream->dec_cpylen; | 893 | stream->dec_position = stream->dec_cpylen; |
872 | 894 | ||
873 | case DEC_CPYOFF: | 895 | case DEC_CPYOFF: |
@@ -881,7 +903,8 @@ xd3_decode_input (xd3_stream *stream) | |||
881 | return XD3_INVALID_INPUT; | 903 | return XD3_INVALID_INPUT; |
882 | } | 904 | } |
883 | 905 | ||
884 | /* Check copy window bounds: VCD_TARGET window may not exceed current position. */ | 906 | /* Check copy window bounds: VCD_TARGET window may not exceed |
907 | current position. */ | ||
885 | if ((stream->dec_win_ind & VCD_TARGET) && | 908 | if ((stream->dec_win_ind & VCD_TARGET) && |
886 | (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > stream->dec_winstart)) | 909 | (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > stream->dec_winstart)) |
887 | { | 910 | { |
@@ -896,9 +919,9 @@ xd3_decode_input (xd3_stream *stream) | |||
896 | /* Length of target window */ | 919 | /* Length of target window */ |
897 | SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); | 920 | SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); |
898 | 921 | ||
899 | /* Set the maximum decoder position, beyond which we should not decode any data. | 922 | /* Set the maximum decoder position, beyond which we should not |
900 | * This is the maximum value for dec_position. This may not exceed the size of a | 923 | * decode any data. This is the maximum value for dec_position. |
901 | * usize_t. */ | 924 | * This may not exceed the size of a usize_t. */ |
902 | if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) | 925 | if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) |
903 | { | 926 | { |
904 | stream->msg = "decoder target window overflows a usize_t"; | 927 | stream->msg = "decoder target window overflows a usize_t"; |
@@ -973,8 +996,8 @@ xd3_decode_input (xd3_stream *stream) | |||
973 | } | 996 | } |
974 | } | 997 | } |
975 | 998 | ||
976 | /* Returning here gives the application a chance to inspect the header, skip the | 999 | /* Returning here gives the application a chance to inspect the |
977 | * window, etc. */ | 1000 | * header, skip the window, etc. */ |
978 | if (stream->current_window == 0) { return XD3_GOTHEADER; } | 1001 | if (stream->current_window == 0) { return XD3_GOTHEADER; } |
979 | else { return XD3_WINSTART; } | 1002 | else { return XD3_WINSTART; } |
980 | 1003 | ||
@@ -986,8 +1009,8 @@ xd3_decode_input (xd3_stream *stream) | |||
986 | 1009 | ||
987 | case DEC_EMIT: | 1010 | case DEC_EMIT: |
988 | 1011 | ||
989 | /* To speed VCD_SOURCE block-address calculations, the source cpyoff_blocks and | 1012 | /* To speed VCD_SOURCE block-address calculations, the source |
990 | * cpyoff_blkoff are pre-computed. */ | 1013 | * cpyoff_blocks and cpyoff_blkoff are pre-computed. */ |
991 | if (stream->dec_win_ind & VCD_SOURCE) | 1014 | if (stream->dec_win_ind & VCD_SOURCE) |
992 | { | 1015 | { |
993 | xd3_source *src = stream->src; | 1016 | xd3_source *src = stream->src; |
@@ -1030,8 +1053,8 @@ xd3_decode_input (xd3_stream *stream) | |||
1030 | stream->dec_laststart = stream->dec_winstart; | 1053 | stream->dec_laststart = stream->dec_winstart; |
1031 | stream->dec_window_count += 1; | 1054 | stream->dec_window_count += 1; |
1032 | 1055 | ||
1033 | /* Note: the updates to dec_winstart & current_window are deferred until after the | 1056 | /* Note: the updates to dec_winstart & current_window are |
1034 | * next DEC_WININD byte is read. */ | 1057 | * deferred until after the next DEC_WININD byte is read. */ |
1035 | stream->dec_state = DEC_WININD; | 1058 | stream->dec_state = DEC_WININD; |
1036 | return XD3_WINFINISH; | 1059 | return XD3_WINFINISH; |
1037 | } | 1060 | } |
diff --git a/xdelta3/xdelta3-djw.h b/xdelta3/xdelta3-djw.h index a9f6e6f..2623e63 100644 --- a/xdelta3/xdelta3-djw.h +++ b/xdelta3/xdelta3-djw.h | |||
@@ -601,7 +601,10 @@ djw_count_freqs (djw_weight *freq, xd3_output *input) | |||
601 | 601 | ||
602 | IF_DEBUG1 ({int i; | 602 | IF_DEBUG1 ({int i; |
603 | DP(RINT "freqs: "); | 603 | DP(RINT "freqs: "); |
604 | for (i = 0; i < ALPHABET_SIZE; i += 1) { DP(RINT "%u ", freq[i]); } | 604 | for (i = 0; i < ALPHABET_SIZE; i += 1) |
605 | { | ||
606 | DP(RINT "%u ", freq[i]); | ||
607 | } | ||
605 | DP(RINT "\n");}); | 608 | DP(RINT "\n");}); |
606 | 609 | ||
607 | return size; | 610 | return size; |
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index 4d642df..bb06a13 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -555,10 +555,10 @@ main_format_bcnt (xoff_t r, char *buf) | |||
555 | for (i = 0; i < SIZEOF_ARRAY(fmts); i += 1) | 555 | for (i = 0; i < SIZEOF_ARRAY(fmts); i += 1) |
556 | { | 556 | { |
557 | if (r <= (10 * 1024) || i == (-1 + (int)SIZEOF_ARRAY(fmts))) | 557 | if (r <= (10 * 1024) || i == (-1 + (int)SIZEOF_ARRAY(fmts))) |
558 | { | 558 | { |
559 | sprintf (buf, "%"Q"u %s", r, fmts[i]); | 559 | sprintf (buf, "%"Q"u %s", r, fmts[i]); |
560 | break; | 560 | break; |
561 | } | 561 | } |
562 | r /= 1024; | 562 | r /= 1024; |
563 | } | 563 | } |
564 | return buf; | 564 | return buf; |
@@ -2436,7 +2436,7 @@ main_getblk_func (xd3_stream *stream, | |||
2436 | xoff_t pos = blkno * source->blksize; | 2436 | xoff_t pos = blkno * source->blksize; |
2437 | main_file *sfile = (main_file*) source->ioh; | 2437 | main_file *sfile = (main_file*) source->ioh; |
2438 | main_blklru *blru = NULL; | 2438 | main_blklru *blru = NULL; |
2439 | usize_t onblk = xd3_bytes_on_srcblk (source, blkno); | 2439 | usize_t onblk = xd3_bytes_on_srcblk_fast (source, blkno); |
2440 | usize_t nread; | 2440 | usize_t nread; |
2441 | int ret; | 2441 | int ret; |
2442 | int i; | 2442 | int i; |
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h index 0739e2d..a2d762a 100644 --- a/xdelta3/xdelta3-test.h +++ b/xdelta3/xdelta3-test.h | |||
@@ -49,12 +49,13 @@ static int test_exponential_dist (usize_t mean, usize_t max); | |||
49 | 49 | ||
50 | #define CHECK(cond) if (!(cond)) { DP(RINT "check failure: " #cond); abort(); } | 50 | #define CHECK(cond) if (!(cond)) { DP(RINT "check failure: " #cond); abort(); } |
51 | 51 | ||
52 | /* Use a fixed soft config so that test values are fixed. See also test_compress_text(). */ | 52 | /* Use a fixed soft config so that test values are fixed. See also |
53 | test_compress_text(). */ | ||
53 | static const char* test_softcfg_str = "-C64,64,4,128,16,8,128"; | 54 | static const char* test_softcfg_str = "-C64,64,4,128,16,8,128"; |
54 | 55 | ||
55 | /****************************************************************************************** | 56 | /*********************************************************************** |
56 | TEST HELPERS | 57 | TEST HELPERS |
57 | ******************************************************************************************/ | 58 | ***********************************************************************/ |
58 | 59 | ||
59 | static void DOT (void) { DP(RINT "."); } | 60 | static void DOT (void) { DP(RINT "."); } |
60 | static int do_cmd (xd3_stream *stream, const char *buf) | 61 | static int do_cmd (xd3_stream *stream, const char *buf) |
@@ -193,9 +194,10 @@ test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) | |||
193 | goto failure; | 194 | goto failure; |
194 | } | 195 | } |
195 | 196 | ||
196 | /* Then modify the data to produce copies, everything not copied is an add. The | 197 | /* Then modify the data to produce copies, everything not copied is |
197 | * following logic produces the TEST_ADD_RATIO. The variable SADD contains the number | 198 | * an add. The following logic produces the TEST_ADD_RATIO. The |
198 | * of adds so far, which should not exceed SADD_MAX. */ | 199 | * variable SADD contains the number of adds so far, which should |
200 | * not exceed SADD_MAX. */ | ||
199 | for (i = 0; i < ss; ) | 201 | for (i = 0; i < ss; ) |
200 | { | 202 | { |
201 | usize_t left = ss - i; | 203 | usize_t left = ss - i; |
@@ -350,13 +352,14 @@ test_file_size (const char* file, xoff_t *size) | |||
350 | return 0; | 352 | return 0; |
351 | } | 353 | } |
352 | 354 | ||
353 | /****************************************************************************************** | 355 | /*********************************************************************** |
354 | READ OFFSET | 356 | READ OFFSET |
355 | ******************************************************************************************/ | 357 | ***********************************************************************/ |
356 | 358 | ||
357 | /* Common test for read_integer errors: encodes a 64-bit value and then attempts to read | 359 | /* Common test for read_integer errors: encodes a 64-bit value and |
358 | * as a 32-bit value. If TRUNC is non-zero, attempts to get errors by shortening the | 360 | * then attempts to read as a 32-bit value. If TRUNC is non-zero, |
359 | * input, otherwise it should overflow. Expects XD3_INTERNAL and MSG. */ | 361 | * attempts to get errors by shortening the input, otherwise it should |
362 | * overflow. Expects XD3_INTERNAL and MSG. */ | ||
360 | static int | 363 | static int |
361 | test_read_integer_error (xd3_stream *stream, int trunto, const char *msg) | 364 | test_read_integer_error (xd3_stream *stream, int trunto, const char *msg) |
362 | { | 365 | { |
@@ -538,9 +541,9 @@ test_usize_t_overflow (xd3_stream *stream, int unused) | |||
538 | return XD3_INTERNAL; | 541 | return XD3_INTERNAL; |
539 | } | 542 | } |
540 | 543 | ||
541 | /****************************************************************************************** | 544 | /*********************************************************************** |
542 | Address cache | 545 | Address cache |
543 | ******************************************************************************************/ | 546 | ***********************************************************************/ |
544 | 547 | ||
545 | static int | 548 | static int |
546 | test_address_cache (xd3_stream *stream, int unused) | 549 | test_address_cache (xd3_stream *stream, int unused) |
@@ -644,9 +647,9 @@ test_address_cache (xd3_stream *stream, int unused) | |||
644 | return 0; | 647 | return 0; |
645 | } | 648 | } |
646 | 649 | ||
647 | /****************************************************************************************** | 650 | /*********************************************************************** |
648 | Encode and decode with single bit error | 651 | Encode and decode with single bit error |
649 | ******************************************************************************************/ | 652 | ***********************************************************************/ |
650 | 653 | ||
651 | /* It compresses from 256 to around 185 bytes. | 654 | /* It compresses from 256 to around 185 bytes. |
652 | * Avoids matching addresses that are a single-bit difference. | 655 | * Avoids matching addresses that are a single-bit difference. |
@@ -814,9 +817,10 @@ test_decompress_single_bit_error (xd3_stream *stream, int expected_non_failures) | |||
814 | #if 1 | 817 | #if 1 |
815 | #define TEST_FAILURES() | 818 | #define TEST_FAILURES() |
816 | #else | 819 | #else |
817 | /* For checking non-failure cases by hand, enable this macro and run xdelta printdelta | 820 | /* For checking non-failure cases by hand, enable this macro and run |
818 | * with print_cpymode enabled. Every non-failure should change a copy address mode, | 821 | * xdelta printdelta with print_cpymode enabled. Every non-failure |
819 | * which doesn't cause a failure because the address cache starts out with all zeros. | 822 | * should change a copy address mode, which doesn't cause a failure |
823 | * because the address cache starts out with all zeros. | ||
820 | 824 | ||
821 | ./xdelta3 test | 825 | ./xdelta3 test |
822 | for i in test_text.xz.*; do ./xdelta3 printdelta $i > $i.out; diff $i.out test_text.xz.0.out; done | 826 | for i in test_text.xz.*; do ./xdelta3 printdelta $i > $i.out; diff $i.out test_text.xz.0.out; done |
@@ -909,9 +913,9 @@ test_decompress_single_bit_error (xd3_stream *stream, int expected_non_failures) | |||
909 | return 0; | 913 | return 0; |
910 | } | 914 | } |
911 | 915 | ||
912 | /****************************************************************************************** | 916 | /*********************************************************************** |
913 | Secondary compression tests | 917 | Secondary compression tests |
914 | ******************************************************************************************/ | 918 | ***********************************************************************/ |
915 | 919 | ||
916 | #if SECONDARY_ANY | 920 | #if SECONDARY_ANY |
917 | typedef int (*sec_dist_func) (xd3_stream *stream, xd3_output *data); | 921 | typedef int (*sec_dist_func) (xd3_stream *stream, xd3_output *data); |
@@ -1031,8 +1035,8 @@ sec_dist_func7 (xd3_stream *stream, xd3_output *data) | |||
1031 | return 0; | 1035 | return 0; |
1032 | } | 1036 | } |
1033 | 1037 | ||
1034 | /* Test distribution: A small number of frequent characters, difficult to divide into many | 1038 | /* Test distribution: A small number of frequent characters, difficult |
1035 | * groups */ | 1039 | * to divide into many groups */ |
1036 | static int | 1040 | static int |
1037 | sec_dist_func8 (xd3_stream *stream, xd3_output *data) | 1041 | sec_dist_func8 (xd3_stream *stream, xd3_output *data) |
1038 | { | 1042 | { |
@@ -1058,9 +1062,9 @@ sec_dist_func9 (xd3_stream *stream, xd3_output *data) | |||
1058 | int prom = 0; | 1062 | int prom = 0; |
1059 | int pcount = 0; | 1063 | int pcount = 0; |
1060 | 1064 | ||
1061 | /* 200 was long enough to trigger it--only when stricter checking that counted all | 1065 | /* 200 was long enough to trigger it--only when stricter checking |
1062 | * blocks was turned on, but it seems I deleted this code. (missing fgk_free_block on | 1066 | * that counted all blocks was turned on, but it seems I deleted |
1063 | * line 398). */ | 1067 | * this code. (missing fgk_free_block on line 398). */ |
1064 | for (i = 0; i < ALPHABET_SIZE*200; i += 1) | 1068 | for (i = 0; i < ALPHABET_SIZE*200; i += 1) |
1065 | { | 1069 | { |
1066 | repeat: | 1070 | repeat: |
@@ -1259,9 +1263,10 @@ test_secondary (xd3_stream *stream, const xd3_sec_type *sec, int groups) | |||
1259 | goto fail; | 1263 | goto fail; |
1260 | } | 1264 | } |
1261 | 1265 | ||
1262 | /* Single-bit error test, only cover the first 10 bytes. Some non-failures are | 1266 | /* Single-bit error test, only cover the first 10 bytes. |
1263 | * expected in the Huffman case: Changing the clclen array, for example, may not | 1267 | * Some non-failures are expected in the Huffman case: |
1264 | * harm the decoding. Really looking for faults here. */ | 1268 | * Changing the clclen array, for example, may not harm the |
1269 | * decoding. Really looking for faults here. */ | ||
1265 | { | 1270 | { |
1266 | int i; | 1271 | int i; |
1267 | int bytes = min (compress_size, 10U); | 1272 | int bytes = min (compress_size, 10U); |
@@ -1310,9 +1315,9 @@ IF_DJW (static int test_secondary_huff (xd3_stream *stream, int gp) | |||
1310 | { return test_secondary (stream, & djw_sec_type, gp); }) | 1315 | { return test_secondary (stream, & djw_sec_type, gp); }) |
1311 | #endif | 1316 | #endif |
1312 | 1317 | ||
1313 | /****************************************************************************************** | 1318 | /*********************************************************************** |
1314 | TEST INSTRUCTION TABLE | 1319 | TEST INSTRUCTION TABLE |
1315 | ******************************************************************************************/ | 1320 | ***********************************************************************/ |
1316 | 1321 | ||
1317 | /* Test that xd3_choose_instruction() does the right thing for its code table. */ | 1322 | /* Test that xd3_choose_instruction() does the right thing for its code table. */ |
1318 | static int | 1323 | static int |
@@ -1369,9 +1374,9 @@ test_choose_instruction (xd3_stream *stream, int ignore) | |||
1369 | return 0; | 1374 | return 0; |
1370 | } | 1375 | } |
1371 | 1376 | ||
1372 | /****************************************************************************************** | 1377 | /*********************************************************************** |
1373 | TEST INSTRUCTION TABLE CODING | 1378 | TEST INSTRUCTION TABLE CODING |
1374 | ******************************************************************************************/ | 1379 | ***********************************************************************/ |
1375 | 1380 | ||
1376 | #if GENERIC_ENCODE_TABLES | 1381 | #if GENERIC_ENCODE_TABLES |
1377 | /* Test that encoding and decoding a code table works */ | 1382 | /* Test that encoding and decoding a code table works */ |
@@ -1405,12 +1410,13 @@ test_encode_code_table (xd3_stream *stream, int ignore) | |||
1405 | } | 1410 | } |
1406 | #endif | 1411 | #endif |
1407 | 1412 | ||
1408 | /****************************************************************************************** | 1413 | /*********************************************************************** |
1409 | 64BIT STREAMING | 1414 | 64BIT STREAMING |
1410 | ******************************************************************************************/ | 1415 | ***********************************************************************/ |
1411 | 1416 | ||
1412 | /* This test encodes and decodes a series of 1 megabyte windows, each containing a long | 1417 | /* This test encodes and decodes a series of 1 megabyte windows, each |
1413 | * run of zeros along with a single xoff_t size record to indicate the sequence. */ | 1418 | * containing a long run of zeros along with a single xoff_t size |
1419 | * record to indicate the sequence. */ | ||
1414 | static int | 1420 | static int |
1415 | test_streaming (xd3_stream *in_stream, uint8_t *encbuf, uint8_t *decbuf, uint8_t *delbuf, usize_t megs) | 1421 | test_streaming (xd3_stream *in_stream, uint8_t *encbuf, uint8_t *decbuf, uint8_t *delbuf, usize_t megs) |
1416 | { | 1422 | { |
@@ -1503,14 +1509,16 @@ test_compressed_stream_overflow (xd3_stream *stream, int ignore) | |||
1503 | return ret; | 1509 | return ret; |
1504 | } | 1510 | } |
1505 | 1511 | ||
1506 | /****************************************************************************************** | 1512 | /*********************************************************************** |
1507 | COMMAND LINE | 1513 | COMMAND LINE |
1508 | ******************************************************************************************/ | 1514 | ***********************************************************************/ |
1509 | 1515 | ||
1510 | /* For each pair of command templates in the array below, test that encoding and decoding | 1516 | /* For each pair of command templates in the array below, test that |
1511 | * commands work. Also check for the expected size delta, which should be approximately | 1517 | * encoding and decoding commands work. Also check for the expected |
1512 | * TEST_ADD_RATIO times the file size created by test_make_inputs. Due to differences in | 1518 | * size delta, which should be approximately TEST_ADD_RATIO times the |
1513 | * the application header, it is suppressed (-A) so that all delta files are the same. */ | 1519 | * file size created by test_make_inputs. Due to differences in the |
1520 | * application header, it is suppressed (-A) so that all delta files | ||
1521 | * are the same. */ | ||
1514 | static int | 1522 | static int |
1515 | test_command_line_arguments (xd3_stream *stream, int ignore) | 1523 | test_command_line_arguments (xd3_stream *stream, int ignore) |
1516 | { | 1524 | { |
@@ -1616,14 +1624,15 @@ test_command_line_arguments (xd3_stream *stream, int ignore) | |||
1616 | return 0; | 1624 | return 0; |
1617 | } | 1625 | } |
1618 | 1626 | ||
1619 | /****************************************************************************************** | 1627 | /*********************************************************************** |
1620 | EXTERNAL I/O DECOMPRESSION/RECOMPRESSION | 1628 | EXTERNAL I/O DECOMPRESSION/RECOMPRESSION |
1621 | ******************************************************************************************/ | 1629 | ***********************************************************************/ |
1622 | 1630 | ||
1623 | #if EXTERNAL_COMPRESSION | 1631 | #if EXTERNAL_COMPRESSION |
1624 | /* This performs one step of the test_externally_compressed_io function described below. | 1632 | /* This performs one step of the test_externally_compressed_io |
1625 | * It builds a pipe containing both Xdelta and external compression/decompression that | 1633 | * function described below. It builds a pipe containing both Xdelta |
1626 | * should not modify the data passing through. */ | 1634 | * and external compression/decompression that should not modify the |
1635 | * data passing through. */ | ||
1627 | static int | 1636 | static int |
1628 | test_compressed_pipe (xd3_stream *stream, main_extcomp *ext, char* buf, | 1637 | test_compressed_pipe (xd3_stream *stream, main_extcomp *ext, char* buf, |
1629 | const char* comp_options, const char* decomp_options, | 1638 | const char* comp_options, const char* decomp_options, |
@@ -1668,11 +1677,12 @@ test_compressed_pipe (xd3_stream *stream, main_extcomp *ext, char* buf, | |||
1668 | * | 1677 | * |
1669 | * --> | gzip -cf | xdelta3 -cf | xdelta3 -dcf | gzip -dcf | --> | 1678 | * --> | gzip -cf | xdelta3 -cf | xdelta3 -dcf | gzip -dcf | --> |
1670 | * | 1679 | * |
1671 | * is transparent, i.e., does not modify the stream of data. However, we also want to | 1680 | * is transparent, i.e., does not modify the stream of data. However, |
1672 | * verify that at the center the data is properly compressed, i.e., that we do not just | 1681 | * we also want to verify that at the center the data is properly |
1673 | * have a re-compressed gzip format, that we have an VCDIFF format. We do this in two | 1682 | * compressed, i.e., that we do not just have a re-compressed gzip |
1674 | * steps. First test the above pipe, then test with suppressed output recompression | 1683 | * format, that we have an VCDIFF format. We do this in two steps. |
1675 | * (-D). The result should be the original input: | 1684 | * First test the above pipe, then test with suppressed output |
1685 | * recompression (-D). The result should be the original input: | ||
1676 | * | 1686 | * |
1677 | * --> | gzip -cf | xdelta3 -cf | xdelta3 -Ddcf | --> | 1687 | * --> | gzip -cf | xdelta3 -cf | xdelta3 -Ddcf | --> |
1678 | * | 1688 | * |
@@ -1717,14 +1727,17 @@ test_externally_compressed_io (xd3_stream *stream, int ignore) | |||
1717 | return 0; | 1727 | return 0; |
1718 | } | 1728 | } |
1719 | 1729 | ||
1720 | /* This tests the proper functioning of external decompression for source files. The | 1730 | /* This tests the proper functioning of external decompression for |
1721 | * source and target files are identical and compressed by gzip. Decoding such a delta | 1731 | * source files. The source and target files are identical and |
1722 | * with recompression disbaled (-R) should produce the original, uncompressed | 1732 | * compressed by gzip. Decoding such a delta with recompression |
1723 | * source/target file. Then it checks with output recompression enabled--in this case the | 1733 | * disbaled (-R) should produce the original, uncompressed |
1724 | * output should be a compressed copy of the original source/target file. Then it checks | 1734 | * source/target file. Then it checks with output recompression |
1725 | * that encoding with decompression disabled works--the compressed files are identical and | 1735 | * enabled--in this case the output should be a compressed copy of the |
1726 | * decoding them should always produce a compressed output, regardless of -R since the | 1736 | * original source/target file. Then it checks that encoding with |
1727 | * encoded delta file had decompression disabled.. | 1737 | * decompression disabled works--the compressed files are identical |
1738 | * and decoding them should always produce a compressed output, | ||
1739 | * regardless of -R since the encoded delta file had decompression | ||
1740 | * disabled.. | ||
1728 | */ | 1741 | */ |
1729 | static int | 1742 | static int |
1730 | test_source_decompression (xd3_stream *stream, int ignore) | 1743 | test_source_decompression (xd3_stream *stream, int ignore) |
@@ -1789,12 +1802,13 @@ test_source_decompression (xd3_stream *stream, int ignore) | |||
1789 | } | 1802 | } |
1790 | #endif | 1803 | #endif |
1791 | 1804 | ||
1792 | /****************************************************************************************** | 1805 | /*********************************************************************** |
1793 | FORCE, STDOUT | 1806 | FORCE, STDOUT |
1794 | ******************************************************************************************/ | 1807 | ***********************************************************************/ |
1795 | 1808 | ||
1796 | /* This tests that output will not overwrite an existing file unless -f was specified. | 1809 | /* This tests that output will not overwrite an existing file unless |
1797 | * The test is for encoding (the same code handles it for decoding). */ | 1810 | * -f was specified. The test is for encoding (the same code handles |
1811 | * it for decoding). */ | ||
1798 | static int | 1812 | static int |
1799 | test_force_behavior (xd3_stream *stream, int ignore) | 1813 | test_force_behavior (xd3_stream *stream, int ignore) |
1800 | { | 1814 | { |
@@ -1821,9 +1835,9 @@ test_force_behavior (xd3_stream *stream, int ignore) | |||
1821 | return 0; | 1835 | return 0; |
1822 | } | 1836 | } |
1823 | 1837 | ||
1824 | /* This checks the proper operation of the -c flag. When specified the default output | 1838 | /* This checks the proper operation of the -c flag. When specified |
1825 | * becomes stdout, otherwise the input must be provided (encode) or it may be defaulted | 1839 | * the default output becomes stdout, otherwise the input must be |
1826 | * (decode w/ app header). */ | 1840 | * provided (encode) or it may be defaulted (decode w/ app header). */ |
1827 | static int | 1841 | static int |
1828 | test_stdout_behavior (xd3_stream *stream, int ignore) | 1842 | test_stdout_behavior (xd3_stream *stream, int ignore) |
1829 | { | 1843 | { |
@@ -1886,13 +1900,14 @@ test_no_output (xd3_stream *stream, int ignore) | |||
1886 | return 0; | 1900 | return 0; |
1887 | } | 1901 | } |
1888 | 1902 | ||
1889 | /****************************************************************************************** | 1903 | /*********************************************************************** |
1890 | Source identical optimization | 1904 | Source identical optimization |
1891 | ******************************************************************************************/ | 1905 | ***********************************************************************/ |
1892 | 1906 | ||
1893 | /* Computing a delta should be fastest when the two inputs are identical, this checks it. | 1907 | /* Computing a delta should be fastest when the two inputs are |
1894 | * The library is called to compute a delta between a 10000 byte file, 1000 byte winsize, | 1908 | * identical, this checks it. The library is called to compute a |
1895 | * 500 byte source blocksize. The same buffer is used for both source and target. */ | 1909 | * delta between a 10000 byte file, 1000 byte winsize, 500 byte source |
1910 | * blocksize. The same buffer is used for both source and target. */ | ||
1896 | static int | 1911 | static int |
1897 | test_identical_behavior (xd3_stream *stream, int ignore) | 1912 | test_identical_behavior (xd3_stream *stream, int ignore) |
1898 | { | 1913 | { |
@@ -1907,7 +1922,9 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1907 | uint8_t del[IDB_DELSZ]; | 1922 | uint8_t del[IDB_DELSZ]; |
1908 | uint8_t rec[IDB_TGTSZ]; | 1923 | uint8_t rec[IDB_TGTSZ]; |
1909 | xd3_source source; | 1924 | xd3_source source; |
1910 | int encwin = 0; | 1925 | int nextencwin = 0; |
1926 | int winstarts = 0, winfinishes = 0; | ||
1927 | xoff_t srcwin = -1; | ||
1911 | usize_t delpos = 0, recsize; | 1928 | usize_t delpos = 0, recsize; |
1912 | xd3_config config; | 1929 | xd3_config config; |
1913 | 1930 | ||
@@ -1930,9 +1947,8 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1930 | 1947 | ||
1931 | if (ret == XD3_INPUT) | 1948 | if (ret == XD3_INPUT) |
1932 | { | 1949 | { |
1933 | if (encwin == IDB_WINCNT-1) { break; } | 1950 | xd3_avail_input (stream, buf + (IDB_WINSZ * nextencwin), IDB_WINSZ); |
1934 | xd3_avail_input (stream, buf + (IDB_WINSZ * encwin), IDB_WINSZ); | 1951 | nextencwin += 1; |
1935 | encwin += 1; | ||
1936 | continue; | 1952 | continue; |
1937 | } | 1953 | } |
1938 | 1954 | ||
@@ -1941,11 +1957,24 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1941 | source.curblkno = source.getblkno; | 1957 | source.curblkno = source.getblkno; |
1942 | source.onblk = IDB_BLKSZ; | 1958 | source.onblk = IDB_BLKSZ; |
1943 | source.curblk = buf + source.getblkno * IDB_BLKSZ; | 1959 | source.curblk = buf + source.getblkno * IDB_BLKSZ; |
1960 | srcwin = source.getblkno; | ||
1944 | continue; | 1961 | continue; |
1945 | } | 1962 | } |
1946 | 1963 | ||
1947 | if (ret == XD3_WINSTART) { continue; } | 1964 | if (ret == XD3_WINSTART) |
1948 | if (ret == XD3_WINFINISH) { continue; } | 1965 | { |
1966 | winstarts++; | ||
1967 | continue; | ||
1968 | } | ||
1969 | if (ret == XD3_WINFINISH) | ||
1970 | { | ||
1971 | winfinishes++; | ||
1972 | if (winfinishes == IDB_WINCNT) | ||
1973 | { | ||
1974 | break; | ||
1975 | } | ||
1976 | continue; | ||
1977 | } | ||
1949 | 1978 | ||
1950 | if (ret != XD3_OUTPUT) { goto fail; } | 1979 | if (ret != XD3_OUTPUT) { goto fail; } |
1951 | 1980 | ||
@@ -1958,6 +1987,11 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1958 | xd3_consume_output (stream); | 1987 | xd3_consume_output (stream); |
1959 | } | 1988 | } |
1960 | 1989 | ||
1990 | XD3_ASSERT(srcwin == source.blocks - 1); | ||
1991 | XD3_ASSERT(winfinishes == IDB_WINCNT); | ||
1992 | XD3_ASSERT(winstarts == IDB_WINCNT); | ||
1993 | XD3_ASSERT(nextencwin == IDB_WINCNT); | ||
1994 | |||
1961 | /* Reset. */ | 1995 | /* Reset. */ |
1962 | source.blksize = IDB_TGTSZ; | 1996 | source.blksize = IDB_TGTSZ; |
1963 | source.onblk = IDB_TGTSZ; | 1997 | source.onblk = IDB_TGTSZ; |
@@ -1982,7 +2016,8 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1982 | stream->n_add != 0 || | 2016 | stream->n_add != 0 || |
1983 | stream->n_run != 0) { stream->msg = "wrong copy count"; goto fail; }); | 2017 | stream->n_run != 0) { stream->msg = "wrong copy count"; goto fail; }); |
1984 | 2018 | ||
1985 | /* Check that no checksums were computed because the initial match was presumed. */ | 2019 | /* Check that no checksums were computed because the initial match |
2020 | was presumed. */ | ||
1986 | IF_DEBUG (if (stream->large_ckcnt != 0) { stream->msg = "wrong checksum behavior"; goto fail; }); | 2021 | IF_DEBUG (if (stream->large_ckcnt != 0) { stream->msg = "wrong checksum behavior"; goto fail; }); |
1987 | 2022 | ||
1988 | ret = 0; | 2023 | ret = 0; |
@@ -1990,12 +2025,12 @@ test_identical_behavior (xd3_stream *stream, int ignore) | |||
1990 | return ret; | 2025 | return ret; |
1991 | } | 2026 | } |
1992 | 2027 | ||
1993 | /****************************************************************************************** | 2028 | /*********************************************************************** |
1994 | String matching test | 2029 | String matching test |
1995 | ******************************************************************************************/ | 2030 | ***********************************************************************/ |
1996 | 2031 | ||
1997 | /* Check particular matching behaviors by calling xd3_string_match_soft directly with | 2032 | /* Check particular matching behaviors by calling |
1998 | * specific arguments. */ | 2033 | * xd3_string_match_soft directly with specific arguments. */ |
1999 | typedef struct _string_match_test string_match_test; | 2034 | typedef struct _string_match_test string_match_test; |
2000 | 2035 | ||
2001 | typedef enum | 2036 | typedef enum |
@@ -2285,9 +2320,9 @@ test_in_memory (xd3_stream *stream, int ignore) | |||
2285 | return 0; | 2320 | return 0; |
2286 | } | 2321 | } |
2287 | 2322 | ||
2288 | /****************************************************************************************** | 2323 | /*********************************************************************** |
2289 | TEST MAIN | 2324 | TEST MAIN |
2290 | ******************************************************************************************/ | 2325 | ***********************************************************************/ |
2291 | 2326 | ||
2292 | static int | 2327 | static int |
2293 | xd3_selftest (void) | 2328 | xd3_selftest (void) |
@@ -2322,13 +2357,13 @@ xd3_selftest (void) | |||
2322 | IF_GENCODETBL (DO_TEST (address_cache, XD3_ALT_CODE_TABLE, 0)); | 2357 | IF_GENCODETBL (DO_TEST (address_cache, XD3_ALT_CODE_TABLE, 0)); |
2323 | 2358 | ||
2324 | DO_TEST (string_matching, 0, 0); | 2359 | DO_TEST (string_matching, 0, 0); |
2325 | |||
2326 | DO_TEST (choose_instruction, 0, 0); | 2360 | DO_TEST (choose_instruction, 0, 0); |
2361 | DO_TEST (identical_behavior, 0, 0); | ||
2362 | DO_TEST (in_memory, 0, 0); | ||
2363 | |||
2327 | IF_GENCODETBL (DO_TEST (choose_instruction, XD3_ALT_CODE_TABLE, 0)); | 2364 | IF_GENCODETBL (DO_TEST (choose_instruction, XD3_ALT_CODE_TABLE, 0)); |
2328 | IF_GENCODETBL (DO_TEST (encode_code_table, 0, 0)); | 2365 | IF_GENCODETBL (DO_TEST (encode_code_table, 0, 0)); |
2329 | 2366 | ||
2330 | DO_TEST (in_memory, 0, 0); | ||
2331 | DO_TEST (identical_behavior, 0, 0); | ||
2332 | DO_TEST (iopt_flush_instructions, 0, 0); | 2367 | DO_TEST (iopt_flush_instructions, 0, 0); |
2333 | DO_TEST (source_cksum_offset, 0, 0); | 2368 | DO_TEST (source_cksum_offset, 0, 0); |
2334 | 2369 | ||
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index 0381206..58fb8b5 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -268,9 +268,9 @@ | |||
268 | 268 | ||
269 | #include "xdelta3.h" | 269 | #include "xdelta3.h" |
270 | 270 | ||
271 | /****************************************************************************************** | 271 | /*********************************************************************** |
272 | STATIC CONFIGURATION | 272 | STATIC CONFIGURATION |
273 | ******************************************************************************************/ | 273 | ***********************************************************************/ |
274 | 274 | ||
275 | #ifndef XD3_MAIN /* the main application */ | 275 | #ifndef XD3_MAIN /* the main application */ |
276 | #define XD3_MAIN 0 | 276 | #define XD3_MAIN 0 |
@@ -304,7 +304,7 @@ | |||
304 | #define IF_ENCODER(x) | 304 | #define IF_ENCODER(x) |
305 | #endif | 305 | #endif |
306 | 306 | ||
307 | /******************************************************************************************/ | 307 | /***********************************************************************/ |
308 | 308 | ||
309 | typedef enum { | 309 | typedef enum { |
310 | 310 | ||
@@ -354,13 +354,13 @@ typedef enum | |||
354 | XD3_CPY = 3, /* XD3_CPY rtypes are represented as (XD3_CPY + copy-mode value) */ | 354 | XD3_CPY = 3, /* XD3_CPY rtypes are represented as (XD3_CPY + copy-mode value) */ |
355 | } xd3_rtype; | 355 | } xd3_rtype; |
356 | 356 | ||
357 | /******************************************************************************************/ | 357 | /***********************************************************************/ |
358 | 358 | ||
359 | #include "xdelta3-list.h" | 359 | #include "xdelta3-list.h" |
360 | 360 | ||
361 | XD3_MAKELIST(xd3_rlist, xd3_rinst, link); | 361 | XD3_MAKELIST(xd3_rlist, xd3_rinst, link); |
362 | 362 | ||
363 | /******************************************************************************************/ | 363 | /***********************************************************************/ |
364 | 364 | ||
365 | #ifndef unlikely /* The unlikely macro - any good? */ | 365 | #ifndef unlikely /* The unlikely macro - any good? */ |
366 | #if defined(__GNUC__) && __GNUC__ >= 3 | 366 | #if defined(__GNUC__) && __GNUC__ >= 3 |
@@ -536,7 +536,7 @@ IF_BUILD_DEFAULT(static const xd3_smatcher __smatcher_default;) | |||
536 | #define IF_REGRESSION(x) | 536 | #define IF_REGRESSION(x) |
537 | #endif | 537 | #endif |
538 | 538 | ||
539 | /******************************************************************************************/ | 539 | /***********************************************************************/ |
540 | 540 | ||
541 | #if XD3_ENCODER | 541 | #if XD3_ENCODER |
542 | static void* xd3_alloc0 (xd3_stream *stream, | 542 | static void* xd3_alloc0 (xd3_stream *stream, |
@@ -565,6 +565,7 @@ static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_ri | |||
565 | static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, uint code); | 565 | static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, uint code); |
566 | 566 | ||
567 | static usize_t xd3_sizeof_output (xd3_output *output); | 567 | static usize_t xd3_sizeof_output (xd3_output *output); |
568 | static void xd3_encode_reset (xd3_stream *stream); | ||
568 | 569 | ||
569 | static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos); | 570 | static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos); |
570 | static int xd3_source_extend_match (xd3_stream *stream); | 571 | static int xd3_source_extend_match (xd3_stream *stream); |
@@ -588,7 +589,7 @@ static int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp, | |||
588 | static int xd3_selftest (void); | 589 | static int xd3_selftest (void); |
589 | #endif | 590 | #endif |
590 | 591 | ||
591 | /******************************************************************************************/ | 592 | /***********************************************************************/ |
592 | 593 | ||
593 | #define UINT32_OFLOW_MASK 0xfe000000U | 594 | #define UINT32_OFLOW_MASK 0xfe000000U |
594 | #define UINT64_OFLOW_MASK 0xfe00000000000000ULL | 595 | #define UINT64_OFLOW_MASK 0xfe00000000000000ULL |
@@ -644,7 +645,7 @@ const char* xd3_strerror (int ret) | |||
644 | return NULL; | 645 | return NULL; |
645 | } | 646 | } |
646 | 647 | ||
647 | /******************************************************************************************/ | 648 | /***********************************************************************/ |
648 | 649 | ||
649 | #if SECONDARY_ANY == 0 | 650 | #if SECONDARY_ANY == 0 |
650 | #define IF_SEC(x) | 651 | #define IF_SEC(x) |
@@ -707,7 +708,7 @@ static const xd3_sec_type djw_sec_type = | |||
707 | return XD3_INTERNAL; | 708 | return XD3_INTERNAL; |
708 | #endif | 709 | #endif |
709 | 710 | ||
710 | /******************************************************************************************/ | 711 | /***********************************************************************/ |
711 | 712 | ||
712 | /* Process the inline pass. */ | 713 | /* Process the inline pass. */ |
713 | #define __XDELTA3_C_INLINE_PASS__ | 714 | #define __XDELTA3_C_INLINE_PASS__ |
@@ -734,9 +735,9 @@ static const xd3_sec_type djw_sec_type = | |||
734 | #endif /* __XDELTA3_C_HEADER_PASS__ */ | 735 | #endif /* __XDELTA3_C_HEADER_PASS__ */ |
735 | #ifdef __XDELTA3_C_INLINE_PASS__ | 736 | #ifdef __XDELTA3_C_INLINE_PASS__ |
736 | 737 | ||
737 | /****************************************************************************************** | 738 | /**************************************************************** |
738 | Instruction tables | 739 | Instruction tables |
739 | ******************************************************************************************/ | 740 | *****************************************************************/ |
740 | 741 | ||
741 | /* The following code implements a parametrized description of the | 742 | /* The following code implements a parametrized description of the |
742 | * code table given above for a few reasons. It is not necessary for | 743 | * code table given above for a few reasons. It is not necessary for |
@@ -969,9 +970,10 @@ xd3_alternate_code_table (void) | |||
969 | return __alternate_code_table; | 970 | return __alternate_code_table; |
970 | } | 971 | } |
971 | 972 | ||
972 | /* This function computes the ideal second instruction INST based on preceding instruction | 973 | /* This function computes the ideal second instruction INST based on |
973 | * PREV. If it is possible to issue a double instruction based on this pair it sets | 974 | * preceding instruction PREV. If it is possible to issue a double |
974 | * PREV->code2, otherwise it sets INST->code1. */ | 975 | * instruction based on this pair it sets PREV->code2, otherwise it |
976 | * sets INST->code1. */ | ||
975 | static void | 977 | static void |
976 | xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_rinst *inst) | 978 | xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_rinst *inst) |
977 | { | 979 | { |
@@ -999,17 +1001,19 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri | |||
999 | { | 1001 | { |
1000 | int prev_mode = prev->type - XD3_CPY; | 1002 | int prev_mode = prev->type - XD3_CPY; |
1001 | 1003 | ||
1002 | /* If previous is a copy. Note: as long as the previous is not a RUN | 1004 | /* If previous is a copy. Note: as long as the previous |
1003 | * instruction, it should be a copy because it cannot be an add. This check | 1005 | * is not a RUN instruction, it should be a copy because |
1004 | * is more clear. */ | 1006 | * it cannot be an add. This check is more clear. */ |
1005 | if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) | 1007 | if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) |
1006 | { | 1008 | { |
1007 | const xd3_code_table_sizes *sizes = & desc->copyadd_max_sizes[prev_mode]; | 1009 | const xd3_code_table_sizes *sizes = & desc->copyadd_max_sizes[prev_mode]; |
1008 | 1010 | ||
1009 | /* This check and the inst->size-<= above are == in the default table. */ | 1011 | /* This check and the inst->size-<= above are == in |
1012 | the default table. */ | ||
1010 | if (prev->size <= sizes->cpy_max) | 1013 | if (prev->size <= sizes->cpy_max) |
1011 | { | 1014 | { |
1012 | /* The second and third exprs are 0 in the default table. */ | 1015 | /* The second and third exprs are 0 in the |
1016 | default table. */ | ||
1013 | prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_MATCH)) + (inst->size - MIN_ADD); | 1017 | prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_MATCH)) + (inst->size - MIN_ADD); |
1014 | } | 1018 | } |
1015 | } | 1019 | } |
@@ -1021,9 +1025,10 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri | |||
1021 | { | 1025 | { |
1022 | int mode = inst->type - XD3_CPY; | 1026 | int mode = inst->type - XD3_CPY; |
1023 | 1027 | ||
1024 | /* The large copy instruction is offset by the run, large add, and immediate adds, | 1028 | /* The large copy instruction is offset by the run, large add, |
1025 | * then multipled by the number of immediate copies plus one (the large copy) | 1029 | * and immediate adds, then multipled by the number of |
1026 | * (i.e., if there are 15 immediate copy instructions then there are 16 copy | 1030 | * immediate copies plus one (the large copy) (i.e., if there |
1031 | * are 15 immediate copy instructions then there are 16 copy | ||
1027 | * instructions per mode). */ | 1032 | * instructions per mode). */ |
1028 | inst->code1 = 2 + desc->add_sizes + (1 + desc->cpy_sizes) * mode; | 1033 | inst->code1 = 2 + desc->add_sizes + (1 + desc->cpy_sizes) * mode; |
1029 | 1034 | ||
@@ -1118,16 +1123,17 @@ xd3_choose_instruction (/* const xd3_code_table_desc *desc,*/ xd3_rinst *prev, x | |||
1118 | } | 1123 | } |
1119 | #endif /* GENERIC_ENCODE_TABLES */ | 1124 | #endif /* GENERIC_ENCODE_TABLES */ |
1120 | 1125 | ||
1121 | /****************************************************************************************** | 1126 | /*********************************************************************** |
1122 | Instruction table encoder/decoder | 1127 | Instruction table encoder/decoder |
1123 | ******************************************************************************************/ | 1128 | ***********************************************************************/ |
1124 | 1129 | ||
1125 | #if GENERIC_ENCODE_TABLES | 1130 | #if GENERIC_ENCODE_TABLES |
1126 | #if GENERIC_ENCODE_TABLES_COMPUTE == 0 | 1131 | #if GENERIC_ENCODE_TABLES_COMPUTE == 0 |
1127 | 1132 | ||
1128 | /* In this case, we hard-code the result of compute_code_table_encoding for each alternate | 1133 | /* In this case, we hard-code the result of |
1129 | * code table, presuming that saves time/space. This has been 131 bytes, but secondary | 1134 | * compute_code_table_encoding for each alternate code table, |
1130 | * compression was turned off. */ | 1135 | * presuming that saves time/space. This has been 131 bytes, but |
1136 | * secondary compression was turned off. */ | ||
1131 | static const uint8_t __alternate_code_table_compressed[178] = | 1137 | static const uint8_t __alternate_code_table_compressed[178] = |
1132 | {0xd6,0xc3,0xc4,0x00,0x00,0x01,0x8a,0x6f,0x40,0x81,0x27,0x8c,0x00,0x00,0x4a,0x4a,0x0d,0x02,0x01,0x03, | 1138 | {0xd6,0xc3,0xc4,0x00,0x00,0x01,0x8a,0x6f,0x40,0x81,0x27,0x8c,0x00,0x00,0x4a,0x4a,0x0d,0x02,0x01,0x03, |
1133 | 0x01,0x03,0x00,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, | 1139 | 0x01,0x03,0x00,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, |
@@ -1210,9 +1216,9 @@ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *cod | |||
1210 | return ret; | 1216 | return ret; |
1211 | } | 1217 | } |
1212 | 1218 | ||
1213 | /* Compute a delta between alternate and rfc3284 tables. As soon as another alternate | 1219 | /* Compute a delta between alternate and rfc3284 tables. As soon as |
1214 | * table is added, this code should become generic. For now there is only one alternate | 1220 | * another alternate table is added, this code should become generic. |
1215 | * table for testing. */ | 1221 | * For now there is only one alternate table for testing. */ |
1216 | static int | 1222 | static int |
1217 | xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) | 1223 | xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) |
1218 | { | 1224 | { |
@@ -1417,9 +1423,9 @@ xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t si | |||
1417 | return ret; | 1423 | return ret; |
1418 | } | 1424 | } |
1419 | 1425 | ||
1420 | /****************************************************************************************** | 1426 | /*********************************************************************** |
1421 | Permute stuff | 1427 | Permute stuff |
1422 | ******************************************************************************************/ | 1428 | ***********************************************************************/ |
1423 | 1429 | ||
1424 | #if HASH_PERMUTE == 0 | 1430 | #if HASH_PERMUTE == 0 |
1425 | #define PERMUTE(x) (x) | 1431 | #define PERMUTE(x) (x) |
@@ -1465,9 +1471,9 @@ static const uint16_t __single_hash[256] = | |||
1465 | }; | 1471 | }; |
1466 | #endif | 1472 | #endif |
1467 | 1473 | ||
1468 | /****************************************************************************************** | 1474 | /*********************************************************************** |
1469 | Ctable stuff | 1475 | Ctable stuff |
1470 | ******************************************************************************************/ | 1476 | ***********************************************************************/ |
1471 | 1477 | ||
1472 | #if HASH_PRIME | 1478 | #if HASH_PRIME |
1473 | static const usize_t __primes[] = | 1479 | static const usize_t __primes[] = |
@@ -1499,9 +1505,9 @@ xd3_checksum_hash (const xd3_hash_cfg *cfg, const uint32_t cksum) | |||
1499 | #endif | 1505 | #endif |
1500 | } | 1506 | } |
1501 | 1507 | ||
1502 | /****************************************************************************************** | 1508 | /*********************************************************************** |
1503 | Create the hash table. | 1509 | Create the hash table. |
1504 | ******************************************************************************************/ | 1510 | ***********************************************************************/ |
1505 | 1511 | ||
1506 | static inline void | 1512 | static inline void |
1507 | xd3_swap_uint8p (uint8_t** p1, uint8_t** p2) | 1513 | xd3_swap_uint8p (uint8_t** p1, uint8_t** p2) |
@@ -1605,9 +1611,9 @@ xd3_size_hashtable (xd3_stream *stream, | |||
1605 | } | 1611 | } |
1606 | #endif | 1612 | #endif |
1607 | 1613 | ||
1608 | /****************************************************************************************** | 1614 | /*********************************************************************** |
1609 | Cksum function | 1615 | Cksum function |
1610 | ******************************************************************************************/ | 1616 | ***********************************************************************/ |
1611 | 1617 | ||
1612 | #if OLD_LARGE_CKSUM | 1618 | #if OLD_LARGE_CKSUM |
1613 | static inline uint32_t | 1619 | static inline uint32_t |
@@ -1652,9 +1658,9 @@ xd3_scksum (const uint8_t *seg, const int ln) | |||
1652 | #define xd3_scksum(seg,ln) xd3_lcksum(seg,ln) | 1658 | #define xd3_scksum(seg,ln) xd3_lcksum(seg,ln) |
1653 | #endif | 1659 | #endif |
1654 | 1660 | ||
1655 | /****************************************************************************************** | 1661 | /*********************************************************************** |
1656 | Adler32 stream function: code copied from Zlib, defined in RFC1950 | 1662 | Adler32 stream function: code copied from Zlib, defined in RFC1950 |
1657 | ******************************************************************************************/ | 1663 | ***********************************************************************/ |
1658 | 1664 | ||
1659 | #define A32_BASE 65521L /* Largest prime smaller than 2^16 */ | 1665 | #define A32_BASE 65521L /* Largest prime smaller than 2^16 */ |
1660 | #define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ | 1666 | #define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ |
@@ -1700,9 +1706,9 @@ static unsigned long adler32 (unsigned long adler, const uint8_t *buf, usize_t l | |||
1700 | return (s2 << 16) | s1; | 1706 | return (s2 << 16) | s1; |
1701 | } | 1707 | } |
1702 | 1708 | ||
1703 | /****************************************************************************************** | 1709 | /*********************************************************************** |
1704 | Run-length function | 1710 | Run-length function |
1705 | ******************************************************************************************/ | 1711 | ***********************************************************************/ |
1706 | 1712 | ||
1707 | static inline int | 1713 | static inline int |
1708 | xd3_comprun (const uint8_t *seg, int slook, uint8_t *run_cp) | 1714 | xd3_comprun (const uint8_t *seg, int slook, uint8_t *run_cp) |
@@ -1721,9 +1727,9 @@ xd3_comprun (const uint8_t *seg, int slook, uint8_t *run_cp) | |||
1721 | return run_l; | 1727 | return run_l; |
1722 | } | 1728 | } |
1723 | 1729 | ||
1724 | /****************************************************************************************** | 1730 | /*********************************************************************** |
1725 | Basic encoder/decoder functions | 1731 | Basic encoder/decoder functions |
1726 | ******************************************************************************************/ | 1732 | ***********************************************************************/ |
1727 | 1733 | ||
1728 | static int | 1734 | static int |
1729 | xd3_decode_byte (xd3_stream *stream, uint *val) | 1735 | xd3_decode_byte (xd3_stream *stream, uint *val) |
@@ -1980,9 +1986,9 @@ xd3_sizeof_uint64_t (uint64_t num) | |||
1980 | 1986 | ||
1981 | #endif | 1987 | #endif |
1982 | 1988 | ||
1983 | /****************************************************************************************** | 1989 | /*********************************************************************** |
1984 | Address cache stuff | 1990 | Address cache stuff |
1985 | ******************************************************************************************/ | 1991 | ***********************************************************************/ |
1986 | 1992 | ||
1987 | static int | 1993 | static int |
1988 | xd3_alloc_cache (xd3_stream *stream) | 1994 | xd3_alloc_cache (xd3_stream *stream) |
@@ -2135,9 +2141,9 @@ xd3_decode_address (xd3_stream *stream, usize_t here, uint mode, const uint8_t * | |||
2135 | return 0; | 2141 | return 0; |
2136 | } | 2142 | } |
2137 | 2143 | ||
2138 | /****************************************************************************************** | 2144 | /*********************************************************************** |
2139 | Alloc/free | 2145 | Alloc/free |
2140 | ******************************************************************************************/ | 2146 | ***********************************************************************/ |
2141 | 2147 | ||
2142 | static void* | 2148 | static void* |
2143 | __xd3_alloc_func (void* opaque, usize_t items, usize_t size) | 2149 | __xd3_alloc_func (void* opaque, usize_t items, usize_t size) |
@@ -2387,9 +2393,9 @@ xd3_rtype_to_string (xd3_rtype type, int print_mode) | |||
2387 | } | 2393 | } |
2388 | #endif | 2394 | #endif |
2389 | 2395 | ||
2390 | /****************************************************************************************** | 2396 | /**************************************************************** |
2391 | Stream configuration | 2397 | Stream configuration |
2392 | ******************************************************************************************/ | 2398 | ******************************************************************/ |
2393 | 2399 | ||
2394 | int | 2400 | int |
2395 | xd3_config_stream(xd3_stream *stream, | 2401 | xd3_config_stream(xd3_stream *stream, |
@@ -2565,26 +2571,27 @@ xd3_config_stream(xd3_stream *stream, | |||
2565 | return 0; | 2571 | return 0; |
2566 | } | 2572 | } |
2567 | 2573 | ||
2568 | /****************************************************************************************** | 2574 | /***************************************************************** |
2569 | Getblk interface | 2575 | Getblk interface |
2570 | ******************************************************************************************/ | 2576 | ***********************************************************/ |
2571 | 2577 | ||
2572 | /* This function interfaces with the client getblk function, checks its results, etc. */ | 2578 | /* This function interfaces with the client getblk function, checks |
2579 | * its results, etc. */ | ||
2573 | static int | 2580 | static int |
2574 | xd3_getblk (xd3_stream *stream/*, xd3_source *source*/, xoff_t blkno) | 2581 | xd3_getblk (xd3_stream *stream, xoff_t blkno) |
2575 | { | 2582 | { |
2576 | int ret; | 2583 | int ret; |
2577 | xd3_source *source = stream->src; | 2584 | xd3_source *source = stream->src; |
2578 | 2585 | ||
2579 | if (blkno >= source->blocks) | 2586 | if (source->curblk == NULL || |
2587 | blkno != source->curblkno) | ||
2580 | { | 2588 | { |
2581 | IF_DEBUG1 (DP(RINT "[getblk] block %"Q"u\n", blkno)); | 2589 | if (blkno >= source->blocks) |
2582 | stream->msg = "source file too short"; | 2590 | { |
2583 | return XD3_INTERNAL; | 2591 | stream->msg = "source file too short"; |
2584 | } | 2592 | return XD3_INTERNAL; |
2593 | } | ||
2585 | 2594 | ||
2586 | if (blkno != source->curblkno || source->curblk == NULL) | ||
2587 | { | ||
2588 | XD3_ASSERT (source->curblk != NULL || blkno != source->curblkno); | 2595 | XD3_ASSERT (source->curblk != NULL || blkno != source->curblkno); |
2589 | 2596 | ||
2590 | source->getblkno = blkno; | 2597 | source->getblkno = blkno; |
@@ -2603,7 +2610,8 @@ xd3_getblk (xd3_stream *stream/*, xd3_source *source*/, xoff_t blkno) | |||
2603 | XD3_ASSERT (source->curblk != NULL); | 2610 | XD3_ASSERT (source->curblk != NULL); |
2604 | } | 2611 | } |
2605 | 2612 | ||
2606 | if (source->onblk != xd3_bytes_on_srcblk (source, blkno)) | 2613 | if (source->onblk != (blkno == source->blocks - 1 ? |
2614 | source->onlastblk : source->blksize)) | ||
2607 | { | 2615 | { |
2608 | stream->msg = "getblk returned short block"; | 2616 | stream->msg = "getblk returned short block"; |
2609 | return XD3_INTERNAL; | 2617 | return XD3_INTERNAL; |
@@ -2612,9 +2620,9 @@ xd3_getblk (xd3_stream *stream/*, xd3_source *source*/, xoff_t blkno) | |||
2612 | return 0; | 2620 | return 0; |
2613 | } | 2621 | } |
2614 | 2622 | ||
2615 | /****************************************************************************************** | 2623 | /*********************************************************** |
2616 | Stream open/close | 2624 | Stream open/close |
2617 | ******************************************************************************************/ | 2625 | ***************************************************************/ |
2618 | 2626 | ||
2619 | int | 2627 | int |
2620 | xd3_set_source (xd3_stream *stream, | 2628 | xd3_set_source (xd3_stream *stream, |
@@ -2629,8 +2637,9 @@ xd3_set_source (xd3_stream *stream, | |||
2629 | 2637 | ||
2630 | stream->src = src; | 2638 | stream->src = src; |
2631 | blk_num = src->size / src->blksize; | 2639 | blk_num = src->size / src->blksize; |
2632 | tail_size = src->size % src->blksize; | 2640 | tail_size = src->size - (blk_num * src->blksize); |
2633 | src->blocks = blk_num + (tail_size > 0); | 2641 | src->blocks = blk_num + (tail_size > 0); |
2642 | src->onlastblk = xd3_bytes_on_srcblk (src, src->blocks - 1); | ||
2634 | src->srclen = 0; | 2643 | src->srclen = 0; |
2635 | src->srcbase = 0; | 2644 | src->srcbase = 0; |
2636 | 2645 | ||
@@ -2649,7 +2658,22 @@ xd3_close_stream (xd3_stream *stream) | |||
2649 | { | 2658 | { |
2650 | if (stream->enc_state != 0 && stream->enc_state != ENC_ABORTED) | 2659 | if (stream->enc_state != 0 && stream->enc_state != ENC_ABORTED) |
2651 | { | 2660 | { |
2652 | /* If encoding, should be ready for more input but not actually have any. */ | 2661 | if (stream->buf_leftover != NULL) |
2662 | { | ||
2663 | stream->msg = "encoding is incomplete"; | ||
2664 | return XD3_INTERNAL; | ||
2665 | } | ||
2666 | |||
2667 | if (stream->enc_state == ENC_POSTWIN) | ||
2668 | { | ||
2669 | xd3_encode_reset (stream); | ||
2670 | |||
2671 | stream->current_window += 1; | ||
2672 | stream->enc_state = ENC_INPUT; | ||
2673 | } | ||
2674 | |||
2675 | /* If encoding, should be ready for more input but not actually | ||
2676 | have any. */ | ||
2653 | if (stream->enc_state != ENC_INPUT || stream->avail_in != 0) | 2677 | if (stream->enc_state != ENC_INPUT || stream->avail_in != 0) |
2654 | { | 2678 | { |
2655 | stream->msg = "encoding is incomplete"; | 2679 | stream->msg = "encoding is incomplete"; |
@@ -2678,9 +2702,9 @@ xd3_close_stream (xd3_stream *stream) | |||
2678 | return 0; | 2702 | return 0; |
2679 | } | 2703 | } |
2680 | 2704 | ||
2681 | /****************************************************************************************** | 2705 | /************************************************************** |
2682 | Application header | 2706 | Application header |
2683 | ******************************************************************************************/ | 2707 | ****************************************************************/ |
2684 | 2708 | ||
2685 | int | 2709 | int |
2686 | xd3_get_appheader (xd3_stream *stream, | 2710 | xd3_get_appheader (xd3_stream *stream, |
@@ -2698,15 +2722,15 @@ xd3_get_appheader (xd3_stream *stream, | |||
2698 | return 0; | 2722 | return 0; |
2699 | } | 2723 | } |
2700 | 2724 | ||
2701 | /****************************************************************************************** | 2725 | /********************************************************** |
2702 | Decoder stuff | 2726 | Decoder stuff |
2703 | ******************************************************************************************/ | 2727 | *************************************************/ |
2704 | 2728 | ||
2705 | #include "xdelta3-decode.h" | 2729 | #include "xdelta3-decode.h" |
2706 | 2730 | ||
2707 | /****************************************************************************************** | 2731 | /**************************************************************** |
2708 | Encoder stuff | 2732 | Encoder stuff |
2709 | ******************************************************************************************/ | 2733 | *****************************************************************/ |
2710 | 2734 | ||
2711 | #if XD3_ENCODER | 2735 | #if XD3_ENCODER |
2712 | void | 2736 | void |
@@ -3461,9 +3485,9 @@ xd3_emit_hdr (xd3_stream *stream) | |||
3461 | return 0; | 3485 | return 0; |
3462 | } | 3486 | } |
3463 | 3487 | ||
3464 | /****************************************************************************************** | 3488 | /**************************************************************** |
3465 | Encode routines | 3489 | Encode routines |
3466 | ******************************************************************************************/ | 3490 | ****************************************************************/ |
3467 | 3491 | ||
3468 | static int | 3492 | static int |
3469 | xd3_encode_buffer_leftover (xd3_stream *stream) | 3493 | xd3_encode_buffer_leftover (xd3_stream *stream) |
@@ -3716,9 +3740,9 @@ xd3_encode_input (xd3_stream *stream) | |||
3716 | 3740 | ||
3717 | stream->enc_state = ENC_SEARCH; | 3741 | stream->enc_state = ENC_SEARCH; |
3718 | 3742 | ||
3719 | IF_DEBUG1 (DP(RINT "[input window:%"Q"u] input bytes %u offset %"Q"u\n", | 3743 | IF_DEBUG1 (DP(RINT "[WINSTART:%"Q"u] input bytes %u offset %"Q"u\n", |
3720 | stream->current_window, stream->avail_in, stream->total_in)); | 3744 | stream->current_window, stream->avail_in, |
3721 | 3745 | stream->total_in)); | |
3722 | return XD3_WINSTART; | 3746 | return XD3_WINSTART; |
3723 | 3747 | ||
3724 | case ENC_SEARCH: | 3748 | case ENC_SEARCH: |
@@ -3847,6 +3871,9 @@ xd3_encode_input (xd3_stream *stream) | |||
3847 | stream->total_in += (xoff_t) stream->avail_in; | 3871 | stream->total_in += (xoff_t) stream->avail_in; |
3848 | stream->enc_state = ENC_POSTWIN; | 3872 | stream->enc_state = ENC_POSTWIN; |
3849 | 3873 | ||
3874 | IF_DEBUG1 (DP(RINT "[WINFINISH:%"Q"u] in=%"Q"u\n", | ||
3875 | stream->current_window, | ||
3876 | stream->total_in)); | ||
3850 | return XD3_WINFINISH; | 3877 | return XD3_WINFINISH; |
3851 | 3878 | ||
3852 | case ENC_POSTWIN: | 3879 | case ENC_POSTWIN: |
@@ -4390,7 +4417,7 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4390 | matchoff = stream->match_srcpos - stream->match_back; | 4417 | matchoff = stream->match_srcpos - stream->match_back; |
4391 | streamoff = stream->input_position - stream->match_back; | 4418 | streamoff = stream->input_position - stream->match_back; |
4392 | tryblk = matchoff / src->blksize; | 4419 | tryblk = matchoff / src->blksize; |
4393 | tryoff = matchoff % src->blksize; | 4420 | tryoff = matchoff - (tryblk * src->blksize); |
4394 | 4421 | ||
4395 | /* this loops backward over source blocks */ | 4422 | /* this loops backward over source blocks */ |
4396 | while (stream->match_back < stream->match_maxback) | 4423 | while (stream->match_back < stream->match_maxback) |
@@ -4439,7 +4466,7 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4439 | matchoff = stream->match_srcpos + stream->match_fwd; | 4466 | matchoff = stream->match_srcpos + stream->match_fwd; |
4440 | streamoff = stream->input_position + stream->match_fwd; | 4467 | streamoff = stream->input_position + stream->match_fwd; |
4441 | tryblk = matchoff / src->blksize; | 4468 | tryblk = matchoff / src->blksize; |
4442 | tryoff = matchoff % src->blksize; | 4469 | tryoff = matchoff - (tryblk * src->blksize); |
4443 | 4470 | ||
4444 | /* Note: practically the same code as backwards case above: same comments */ | 4471 | /* Note: practically the same code as backwards case above: same comments */ |
4445 | while (stream->match_fwd < stream->match_maxfwd) | 4472 | while (stream->match_fwd < stream->match_maxfwd) |
@@ -4481,10 +4508,11 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4481 | donefwd: | 4508 | donefwd: |
4482 | stream->match_state = MATCH_SEARCHING; | 4509 | stream->match_state = MATCH_SEARCHING; |
4483 | 4510 | ||
4484 | /* If the match ends short of the last instruction end, we probably don't want it. | 4511 | /* If the match ends short of the last instruction end, we probably |
4485 | * There is the possibility that a copy ends short of the last copy but also goes | 4512 | * don't want it. There is the possibility that a copy ends short |
4486 | * further back, in which case we might want it. This code does not implement such: if | 4513 | * of the last copy but also goes further back, in which case we |
4487 | * so we would need more complicated xd3_iopt_erase logic. */ | 4514 | * might want it. This code does not implement such: if so we would |
4515 | * need more complicated xd3_iopt_erase logic. */ | ||
4488 | if (stream->match_fwd < stream->min_match) | 4516 | if (stream->match_fwd < stream->min_match) |
4489 | { | 4517 | { |
4490 | stream->match_fwd = 0; | 4518 | stream->match_fwd = 0; |
@@ -4499,8 +4527,9 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4499 | xoff_t match_position = stream->match_srcpos - stream->match_back; | 4527 | xoff_t match_position = stream->match_srcpos - stream->match_back; |
4500 | xoff_t match_end = stream->match_srcpos + stream->match_fwd; | 4528 | xoff_t match_end = stream->match_srcpos + stream->match_fwd; |
4501 | 4529 | ||
4502 | /* At this point we may have to erase any iopt-buffer instructions that are | 4530 | /* At this point we may have to erase any iopt-buffer |
4503 | * fully covered by a backward-extending copy. */ | 4531 | * instructions that are fully covered by a backward-extending |
4532 | * copy. */ | ||
4504 | if (stream->match_back > 0) | 4533 | if (stream->match_back > 0) |
4505 | { | 4534 | { |
4506 | xd3_iopt_erase (stream, target_position, total); | 4535 | xd3_iopt_erase (stream, target_position, total); |
@@ -4508,7 +4537,8 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4508 | 4537 | ||
4509 | stream->match_back = 0; | 4538 | stream->match_back = 0; |
4510 | 4539 | ||
4511 | /* Update ranges. The first source match occurs with both values set to 0. */ | 4540 | /* Update ranges. The first source match occurs with both |
4541 | values set to 0. */ | ||
4512 | if (stream->match_maxaddr == 0 || | 4542 | if (stream->match_maxaddr == 0 || |
4513 | match_position < stream->match_minaddr) | 4543 | match_position < stream->match_minaddr) |
4514 | { | 4544 | { |
@@ -4735,40 +4765,6 @@ xd3_verify_run_state (xd3_stream *stream, | |||
4735 | XD3_ASSERT (x_run_l > slook || run_l == x_run_l); | 4765 | XD3_ASSERT (x_run_l > slook || run_l == x_run_l); |
4736 | } | 4766 | } |
4737 | #endif /* XD3_DEBUG */ | 4767 | #endif /* XD3_DEBUG */ |
4738 | #endif /* XD3_ENCODER */ | ||
4739 | |||
4740 | /****************************************************************************************** | ||
4741 | TEMPLATE pass | ||
4742 | ******************************************************************************************/ | ||
4743 | |||
4744 | #endif /* __XDELTA3_C_INLINE_PASS__ */ | ||
4745 | #ifdef __XDELTA3_C_TEMPLATE_PASS__ | ||
4746 | |||
4747 | #if XD3_ENCODER | ||
4748 | |||
4749 | /****************************************************************************************** | ||
4750 | Templates | ||
4751 | ******************************************************************************************/ | ||
4752 | |||
4753 | /* Template macros */ | ||
4754 | #define XD3_TEMPLATE(x) XD3_TEMPLATE2(x,TEMPLATE) | ||
4755 | #define XD3_TEMPLATE2(x,n) XD3_TEMPLATE3(x,n) | ||
4756 | #define XD3_TEMPLATE3(x,n) x ## n | ||
4757 | #define XD3_STRINGIFY(x) XD3_STRINGIFY2(x) | ||
4758 | #define XD3_STRINGIFY2(x) #x | ||
4759 | |||
4760 | static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream); | ||
4761 | |||
4762 | static const xd3_smatcher XD3_TEMPLATE(__smatcher_) = | ||
4763 | { | ||
4764 | XD3_STRINGIFY(TEMPLATE), | ||
4765 | XD3_TEMPLATE(xd3_string_match_), | ||
4766 | #if SOFTCFG == 1 | ||
4767 | 0, 0, 0, 0, 0, 0, 0 | ||
4768 | #else | ||
4769 | LLOOK, LSTEP, SLOOK, SCHAIN, SLCHAIN, MAXLAZY, LONGENOUGH | ||
4770 | #endif | ||
4771 | }; | ||
4772 | 4768 | ||
4773 | /* This function computes more source checksums to advance the window. | 4769 | /* This function computes more source checksums to advance the window. |
4774 | * Called at every entrance to the string-match loop and each time | 4770 | * Called at every entrance to the string-match loop and each time |
@@ -4778,10 +4774,9 @@ static const xd3_smatcher XD3_TEMPLATE(__smatcher_) = | |||
4778 | * | 4774 | * |
4779 | * TODO: really would like a good test for this logic. how? | 4775 | * TODO: really would like a good test for this logic. how? |
4780 | * TODO: optimize the inner loop | 4776 | * TODO: optimize the inner loop |
4781 | * TODO: do-templatize this | ||
4782 | */ | 4777 | */ |
4783 | static int | 4778 | static int |
4784 | XD3_TEMPLATE(xd3_srcwin_move_point_) (xd3_stream *stream, usize_t *next_move_point) | 4779 | xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) |
4785 | { | 4780 | { |
4786 | xoff_t logical_input_cksum_pos; | 4781 | xoff_t logical_input_cksum_pos; |
4787 | 4782 | ||
@@ -4845,11 +4840,12 @@ XD3_TEMPLATE(xd3_srcwin_move_point_) (xd3_stream *stream, usize_t *next_move_poi | |||
4845 | stream->srcwin_cksum_pos < stream->src->size) | 4840 | stream->srcwin_cksum_pos < stream->src->size) |
4846 | { | 4841 | { |
4847 | xoff_t blkno = stream->srcwin_cksum_pos / stream->src->blksize; | 4842 | xoff_t blkno = stream->srcwin_cksum_pos / stream->src->blksize; |
4848 | ssize_t oldpos = stream->srcwin_cksum_pos % stream->src->blksize; | 4843 | xoff_t blkbaseoffset = blkno * stream->src->blksize; |
4849 | ssize_t blkpos = xd3_bytes_on_srcblk (stream->src, blkno); | 4844 | ssize_t oldpos = stream->srcwin_cksum_pos - blkbaseoffset; |
4845 | ssize_t blkpos = xd3_bytes_on_srcblk_fast (stream->src, blkno); | ||
4850 | int ret; | 4846 | int ret; |
4851 | 4847 | ||
4852 | if (oldpos + LLOOK > blkpos) | 4848 | if (oldpos + stream->smatcher.large_look > blkpos) |
4853 | { | 4849 | { |
4854 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; | 4850 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; |
4855 | continue; | 4851 | continue; |
@@ -4874,20 +4870,22 @@ XD3_TEMPLATE(xd3_srcwin_move_point_) (xd3_stream *stream, usize_t *next_move_poi | |||
4874 | * the number of bytes available. Each iteration inspects | 4870 | * the number of bytes available. Each iteration inspects |
4875 | * large_look bytes then steps back large_step bytes. The | 4871 | * large_look bytes then steps back large_step bytes. The |
4876 | * if-stmt above ensures at least one large_look of data. */ | 4872 | * if-stmt above ensures at least one large_look of data. */ |
4877 | blkpos -= LLOOK; | 4873 | blkpos -= stream->smatcher.large_look; |
4874 | blkbaseoffset = stream->src->blksize * blkno; | ||
4878 | 4875 | ||
4879 | do | 4876 | do |
4880 | { | 4877 | { |
4881 | uint32_t cksum = xd3_lcksum (stream->src->curblk + blkpos, LLOOK); | 4878 | uint32_t cksum = xd3_lcksum (stream->src->curblk + blkpos, |
4879 | stream->smatcher.large_look); | ||
4882 | usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); | 4880 | usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); |
4883 | 4881 | ||
4884 | stream->large_table[hval] = | 4882 | stream->large_table[hval] = |
4885 | (usize_t) ((stream->src->blksize * blkno) + | 4883 | (usize_t) (blkbaseoffset + |
4886 | (xoff_t)(blkpos + HASH_CKOFFSET)); | 4884 | (xoff_t)(blkpos + HASH_CKOFFSET)); |
4887 | 4885 | ||
4888 | IF_DEBUG (stream->large_ckcnt += 1); | 4886 | IF_DEBUG (stream->large_ckcnt += 1); |
4889 | 4887 | ||
4890 | blkpos -= LSTEP; | 4888 | blkpos -= stream->smatcher.large_step; |
4891 | } | 4889 | } |
4892 | while (blkpos >= oldpos); | 4890 | while (blkpos >= oldpos); |
4893 | 4891 | ||
@@ -4909,6 +4907,41 @@ XD3_TEMPLATE(xd3_srcwin_move_point_) (xd3_stream *stream, usize_t *next_move_poi | |||
4909 | return 0; | 4907 | return 0; |
4910 | } | 4908 | } |
4911 | 4909 | ||
4910 | #endif /* XD3_ENCODER */ | ||
4911 | |||
4912 | /******************************************************************** | ||
4913 | TEMPLATE pass | ||
4914 | *********************************************************************/ | ||
4915 | |||
4916 | #endif /* __XDELTA3_C_INLINE_PASS__ */ | ||
4917 | #ifdef __XDELTA3_C_TEMPLATE_PASS__ | ||
4918 | |||
4919 | #if XD3_ENCODER | ||
4920 | |||
4921 | /******************************************************************** | ||
4922 | Templates | ||
4923 | *******************************************************************/ | ||
4924 | |||
4925 | /* Template macros */ | ||
4926 | #define XD3_TEMPLATE(x) XD3_TEMPLATE2(x,TEMPLATE) | ||
4927 | #define XD3_TEMPLATE2(x,n) XD3_TEMPLATE3(x,n) | ||
4928 | #define XD3_TEMPLATE3(x,n) x ## n | ||
4929 | #define XD3_STRINGIFY(x) XD3_STRINGIFY2(x) | ||
4930 | #define XD3_STRINGIFY2(x) #x | ||
4931 | |||
4932 | static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream); | ||
4933 | |||
4934 | static const xd3_smatcher XD3_TEMPLATE(__smatcher_) = | ||
4935 | { | ||
4936 | XD3_STRINGIFY(TEMPLATE), | ||
4937 | XD3_TEMPLATE(xd3_string_match_), | ||
4938 | #if SOFTCFG == 1 | ||
4939 | 0, 0, 0, 0, 0, 0, 0 | ||
4940 | #else | ||
4941 | LLOOK, LSTEP, SLOOK, SCHAIN, SLCHAIN, MAXLAZY, LONGENOUGH | ||
4942 | #endif | ||
4943 | }; | ||
4944 | |||
4912 | static int | 4945 | static int |
4913 | XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | 4946 | XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) |
4914 | { | 4947 | { |
@@ -4930,24 +4963,27 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
4930 | usize_t match_offset = 0; | 4963 | usize_t match_offset = 0; |
4931 | usize_t next_move_point; | 4964 | usize_t next_move_point; |
4932 | 4965 | ||
4933 | /* If there will be no compression due to settings or short input, skip it entirely. */ | 4966 | /* If there will be no compression due to settings or short input, |
4967 | skip it entirely. */ | ||
4934 | if (! (DO_SMALL || DO_LARGE || DO_RUN) || | 4968 | if (! (DO_SMALL || DO_LARGE || DO_RUN) || |
4935 | stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } | 4969 | stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } |
4936 | 4970 | ||
4937 | if ((ret = xd3_string_match_init (stream))) { return ret; } | 4971 | if ((ret = xd3_string_match_init (stream))) { return ret; } |
4938 | 4972 | ||
4939 | /* The restartloop label is reached when the incremental loop state needs to be | 4973 | /* The restartloop label is reached when the incremental loop state |
4940 | * reset. */ | 4974 | * needs to be reset. */ |
4941 | restartloop: | 4975 | restartloop: |
4942 | 4976 | ||
4943 | /* If there is not enough input remaining for any kind of match, skip it. */ | 4977 | /* If there is not enough input remaining for any kind of match, |
4978 | skip it. */ | ||
4944 | if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } | 4979 | if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } |
4945 | 4980 | ||
4946 | /* Now reset the incremental loop state: */ | 4981 | /* Now reset the incremental loop state: */ |
4947 | 4982 | ||
4948 | /* The min_match variable is updated to avoid matching the same lazy match over and over | 4983 | /* The min_match variable is updated to avoid matching the same lazy |
4949 | * again. For example, if you find a (small) match of length 9 at one position, you | 4984 | * match over and over again. For example, if you find a (small) |
4950 | * will likely find a match of length 8 at the next position. */ | 4985 | * match of length 9 at one position, you will likely find a match |
4986 | * of length 8 at the next position. */ | ||
4951 | if (xd3_iopt_last_matched (stream) > stream->input_position) | 4987 | if (xd3_iopt_last_matched (stream) > stream->input_position) |
4952 | { | 4988 | { |
4953 | stream->min_match = max(MIN_MATCH, 1 + xd3_iopt_last_matched(stream) - stream->input_position); | 4989 | stream->min_match = max(MIN_MATCH, 1 + xd3_iopt_last_matched(stream) - stream->input_position); |
@@ -4972,13 +5008,15 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
4972 | run_l = xd3_comprun (inp, SLOOK, & run_c); | 5008 | run_l = xd3_comprun (inp, SLOOK, & run_c); |
4973 | } | 5009 | } |
4974 | 5010 | ||
4975 | /* Large match state. We continue the loop even after not enough bytes for LLOOK | 5011 | /* Large match state. We continue the loop even after not enough |
4976 | * remain, so always check stream->input_position in DO_LARGE code. */ | 5012 | * bytes for LLOOK remain, so always check stream->input_position in |
5013 | * DO_LARGE code. */ | ||
4977 | if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) | 5014 | if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) |
4978 | { | 5015 | { |
4979 | /* Source window: next_move_point is the point that stream->input_position must reach before | 5016 | /* Source window: next_move_point is the point that |
4980 | * computing more source checksum. */ | 5017 | * stream->input_position must reach before computing more |
4981 | if ((ret = XD3_TEMPLATE(xd3_srcwin_move_point_) (stream, & next_move_point))) | 5018 | * source checksum. */ |
5019 | if ((ret = xd3_srcwin_move_point (stream, & next_move_point))) | ||
4982 | { | 5020 | { |
4983 | return ret; | 5021 | return ret; |
4984 | } | 5022 | } |
@@ -4986,15 +5024,16 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
4986 | lcksum = xd3_lcksum (inp, LLOOK); | 5024 | lcksum = xd3_lcksum (inp, LLOOK); |
4987 | } | 5025 | } |
4988 | 5026 | ||
4989 | /* TRYLAZYLEN: True if a certain length match should be followed by lazy search. This | 5027 | /* TRYLAZYLEN: True if a certain length match should be followed by |
4990 | * checks that LEN is shorter than MAXLAZY and that there is enough leftover data to | 5028 | * lazy search. This checks that LEN is shorter than MAXLAZY and |
4991 | * consider lazy matching. "Enough" is set to 2 since the next match will start at the | 5029 | * that there is enough leftover data to consider lazy matching. |
4992 | * next offset, it must match two extra characters. */ | 5030 | * "Enough" is set to 2 since the next match will start at the next |
5031 | * offset, it must match two extra characters. */ | ||
4993 | #define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) && (POS) + (LEN) <= (MAX) - 2) | 5032 | #define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) && (POS) + (LEN) <= (MAX) - 2) |
4994 | 5033 | ||
4995 | /* HANDLELAZY: This statement is called each time an instruciton is emitted (three | 5034 | /* HANDLELAZY: This statement is called each time an instruciton is |
4996 | * cases). If the instruction is large enough, the loop is restarted, otherwise lazy | 5035 | * emitted (three cases). If the instruction is large enough, the |
4997 | * matching may ensue. */ | 5036 | * loop is restarted, otherwise lazy matching may ensue. */ |
4998 | #define HANDLELAZY(mlen) \ | 5037 | #define HANDLELAZY(mlen) \ |
4999 | if (TRYLAZYLEN ((mlen), (stream->input_position), (stream->avail_in))) \ | 5038 | if (TRYLAZYLEN ((mlen), (stream->input_position), (stream->avail_in))) \ |
5000 | { stream->min_match = (mlen) + LEAST_MATCH_INCR; goto updateone; } \ | 5039 | { stream->min_match = (mlen) + LEAST_MATCH_INCR; goto updateone; } \ |
@@ -5007,12 +5046,13 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5007 | /* Now we try three kinds of string match in order of expense: | 5046 | /* Now we try three kinds of string match in order of expense: |
5008 | * run, large match, small match. */ | 5047 | * run, large match, small match. */ |
5009 | 5048 | ||
5010 | /* Expand the start of a RUN. The test for (run_l == SLOOK) avoids repeating this | 5049 | /* Expand the start of a RUN. The test for (run_l == SLOOK) |
5011 | * check when we pass through a run area performing lazy matching. The run is only | 5050 | * avoids repeating this check when we pass through a run area |
5012 | * expanded once when the min_match is first reached. If lazy matching is | 5051 | * performing lazy matching. The run is only expanded once when |
5013 | * performed, the run_l variable will remain inconsistent until the first | 5052 | * the min_match is first reached. If lazy matching is |
5014 | * non-running input character is reached, at which time the run_l may then again | 5053 | * performed, the run_l variable will remain inconsistent until |
5015 | * grow to SLOOK. */ | 5054 | * the first non-running input character is reached, at which |
5055 | * time the run_l may then again grow to SLOOK. */ | ||
5016 | if (DO_RUN && run_l == SLOOK) | 5056 | if (DO_RUN && run_l == SLOOK) |
5017 | { | 5057 | { |
5018 | usize_t max_len = stream->avail_in - stream->input_position; | 5058 | usize_t max_len = stream->avail_in - stream->input_position; |
@@ -5034,7 +5074,7 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5034 | if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) | 5074 | if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) |
5035 | { | 5075 | { |
5036 | if ((stream->input_position >= next_move_point) && | 5076 | if ((stream->input_position >= next_move_point) && |
5037 | (ret = XD3_TEMPLATE(xd3_srcwin_move_point_) (stream, & next_move_point))) | 5077 | (ret = xd3_srcwin_move_point (stream, & next_move_point))) |
5038 | { | 5078 | { |
5039 | return ret; | 5079 | return ret; |
5040 | } | 5080 | } |
@@ -5043,15 +5083,18 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5043 | 5083 | ||
5044 | IF_DEBUG (xd3_verify_large_state (stream, inp, lcksum)); | 5084 | IF_DEBUG (xd3_verify_large_state (stream, inp, lcksum)); |
5045 | 5085 | ||
5046 | /* Note: To handle large checksum duplicates, this code should be rearranged to | 5086 | /* Note: To handle large checksum duplicates, this code |
5047 | * resemble the small_match case more. But how much of the code can be truly | 5087 | * should be rearranged to resemble the small_match case |
5048 | * shared? The main difference is the need for xd3_source_extend_match to work | 5088 | * more. But how much of the code can be truly shared? The |
5049 | * outside of xd3_string_match, in the case where inputs are identical. */ | 5089 | * main difference is the need for xd3_source_extend_match |
5090 | * to work outside of xd3_string_match, in the case where | ||
5091 | * inputs are identical. */ | ||
5050 | if (unlikely (stream->large_table[linx] != 0)) | 5092 | if (unlikely (stream->large_table[linx] != 0)) |
5051 | { | 5093 | { |
5052 | /* the match_setup will fail if the source window has been decided and the | 5094 | /* the match_setup will fail if the source window has |
5053 | * match lies outside it. You could consider forcing a window at this point | 5095 | * been decided and the match lies outside it. You |
5054 | * to permit a new source window. */ | 5096 | * could consider forcing a window at this point to |
5097 | * permit a new source window. */ | ||
5055 | xoff_t adj_offset = | 5098 | xoff_t adj_offset = |
5056 | xd3_source_cksum_offset(stream, | 5099 | xd3_source_cksum_offset(stream, |
5057 | stream->large_table[linx] - HASH_CKOFFSET); | 5100 | stream->large_table[linx] - HASH_CKOFFSET); |
@@ -5121,8 +5164,9 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5121 | } | 5164 | } |
5122 | } | 5165 | } |
5123 | 5166 | ||
5124 | /* The logic above prevents excess work during lazy matching by increasing min_match | 5167 | /* The logic above prevents excess work during lazy matching by |
5125 | * to avoid smaller matches. Each time we advance stream->input_position by one, the minimum match | 5168 | * increasing min_match to avoid smaller matches. Each time we |
5169 | * advance stream->input_position by one, the minimum match | ||
5126 | * shortens as well. */ | 5170 | * shortens as well. */ |
5127 | if (stream->min_match > MIN_MATCH) | 5171 | if (stream->min_match > MIN_MATCH) |
5128 | { | 5172 | { |
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index ce90cd7..af79839 100644 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -126,7 +126,11 @@ typedef uint64_t xoff_t; | |||
126 | #define Q "I64" | 126 | #define Q "I64" |
127 | #endif | 127 | #endif |
128 | #else | 128 | #else |
129 | #ifndef __uint32_t_defined | ||
130 | typedef unsigned int xoff_t; | ||
131 | #else | ||
129 | typedef uint32_t xoff_t; | 132 | typedef uint32_t xoff_t; |
133 | #endif | ||
130 | #define SIZEOF_XOFF_T 4 | 134 | #define SIZEOF_XOFF_T 4 |
131 | #define SIZEOF_USIZE_T 4 | 135 | #define SIZEOF_USIZE_T 4 |
132 | #define Q | 136 | #define Q |
@@ -614,23 +618,31 @@ struct _xd3_sec_cfg | |||
614 | struct _xd3_config | 618 | struct _xd3_config |
615 | { | 619 | { |
616 | usize_t winsize; /* The encoder window size. */ | 620 | usize_t winsize; /* The encoder window size. */ |
617 | usize_t sprevsz; /* How far back small string matching goes */ | 621 | usize_t sprevsz; /* How far back small string |
618 | usize_t iopt_size; /* entries in the instruction-optimizing buffer */ | 622 | matching goes */ |
619 | usize_t srcwin_maxsz; /* srcwin_size grows by a factor of 2 when no matches are found */ | 623 | usize_t iopt_size; /* entries in the |
624 | instruction-optimizing | ||
625 | buffer */ | ||
626 | usize_t srcwin_maxsz; /* srcwin_size grows by a factor | ||
627 | of 2 when no matches are | ||
628 | found */ | ||
620 | 629 | ||
621 | xd3_getblk_func *getblk; /* The three callbacks. */ | 630 | xd3_getblk_func *getblk; /* The three callbacks. */ |
622 | xd3_alloc_func *alloc; | 631 | xd3_alloc_func *alloc; |
623 | xd3_free_func *freef; | 632 | xd3_free_func *freef; |
624 | void *opaque; /* Not used. */ | 633 | void *opaque; /* Not used. */ |
625 | int flags; /* stream->flags are initialized from xd3_config & | 634 | int flags; /* stream->flags are initialized |
626 | * never modified by the library. Use xd3_set_flags | 635 | * from xd3_config & never |
627 | * to modify flags settings mid-stream. */ | 636 | * modified by the library. Use |
637 | * xd3_set_flags to modify flags | ||
638 | * settings mid-stream. */ | ||
628 | 639 | ||
629 | xd3_sec_cfg sec_data; /* Secondary compressor config: data */ | 640 | xd3_sec_cfg sec_data; /* Secondary compressor config: data */ |
630 | xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ | 641 | xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ |
631 | xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ | 642 | xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ |
632 | 643 | ||
633 | xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for soft config */ | 644 | xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for |
645 | soft config */ | ||
634 | xd3_smatcher smatcher_soft; | 646 | xd3_smatcher smatcher_soft; |
635 | }; | 647 | }; |
636 | 648 | ||
@@ -645,49 +657,66 @@ struct _xd3_source | |||
645 | /* you set */ | 657 | /* you set */ |
646 | xoff_t size; /* size of this source */ | 658 | xoff_t size; /* size of this source */ |
647 | usize_t blksize; /* block size */ | 659 | usize_t blksize; /* block size */ |
648 | const char *name; /* its name, for debug/print purposes */ | 660 | const char *name; /* its name, for debug/print |
661 | purposes */ | ||
649 | void *ioh; /* opaque handle */ | 662 | void *ioh; /* opaque handle */ |
650 | 663 | ||
651 | /* getblk sets */ | 664 | /* getblk sets */ |
652 | xoff_t curblkno; /* current block number: client sets after getblk request */ | 665 | xoff_t curblkno; /* current block number: client |
653 | usize_t onblk; /* number of bytes on current block: client sets, xd3 verifies */ | 666 | sets after getblk request */ |
654 | const uint8_t *curblk; /* current block array: client sets after getblk request */ | 667 | usize_t onblk; /* number of bytes on current |
668 | block: client sets, xd3 | ||
669 | verifies */ | ||
670 | const uint8_t *curblk; /* current block array: client | ||
671 | sets after getblk request */ | ||
655 | 672 | ||
656 | /* xd3 sets */ | 673 | /* xd3 sets */ |
657 | usize_t srclen; /* length of this source window */ | 674 | usize_t srclen; /* length of this source window */ |
658 | xoff_t srcbase; /* offset of this source window in the source itself */ | 675 | xoff_t srcbase; /* offset of this source window |
659 | xoff_t blocks; /* the total number of blocks in this source */ | 676 | in the source itself */ |
660 | usize_t cpyoff_blocks; /* offset of copy window in blocks */ | 677 | xoff_t blocks; /* the total number of blocks in |
661 | usize_t cpyoff_blkoff; /* offset of copy window in blocks, remainder */ | 678 | this source */ |
662 | xoff_t getblkno; /* request block number: xd3 sets current getblk request */ | 679 | usize_t onlastblk; /* cached size info, avoid __udivdi3 */ |
680 | usize_t cpyoff_blocks; /* offset of copy window in | ||
681 | blocks */ | ||
682 | usize_t cpyoff_blkoff; /* offset of copy window in | ||
683 | blocks, remainder */ | ||
684 | xoff_t getblkno; /* request block number: xd3 sets | ||
685 | current getblk request */ | ||
663 | }; | 686 | }; |
664 | 687 | ||
665 | /* The primary xd3_stream object, used for encoding and decoding. You may access only two | 688 | /* The primary xd3_stream object, used for encoding and decoding. You |
666 | * fields: avail_out, next_out. Use the methods above to operate on xd3_stream. */ | 689 | * may access only two fields: avail_out, next_out. Use the methods |
690 | * above to operate on xd3_stream. */ | ||
667 | struct _xd3_stream | 691 | struct _xd3_stream |
668 | { | 692 | { |
669 | /* input state */ | 693 | /* input state */ |
670 | const uint8_t *next_in; /* next input byte */ | 694 | const uint8_t *next_in; /* next input byte */ |
671 | usize_t avail_in; /* number of bytes available at next_in */ | 695 | usize_t avail_in; /* number of bytes available at |
696 | next_in */ | ||
672 | xoff_t total_in; /* how many bytes in */ | 697 | xoff_t total_in; /* how many bytes in */ |
673 | 698 | ||
674 | /* output state */ | 699 | /* output state */ |
675 | uint8_t *next_out; /* next output byte */ | 700 | uint8_t *next_out; /* next output byte */ |
676 | usize_t avail_out; /* number of bytes available at next_out */ | 701 | usize_t avail_out; /* number of bytes available at |
702 | next_out */ | ||
677 | usize_t space_out; /* total out space */ | 703 | usize_t space_out; /* total out space */ |
678 | xoff_t current_window; /* number of windows encoded/decoded */ | 704 | xoff_t current_window; /* number of windows encoded/decoded */ |
679 | xoff_t total_out; /* how many bytes out */ | 705 | xoff_t total_out; /* how many bytes out */ |
680 | 706 | ||
681 | /* to indicate an error, xd3 sets */ | 707 | /* to indicate an error, xd3 sets */ |
682 | const char *msg; /* last error message, NULL if no error */ | 708 | const char *msg; /* last error message, NULL if |
709 | no error */ | ||
683 | 710 | ||
684 | /* source configuration */ | 711 | /* source configuration */ |
685 | xd3_source *src; /* source array */ | 712 | xd3_source *src; /* source array */ |
686 | 713 | ||
687 | /* encoder memory configuration */ | 714 | /* encoder memory configuration */ |
688 | usize_t winsize; /* suggested window size */ | 715 | usize_t winsize; /* suggested window size */ |
689 | usize_t sprevsz; /* small string, previous window size (power of 2) */ | 716 | usize_t sprevsz; /* small string, previous window |
690 | usize_t sprevmask; /* small string, previous window size mask */ | 717 | size (power of 2) */ |
718 | usize_t sprevmask; /* small string, previous window | ||
719 | size mask */ | ||
691 | uint iopt_size; | 720 | uint iopt_size; |
692 | uint iopt_unlimited; | 721 | uint iopt_unlimited; |
693 | uint srcwin_maxsz; | 722 | uint srcwin_maxsz; |
@@ -696,7 +725,8 @@ struct _xd3_stream | |||
696 | xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */ | 725 | xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */ |
697 | xd3_alloc_func *alloc; /* malloc function */ | 726 | xd3_alloc_func *alloc; /* malloc function */ |
698 | xd3_free_func *free; /* free function */ | 727 | xd3_free_func *free; /* free function */ |
699 | void* opaque; /* private data object passed to alloc, free, and getblk */ | 728 | void* opaque; /* private data object passed to |
729 | alloc, free, and getblk */ | ||
700 | int flags; /* various options */ | 730 | int flags; /* various options */ |
701 | 731 | ||
702 | /* secondary compressor configuration */ | 732 | /* secondary compressor configuration */ |
@@ -710,8 +740,10 @@ struct _xd3_stream | |||
710 | xd3_hash_cfg large_hash; /* large hash config */ | 740 | xd3_hash_cfg large_hash; /* large hash config */ |
711 | 741 | ||
712 | usize_t *small_table; /* table of small checksums */ | 742 | usize_t *small_table; /* table of small checksums */ |
713 | xd3_slist *small_prev; /* table of previous offsets, circular linked list */ | 743 | xd3_slist *small_prev; /* table of previous offsets, |
714 | int small_reset; /* true if small table should be reset */ | 744 | circular linked list */ |
745 | int small_reset; /* true if small table should | ||
746 | be reset */ | ||
715 | 747 | ||
716 | xd3_hash_cfg small_hash; /* small hash config */ | 748 | xd3_hash_cfg small_hash; /* small hash config */ |
717 | xd3_addr_cache acache; /* the vcdiff address cache */ | 749 | xd3_addr_cache acache; /* the vcdiff address cache */ |
@@ -719,39 +751,54 @@ struct _xd3_stream | |||
719 | 751 | ||
720 | usize_t taroff; /* base offset of the target input */ | 752 | usize_t taroff; /* base offset of the target input */ |
721 | usize_t input_position; /* current input position */ | 753 | usize_t input_position; /* current input position */ |
722 | usize_t min_match; /* current minimum match length, avoids redundent matches */ | 754 | usize_t min_match; /* current minimum match |
723 | usize_t unencoded_offset; /* current input, first unencoded offset. this value is <= the first | 755 | length, avoids redundent |
724 | * instruction's position in the iopt buffer, if there is at least one | 756 | matches */ |
757 | usize_t unencoded_offset; /* current input, first | ||
758 | * unencoded offset. this value | ||
759 | * is <= the first instruction's | ||
760 | * position in the iopt buffer, | ||
761 | * if there is at least one | ||
725 | * match in the buffer. */ | 762 | * match in the buffer. */ |
726 | 763 | ||
727 | // SRCWIN | 764 | // SRCWIN |
728 | // these variables plus srcwin_maxsz above (set by config) | 765 | // these variables plus srcwin_maxsz above (set by config) |
729 | int srcwin_decided; /* boolean: true if the srclen,srcbase have been decided. */ | 766 | int srcwin_decided; /* boolean: true if the |
767 | srclen,srcbase have been | ||
768 | decided. */ | ||
730 | xoff_t srcwin_cksum_pos; /* Source checksum position */ | 769 | xoff_t srcwin_cksum_pos; /* Source checksum position */ |
731 | 770 | ||
732 | // MATCH | 771 | // MATCH |
733 | xd3_match_state match_state; /* encoder match state */ | 772 | xd3_match_state match_state; /* encoder match state */ |
734 | xoff_t match_srcpos; /* current match source position relative to srcbase */ | 773 | xoff_t match_srcpos; /* current match source |
735 | xoff_t match_minaddr; /* smallest matching address to set window params | 774 | position relative to |
736 | * (reset each window xd3_encode_reset) */ | 775 | srcbase */ |
737 | xoff_t match_maxaddr; /* largest matching address to set window params | 776 | xoff_t match_minaddr; /* smallest matching address to |
738 | * (reset each window xd3_encode_reset) */ | 777 | * set window params (reset each |
778 | * window xd3_encode_reset) */ | ||
779 | xoff_t match_maxaddr; /* largest matching address to | ||
780 | * set window params (reset each | ||
781 | * window xd3_encode_reset) */ | ||
739 | usize_t match_back; /* match extends back so far */ | 782 | usize_t match_back; /* match extends back so far */ |
740 | usize_t match_maxback; /* match extends back maximum */ | 783 | usize_t match_maxback; /* match extends back maximum */ |
741 | usize_t match_fwd; /* match extends forward so far */ | 784 | usize_t match_fwd; /* match extends forward so far */ |
742 | usize_t match_maxfwd; /* match extends forward maximum */ | 785 | usize_t match_maxfwd; /* match extends forward maximum */ |
743 | 786 | ||
744 | xoff_t maxsrcaddr; /* address of the last source match (across windows) */ | 787 | xoff_t maxsrcaddr; /* address of the last source |
788 | match (across windows) */ | ||
745 | 789 | ||
746 | uint8_t *buf_in; /* for saving buffered input */ | 790 | uint8_t *buf_in; /* for saving buffered input */ |
747 | usize_t buf_avail; /* amount of saved input */ | 791 | usize_t buf_avail; /* amount of saved input */ |
748 | const uint8_t *buf_leftover; /* leftover content of next_in (i.e., user's buffer) */ | 792 | const uint8_t *buf_leftover; /* leftover content of next_in |
793 | (i.e., user's buffer) */ | ||
749 | usize_t buf_leftavail; /* amount of leftover content */ | 794 | usize_t buf_leftavail; /* amount of leftover content */ |
750 | 795 | ||
751 | xd3_output *enc_current; /* current output buffer */ | 796 | xd3_output *enc_current; /* current output buffer */ |
752 | xd3_output *enc_free; /* free output buffers */ | 797 | xd3_output *enc_free; /* free output buffers */ |
753 | xd3_output *enc_heads[4]; /* array of encoded outputs: head of chain */ | 798 | xd3_output *enc_heads[4]; /* array of encoded outputs: |
754 | xd3_output *enc_tails[4]; /* array of encoded outputs: tail of chain */ | 799 | head of chain */ |
800 | xd3_output *enc_tails[4]; /* array of encoded outputs: | ||
801 | tail of chain */ | ||
755 | 802 | ||
756 | xd3_rlist iopt_used; /* instruction optimizing buffer */ | 803 | xd3_rlist iopt_used; /* instruction optimizing buffer */ |
757 | xd3_rlist iopt_free; | 804 | xd3_rlist iopt_free; |
@@ -776,16 +823,21 @@ struct _xd3_stream | |||
776 | uint8_t *dec_codetbl; /* Optional code table: storage. */ | 823 | uint8_t *dec_codetbl; /* Optional code table: storage. */ |
777 | usize_t dec_codetblbytes; /* Optional code table: position. */ | 824 | usize_t dec_codetblbytes; /* Optional code table: position. */ |
778 | 825 | ||
779 | uint32_t dec_appheadsz; /* Optional application header: size. */ | 826 | uint32_t dec_appheadsz; /* Optional application header: |
780 | uint8_t *dec_appheader; /* Optional application header: storage */ | 827 | size. */ |
781 | usize_t dec_appheadbytes; /* Optional application header: position. */ | 828 | uint8_t *dec_appheader; /* Optional application header: |
829 | storage */ | ||
830 | usize_t dec_appheadbytes; /* Optional application header: | ||
831 | position. */ | ||
782 | 832 | ||
783 | usize_t dec_cksumbytes; /* Optional checksum: position. */ | 833 | usize_t dec_cksumbytes; /* Optional checksum: position. */ |
784 | uint8_t dec_cksum[4]; /* Optional checksum: storage. */ | 834 | uint8_t dec_cksum[4]; /* Optional checksum: storage. */ |
785 | uint32_t dec_adler32; /* Optional checksum: value. */ | 835 | uint32_t dec_adler32; /* Optional checksum: value. */ |
786 | 836 | ||
787 | uint32_t dec_cpylen; /* length of copy window (VCD_SOURCE or VCD_TARGET) */ | 837 | uint32_t dec_cpylen; /* length of copy window |
788 | xoff_t dec_cpyoff; /* offset of copy window (VCD_SOURCE or VCD_TARGET) */ | 838 | (VCD_SOURCE or VCD_TARGET) */ |
839 | xoff_t dec_cpyoff; /* offset of copy window | ||
840 | (VCD_SOURCE or VCD_TARGET) */ | ||
789 | uint32_t dec_enclen; /* length of delta encoding */ | 841 | uint32_t dec_enclen; /* length of delta encoding */ |
790 | uint32_t dec_tgtlen; /* length of target window */ | 842 | uint32_t dec_tgtlen; /* length of target window */ |
791 | 843 | ||
@@ -1114,7 +1166,10 @@ const char* xd3_errstring (xd3_stream *stream) | |||
1114 | 1166 | ||
1115 | /* This function tells the number of bytes expected to be set in | 1167 | /* This function tells the number of bytes expected to be set in |
1116 | * source->onblk after a getblk request. This is for convenience of | 1168 | * source->onblk after a getblk request. This is for convenience of |
1117 | * handling a partial last block. */ | 1169 | * handling a partial last block. Note that this is a relatively |
1170 | * expensive function for 64-bit binaries on platforms w/o native | ||
1171 | * 64-bit integers, so source->onlastblk is set to this value. | ||
1172 | * TODO: force source->blksize to a power of two? */ | ||
1118 | static inline | 1173 | static inline |
1119 | usize_t xd3_bytes_on_srcblk (xd3_source *source, xoff_t blkno) | 1174 | usize_t xd3_bytes_on_srcblk (xd3_source *source, xoff_t blkno) |
1120 | { | 1175 | { |
@@ -1128,4 +1183,12 @@ usize_t xd3_bytes_on_srcblk (xd3_source *source, xoff_t blkno) | |||
1128 | return (usize_t)((source->size - 1) % source->blksize) + 1; | 1183 | return (usize_t)((source->size - 1) % source->blksize) + 1; |
1129 | } | 1184 | } |
1130 | 1185 | ||
1186 | static inline | ||
1187 | usize_t xd3_bytes_on_srcblk_fast (xd3_source *source, xoff_t blkno) | ||
1188 | { | ||
1189 | return (blkno == source->blocks - 1 ? | ||
1190 | source->onlastblk : | ||
1191 | source->blksize); | ||
1192 | } | ||
1193 | |||
1131 | #endif /* _XDELTA3_H_ */ | 1194 | #endif /* _XDELTA3_H_ */ |