summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2007-02-01 09:17:19 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2007-02-01 09:17:19 +0000
commit8748d16e6e5bf741ede89af1940f8291fb1b8046 (patch)
tree2c9d393e21eb669ae6bdecf931331e1202bffec6
parent9f465a9db201b97c43d69778eabd222d4fc09fd5 (diff)
Implmeent xd3_encode_memory() and xd3_decode_memory(), add comments.
-rwxr-xr-xxdelta3/Makefile23
-rwxr-xr-xxdelta3/linkxd3lib.c4
-rwxr-xr-xxdelta3/setup.py2
-rwxr-xr-xxdelta3/xdelta3-regtest.py48
-rwxr-xr-xxdelta3/xdelta3-test.h56
-rwxr-xr-xxdelta3/xdelta3.c186
-rwxr-xr-xxdelta3/xdelta3.h125
-rwxr-xr-xxdelta3/xdelta3.prj35
8 files changed, 344 insertions, 135 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile
index ea86e3d..b300310 100755
--- a/xdelta3/Makefile
+++ b/xdelta3/Makefile
@@ -13,13 +13,19 @@ SOURCES = xdelta3-cfgs.h \
13 xdelta3.c \ 13 xdelta3.c \
14 xdelta3.h 14 xdelta3.h
15 15
16TARGETS = xdelta3 xdelta3-debug xdelta3-64 xdelta3-everything \ 16TARGETS = xdelta3-debug \
17 xdelta3-Opg xdelta3-64-O xdelta3-Op xdelta3-O \ 17 xdelta3 \
18 xdelta3-32 \
19 xdelta3-64 \
20 xdelta3-everything \
21 xdelta3-Opg \
22 xdelta3-64-O \
23 xdelta3-Op \
18 xdelta3-decoder xdelta3-decoder-nomain.o \ 24 xdelta3-decoder xdelta3-decoder-nomain.o \
19 $(PYTGT) \
20 xdelta3-nosec.o xdelta3-all.o xdelta3-fgk.o xdelta3-djw.o \ 25 xdelta3-nosec.o xdelta3-all.o xdelta3-fgk.o xdelta3-djw.o \
21 xdelta3-noext xdelta3-tools xdelta3-tune \ 26 xdelta3-noext xdelta3-tools xdelta3-tune \
22 xdelta3-notools 27 xdelta3-notools \
28 $(PYTGT) \
23 29
24PYTHON = python 30PYTHON = python
25PYTGT = build/lib.linux-i686-2.4/xdelta3.so 31PYTGT = build/lib.linux-i686-2.4/xdelta3.so
@@ -37,8 +43,13 @@ all: xdelta3-debug xdelta3 $(PYTGT)
37 43
38all-targets: $(TARGETS) 44all-targets: $(TARGETS)
39 45
46all-targets-test: all-targets test
47
40pytgt: $(PYTGT) 48pytgt: $(PYTGT)
41 49
50test:
51 ./xdelta3-debug test
52
42tar: 53tar:
43 tar --exclude ".svn" -czf /tmp/$(RELDIR)-tmp.tar.gz $(SOURCES) $(PYFILES) $(EXTRA) 54 tar --exclude ".svn" -czf /tmp/$(RELDIR)-tmp.tar.gz $(SOURCES) $(PYFILES) $(EXTRA)
44 rm -rf /tmp/$(RELDIR) 55 rm -rf /tmp/$(RELDIR)
@@ -81,8 +92,8 @@ xdelta3-decoder-nomain.o: $(SOURCES) linkxd3lib.c
81 -o xdelta3-decoder-nomain.o 92 -o xdelta3-decoder-nomain.o
82 strip xdelta3-decoder-nomain.o 93 strip xdelta3-decoder-nomain.o
83 94
84xdelta3-O: $(SOURCES) 95xdelta3-32: $(SOURCES)
85 $(CC) -g -O2 -Wall -Wshadow xdelta3.c -o xdelta3-O -DXD3_MAIN=1 -DSECONDARY_DJW=1 -DREGRESSION_TEST=1 -lm 96 $(CC) -g -O2 -Wall -Wshadow xdelta3.c -o xdelta3-32 -DXD3_MAIN=1 -DSECONDARY_DJW=1 -DREGRESSION_TEST=1 -lm
86 97
87xdelta3-O++: $(SOURCES) 98xdelta3-O++: $(SOURCES)
88 $(CXX) -g -O2 -Wall -Wshadow xdelta3.c -o xdelta3-O++ -DXD3_MAIN=1 -DSECONDARY_DJW=1 -DREGRESSION_TEST=1 -lm 99 $(CXX) -g -O2 -Wall -Wshadow xdelta3.c -o xdelta3-O++ -DXD3_MAIN=1 -DSECONDARY_DJW=1 -DREGRESSION_TEST=1 -lm
diff --git a/xdelta3/linkxd3lib.c b/xdelta3/linkxd3lib.c
index feed876..6064467 100755
--- a/xdelta3/linkxd3lib.c
+++ b/xdelta3/linkxd3lib.c
@@ -27,7 +27,7 @@ int main() {
27 use (xd3_set_source (& stream, & source)); 27 use (xd3_set_source (& stream, & source));
28 xd3_set_flags (& stream, 0); 28 xd3_set_flags (& stream, 0);
29 29
30 use (xd3_decode_completely_stream (& stream, NULL, 0, NULL, NULL, 0)); 30 use (xd3_decode_stream (& stream, NULL, 0, NULL, NULL, 0));
31 use (xd3_decode_input (&stream)); 31 use (xd3_decode_input (&stream));
32 use (xd3_decoder_needs_source (& stream)); 32 use (xd3_decoder_needs_source (& stream));
33 use (xd3_get_appheader (& stream, NULL, NULL)); 33 use (xd3_get_appheader (& stream, NULL, NULL));
@@ -37,7 +37,7 @@ int main() {
37 37
38#if XD3_ENCODER 38#if XD3_ENCODER
39 use (xd3_encode_input (&stream)); 39 use (xd3_encode_input (&stream));
40 use (xd3_encode_completely_stream (& stream, NULL, 0, NULL, NULL, 0)); 40 use (xd3_encode_stream (& stream, NULL, 0, NULL, NULL, 0));
41 use (xd3_set_appheader (& stream)); 41 use (xd3_set_appheader (& stream));
42 use (xd3_encoder_used_source (& stream)); 42 use (xd3_encoder_used_source (& stream));
43 use (xd3_encoder_srcbase (& stream)); 43 use (xd3_encoder_srcbase (& stream));
diff --git a/xdelta3/setup.py b/xdelta3/setup.py
index 289219e..2fe3b19 100755
--- a/xdelta3/setup.py
+++ b/xdelta3/setup.py
@@ -39,6 +39,8 @@ xdelta3_ext = Extension('xdelta3',
39# $Format: "REL='$Xdelta3Version$'" $ 39# $Format: "REL='$Xdelta3Version$'" $
40REL='0m' 40REL='0m'
41 41
42# This provides xdelta3.main(), which calls the xdelta3 command-line main()
43# from python.
42setup(name='xdelta3', 44setup(name='xdelta3',
43 version=REL, 45 version=REL,
44 ext_modules=[xdelta3_ext]) 46 ext_modules=[xdelta3_ext])
diff --git a/xdelta3/xdelta3-regtest.py b/xdelta3/xdelta3-regtest.py
index 764eed4..656d617 100755
--- a/xdelta3/xdelta3-regtest.py
+++ b/xdelta3/xdelta3-regtest.py
@@ -46,8 +46,8 @@ MAX_RUN = 1000 * 1000 * 10
46 46
47# 47#
48# 48#
49#RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS' 49RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS'
50RCSDIR = 'Z:/Polaroid/orbit_linux/home/jmacd/PRCS' 50#RCSDIR = 'Z:/Polaroid/orbit_linux/home/jmacd/PRCS'
51 51
52TMPDIR = '/tmp/xd3regtest.%d' % os.getpid() 52TMPDIR = '/tmp/xd3regtest.%d' % os.getpid()
53 53
@@ -712,15 +712,17 @@ class RandomTester:
712 runner.extra = ['-I', '0', '-D', '-C', ','.join(strs)] 712 runner.extra = ['-I', '0', '-D', '-C', ','.join(strs)]
713 result = TimeRun(runner.Runner(f1, 1, f2, 2)) 713 result = TimeRun(runner.Runner(f1, 1, f2, 2))
714 714
715 print 'config %s dsize %d time %.7f in %u trials' % \ 715 tr = RandomTestResult(config,
716 (' '.join(strs), 716 result.time.mean,
717 result.r1.dsize, 717 result.r1.dsize)
718 result.time.mean, 718
719 self.results.append(tr)
720
721 print 'Trial %d: %s in %u trials' % \
722 (trial_num++,
723 tr,
719 result.trials) 724 result.trials)
720 725
721 self.results.append(RandomTestResult(config,
722 result.time.mean,
723 result.r1.dsize))
724 return 726 return
725 #end 727 #end
726 728
@@ -782,19 +784,27 @@ def RunSpeed():
782if __name__ == "__main__": 784if __name__ == "__main__":
783 try: 785 try:
784 os.mkdir(TMPDIR) 786 os.mkdir(TMPDIR)
785 #rcsf = Test() 787 rcsf = Test()
786 #rcsf.PairsByDate(Xdelta3Pair()) 788
787 #RunSpeed()
788 #f1, f2 = MakeBigFiles(rcsf)
789 f1 = '/tmp/big.1'
790 f2 = '/tmp/big.2'
791 test = RandomTester()
792 while 1: 789 while 1:
793 while not test.HasEnoughResults(): 790 f1, f2 = MakeBigFiles(rcsf)
794 test.RandomBigRun(f1, f2) 791 #f1 = '/tmp/big.1'
792 #f2 = '/tmp/big.2'
793 test = RandomTester()
794 while 1:
795 while not test.HasEnoughResults():
796 test.RandomBigRun(f1, f2)
797 #end
798 test.ScoreTests()
795 #end 799 #end
796 test.ScoreTests()
797 #end 800 #end
801
802 # This tests pairwise (date-ordered) performance
803 #rcsf.PairsByDate(Xdelta3Pair())
804
805 # This tests the raw speed of 0-byte inputs
806 #RunSpeed()
807
798 except CommandError: 808 except CommandError:
799 pass 809 pass
800 else: 810 else:
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h
index af90a90..ea0bd49 100755
--- a/xdelta3/xdelta3-test.h
+++ b/xdelta3/xdelta3-test.h
@@ -670,7 +670,7 @@ static const uint8_t test_apphead[] = "header test";
670static int 670static int
671test_compress_text (xd3_stream *stream, 671test_compress_text (xd3_stream *stream,
672 uint8_t *encoded, 672 uint8_t *encoded,
673 usize_t *encoded_size) 673 usize_t *encoded_size)
674{ 674{
675 int ret; 675 int ret;
676 xd3_config cfg; 676 xd3_config cfg;
@@ -701,8 +701,8 @@ test_compress_text (xd3_stream *stream,
701 701
702 xd3_set_appheader (stream, test_apphead, sizeof (test_apphead)); 702 xd3_set_appheader (stream, test_apphead, sizeof (test_apphead));
703 703
704 if ((ret = xd3_encode_completely_stream (stream, test_text, sizeof (test_text), 704 if ((ret = xd3_encode_stream (stream, test_text, sizeof (test_text),
705 encoded, encoded_size, 4*sizeof (test_text)))) { goto fail; } 705 encoded, encoded_size, 4*sizeof (test_text)))) { goto fail; }
706 706
707 if ((ret = xd3_close_stream (stream))) { goto fail; } 707 if ((ret = xd3_close_stream (stream))) { goto fail; }
708 708
@@ -1384,7 +1384,7 @@ test_streaming (xd3_stream *in_stream, uint8_t *encbuf, uint8_t *decbuf, uint8_t
1384 1384
1385 if ((i % 200) == 199) { DOT (); } 1385 if ((i % 200) == 199) { DOT (); }
1386 1386
1387 if ((ret = xd3_process_completely_stream (& estream, xd3_encode_input, 0, 1387 if ((ret = xd3_process_stream (& estream, xd3_encode_input, 0,
1388 encbuf, 1 << 20, 1388 encbuf, 1 << 20,
1389 delbuf, & delsize, 1 << 10))) 1389 delbuf, & delsize, 1 << 10)))
1390 { 1390 {
@@ -1392,7 +1392,7 @@ test_streaming (xd3_stream *in_stream, uint8_t *encbuf, uint8_t *decbuf, uint8_t
1392 goto fail; 1392 goto fail;
1393 } 1393 }
1394 1394
1395 if ((ret = xd3_process_completely_stream (& dstream, xd3_decode_input, 0, 1395 if ((ret = xd3_process_stream (& dstream, xd3_decode_input, 0,
1396 delbuf, delsize, 1396 delbuf, delsize,
1397 decbuf, & decsize, 1 << 20))) 1397 decbuf, & decsize, 1 << 20)))
1398 { 1398 {
@@ -1921,7 +1921,7 @@ test_identical_behavior (xd3_stream *stream, int ignore)
1921 if ((ret = xd3_set_source (stream, & source))) { goto fail; } 1921 if ((ret = xd3_set_source (stream, & source))) { goto fail; }
1922 1922
1923 /* Decode. */ 1923 /* Decode. */
1924 if ((ret = xd3_decode_completely_stream (stream, del, delpos, rec, & recsize, IDB_TGTSZ))) { goto fail; } 1924 if ((ret = xd3_decode_stream (stream, del, delpos, rec, & recsize, IDB_TGTSZ))) { goto fail; }
1925 1925
1926 /* Check result size and data. */ 1926 /* Check result size and data. */
1927 if (recsize != IDB_TGTSZ) { stream->msg = "wrong size reconstruction"; goto fail; } 1927 if (recsize != IDB_TGTSZ) { stream->msg = "wrong size reconstruction"; goto fail; }
@@ -2135,7 +2135,7 @@ test_iopt_flush_instructions (xd3_stream *stream, int ignore)
2135 target[tpos++] = i; 2135 target[tpos++] = i;
2136 } 2136 }
2137 2137
2138 if ((ret = xd3_encode_completely_stream (stream, target, tpos, 2138 if ((ret = xd3_encode_stream (stream, target, tpos,
2139 delta, & delta_size, sizeof (delta)))) 2139 delta, & delta_size, sizeof (delta))))
2140 { 2140 {
2141 return ret; 2141 return ret;
@@ -2144,8 +2144,8 @@ test_iopt_flush_instructions (xd3_stream *stream, int ignore)
2144 xd3_free_stream(stream); 2144 xd3_free_stream(stream);
2145 if ((ret = xd3_config_stream (stream, & config))) { return ret; } 2145 if ((ret = xd3_config_stream (stream, & config))) { return ret; }
2146 2146
2147 if ((ret = xd3_decode_completely_stream (stream, delta, delta_size, 2147 if ((ret = xd3_decode_stream (stream, delta, delta_size,
2148 recon, & recon_size, sizeof (recon)))) 2148 recon, & recon_size, sizeof (recon))))
2149 { 2149 {
2150 return ret; 2150 return ret;
2151 } 2151 }
@@ -2206,6 +2206,43 @@ test_source_cksum_offset (xd3_stream *stream, int ignore)
2206 return 0; 2206 return 0;
2207} 2207}
2208 2208
2209static int
2210test_in_memory (xd3_stream *stream, int ignore)
2211{
2212 // test_text is 256 bytes
2213 char ibuf[sizeof(test_text)];
2214 char dbuf[sizeof(test_text)];
2215 char obuf[sizeof(test_text)];
2216 int size = sizeof(test_text);
2217 int dsize, osize;
2218 int r1, r2;
2219 int eflags = SECONDARY_DJW ? XD3_SEC_DJW : 0;
2220
2221 memcpy(ibuf, test_text, size);
2222 memset(ibuf + 128, 0, 16);
2223
2224 r1 = xd3_encode_memory(ibuf, size,
2225 test_text, size,
2226 dbuf, &dsize, size, eflags);
2227
2228 r2 = xd3_decode_memory(dbuf, dsize,
2229 test_text, size,
2230 obuf, &osize, size, 0);
2231
2232 if (r1 != 0 || r2 != 0 || dsize >= (size/2) || dsize < 1 ||
2233 osize != size) {
2234 stream->msg = "encode/decode size error";
2235 return XD3_INTERNAL;
2236 }
2237
2238 if (memcmp(obuf, ibuf, size) != 0) {
2239 stream->msg = "encode/decode data error";
2240 return XD3_INTERNAL;
2241 }
2242
2243 return 0;
2244}
2245
2209/****************************************************************************************** 2246/******************************************************************************************
2210 TEST MAIN 2247 TEST MAIN
2211 ******************************************************************************************/ 2248 ******************************************************************************************/
@@ -2248,6 +2285,7 @@ xd3_selftest (void)
2248 IF_GENCODETBL (DO_TEST (choose_instruction, XD3_ALT_CODE_TABLE, 0)); 2285 IF_GENCODETBL (DO_TEST (choose_instruction, XD3_ALT_CODE_TABLE, 0));
2249 IF_GENCODETBL (DO_TEST (encode_code_table, 0, 0)); 2286 IF_GENCODETBL (DO_TEST (encode_code_table, 0, 0));
2250 2287
2288 DO_TEST (in_memory, 0, 0);
2251 DO_TEST (identical_behavior, 0, 0); 2289 DO_TEST (identical_behavior, 0, 0);
2252 DO_TEST (iopt_flush_instructions, 0, 0); 2290 DO_TEST (iopt_flush_instructions, 0, 0);
2253 DO_TEST (source_cksum_offset, 0, 0); 2291 DO_TEST (source_cksum_offset, 0, 0);
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index aaea811..5740777 100755
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -763,9 +763,7 @@ static const xd3_sec_type djw_sec_type =
763 * allowing to vary the distribution of single- and 763 * allowing to vary the distribution of single- and
764 * double-instructions and change the number of near and same copy 764 * double-instructions and change the number of near and same copy
765 * modes. More exotic tables are only possible by extending this 765 * modes. More exotic tables are only possible by extending this
766 * code, but a detailed experiment would need to be carried out first, 766 * code. TODO: experiment with a double-copy instruction.
767 * probably using separate code. I would like to experiment with a
768 * double-copy instruction, for example.
769 * 767 *
770 * For performance reasons, both the parametrized and non-parametrized 768 * For performance reasons, both the parametrized and non-parametrized
771 * versions of xd3_choose_instruction remain. The parametrized 769 * versions of xd3_choose_instruction remain. The parametrized
@@ -1209,8 +1207,8 @@ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *cod
1209 1207
1210 if ((ret = xd3_set_source (& stream, & source))) { goto fail; } 1208 if ((ret = xd3_set_source (& stream, & source))) { goto fail; }
1211 1209
1212 if ((ret = xd3_encode_completely_stream (& stream, code_string, CODE_TABLE_STRING_SIZE, 1210 if ((ret = xd3_encode_stream (& stream, code_string, CODE_TABLE_STRING_SIZE,
1213 comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE))) { goto fail; } 1211 comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE))) { goto fail; }
1214 1212
1215 fail: 1213 fail:
1216 1214
@@ -1405,7 +1403,7 @@ xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t si
1405 1403
1406 if ((ret = xd3_config_stream (& stream, NULL)) || 1404 if ((ret = xd3_config_stream (& stream, NULL)) ||
1407 (ret = xd3_set_source (& stream, & source)) || 1405 (ret = xd3_set_source (& stream, & source)) ||
1408 (ret = xd3_decode_completely_stream (& stream, data, size, code_string, & code_size, sizeof (code_string)))) 1406 (ret = xd3_decode_stream (& stream, data, size, code_string, & code_size, sizeof (code_string))))
1409 { 1407 {
1410 in_stream->msg = stream.msg; 1408 in_stream->msg = stream.msg;
1411 goto fail; 1409 goto fail;
@@ -3809,17 +3807,15 @@ xd3_encode_input (xd3_stream *stream)
3809 Client convenience functions 3807 Client convenience functions
3810 ******************************************************************************************/ 3808 ******************************************************************************************/
3811 3809
3812/* This function invokes either encode or decode to and from in-memory arrays. The output array
3813 * must be large enough to hold the output or else ENOSPC is returned. */
3814static int 3810static int
3815xd3_process_completely_stream (xd3_stream *stream, 3811xd3_process_stream (xd3_stream *stream,
3816 int (*func) (xd3_stream *), 3812 int (*func) (xd3_stream *),
3817 int close_stream, 3813 int close_stream,
3818 const uint8_t *input, 3814 const uint8_t *input,
3819 usize_t input_size, 3815 usize_t input_size,
3820 uint8_t *output, 3816 uint8_t *output,
3821 usize_t *output_size, 3817 usize_t *output_size,
3822 usize_t avail_size) 3818 usize_t output_size_max)
3823{ 3819{
3824 (*output_size) = 0; 3820 (*output_size) = 0;
3825 3821
@@ -3842,13 +3838,17 @@ xd3_process_completely_stream (xd3_stream *stream,
3842 stream->msg = "stream requires source input"; 3838 stream->msg = "stream requires source input";
3843 return XD3_INTERNAL; 3839 return XD3_INTERNAL;
3844 } 3840 }
3845 case 0: /* there is no plain "success" return for xd3_encode/decode */ 3841 case 0:
3846 XD3_ASSERT (ret != 0); 3842 {
3843 /* xd3_encode_input/xd3_decode_input never return 0 */
3844 stream->msg = "invalid return: 0";
3845 return XD3_INTERNAL;
3846 }
3847 default: 3847 default:
3848 return ret; 3848 return ret;
3849 } 3849 }
3850 3850
3851 if (*output_size + stream->avail_out > avail_size) 3851 if (*output_size + stream->avail_out > output_size_max)
3852 { 3852 {
3853 stream->msg = "insufficient output space"; 3853 stream->msg = "insufficient output space";
3854 return ENOSPC; 3854 return ENOSPC;
@@ -3864,34 +3864,129 @@ xd3_process_completely_stream (xd3_stream *stream,
3864 return (close_stream == 0) ? 0 : xd3_close_stream (stream); 3864 return (close_stream == 0) ? 0 : xd3_close_stream (stream);
3865} 3865}
3866 3866
3867static int
3868xd3_process_memory (int (*func) (xd3_stream *),
3869 int close_stream,
3870 const uint8_t *input,
3871 usize_t input_size,
3872 const uint8_t *source,
3873 usize_t source_size,
3874 uint8_t *output,
3875 usize_t *output_size,
3876 usize_t output_size_max,
3877 int flags) {
3878 xd3_stream stream;
3879 xd3_config config;
3880 xd3_source src;
3881 int ret;
3882
3883 /* TODO: for small inputs, the xd3_stream could be configured to allocate MUCH less
3884 * memory. Most of the allocations sizes are defaulted (see xdelta3.h), and assume
3885 * large inputs. */
3886 memset (& stream, 0, sizeof (stream));
3887 memset (& config, 0, sizeof (config));
3888
3889 config.flags = flags;
3890 config.srcwin_maxsz = source_size;
3891 config.winsize = input_size;
3892
3893 if ((ret = xd3_config_stream (&stream, &config)) != 0)
3894 {
3895 goto exit;
3896 }
3897
3898 if (source != NULL)
3899 {
3900 memset (& src, 0, sizeof (src));
3901 src.size = source_size;
3902 src.blksize = source_size;
3903 src.onblk = source_size;
3904 src.curblk = source;
3905 src.curblkno = 0;
3906
3907 if ((ret = xd3_set_source (&stream, &src)) != 0)
3908 {
3909 goto exit;
3910 }
3911 }
3912
3913 if ((ret = xd3_process_stream (& stream,
3914 func, 1,
3915 input, input_size,
3916 output,
3917 output_size,
3918 output_size_max)) != 0)
3919 {
3920 goto exit;
3921 }
3922
3923 exit:
3924 xd3_free_stream(&stream);
3925 return ret;
3926}
3927
3867int 3928int
3868xd3_decode_completely_stream (xd3_stream *stream, 3929xd3_decode_stream (xd3_stream *stream,
3869 const uint8_t *input, 3930 const uint8_t *input,
3870 usize_t input_size, 3931 usize_t input_size,
3871 uint8_t *output, 3932 uint8_t *output,
3872 usize_t *output_size, 3933 usize_t *output_size,
3873 usize_t avail_size) 3934 usize_t output_size_max)
3874{ 3935{
3875 return xd3_process_completely_stream (stream, & xd3_decode_input, 1, 3936 return xd3_process_stream (stream, & xd3_decode_input, 1,
3876 input, input_size, 3937 input, input_size,
3877 output, output_size, avail_size); 3938 output, output_size, output_size_max);
3878} 3939}
3879 3940
3941int
3942xd3_decode_memory (const uint8_t *input,
3943 usize_t input_size,
3944 const uint8_t *source,
3945 usize_t source_size,
3946 uint8_t *output,
3947 usize_t *output_size,
3948 usize_t output_size_max,
3949 int flags) {
3950 return xd3_process_memory (& xd3_decode_input, 1,
3951 input, input_size,
3952 source, source_size,
3953 output, output_size, output_size_max,
3954 flags);
3955}
3956
3957
3880#if XD3_ENCODER 3958#if XD3_ENCODER
3881int 3959int
3882xd3_encode_completely_stream (xd3_stream *stream, 3960xd3_encode_stream (xd3_stream *stream,
3883 const uint8_t *input, 3961 const uint8_t *input,
3884 usize_t input_size, 3962 usize_t input_size,
3885 uint8_t *output, 3963 uint8_t *output,
3886 usize_t *output_size, 3964 usize_t *output_size,
3887 usize_t avail_size) 3965 usize_t output_size_max)
3888{ 3966{
3889 return xd3_process_completely_stream (stream, & xd3_encode_input, 1, 3967 return xd3_process_stream (stream, & xd3_encode_input, 1,
3890 input, input_size, 3968 input, input_size,
3891 output, output_size, avail_size); 3969 output, output_size, output_size_max);
3970}
3971
3972int
3973xd3_encode_memory (const uint8_t *input,
3974 usize_t input_size,
3975 const uint8_t *source,
3976 usize_t source_size,
3977 uint8_t *output,
3978 usize_t *output_size,
3979 usize_t output_size_max,
3980 int flags) {
3981 return xd3_process_memory (& xd3_encode_input, 1,
3982 input, input_size,
3983 source, source_size,
3984 output, output_size, output_size_max,
3985 flags);
3892} 3986}
3893#endif 3987#endif
3894 3988
3989
3895/****************************************************************************************** 3990/******************************************************************************************
3896 String matching helpers 3991 String matching helpers
3897 ******************************************************************************************/ 3992 ******************************************************************************************/
@@ -3996,7 +4091,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
3996 stream->srcwin_cksum_pos = stream->maxsrcaddr; 4091 stream->srcwin_cksum_pos = stream->maxsrcaddr;
3997 } 4092 }
3998 4093
3999 if (logical_input_cksum_pos < stream->srcwin_cksum_pos) 4094 if (logical_input_cksum_pos < stream->srcwin_cksum_pos)
4000 { 4095 {
4001 logical_input_cksum_pos = stream->srcwin_cksum_pos; 4096 logical_input_cksum_pos = stream->srcwin_cksum_pos;
4002 } 4097 }
@@ -4004,7 +4099,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4004 /* Advance an extra srcwin_size bytes */ 4099 /* Advance an extra srcwin_size bytes */
4005 logical_input_cksum_pos += stream->srcwin_size; 4100 logical_input_cksum_pos += stream->srcwin_size;
4006 4101
4007 IF_DEBUG1 (P(RINT "[srcwin_move_point] T=%"Q"u S=%"Q"u/%"Q"u\n", 4102 IF_DEBUG1 (P(RINT "[srcwin_move_point] T=%"Q"u S=%"Q"u/%"Q"u\n",
4008 stream->total_in + stream->input_position, 4103 stream->total_in + stream->input_position,
4009 stream->srcwin_cksum_pos, 4104 stream->srcwin_cksum_pos,
4010 logical_input_cksum_pos)); 4105 logical_input_cksum_pos));
@@ -4038,6 +4133,9 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4038 diff = logical_input_cksum_pos - stream->srcwin_cksum_pos; 4133 diff = logical_input_cksum_pos - stream->srcwin_cksum_pos;
4039 onblk = min(blkoff + diff, onblk); 4134 onblk = min(blkoff + diff, onblk);
4040 4135
4136 /* TODO: This block needs to be included in the template pass... duh.
4137 */
4138
4041 /* Note: I experimented with rewriting this block to use LARGE_CKSUM_UPDATE() 4139 /* Note: I experimented with rewriting this block to use LARGE_CKSUM_UPDATE()
4042 * instead of recalculating the cksum every N bytes. It seemed to make performance 4140 * instead of recalculating the cksum every N bytes. It seemed to make performance
4043 * worse. */ 4141 * worse. */
@@ -4066,7 +4164,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4066 4164
4067/* This function handles the 32/64bit ambiguity -- file positions are 64bit but the hash 4165/* This function handles the 32/64bit ambiguity -- file positions are 64bit but the hash
4068 * table for source-offsets is 32bit. */ 4166 * table for source-offsets is 32bit. */
4069static xoff_t 4167static xoff_t
4070xd3_source_cksum_offset(xd3_stream *stream, usize_t low) 4168xd3_source_cksum_offset(xd3_stream *stream, usize_t low)
4071{ 4169{
4072 xoff_t scp = stream->srcwin_cksum_pos; 4170 xoff_t scp = stream->srcwin_cksum_pos;
@@ -4179,7 +4277,7 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos)
4179 greedy_or_not = stream->unencoded_offset; 4277 greedy_or_not = stream->unencoded_offset;
4180 } 4278 }
4181 4279
4182 4280
4183 4281
4184 /* Backward target match limit. */ 4282 /* Backward target match limit. */
4185 XD3_ASSERT (stream->input_position >= greedy_or_not); 4283 XD3_ASSERT (stream->input_position >= greedy_or_not);
@@ -4295,7 +4393,7 @@ xd3_source_extend_match (xd3_stream *stream)
4295 { 4393 {
4296 break; 4394 break;
4297 } 4395 }
4298 4396
4299 /* could be a XD3_GETSRCBLK failure. */ 4397 /* could be a XD3_GETSRCBLK failure. */
4300 return ret; 4398 return ret;
4301 } 4399 }
@@ -4387,7 +4485,7 @@ xd3_source_extend_match (xd3_stream *stream)
4387 4485
4388 /* Correct the variables to remove match_back from the equation. */ 4486 /* Correct the variables to remove match_back from the equation. */
4389 // IT'S A BUG! 4487 // IT'S A BUG!
4390 4488
4391 usize_t target_position = stream->input_position - stream->match_back; 4489 usize_t target_position = stream->input_position - stream->match_back;
4392 usize_t match_length = stream->match_back + stream->match_fwd; 4490 usize_t match_length = stream->match_back + stream->match_fwd;
4393 xoff_t match_position = stream->match_srcpos - stream->match_back; 4491 xoff_t match_position = stream->match_srcpos - stream->match_back;
@@ -4554,6 +4652,8 @@ xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0,
4554 * comparison to zlib) in order to support the PROMOTE decision, which is to prefer the 4652 * comparison to zlib) in order to support the PROMOTE decision, which is to prefer the
4555 * most recently used matching address of a certain string to aid the VCDIFF same cache. 4653 * most recently used matching address of a certain string to aid the VCDIFF same cache.
4556 * 4654 *
4655 * --- TODO: declare the PROMOTE experiment a failure -- remove the extra LIST --
4656 *
4557 * Weak reasoning? it's time to modularize this routine...? Let's say the PROMOTE 4657 * Weak reasoning? it's time to modularize this routine...? Let's say the PROMOTE
4558 * feature supported by this slow data structure contributes around 2% improvement in 4658 * feature supported by this slow data structure contributes around 2% improvement in
4559 * compressed size, is there a better code table that doesn't use the SAME address cache, 4659 * compressed size, is there a better code table that doesn't use the SAME address cache,
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index fd91ac8..ca4c79a 100755
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -597,6 +597,11 @@ struct _xd3_source
597 const char *name; /* its name, for debug/print purposes */ 597 const char *name; /* its name, for debug/print purposes */
598 void *ioh; /* opaque handle */ 598 void *ioh; /* opaque handle */
599 599
600 /* getblk sets */
601 xoff_t curblkno; /* current block number: client sets after getblk request */
602 usize_t onblk; /* number of bytes on current block: client sets, xd3 verifies */
603 const uint8_t *curblk; /* current block array: client sets after getblk request */
604
600 /* xd3 sets */ 605 /* xd3 sets */
601 usize_t srclen; /* length of this source window */ 606 usize_t srclen; /* length of this source window */
602 xoff_t srcbase; /* offset of this source window in the source itself */ 607 xoff_t srcbase; /* offset of this source window in the source itself */
@@ -604,11 +609,6 @@ struct _xd3_source
604 usize_t cpyoff_blocks; /* offset of copy window in blocks */ 609 usize_t cpyoff_blocks; /* offset of copy window in blocks */
605 usize_t cpyoff_blkoff; /* offset of copy window in blocks, remainder */ 610 usize_t cpyoff_blkoff; /* offset of copy window in blocks, remainder */
606 xoff_t getblkno; /* request block number: xd3 sets current getblk request */ 611 xoff_t getblkno; /* request block number: xd3 sets current getblk request */
607
608 /* getblk sets */
609 xoff_t curblkno; /* current block number: client sets after getblk request */
610 usize_t onblk; /* number of bytes on current block: client sets, xd3 verifies */
611 const uint8_t *curblk; /* current block array: client sets after getblk request */
612}; 612};
613 613
614/* The primary xd3_stream object, used for encoding and decoding. You may access only two 614/* The primary xd3_stream object, used for encoding and decoding. You may access only two
@@ -812,11 +812,86 @@ struct _xd3_stream
812 PUBLIC FUNCTIONS 812 PUBLIC FUNCTIONS
813 ******************************************************************************************/ 813 ******************************************************************************************/
814 814
815/* The two I/O disciplines, encode and decode, have similar stream semantics. It is 815/* This function configures an xd3_stream using the provided in-memory input buffer,
816 * recommended that applications use the same code for compression and decompression - 816 * source buffer, output buffer, and flags. The output array must be large enough or else
817 * because there are only a few differences in handling encoding/decoding. 817 * ENOSPC will be returned. This is the simplest in-memory encoding interface. */
818int xd3_encode_memory (const uint8_t *input,
819 usize_t input_size,
820 const uint8_t *source,
821 usize_t source_size,
822 uint8_t *output,
823 usize_t *output_size,
824 usize_t avail_output,
825 int flags);
826
827/* The reverse of xd3_encode_memory. */
828int xd3_decode_memory (const uint8_t *input,
829 usize_t input_size,
830 const uint8_t *source,
831 usize_t source_size,
832 uint8_t *output,
833 usize_t *output_size,
834 usize_t avail_output,
835 int flags);
836
837/* This function encodes an in-memory input. Everything else about the xd3_stream is
838 * configurable. The output array must be large enough to hold the output or else ENOSPC
839 * is returned. The source (if any) should be set using xd3_set_source() with a
840 * single-block xd3_source. This calls the underlying non-blocking interface,
841 * xd3_encode_input(), handling the necessary input/output states. This method be
842 * considered a reference for any application using xd3_encode_input() directly.
843 *
844 * xd3_stream stream;
845 * xd3_config config;
846 * xd3_source src;
847 *
848 * memset (& src, 0, sizeof (src));
849 * memset (& stream, 0, sizeof (stream));
850 * memset (& config, 0, sizeof (config));
818 * 851 *
819 * See also the xd3_avail_input() and xd3_consume_output() routines, inlined below. 852 * if (source != NULL)
853 * {
854 * src.size = source_size;
855 * src.blksize = source_size;
856 * src.curblkno = 0;
857 * src.onblk = source_size;
858 * src.curblk = source;
859 * xd3_set_source(&stream, &src);
860 * }
861 *
862 * config.flags = flags;
863 * config.srcwin_maxsz = source_size;
864 * config.winsize = input_size;
865 *
866 * ... set smatcher, appheader, encoding-table, compression-level, etc.
867 *
868 * xd3_config_stream(&stream, &config);
869 * xd3_encode_stream(&stream, ...);
870 * xd3_free_stream(&stream);
871 *
872 * DO NOT USE except for testing. These methods are allocate bad buffer sizes.
873 */
874int xd3_encode_stream (xd3_stream *stream,
875 const uint8_t *input,
876 usize_t input_size,
877 uint8_t *output,
878 usize_t *output_size,
879 usize_t avail_output);
880
881/* The reverse of xd3_encode_stream. */
882int xd3_decode_stream (xd3_stream *stream,
883 const uint8_t *input,
884 usize_t input_size,
885 uint8_t *output,
886 usize_t *output_size,
887 usize_t avail_size);
888
889/* This is the non-blocking interface.
890 *
891 * Handling input and output states is the same for encoding or decoding using the
892 * xd3_avail_input() and xd3_consume_output() routines, inlined below.
893 *
894 * Return values:
820 * 895 *
821 * XD3_INPUT: the process requires more input: call xd3_avail_input() then repeat 896 * XD3_INPUT: the process requires more input: call xd3_avail_input() then repeat
822 * XD3_OUTPUT: the process has more output: read stream->next_out, stream->avail_out, 897 * XD3_OUTPUT: the process has more output: read stream->next_out, stream->avail_out,
@@ -844,14 +919,6 @@ struct _xd3_stream
844 * consistent for either encoding or decoding. 919 * consistent for either encoding or decoding.
845 * XD3_GETSRCBLK: If the xd3_getblk() callback is NULL, this value is returned to 920 * XD3_GETSRCBLK: If the xd3_getblk() callback is NULL, this value is returned to
846 * initiate a non-blocking source read. 921 * initiate a non-blocking source read.
847 *
848 * For simple usage, see the xd3_process_completely_stream() function, which underlies
849 * xd3_encode_completely_stream() and xd3_decode_completely_stream() [xdelta3.c]. For
850 * real application usage, including the application header, the see command-line utility
851 * [xdelta3-main.h].
852 *
853 * main_input() implements the command-line encode and decode as well as the optional
854 * VCDIFF_TOOLS printhdr, printhdrs, and printdelta with a single loop [xdelta3-main.h].
855 */ 922 */
856int xd3_decode_input (xd3_stream *stream); 923int xd3_decode_input (xd3_stream *stream);
857int xd3_encode_input (xd3_stream *stream); 924int xd3_encode_input (xd3_stream *stream);
@@ -868,7 +935,7 @@ int xd3_config_stream (xd3_stream *stream,
868 * resources it supplied. */ 935 * resources it supplied. */
869int xd3_close_stream (xd3_stream *stream); 936int xd3_close_stream (xd3_stream *stream);
870 937
871/* This unconditionally closes/frees the stream, future close() will succeed.*/ 938/* This unconditionally closes/frees the stream, future close() will succeed. */
872void xd3_abort_stream (xd3_stream *stream); 939void xd3_abort_stream (xd3_stream *stream);
873 940
874/* xd3_free_stream frees all memory allocated for the stream. The application is 941/* xd3_free_stream frees all memory allocated for the stream. The application is
@@ -884,36 +951,18 @@ void xd3_free_stream (xd3_stream *stream);
884int xd3_set_source (xd3_stream *stream, 951int xd3_set_source (xd3_stream *stream,
885 xd3_source *source); 952 xd3_source *source);
886 953
887/* This function invokes xd3_encode_input using whole-file, in-memory inputs. The output
888 * array must be large enough to hold the output or else ENOSPC is returned. */
889int xd3_encode_completely_stream (xd3_stream *stream,
890 const uint8_t *input,
891 usize_t input_size,
892 uint8_t *output,
893 usize_t *output_size,
894 usize_t avail_output);
895
896/* This function invokes xd3_decode_input using whole-file, in-memory inputs. The output
897 * array must be large enough to hold the output or else ENOSPC is returned. */
898int xd3_decode_completely_stream (xd3_stream *stream,
899 const uint8_t *input,
900 usize_t input_size,
901 uint8_t *output,
902 usize_t *output_size,
903 usize_t avail_size);
904
905/* This should be called before the first call to xd3_encode_input() to include 954/* This should be called before the first call to xd3_encode_input() to include
906 * application-specific data in the VCDIFF header. */ 955 * application-specific data in the VCDIFF header. */
907void xd3_set_appheader (xd3_stream *stream, 956void xd3_set_appheader (xd3_stream *stream,
908 const uint8_t *data, 957 const uint8_t *data,
909 usize_t size); 958 usize_t size);
910 959
911/* xd3_get_appheader may be called in the decoder after XD3_GOTHEADER. For convenience, 960/* xd3_get_appheader may be called in the decoder after XD3_GOTHEADER. For convenience,
912 * the decoder always adds a single byte padding to the end of the application header, 961 * the decoder always adds a single byte padding to the end of the application header,
913 * which is set to zero in case the application header is a string. */ 962 * which is set to zero in case the application header is a string. */
914int xd3_get_appheader (xd3_stream *stream, 963int xd3_get_appheader (xd3_stream *stream,
915 uint8_t **data, 964 uint8_t **data,
916 usize_t *size); 965 usize_t *size);
917 966
918/* After receiving XD3_GOTHEADER, the decoder should check this function which returns 1 967/* After receiving XD3_GOTHEADER, the decoder should check this function which returns 1
919 * if the decoder will require source data. */ 968 * if the decoder will require source data. */
diff --git a/xdelta3/xdelta3.prj b/xdelta3/xdelta3.prj
index ae05516..684b109 100755
--- a/xdelta3/xdelta3.prj
+++ b/xdelta3/xdelta3.prj
@@ -1,12 +1,11 @@
1;; -*- Prcs -*- 1;; -*- Prcs -*-
2(Created-By-Prcs-Version 1 3 4) 2(Created-By-Prcs-Version 1 3 4)
3(Project-Description "") 3(Project-Description "")
4(Project-Version xdelta3 0 9) 4(Project-Version xdelta3 0 11)
5(Parent-Version xdelta3 0 8) 5(Parent-Version xdelta3 0 10)
6(Version-Log "rename encode/decode_completely to encode/decode_completely_stream 6(Version-Log "compiles on cygwin, copyright years updated, python experiments")
7")
8(New-Version-Log "") 7(New-Version-Log "")
9(Checkin-Time "Sun, 28 Jan 2007 21:08:28 -0800") 8(Checkin-Time "Wed, 31 Jan 2007 22:47:01 -0800")
10(Checkin-Login jmacd) 9(Checkin-Login jmacd)
11(Populate-Ignore ()) 10(Populate-Ignore ())
12(Project-Keywords 11(Project-Keywords
@@ -16,18 +15,18 @@
16(Files 15(Files
17 (COPYING (xdelta3/b/29_COPYING 1.1 644)) 16 (COPYING (xdelta3/b/29_COPYING 1.1 644))
18 17
19 (xdelta3-cfgs.h (xdelta3/9_xdelta3-cf 1.2 744)) 18 (xdelta3-cfgs.h (xdelta3/9_xdelta3-cf 1.3 744))
20 (xdelta3-decode.h (xdelta3/b/30_xdelta3-de 1.1 744)) 19 (xdelta3-decode.h (xdelta3/b/30_xdelta3-de 1.3 744))
21 (xdelta3-djw.h (xdelta3/8_xdelta3-dj 1.2 744)) 20 (xdelta3-djw.h (xdelta3/8_xdelta3-dj 1.4 744))
22 (xdelta3-fgk.h (xdelta3/7_xdelta3-fg 1.2 744)) 21 (xdelta3-fgk.h (xdelta3/7_xdelta3-fg 1.3 744))
23 (xdelta3-list.h (xdelta3/6_xdelta3-li 1.2 644)) 22 (xdelta3-list.h (xdelta3/6_xdelta3-li 1.3 744))
24 (xdelta3-main.h (xdelta3/5_xdelta3-ma 1.5 744)) 23 (xdelta3-main.h (xdelta3/5_xdelta3-ma 1.7 744))
25 (xdelta3-python.h (xdelta3/4_xdelta3-py 1.2 644)) 24 (xdelta3-python.h (xdelta3/4_xdelta3-py 1.3 744))
26 (xdelta3-regtest.py (xdelta3/10_xdelta3-re 1.4 744)) 25 (xdelta3-regtest.py (xdelta3/10_xdelta3-re 1.6 744))
27 (xdelta3-second.h (xdelta3/3_xdelta3-se 1.2 744)) 26 (xdelta3-second.h (xdelta3/3_xdelta3-se 1.3 744))
28 (xdelta3-test.h (xdelta3/2_xdelta3-te 1.4 744)) 27 (xdelta3-test.h (xdelta3/2_xdelta3-te 1.5 744))
29 (xdelta3.c (xdelta3/16_xdelta3.c 1.5 744)) 28 (xdelta3.c (xdelta3/16_xdelta3.c 1.6 744))
30 (xdelta3.h (xdelta3/1_xdelta3.h 1.4 744)) 29 (xdelta3.h (xdelta3/1_xdelta3.h 1.5 744))
31 30
32 (Makefile (xdelta3/0_Makefile 1.4 744)) 31 (Makefile (xdelta3/0_Makefile 1.4 744))
33 (setup.py (xdelta3/11_setup.py 1.2 744)) 32 (setup.py (xdelta3/11_setup.py 1.2 744))
@@ -44,7 +43,7 @@
44 43
45 (README (xdelta3/b/31_README 1.1 744)) 44 (README (xdelta3/b/31_README 1.1 744))
46 (badcopy.vcproj (xdelta3/b/32_badcopy.vc 1.1 744)) 45 (badcopy.vcproj (xdelta3/b/32_badcopy.vc 1.1 744))
47 (xdelta3.vcproj (xdelta3/b/33_xdelta3.vc 1.1 744)) 46 (xdelta3.vcproj (xdelta3/b/33_xdelta3.vc 1.2 744))
48) 47)
49(Merge-Parents) 48(Merge-Parents)
50(New-Merge-Parents) 49(New-Merge-Parents)