summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/Makefile10
-rw-r--r--xdelta3/setup.py1
-rw-r--r--xdelta3/xdelta3-main.h184
-rwxr-xr-xxdelta3/xdelta3-regtest.py40
-rw-r--r--xdelta3/xdelta3-test.h14
-rwxr-xr-xxdelta3/xdelta3-test.py12
-rw-r--r--xdelta3/xdelta3.c111
-rw-r--r--xdelta3/xdelta3.h4
8 files changed, 250 insertions, 126 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile
index 21e088a..aa35a4a 100644
--- a/xdelta3/Makefile
+++ b/xdelta3/Makefile
@@ -3,6 +3,7 @@
3 3
4UNAME = $(shell uname) 4UNAME = $(shell uname)
5CYGWIN = $(findstring CYGWIN, $(UNAME)) 5CYGWIN = $(findstring CYGWIN, $(UNAME))
6DARWIN = $(findstring Darwin, $(UNAME))
6PYVER = 2.5 7PYVER = 2.5
7 8
8ifeq ("$(CYGWIN)", "") 9ifeq ("$(CYGWIN)", "")
@@ -50,6 +51,7 @@ PYTHON = python
50 51
51WIXDIR = "/cygdrive/c/Program Files/wix2.0.4820" 52WIXDIR = "/cygdrive/c/Program Files/wix2.0.4820"
52 53
54# -arch x86_64
53CFLAGS= -Wall -Wshadow -fno-builtin 55CFLAGS= -Wall -Wshadow -fno-builtin
54 56
55# $Format: "REL=$Xdelta3Version$" $ 57# $Format: "REL=$Xdelta3Version$" $
@@ -67,7 +69,7 @@ EXTRA = Makefile COPYING linkxd3lib.c badcopy.c xdelta3.swig \
67 xdelta3.py xdelta3_wrap.c xdelta3.wxs xdelta3.wxi \ 69 xdelta3.py xdelta3_wrap.c xdelta3.wxs xdelta3.wxi \
68 README readme.txt 70 README readme.txt
69 71
70SWIG_FLAGS = -DXD3_DEBUG=0 \ 72SWIG_FLAGS = -DXD3_DEBUG=1 \
71 -DEXTERNAL_COMPRESSION=0 \ 73 -DEXTERNAL_COMPRESSION=0 \
72 -DXD3_USE_LARGEFILE64=1 \ 74 -DXD3_USE_LARGEFILE64=1 \
73 -DGENERIC_ENCODE_TABLES=1 \ 75 -DGENERIC_ENCODE_TABLES=1 \
@@ -199,11 +201,17 @@ xdelta3module.dll: xdelta3_wrap.o xdelta3.o
199 -o xdelta3module.dll 201 -o xdelta3module.dll
200 cp $(SWIGTGT) /usr/lib/python$(PYVER)/site-packages 202 cp $(SWIGTGT) /usr/lib/python$(PYVER)/site-packages
201 203
204ifeq ("$(DARWIN)", "")
202xdelta3module.so: xdelta3_wrap.o xdelta3.o 205xdelta3module.so: xdelta3_wrap.o xdelta3.o
203 ld -shared xdelta3.o xdelta3_wrap.o \ 206 ld -shared xdelta3.o xdelta3_wrap.o \
204 -o xdelta3module.so \ 207 -o xdelta3module.so \
205 /usr/lib/libpython$(PYVER).so \ 208 /usr/lib/libpython$(PYVER).so \
206 -lc 209 -lc
210else
211xdelta3module.so: xdelta3_wrap.o xdelta3.o
212 gcc -Wl,-F. -bundle -undefined dynamic_lookup $(CFLAGS) \
213 xdelta3.o xdelta3_wrap.o -o xdelta3module.so
214endif
207 215
208xdelta3-decoder: $(SOURCES) 216xdelta3-decoder: $(SOURCES)
209 $(CC) -O3 -Wall -Wshadow xdelta3.c \ 217 $(CC) -O3 -Wall -Wshadow xdelta3.c \
diff --git a/xdelta3/setup.py b/xdelta3/setup.py
index b2c9022..edcb1fd 100644
--- a/xdelta3/setup.py
+++ b/xdelta3/setup.py
@@ -46,6 +46,7 @@ xdelta3_ext = Extension('xdelta3main',
46 extra_compile_args = [ '-O3', 46 extra_compile_args = [ '-O3',
47 '-g', 47 '-g',
48 '-fno-builtin', 48 '-fno-builtin',
49 # '-arch', 'x86_64',
49 ]) 50 ])
50 51
51# $Format: "REL='$Xdelta3Version$'" $ 52# $Format: "REL='$Xdelta3Version$'" $
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 8848ed4..db4c011 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -1538,7 +1538,7 @@ main_recode_func (xd3_stream* stream, main_file *ofile)
1538 option_appheader != NULL) 1538 option_appheader != NULL)
1539 { 1539 {
1540 xd3_set_appheader (recode_stream, option_appheader, 1540 xd3_set_appheader (recode_stream, option_appheader,
1541 strlen (option_appheader)); 1541 strlen ((char*) option_appheader));
1542 } 1542 }
1543 else if (option_use_appheader != 0 && 1543 else if (option_use_appheader != 0 &&
1544 option_appheader == NULL) 1544 option_appheader == NULL)
@@ -1619,7 +1619,7 @@ main_init_recode_stream (void)
1619 1619
1620 if ((ret = main_set_secondary_flags (&recode_config)) || 1620 if ((ret = main_set_secondary_flags (&recode_config)) ||
1621 (ret = xd3_config_stream (recode_stream, &recode_config)) || 1621 (ret = xd3_config_stream (recode_stream, &recode_config)) ||
1622 (ret = xd3_encode_init_buffers (recode_stream))) 1622 (ret = xd3_encode_init_partial (recode_stream)))
1623 { 1623 {
1624 XPR(NT XD3_LIB_ERRMSG (recode_stream, ret)); 1624 XPR(NT XD3_LIB_ERRMSG (recode_stream, ret));
1625 xd3_free_stream (recode_stream); 1625 xd3_free_stream (recode_stream);
@@ -1706,47 +1706,141 @@ main_merge_func (xd3_stream* stream, main_file *no_write)
1706 return 0; 1706 return 0;
1707} 1707}
1708 1708
1709
1710#define MERGE_IN_PROGRESS 0
1709#if MERGE_IN_PROGRESS 1711#if MERGE_IN_PROGRESS
1710/* This is called after all windows have been read, as a final step in 1712/* This is called after all windows have been read, as a final step in
1711 * main_input(). This is only called for the final merge step. */ 1713 * main_input(). This is only called for the final merge step. */
1712static int 1714static int
1713main_merge_output (xd3_stream *stream) 1715main_merge_output (xd3_stream *stream, main_file *ofile)
1714{ 1716{
1715 int inst_pos = 0; 1717 int ret;
1718 usize_t inst_pos = 0;
1716 xoff_t output_pos = 0; 1719 xoff_t output_pos = 0;
1717 usize_t window_pos = 0; 1720 xd3_source recode_source;
1721
1722 /* Enter the ENC_INPUT state and bypass the next_in == NULL test
1723 * and (leftover) input buffering logic. */
1724 XD3_ASSERT(recode_stream->enc_state == ENC_INIT);
1725 recode_stream->enc_state = ENC_INPUT;
1726 recode_stream->next_in = main_bdata;
1727 recode_stream->flags |= XD3_FLUSH;
1718 1728
1719 while (output_pos < option_winsize) 1729 while (inst_pos < stream->whole_target_instlen)
1720 { 1730 {
1721 xd3_winst *inst = &stream->whole_target_inst[inst_pos]; 1731 xoff_t window_srcmin = XOFF_T_MAX;
1722 usize_t take = min(inst->size, option_winsize - output_pos); 1732 xoff_t window_srcmax = 0;
1733 usize_t window_pos = 0;
1723 1734
1724 switch (inst->type) 1735 XD3_ASSERT (recode_stream->enc_state == ENC_INPUT);
1725 { 1736
1726 case XD3_RUN: 1737 if ((ret = xd3_encode_input (recode_stream)) != XD3_WINSTART)
1727 if ((ret = xd3_emit_run (recode_stream, window_pos, take, 1738 {
1728 stream->whole_target_adds[inst->addr]))) 1739 XPR(NT "invalid merge state: %s\n", xd3_mainerror (ret));
1729 { 1740 return XD3_INVALID;
1730 return ret; 1741 }
1731 } 1742
1732 break; 1743 /* TODO: The inner loop termination condition can be used to
1733 1744 * change window sizes, however keeping the last delta in the
1734 case XD3_ADD: 1745 * chain's window size allows re-using its adler32 checksums.
1735 /* Adds are implicit, put them into the input buffer. */ 1746 * For now this will change window size and not use adler32. */
1736 memcpy (main_bdata, stream->whole_target_adds + inst->addr, take); 1747 while (window_pos < option_winsize &&
1737 break; 1748 inst_pos < stream->whole_target_instlen)
1738 1749 {
1739 default: /* XD3_COPY + mode */ 1750 xd3_winst *inst = &stream->whole_target_inst[inst_pos];
1740 if ((ret = xd3_found_match (stream, window_pos, take, inst->addr, 1751 usize_t take = min(inst->size, option_winsize - window_pos);
1741 IS_SOURCE)))
1742 {
1743 return ret;
1744 }
1745 break;
1746 }
1747 1752
1748 //xd3_avail_input (recode_stream, main_bdata, 1753 switch (inst->type)
1754 {
1755 case XD3_RUN:
1756 if ((ret = xd3_emit_run (recode_stream, window_pos, take,
1757 stream->whole_target_adds[inst->addr])))
1758 {
1759 return ret;
1760 }
1761 break;
1762
1763 case XD3_ADD:
1764 /* Adds are implicit, put them into the input buffer. */
1765 memcpy (main_bdata + window_pos,
1766 stream->whole_target_adds + inst->addr, take);
1767 break;
1768
1769 default: /* XD3_COPY + copy mode */
1770 window_srcmin = min(window_srcmin, inst->addr);
1771 window_srcmax = max(window_srcmax, inst->addr + take);
1772 if ((ret = xd3_found_match (recode_stream, window_pos, take, inst->addr,
1773 inst->mode == VCD_SOURCE)))
1774 {
1775 return ret;
1776 }
1777 break;
1778 }
1779
1780 window_pos += take;
1781 output_pos += take;
1782
1783 if (take == inst->size)
1784 {
1785 inst_pos += 1;
1786 }
1787 else
1788 {
1789 /* Modify the instruction for the next pass. */
1790 /* TODO: this seems to be broken, as initial testing indicates. */
1791 if (inst->type != XD3_RUN)
1792 {
1793 inst->addr += take;
1794 }
1795 inst->size -= take;
1796 }
1797 }
1798
1799 xd3_avail_input (recode_stream, main_bdata, window_pos);
1800
1801 recode_stream->enc_state = ENC_INSTR;
1802 recode_stream->srcwin_decided = 1;
1803 recode_stream->src = &recode_source;
1804 recode_source.srclen = window_srcmax - window_srcmin;
1805 recode_source.srcbase = window_srcmin;
1806 recode_stream->taroff = recode_source.srclen;
1807
1808 for (;;)
1809 {
1810 switch ((ret = xd3_encode_input (recode_stream)))
1811 {
1812 case XD3_INPUT: {
1813 goto done_window;
1814 }
1815 case XD3_OUTPUT: {
1816 /* main_file_write below */
1817 break;
1818 }
1819 case XD3_GOTHEADER:
1820 case XD3_WINSTART:
1821 case XD3_WINFINISH: {
1822 /* ignore */
1823 continue;
1824 }
1825 case XD3_GETSRCBLK:
1826 case 0: {
1827 return XD3_INTERNAL;
1828 }
1829 default:
1830 return ret;
1831 }
1832
1833 if ((ret = main_write_output(recode_stream, ofile)))
1834 {
1835 return ret;
1836 }
1837
1838 xd3_consume_output (recode_stream);
1839 }
1840 done_window:
1841 (void) 0;
1749 } 1842 }
1843
1750 return 0; 1844 return 0;
1751} 1845}
1752#endif 1846#endif
@@ -3158,7 +3252,7 @@ main_input (xd3_cmd cmd,
3158 3252
3159 /* Check if the user expected a source to be required although 3253 /* Check if the user expected a source to be required although
3160 * it was not. */ 3254 * it was not. */
3161 if (have_src && ! need_src && ! option_quiet) 3255 if (have_src && ! need_src && option_verbose)
3162 { 3256 {
3163 XPR(NT "warning: output window %"Q"u does not " 3257 XPR(NT "warning: output window %"Q"u does not "
3164 "copy source\n", stream.current_window); 3258 "copy source\n", stream.current_window);
@@ -3244,7 +3338,7 @@ main_input (xd3_cmd cmd,
3244 main_file_isopen (sfile)) 3338 main_file_isopen (sfile))
3245 { 3339 {
3246 /* Warn when no source copies are found */ 3340 /* Warn when no source copies are found */
3247 if (! xd3_encoder_used_source (& stream)) 3341 if (option_verbose && ! xd3_encoder_used_source (& stream))
3248 { 3342 {
3249 XPR(NT "warning: input window %"Q"u..%"Q"u has " 3343 XPR(NT "warning: input window %"Q"u..%"Q"u has "
3250 "no source copies\n", 3344 "no source copies\n",
@@ -3321,6 +3415,14 @@ done:
3321 main_file_close (sfile); 3415 main_file_close (sfile);
3322 } 3416 }
3323 3417
3418#if MERGE_IN_PROGRESS
3419 if (cmd == CMD_MERGE &&
3420 (ret = main_merge_output (& stream, ofile)))
3421 {
3422 return EXIT_FAILURE;
3423 }
3424#endif
3425
3324 /* If output file is not open yet because of delayed-open, it means 3426 /* If output file is not open yet because of delayed-open, it means
3325 * we never encountered a window in the delta, but it could have had 3427 * we never encountered a window in the delta, but it could have had
3326 * a VCDIFF header? TODO: solve this elsewhere. For now, it prints 3428 * a VCDIFF header? TODO: solve this elsewhere. For now, it prints
@@ -3350,14 +3452,6 @@ done:
3350 } 3452 }
3351#endif 3453#endif
3352 3454
3353#if MERGE_IN_PROGRESS
3354 if (cmd == CMD_MERGE &&
3355 (ret = main_merge_output (& stream)))
3356 {
3357 return EXIT_FAILURE;
3358 }
3359#endif
3360
3361 if ((ret = xd3_close_stream (& stream))) 3455 if ((ret = xd3_close_stream (& stream)))
3362 { 3456 {
3363 XPR(NT XD3_LIB_ERRMSG (& stream, ret)); 3457 XPR(NT XD3_LIB_ERRMSG (& stream, ret));
@@ -3659,8 +3753,10 @@ main (int argc, char **argv)
3659 else if (strcmp (my_optstr, "printdelta") == 0) 3753 else if (strcmp (my_optstr, "printdelta") == 0)
3660 { cmd = CMD_PRINTDELTA; } 3754 { cmd = CMD_PRINTDELTA; }
3661 else if (strcmp (my_optstr, "recode") == 0) { cmd = CMD_RECODE; } 3755 else if (strcmp (my_optstr, "recode") == 0) { cmd = CMD_RECODE; }
3756#if MERGE_IN_PROGRESS
3662 else if (strcmp (my_optstr, "merge") == 0) { cmd = CMD_MERGE; } 3757 else if (strcmp (my_optstr, "merge") == 0) { cmd = CMD_MERGE; }
3663#endif 3758#endif
3759#endif
3664 3760
3665 /* If no option was found and still no command, let the default 3761 /* If no option was found and still no command, let the default
3666 * command be encode. The remaining args are treated as 3762 * command be encode. The remaining args are treated as
@@ -3778,6 +3874,7 @@ main (int argc, char **argv)
3778 3874
3779 sfilename = my_optarg; 3875 sfilename = my_optarg;
3780 break; 3876 break;
3877#if MERGE_IN_PROGRESS
3781 case 'm': 3878 case 'm':
3782 if ((merge = (main_merge*) 3879 if ((merge = (main_merge*)
3783 main_malloc (sizeof (main_merge))) == NULL) 3880 main_malloc (sizeof (main_merge))) == NULL)
@@ -3787,7 +3884,7 @@ main (int argc, char **argv)
3787 main_merge_list_push_back (& merge_order, merge); 3884 main_merge_list_push_back (& merge_order, merge);
3788 merge->filename = my_optarg; 3885 merge->filename = my_optarg;
3789 break; 3886 break;
3790 3887#endif
3791 case 'V': 3888 case 'V':
3792 ret = main_version (); goto exit; 3889 ret = main_version (); goto exit;
3793 default: 3890 default:
@@ -3902,7 +3999,6 @@ main (int argc, char **argv)
3902 3999
3903 while (! main_merge_list_empty (& merge_order)) 4000 while (! main_merge_list_empty (& merge_order))
3904 { 4001 {
3905 /* TODO: More merge cleanup, once implemented. */
3906 merge = main_merge_list_pop_front (& merge_order); 4002 merge = main_merge_list_pop_front (& merge_order);
3907 main_free (merge); 4003 main_free (merge);
3908 } 4004 }
diff --git a/xdelta3/xdelta3-regtest.py b/xdelta3/xdelta3-regtest.py
index e86c621..f9a11bd 100755
--- a/xdelta3/xdelta3-regtest.py
+++ b/xdelta3/xdelta3-regtest.py
@@ -1,6 +1,6 @@
1#!/usr/bin/python2.5 1#!/usr/bin/python2.5
2# xdelta 3 - delta compression tools and library 2# xdelta 3 - delta compression tools and library
3# Copyright (C) 2003, 2006, 2007. Joshua P. MacDonald 3# Copyright (C) 2003, 2006, 2007, 2008. Joshua P. MacDonald
4# 4#
5# This program is free software; you can redistribute it and/or modify 5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by 6# it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
19# TODO: test 1.5 vs. greedy 19# TODO: test 1.5 vs. greedy
20 20
21import os, sys, math, re, time, types, array, random 21import os, sys, math, re, time, types, array, random
22import xdelta3main
23import xdelta3 22import xdelta3
24 23
25#RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS' 24#RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS'
@@ -27,7 +26,10 @@ import xdelta3
27#SAMPLEDIR = "/tmp/WESNOTH_tmp/diff" 26#SAMPLEDIR = "/tmp/WESNOTH_tmp/diff"
28 27
29#RCSDIR = 'G:/jmacd/PRCS_copy' 28#RCSDIR = 'G:/jmacd/PRCS_copy'
30SAMPLEDIR = "C:/sample_data/Wesnoth/tar" 29#SAMPLEDIR = "C:/sample_data/Wesnoth/tar"
30
31#RCSDIR = '/Users/jmacd/src/ftp.kernel.org/pub/scm/linux/kernel/bkcvs/linux-2.4/net/x25'
32RCSDIR = '/Users/jmacd/src/ftp.kernel.org'
31 33
32# 34#
33MIN_SIZE = 0 35MIN_SIZE = 0
@@ -38,8 +40,6 @@ SKIP_TRIALS = 2
38MIN_TRIALS = 3 40MIN_TRIALS = 3
39MAX_TRIALS = 15 41MAX_TRIALS = 15
40 42
41SKIP_DECODE = 1
42
43# 10 = fast 1.5 = slow 43# 10 = fast 1.5 = slow
44MIN_STDDEV_PCT = 1.5 44MIN_STDDEV_PCT = 1.5
45 45
@@ -57,7 +57,7 @@ MAX_RUN = 1000 * 1000 * 10
57 57
58# Testwide defaults 58# Testwide defaults
59ALL_ARGS = [ 59ALL_ARGS = [
60 # -v 60 '-vv'
61 ] 61 ]
62 62
63# The first 7 args go to -C 63# The first 7 args go to -C
@@ -231,11 +231,6 @@ class TimedTest:
231 lambda x: x.Encode(self.target, self.source, DFILE)) 231 lambda x: x.Encode(self.target, self.source, DFILE))
232 self.encode_size = runnable.EncodeSize(DFILE) 232 self.encode_size = runnable.EncodeSize(DFILE)
233 233
234 if SKIP_DECODE:
235 self.decode_time = StatList([1, 1], 'not decoded')
236 return
237 #end
238
239 self.decode_time = self.DoTest(RFILE, 234 self.decode_time = self.DoTest(RFILE,
240 lambda x: x.Decode(DFILE, self.source, RFILE), 235 lambda x: x.Decode(DFILE, self.source, RFILE),
241 ) 236 )
@@ -404,9 +399,10 @@ class Xdelta3Runner:
404 399
405 def Main(self, args): 400 def Main(self, args):
406 try: 401 try:
407 xdelta3main.main(args) 402 #print 'Run %s' % (' '.join(args))
403 xdelta3.xd3_main_cmdline(args)
408 except Exception, e: 404 except Exception, e:
409 raise CommandError(args, "xdelta3.main exception") 405 raise CommandError(args, "xdelta3.main exception: %s" % e)
410 #end 406 #end
411 #end 407 #end
412#end 408#end
@@ -904,10 +900,7 @@ class RandomTest:
904 #end 900 #end
905 901
906 def __str__(self): 902 def __str__(self):
907 decodestr = '' 903 decodestr = ' %.6f' % self.decodetime
908 if not SKIP_DECODE:
909 decodestr = ' %.6f' % self.decodetime
910 #end
911 return 'time %.6f%s size %d%s << %s >>%s' % ( 904 return 'time %.6f%s size %d%s << %s >>%s' % (
912 self.time(), ((self.time_pos != None) and (" (%s)" % self.time_pos) or ""), 905 self.time(), ((self.time_pos != None) and (" (%s)" % self.time_pos) or ""),
913 self.size(), ((self.size_pos != None) and (" (%s)" % self.size_pos) or ""), 906 self.size(), ((self.size_pos != None) and (" (%s)" % self.size_pos) or ""),
@@ -1202,19 +1195,20 @@ if __name__ == "__main__":
1202 RunCommand(['rm', '-rf', TMPDIR]) 1195 RunCommand(['rm', '-rf', TMPDIR])
1203 os.mkdir(TMPDIR) 1196 os.mkdir(TMPDIR)
1204 1197
1205 #rcsf = GetTestRcsFiles() 1198 rcsf = GetTestRcsFiles()
1206 #generator = rcsf.Generator() 1199 #generator = rcsf.Generator()
1207 1200
1208 sample = SampleDataTest([SAMPLEDIR]) 1201 #sample = SampleDataTest([SAMPLEDIR])
1209 generator = sample.Generator() 1202 #generator = sample.Generator()
1210 1203
1211 rand = random.Random(135135135135135) 1204 #rand = random.Random(135135135135135)
1212 RunTestLoop(rand, generator, TEST_ROUNDS) 1205 #RunTestLoop(rand, generator, TEST_ROUNDS)
1213 1206
1214 #RunSpeedTest() 1207 #RunSpeedTest()
1215 1208
1216 #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9'])) 1209 #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9']))
1217 #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw'])) 1210 x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw']))
1211 x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-1', '-S', 'djw']))
1218 #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-T'])) 1212 #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-T']))
1219 1213
1220 #x1r = rcsf.AllPairsByDate(Xdelta1RunClass()) 1214 #x1r = rcsf.AllPairsByDate(Xdelta1RunClass())
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h
index 281d1b6..5389d57 100644
--- a/xdelta3/xdelta3-test.h
+++ b/xdelta3/xdelta3-test.h
@@ -576,7 +576,7 @@ static int
576test_forward_match (xd3_stream *stream, int unused) 576test_forward_match (xd3_stream *stream, int unused)
577{ 577{
578 int i; 578 int i;
579 char buf1[256], buf2[256]; 579 uint8_t buf1[256], buf2[256];
580 580
581 memset(buf1, 0, 256); 581 memset(buf1, 0, 256);
582 memset(buf2, 0, 256); 582 memset(buf2, 0, 256);
@@ -615,7 +615,7 @@ test_address_cache (xd3_stream *stream, int unused)
615 stream->acache.s_near = stream->code_table_desc->near_modes; 615 stream->acache.s_near = stream->code_table_desc->near_modes;
616 stream->acache.s_same = stream->code_table_desc->same_modes; 616 stream->acache.s_same = stream->code_table_desc->same_modes;
617 617
618 if ((ret = xd3_encode_init (stream))) { return ret; } 618 if ((ret = xd3_encode_init_partial (stream))) { return ret; }
619 619
620 addrs = xd3_alloc (stream, sizeof (usize_t), ADDR_CACHE_ROUNDS); 620 addrs = xd3_alloc (stream, sizeof (usize_t), ADDR_CACHE_ROUNDS);
621 modes = xd3_alloc (stream, sizeof (uint8_t), ADDR_CACHE_ROUNDS); 621 modes = xd3_alloc (stream, sizeof (uint8_t), ADDR_CACHE_ROUNDS);
@@ -758,7 +758,7 @@ test_compress_text (xd3_stream *stream,
758 758
759 (*encoded_size) = 0; 759 (*encoded_size) = 0;
760 760
761 xd3_set_appheader (stream, test_apphead, strlen (test_apphead)); 761 xd3_set_appheader (stream, test_apphead, strlen ((char*) test_apphead));
762 762
763 if ((ret = xd3_encode_stream (stream, test_text, sizeof (test_text), 763 if ((ret = xd3_encode_stream (stream, test_text, sizeof (test_text),
764 encoded, encoded_size, 4*sizeof (test_text)))) { goto fail; } 764 encoded, encoded_size, 4*sizeof (test_text)))) { goto fail; }
@@ -830,8 +830,8 @@ test_decompress_text (xd3_stream *stream, uint8_t *enc, usize_t enc_size, usize_
830 830
831 if ((ret = xd3_get_appheader (stream, & apphead, & apphead_size))) { goto fail; } 831 if ((ret = xd3_get_appheader (stream, & apphead, & apphead_size))) { goto fail; }
832 832
833 if (apphead_size != strlen (test_apphead) || 833 if (apphead_size != strlen ((char*) test_apphead) ||
834 memcmp (apphead, test_apphead, strlen (test_apphead)) != 0) 834 memcmp (apphead, test_apphead, strlen ((char*) test_apphead)) != 0)
835 { 835 {
836 stream->msg = "incorrect appheader"; 836 stream->msg = "incorrect appheader";
837 ret = XD3_INTERNAL; 837 ret = XD3_INTERNAL;
@@ -2459,7 +2459,7 @@ test_string_matching (xd3_stream *stream, int ignore)
2459 config.smatcher_soft.long_enough = 10; 2459 config.smatcher_soft.long_enough = 10;
2460 2460
2461 if ((ret = xd3_config_stream (stream, & config))) { return ret; } 2461 if ((ret = xd3_config_stream (stream, & config))) { return ret; }
2462 if ((ret = xd3_encode_init (stream))) { return ret; } 2462 if ((ret = xd3_encode_init_full (stream))) { return ret; }
2463 2463
2464 xd3_avail_input (stream, (uint8_t*)test->input, len); 2464 xd3_avail_input (stream, (uint8_t*)test->input, len);
2465 2465
@@ -2686,7 +2686,7 @@ xd3_selftest (void)
2686#ifndef WIN32 2686#ifndef WIN32
2687 if (getuid() == 0) 2687 if (getuid() == 0)
2688 { 2688 {
2689 DP(RINT "This test should not be run as root.\n"); 2689 DP(RINT "xdelta3: This test should not be run as root.\n");
2690 ret = XD3_INVALID; 2690 ret = XD3_INVALID;
2691 goto failure; 2691 goto failure;
2692 } 2692 }
diff --git a/xdelta3/xdelta3-test.py b/xdelta3/xdelta3-test.py
index 2c37030..7fcc3d5 100755
--- a/xdelta3/xdelta3-test.py
+++ b/xdelta3/xdelta3-test.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.4 1#!/usr/bin/python2.5
2# xdelta 3 - delta compression tools and library 2# xdelta 3 - delta compression tools and library
3# Copyright (C) 2003, 2006, 2007. Joshua P. MacDonald 3# Copyright (C) 2003, 2006, 2007. Joshua P. MacDonald
4# 4#
@@ -142,6 +142,14 @@ assert result1 == 0 and result9 == 0
142assert len(level1) > len(level9) 142assert len(level1) > len(level9)
143 143
144# 144#
145# 145# Issue 65
146print 'encode: 65 ...'
147source = 'Hello World'
148target = 'Hello everyone'
149result, patch = xdelta3.xd3_encode_memory(target, source, len(target))
150assert result != 0
151
152result, patch = xdelta3.xd3_encode_memory(target, source, 2 * len(target))
153assert result == 0
146 154
147print 'PASS' 155print 'PASS'
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 1800c90..7e798bd 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -1908,6 +1908,16 @@ xd3_sizeof_uint64_t (uint64_t num)
1908static int 1908static int
1909xd3_alloc_cache (xd3_stream *stream) 1909xd3_alloc_cache (xd3_stream *stream)
1910{ 1910{
1911 if (stream->acache.near_array != NULL)
1912 {
1913 xd3_free (stream, stream->acache.near_array);
1914 }
1915
1916 if (stream->acache.same_array != NULL)
1917 {
1918 xd3_free (stream, stream->acache.same_array);
1919 }
1920
1911 if (((stream->acache.s_near > 0) && 1921 if (((stream->acache.s_near > 0) &&
1912 (stream->acache.near_array = (usize_t*) 1922 (stream->acache.near_array = (usize_t*)
1913 xd3_alloc (stream, stream->acache.s_near, sizeof (usize_t))) 1923 xd3_alloc (stream, stream->acache.s_near, sizeof (usize_t)))
@@ -2087,6 +2097,8 @@ xd3_alloc (xd3_stream *stream,
2087 if (a != NULL) 2097 if (a != NULL)
2088 { 2098 {
2089 IF_DEBUG (stream->alloc_cnt += 1); 2099 IF_DEBUG (stream->alloc_cnt += 1);
2100 IF_DEBUG1 (DP(RINT "[stream %p malloc] size %u ptr %p\n",
2101 stream, elts * size, a));
2090 } 2102 }
2091 else 2103 else
2092 { 2104 {
@@ -2104,6 +2116,8 @@ xd3_free (xd3_stream *stream,
2104 { 2116 {
2105 IF_DEBUG (stream->free_cnt += 1); 2117 IF_DEBUG (stream->free_cnt += 1);
2106 XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); 2118 XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt);
2119 IF_DEBUG1 (DP(RINT "[stream %p free] %p\n",
2120 stream, ptr));
2107 stream->free (stream->opaque, ptr); 2121 stream->free (stream->opaque, ptr);
2108 } 2122 }
2109} 2123}
@@ -2781,10 +2795,11 @@ xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst)
2781 stream->l_tcpy += inst->size; 2795 stream->l_tcpy += inst->size;
2782 } 2796 }
2783 2797
2784 XD3_ASSERT (inst->size >= MIN_MATCH); 2798 /* Note: used to assert inst->size >= MIN_MATCH, but not true
2785 2799 * for merge operations & identical match heuristics. */
2786 /* the "here" position is always offset by taroff */ 2800 /* the "here" position is always offset by taroff */
2787 if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, & inst->type))) 2801 if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff,
2802 & inst->type)))
2788 { 2803 {
2789 return ret; 2804 return ret;
2790 } 2805 }
@@ -3262,8 +3277,6 @@ xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t run_c)
3262 xd3_rinst* ri; 3277 xd3_rinst* ri;
3263 int ret; 3278 int ret;
3264 3279
3265 XD3_ASSERT (pos + size <= stream->avail_in);
3266
3267 if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } 3280 if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; }
3268 3281
3269 ri->type = XD3_RUN; 3282 ri->type = XD3_RUN;
@@ -3283,8 +3296,6 @@ xd3_found_match (xd3_stream *stream, usize_t pos,
3283 xd3_rinst* ri; 3296 xd3_rinst* ri;
3284 int ret; 3297 int ret;
3285 3298
3286 XD3_ASSERT (pos + size <= stream->avail_in);
3287
3288 if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } 3299 if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; }
3289 3300
3290 ri->type = XD3_CPY; 3301 ri->type = XD3_CPY;
@@ -3574,12 +3585,43 @@ xd3_alloc_iopt (xd3_stream *stream, int elts)
3574 return 0; 3585 return 0;
3575} 3586}
3576 3587
3577/* This function allocates the encoder output buffers. */ 3588/* This function allocates all memory initially used by the encoder. */
3578static int 3589static int
3579xd3_encode_init_buffers (xd3_stream *stream) 3590xd3_encode_init (xd3_stream *stream, int full_init)
3580{ 3591{
3581 int i; 3592 int i;
3582 3593
3594 if (full_init)
3595 {
3596 int large_comp = (stream->src != NULL);
3597 int small_comp = ! (stream->flags & XD3_NOCOMPRESS);
3598
3599 /* Memory allocations for checksum tables are delayed until
3600 * xd3_string_match_init in the first call to string_match--that way
3601 * identical or short inputs require no table allocation. */
3602 if (large_comp)
3603 {
3604 usize_t hash_values = (stream->srcwin_maxsz / stream->smatcher.large_step);
3605
3606 xd3_size_hashtable (stream,
3607 hash_values,
3608 & stream->large_hash);
3609 }
3610
3611 if (small_comp)
3612 {
3613 /* TODO: This is under devel: used to have min(sprevsz) here, which sort
3614 * of makes sense, but observed fast performance w/ larger tables, which
3615 * also sort of makes sense. @@@ */
3616 usize_t hash_values = stream->winsize;
3617
3618 xd3_size_hashtable (stream,
3619 hash_values,
3620 & stream->small_hash);
3621 }
3622 }
3623
3624 /* data buffers */
3583 for (i = 0; i < ENC_SECTS; i += 1) 3625 for (i = 0; i < ENC_SECTS; i += 1)
3584 { 3626 {
3585 if ((stream->enc_heads[i] = 3627 if ((stream->enc_heads[i] =
@@ -3590,43 +3632,6 @@ xd3_encode_init_buffers (xd3_stream *stream)
3590 } 3632 }
3591 } 3633 }
3592 3634
3593 return 0;
3594}
3595
3596/* This function allocates all memory initially used by the encoder. */
3597int
3598xd3_encode_init (xd3_stream *stream)
3599{
3600 int large_comp = (stream->src != NULL);
3601 int small_comp = ! (stream->flags & XD3_NOCOMPRESS);
3602
3603 /* Memory allocations for checksum tables are delayed until
3604 * xd3_string_match_init in the first call to string_match--that way
3605 * identical or short inputs require no table allocation. */
3606 if (large_comp)
3607 {
3608 usize_t hash_values = (stream->srcwin_maxsz / stream->smatcher.large_step);
3609
3610 xd3_size_hashtable (stream,
3611 hash_values,
3612 & stream->large_hash);
3613 }
3614
3615 if (small_comp)
3616 {
3617 /* TODO: This is under devel: used to have min(sprevsz) here, which sort
3618 * of makes sense, but observed fast performance w/ larger tables, which
3619 * also sort of makes sense. @@@ */
3620 usize_t hash_values = stream->winsize;
3621
3622 xd3_size_hashtable (stream,
3623 hash_values,
3624 & stream->small_hash);
3625 }
3626
3627 /* data buffers */
3628 if (xd3_encode_init_buffers(stream) != 0) { goto fail; }
3629
3630 /* iopt buffer */ 3635 /* iopt buffer */
3631 xd3_rlist_init (& stream->iopt_used); 3636 xd3_rlist_init (& stream->iopt_used);
3632 xd3_rlist_init (& stream->iopt_free); 3637 xd3_rlist_init (& stream->iopt_free);
@@ -3648,6 +3653,18 @@ xd3_encode_init (xd3_stream *stream)
3648 return ENOMEM; 3653 return ENOMEM;
3649} 3654}
3650 3655
3656int
3657xd3_encode_init_full (xd3_stream *stream)
3658{
3659 return xd3_encode_init (stream, 1);
3660}
3661
3662int
3663xd3_encode_init_partial (xd3_stream *stream)
3664{
3665 return xd3_encode_init (stream, 0);
3666}
3667
3651/* Called after the ENC_POSTOUT state, this puts the output buffers 3668/* Called after the ENC_POSTOUT state, this puts the output buffers
3652 * back into separate lists and re-initializes some variables. (The 3669 * back into separate lists and re-initializes some variables. (The
3653 * output lists were spliced together during the ENC_FLUSH state.) */ 3670 * output lists were spliced together during the ENC_FLUSH state.) */
@@ -3708,7 +3725,7 @@ xd3_encode_input (xd3_stream *stream)
3708 { 3725 {
3709 case ENC_INIT: 3726 case ENC_INIT:
3710 /* Only reached on first time through: memory setup. */ 3727 /* Only reached on first time through: memory setup. */
3711 if ((ret = xd3_encode_init (stream))) { return ret; } 3728 if ((ret = xd3_encode_init_full (stream))) { return ret; }
3712 3729
3713 stream->enc_state = ENC_INPUT; 3730 stream->enc_state = ENC_INPUT;
3714 3731
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index 4d04b49..9b009f1 100644
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -1159,13 +1159,13 @@ int xd3_decoder_needs_source (xd3_stream *stream);
1159/* To generate a VCDIFF encoded delta with xd3_encode_init() from 1159/* To generate a VCDIFF encoded delta with xd3_encode_init() from
1160 * another format, use: 1160 * another format, use:
1161 * 1161 *
1162 * xd3_encode_init() -- initialze encoder state 1162 * xd3_encode_init_partial() -- initialze encoder state (w/o hash tables)
1163 * xd3_init_cache() -- reset VCDIFF address cache 1163 * xd3_init_cache() -- reset VCDIFF address cache
1164 * xd3_found_match() -- to report a copy instruction 1164 * xd3_found_match() -- to report a copy instruction
1165 * 1165 *
1166 * set stream->enc_state to ENC_INSTR and call xd3_encode_input as usual. 1166 * set stream->enc_state to ENC_INSTR and call xd3_encode_input as usual.
1167 */ 1167 */
1168int xd3_encode_init (xd3_stream *stream); 1168int xd3_encode_init_partial (xd3_stream *stream);
1169void xd3_init_cache (xd3_addr_cache* acache); 1169void xd3_init_cache (xd3_addr_cache* acache);
1170int xd3_found_match (xd3_stream *stream, 1170int xd3_found_match (xd3_stream *stream,
1171 usize_t pos, usize_t size, 1171 usize_t pos, usize_t size,