summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3')
-rwxr-xr-xxdelta3/xdelta3-cfgs.h20
-rwxr-xr-xxdelta3/xdelta3-main.h196
-rwxr-xr-xxdelta3/xdelta3-test.h42
-rwxr-xr-xxdelta3/xdelta3.c169
-rwxr-xr-xxdelta3/xdelta3.h68
5 files changed, 217 insertions, 278 deletions
diff --git a/xdelta3/xdelta3-cfgs.h b/xdelta3/xdelta3-cfgs.h
index 329f3e9..b7b8f72 100755
--- a/xdelta3/xdelta3-cfgs.h
+++ b/xdelta3/xdelta3-cfgs.h
@@ -23,16 +23,16 @@
23#if XD3_BUILD_SOFT 23#if XD3_BUILD_SOFT
24 24
25#define TEMPLATE soft 25#define TEMPLATE soft
26#define LLOOK stream->large_look 26#define LLOOK stream->smatcher.large_look
27#define LSTEP stream->large_step 27#define LSTEP stream->smatcher.large_step
28#define SLOOK stream->small_look 28#define SLOOK stream->smatcher.small_look
29#define SCHAIN stream->small_chain 29#define SCHAIN stream->smatcher.small_chain
30#define SLCHAIN stream->small_lchain 30#define SLCHAIN stream->smatcher.small_lchain
31#define SSMATCH stream->ssmatch 31#define SSMATCH stream->smatcher.ssmatch
32#define TRYLAZY stream->try_lazy 32#define TRYLAZY stream->smatcher.try_lazy
33#define MAXLAZY stream->max_lazy 33#define MAXLAZY stream->smatcher.max_lazy
34#define LONGENOUGH stream->long_enough 34#define LONGENOUGH stream->smatcher.long_enough
35#define PROMOTE stream->promote 35#define PROMOTE stream->smatcher.promote
36 36
37#define SOFTCFG 1 37#define SOFTCFG 1
38#include "xdelta3.c" 38#include "xdelta3.c"
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 4af4b87..0fe848c 100755
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -29,23 +29,11 @@
29 * 7. basic file support and OS interface 29 * 7. basic file support and OS interface
30 */ 30 */
31 31
32/* Definite TODO list: 32/* TODO list:
33 * 1. do exact gzip-like filename, stdout handling. make a .xz extension, refuse 33 * 1. do exact gzip-like filename, stdout handling. make a .xz extension, refuse
34 * to encode to stdout without -cf, etc. 34 * to encode to stdout without -cf, etc.
35 * 2. Allow the user to add a comment string to the app header without disturbing the default 35 * 2. Allow the user to add a comment string to the app header without disturbing the default
36 * behavior. 36 * behavior.
37 * 3. Define zero-length window behavior
38 * 4. Separate getopt() code from main and make flags modular, implement help.
39 * 5. Catch up on related research!
40 */
41
42/* Nice idea TODO list:
43 *
44 * 1. Should probably have a write buffer (option)?
45 * 2. Add a reporting function for displaying progress, warning messages out of the library.
46 * 3. Add WIN32 support in addition to XD3_POSIX/XD3_STDIO. Should almost compile under windows
47 * with XD3_STDIO, but not quite (e.g., stat()?).
48 * 4. Update-in-place, partial-encoding per the latest RFC: see "Wishful TODO" comments below
49 */ 37 */
50 38
51/* On error handling and printing: 39/* On error handling and printing:
@@ -72,13 +60,8 @@
72#endif 60#endif
73 61
74/* XPRINTX (used by main) prefixes an "xdelta3: " to the output. */ 62/* XPRINTX (used by main) prefixes an "xdelta3: " to the output. */
75#if 0 && XD3_DEBUG
76#define XPR fprintf (stderr, "xdelta3[%u]: ", getpid()); fprintf
77#define NT stderr,
78#else
79#define XPR fprintf 63#define XPR fprintf
80#define NT stderr, "xdelta3: " 64#define NT stderr, "xdelta3: "
81#endif
82 65
83#define VC fprintf 66#define VC fprintf
84#define OUT vcout, 67#define OUT vcout,
@@ -96,11 +79,8 @@
96 79
97#define PRINTHDR_SPECIAL -4378291 80#define PRINTHDR_SPECIAL -4378291
98 81
99#define PIPE_BUFSIZE (usize_t)(1 << 12) 82/* The number of soft-config variables. */
100#define MIN_BUFSIZE (usize_t)(1 << 12) 83#define XD3_SOFTCFG_VARCNT 1
101
102/* The number of soft-config variables. Update as field count changes! */
103#define XD3_SOFTCFG_VARCNT 10
104 84
105/* this is used as in XPR(NT XD3_LIB_ERRMSG (stream, ret)) to print an error message 85/* this is used as in XPR(NT XD3_LIB_ERRMSG (stream, ret)) to print an error message
106 * from the library. */ 86 * from the library. */
@@ -250,6 +230,7 @@ static const char *option_source_filename = NULL;
250 230
251static usize_t option_winsize = XD3_DEFAULT_WINSIZE; 231static usize_t option_winsize = XD3_DEFAULT_WINSIZE;
252static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; 232static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ;
233static usize_t option_memsize = XD3_DEFAULT_MEMSIZE;
253 234
254/* Wishful TODO: Support should probably be for partial deltas & update-in-place deltas, 235/* Wishful TODO: Support should probably be for partial deltas & update-in-place deltas,
255 * following the latest draft RFC specs partial deltas [the changes have moderate 236 * following the latest draft RFC specs partial deltas [the changes have moderate
@@ -345,16 +326,19 @@ main_config (void)
345 P(RINT "XD3_DEBUG=%d\n", XD3_DEBUG); 326 P(RINT "XD3_DEBUG=%d\n", XD3_DEBUG);
346 P(RINT "XD3_USE_LARGEFILE64=%d\n", XD3_USE_LARGEFILE64); 327 P(RINT "XD3_USE_LARGEFILE64=%d\n", XD3_USE_LARGEFILE64);
347 P(RINT "XD3_ENCODER=%d\n", XD3_ENCODER); 328 P(RINT "XD3_ENCODER=%d\n", XD3_ENCODER);
348 /* Runtime sizes */ 329
330 /* Runtime sizes/command-line */
349 P(RINT "XD3_DEFAULT_WINSIZE=%d\n", XD3_DEFAULT_WINSIZE); 331 P(RINT "XD3_DEFAULT_WINSIZE=%d\n", XD3_DEFAULT_WINSIZE);
350 P(RINT "XD3_DEFAULT_SRCBLKSZ=%d\n", XD3_DEFAULT_SRCBLKSZ);
351 P(RINT "XD3_DEFAULT_SRCWINSZ=%d\n", XD3_DEFAULT_SRCWINSZ); 332 P(RINT "XD3_DEFAULT_SRCWINSZ=%d\n", XD3_DEFAULT_SRCWINSZ);
352 P(RINT "XD3_DEFAULT_MEMSIZE=%d\n", XD3_DEFAULT_MEMSIZE); 333 P(RINT "XD3_DEFAULT_MEMSIZE=%d\n", XD3_DEFAULT_MEMSIZE);
334
335 /* TODO: the following cannot be set by command-line */
353 P(RINT "XD3_ALLOCSIZE=%d\n", XD3_ALLOCSIZE); 336 P(RINT "XD3_ALLOCSIZE=%d\n", XD3_ALLOCSIZE);
354 P(RINT "XD3_HARDMAXWINSIZE=%d\n", XD3_HARDMAXWINSIZE); 337 P(RINT "XD3_DEFAULT_CKSUM_SIZE=%d\n", XD3_DEFAULT_CKSUM_ADVANCE);
355 P(RINT "XD3_NODECOMPRESSSIZE=%d\n", XD3_NODECOMPRESSSIZE);
356 P(RINT "XD3_DEFAULT_IOPT_SIZE=%d\n", XD3_DEFAULT_IOPT_SIZE); 338 P(RINT "XD3_DEFAULT_IOPT_SIZE=%d\n", XD3_DEFAULT_IOPT_SIZE);
357 P(RINT "XD3_DEFAULT_SPREVSZ=%d\n", XD3_DEFAULT_SPREVSZ); 339 P(RINT "XD3_DEFAULT_SPREVSZ=%d\n", XD3_DEFAULT_SPREVSZ);
340 P(RINT "XD3_HARDMAXWINSIZE=%d\n", XD3_HARDMAXWINSIZE);
341 P(RINT "XD3_NODECOMPRESSSIZE=%d\n", XD3_NODECOMPRESSSIZE);
358 342
359 return EXIT_SUCCESS; 343 return EXIT_SUCCESS;
360} 344}
@@ -1271,10 +1255,10 @@ main_decompress_input_check (main_file *ifile,
1271{ 1255{
1272 int i; 1256 int i;
1273 int ret; 1257 int ret;
1274 uint8_t check_buf[PIPE_BUFSIZE]; 1258 uint8_t check_buf[XD3_ALLOCSIZE];
1275 usize_t check_nread; 1259 usize_t check_nread;
1276 1260
1277 if ((ret = main_file_read (ifile, check_buf, min (input_size, PIPE_BUFSIZE), & check_nread, "input read failed"))) 1261 if ((ret = main_file_read (ifile, check_buf, min (input_size, XD3_ALLOCSIZE), & check_nread, "input read failed")))
1278 { 1262 {
1279 return ret; 1263 return ret;
1280 } 1264 }
@@ -1299,7 +1283,7 @@ main_decompress_input_check (main_file *ifile,
1299 1283
1300 return main_input_decompress_setup (decomp, ifile, 1284 return main_input_decompress_setup (decomp, ifile,
1301 input_buf, input_size, 1285 input_buf, input_size,
1302 check_buf, PIPE_BUFSIZE, 1286 check_buf, XD3_ALLOCSIZE,
1303 check_nread, nread); 1287 check_nread, nread);
1304 } 1288 }
1305 } 1289 }
@@ -1307,9 +1291,9 @@ main_decompress_input_check (main_file *ifile,
1307 /* Now read the rest of the input block. */ 1291 /* Now read the rest of the input block. */
1308 (*nread) = 0; 1292 (*nread) = 0;
1309 1293
1310 if (check_nread == PIPE_BUFSIZE) 1294 if (check_nread == XD3_ALLOCSIZE)
1311 { 1295 {
1312 ret = main_file_read (ifile, input_buf + PIPE_BUFSIZE, input_size - PIPE_BUFSIZE, nread, "input read failed"); 1296 ret = main_file_read (ifile, input_buf + XD3_ALLOCSIZE, input_size - XD3_ALLOCSIZE, nread, "input read failed");
1313 } 1297 }
1314 1298
1315 memcpy (input_buf, check_buf, check_nread); 1299 memcpy (input_buf, check_buf, check_nread);
@@ -1834,11 +1818,23 @@ main_set_source (xd3_stream *stream, int cmd, main_file *sfile, xd3_source *sour
1834 1818
1835 if (option_verbose > 1) { XPR(NT "source window size: %u\n", option_srcwinsz); } 1819 if (option_verbose > 1) { XPR(NT "source window size: %u\n", option_srcwinsz); }
1836 if (option_verbose > 1) { XPR(NT "source block size: %u\n", source->blksize); } 1820 if (option_verbose > 1) { XPR(NT "source block size: %u\n", source->blksize); }
1837 1821 if (option_verbose > 1) { XPR(NT "memory size: %u\n", option_memsize); }
1822
1838 lru_size = (option_srcwinsz / source->blksize); 1823 lru_size = (option_srcwinsz / source->blksize);
1839 lru_size = max(1, lru_size); 1824 lru_size = max(1, lru_size);
1840 1825
1841 XD3_ASSERT(lru_size <= 128); /* TODO: fix performance here */ 1826 if (lru_size > 128)
1827 {
1828 /* TODO: fix performance here, the LRU is scanned sequentially to find blocks,
1829 * except in encode, where it uses FIFO. Fix is to set source->blksize
1830 * accordingly. */
1831 if (IS_ENCODE(cmd) && ! option_quiet)
1832 {
1833 XPR(NT "warning: large source window (--B %u) "
1834 "hurts performance except for encoding\n",
1835 option_srcwinsz);
1836 }
1837 }
1842 1838
1843 if ((lru = main_malloc (sizeof (main_blklru) * lru_size)) == NULL) 1839 if ((lru = main_malloc (sizeof (main_blklru) * lru_size)) == NULL)
1844 { 1840 {
@@ -2179,18 +2175,16 @@ main_input (xd3_cmd cmd,
2179 } 2175 }
2180 } 2176 }
2181 2177
2182 config.large_look = values[0]; 2178 config.smatcher_soft.large_look = values[0];
2183 config.large_step = values[1]; 2179 config.smatcher_soft.large_step = values[1];
2184 config.small_look = values[2]; 2180 config.smatcher_soft.small_look = values[2];
2185 config.small_chain = values[3]; 2181 config.smatcher_soft.small_chain = values[3];
2186 config.small_lchain = values[4]; 2182 config.smatcher_soft.small_lchain = values[4];
2187 config.ssmatch = values[5]; 2183 config.smatcher_soft.ssmatch = values[5];
2188 config.try_lazy = values[6]; 2184 config.smatcher_soft.try_lazy = values[6];
2189 config.max_lazy = values[7]; 2185 config.smatcher_soft.max_lazy = values[7];
2190 config.long_enough = values[8]; 2186 config.smatcher_soft.long_enough = values[8];
2191 config.promote = values[9]; 2187 config.smatcher_soft.promote = values[9];
2192 config.srcwin_size = values[10];
2193 config.srcwin_maxsz = values[11];
2194 } 2188 }
2195 else if (option_level < 5) { config.smatch_cfg = XD3_SMATCH_FAST; } 2189 else if (option_level < 5) { config.smatch_cfg = XD3_SMATCH_FAST; }
2196 else { config.smatch_cfg = XD3_SMATCH_SLOW; } 2190 else { config.smatch_cfg = XD3_SMATCH_SLOW; }
@@ -2210,33 +2204,32 @@ main_input (xd3_cmd cmd,
2210 2204
2211 start_time = get_millisecs_now (); 2205 start_time = get_millisecs_now ();
2212 2206
2213 /* allocate an input buffer. min(file_size, option_winsize) */ 2207 xoff_t input_size = 0;
2214 { 2208 if (main_file_stat (ifile, & input_size, 0) == 0)
2215 xoff_t input_size = 0;
2216 config.winsize = option_winsize;
2217 if (main_file_stat (ifile, & input_size, 0) == 0)
2218 {
2219 config.winsize = min (input_size, (xoff_t) option_winsize);
2220 }
2221 config.winsize = max (config.winsize, MIN_BUFSIZE);
2222 }
2223 {
2224 /* Source blocksize is not user-settable, only option_srcwinsz is,
2225 * which determines the number of blocks. */
2226 source.blksize = XD3_DEFAULT_SRCBLKSZ;
2227 option_srcwinsz = max(option_srcwinsz, MIN_BUFSIZE);
2228 config.srcwin_maxsz = option_srcwinsz;
2229 }
2230
2231 if (option_verbose > 1) { XPR(NT "input buffer size: %u\n", config.winsize); }
2232
2233 if ((main_bdata = main_malloc (config.winsize)) == NULL)
2234 { 2209 {
2235 return EXIT_FAILURE; 2210 option_winsize = min (input_size, (xoff_t) option_winsize);
2236 } 2211 }
2237 2212
2213 option_srcwinsz = max(option_srcwinsz, XD3_ALLOCSIZE);
2214 option_winsize = max(option_winsize, XD3_ALLOCSIZE);
2215
2216 source.blksize = max(XD3_DEFAULT_WINSIZE, option_srcwinsz / 32);
2217
2218 config.srcwin_maxsz = option_srcwinsz;
2219 config.winsize = option_winsize;
2220 config.memsize = option_memsize;
2238 config.getblk = main_getblk_func; 2221 config.getblk = main_getblk_func;
2239 config.flags = stream_flags; 2222 config.flags = stream_flags;
2223
2224 if (option_verbose > 1)
2225 {
2226 XPR(NT "input buffer size: %u\n", option_winsize);
2227 }
2228
2229 if ((main_bdata = main_malloc (option_winsize)) == NULL)
2230 {
2231 return EXIT_FAILURE;
2232 }
2240 2233
2241 if ((ret = xd3_config_stream (& stream, & config))) 2234 if ((ret = xd3_config_stream (& stream, & config)))
2242 { 2235 {
@@ -2254,14 +2247,6 @@ main_input (xd3_cmd cmd,
2254 } 2247 }
2255 } 2248 }
2256 2249
2257 /*XD3_ASSERT (option_first_offset <= option_last_offset);*/
2258 /*XD3_ASSERT (option_first_window <= option_last_window);*/
2259
2260 /*if (option_first_offset != 0 && (ret = main_file_seek (ifile, option_first_offset)))
2261 {
2262 return EXIT_FAILURE;
2263 }*/
2264
2265 /* This times each window. */ 2250 /* This times each window. */
2266 get_millisecs_since (); 2251 get_millisecs_since ();
2267 2252
@@ -2558,7 +2543,7 @@ main (int argc, char **argv)
2558 main_file ifile; 2543 main_file ifile;
2559 main_file ofile; 2544 main_file ofile;
2560 main_file sfile; 2545 main_file sfile;
2561 static char *flags = "0123456789cdefhnqvDJNRTVs:B:C:E:F:L:O:P:W:A::S::"; 2546 static char *flags = "0123456789cdefhnqvDJNRTVs:B:C:E:F:L:O:P:M:W:A::S::";
2562 int my_optind; 2547 int my_optind;
2563 char *my_optarg; 2548 char *my_optarg;
2564 char *my_optstr; 2549 char *my_optstr;
@@ -2720,12 +2705,6 @@ main (int argc, char **argv)
2720 XPR(NT "encoder support not compiled\n"); 2705 XPR(NT "encoder support not compiled\n");
2721 return EXIT_FAILURE; 2706 return EXIT_FAILURE;
2722#endif 2707#endif
2723
2724 //case 'F': if ((ret = main_strtoxoff (my_optarg, & option_first_window, 'F'))) { goto exit; } break;
2725 //case 'L': if ((ret = main_strtoxoff (my_optarg, & option_last_window, 'L'))) { goto exit; } break;
2726 //case 'O': if ((ret = main_strtoxoff (my_optarg, & option_first_offset, 'O'))) { goto exit; } break;
2727 //case 'E': if ((ret = main_strtoxoff (my_optarg, & option_last_offset, 'E'))) { goto exit; } break;
2728
2729 case 'P': 2708 case 'P':
2730 /* only set profile count once, since... */ 2709 /* only set profile count once, since... */
2731 if (option_profile_cnt == 0) 2710 if (option_profile_cnt == 0)
@@ -2749,8 +2728,21 @@ main (int argc, char **argv)
2749 else { option_use_secondary = 1; option_secondary = my_optarg; } break; 2728 else { option_use_secondary = 1; option_secondary = my_optarg; } break;
2750 case 'A': if (my_optarg == NULL) { option_use_appheader = 0; } 2729 case 'A': if (my_optarg == NULL) { option_use_appheader = 0; }
2751 else { option_appheader = (uint8_t*) my_optarg; } break; 2730 else { option_appheader = (uint8_t*) my_optarg; } break;
2752 case 'B': if ((ret = main_atou (my_optarg, & option_srcwinsz, MIN_BUFSIZE, 'B'))) { goto exit; } break; 2731 case 'B': if ((ret = main_atou (my_optarg, & option_srcwinsz, XD3_ALLOCSIZE, 'B')))
2753 case 'W': if ((ret = main_atou (my_optarg, & option_winsize, MIN_BUFSIZE, 'W'))) { goto exit; } break; 2732 {
2733 goto exit;
2734 }
2735 break;
2736 case 'W': if ((ret = main_atou (my_optarg, & option_winsize, XD3_ALLOCSIZE, 'W')))
2737 {
2738 goto exit;
2739 }
2740 break;
2741 case 'M': if ((ret = main_atou (my_optarg, & option_memsize, XD3_ALLOCSIZE, 'M')))
2742 {
2743 goto exit;
2744 }
2745 break;
2754 case 'D': 2746 case 'D':
2755#if EXTERNAL_COMPRESSION == 0 2747#if EXTERNAL_COMPRESSION == 0
2756 if (! option_quiet) 2748 if (! option_quiet)
@@ -2918,44 +2910,46 @@ main (int argc, char **argv)
2918static int 2910static int
2919main_help (void) 2911main_help (void)
2920{ 2912{
2921 /* Not all options are shown, yet: 0-9, l J T C P F L O E 2913 /* TODO: update www/xdelta3-cmdline.html */
2922 * Remember to update www/xdelta3-cmdline.html
2923 */
2924
2925 main_version (); 2914 main_version ();
2926 P(RINT "usage: xdelta3 [command/options] [input [output]]\n"); 2915 P(RINT "usage: xdelta3 [command/options] [input [output]]\n");
2927 P(RINT "commands are:\n"); 2916 P(RINT "commands are:\n");
2928 P(RINT " encode encodes the input%s\n", XD3_ENCODER ? "" : " [Not compiled]");
2929 P(RINT " decode decodes the input\n");
2930 P(RINT " config prints xdelta3 configuration\n"); 2917 P(RINT " config prints xdelta3 configuration\n");
2918 P(RINT " decode decodes the input\n");
2919 P(RINT " encode encodes the input%s\n", XD3_ENCODER ? "" : " [Not compiled]");
2931#if REGRESSION_TEST 2920#if REGRESSION_TEST
2932 P(RINT " test run the builtin tests\n"); 2921 P(RINT " test run the builtin tests\n");
2933#endif 2922#endif
2934#if VCDIFF_TOOLS 2923#if VCDIFF_TOOLS
2935 P(RINT "special commands for VCDIFF inputs:\n"); 2924 P(RINT "special commands for VCDIFF inputs:\n");
2925 P(RINT " printdelta print information about the entire delta\n");
2936 P(RINT " printhdr print information about the first window\n"); 2926 P(RINT " printhdr print information about the first window\n");
2937 P(RINT " printhdrs print information about all windows\n"); 2927 P(RINT " printhdrs print information about all windows\n");
2938 P(RINT " printdelta print information about the entire delta\n");
2939#endif 2928#endif
2940 P(RINT "options are:\n"); 2929 P(RINT "options are:\n");
2930 P(RINT " -0 .. -9 compression level\n");
2931 P(RINT " -A [apphead] disable/provide application header\n");
2932 P(RINT " -B blksize source file block size\n");
2933 P(RINT " -C soft config (see code)\n");
2941 P(RINT " -c use stdout instead of default\n"); 2934 P(RINT " -c use stdout instead of default\n");
2935 P(RINT " -D disable external decompression (encode/decode)\n");
2942 P(RINT " -d same as decode command\n"); 2936 P(RINT " -d same as decode command\n");
2943 P(RINT " -e same as encode command\n"); 2937 P(RINT " -e same as encode command\n");
2944 P(RINT " -f force overwrite\n"); 2938 P(RINT " -f force overwrite\n");
2939 P(RINT " -h show help\n");
2940 P(RINT " -J disable output (check/compute only)\n");
2941 P(RINT " -M memsize memory budget for hash tables\n");
2945 P(RINT " -n disable checksum (encode/decode)\n"); 2942 P(RINT " -n disable checksum (encode/decode)\n");
2946 P(RINT " -D disable external decompression (encode/decode)\n");
2947 P(RINT " -R disable external recompression (decode)\n");
2948 P(RINT " -N disable small string-matching compression\n"); 2943 P(RINT " -N disable small string-matching compression\n");
2944 P(RINT " -P repeat count (for profiling)\n");
2945 P(RINT " -q be quiet\n");
2946 P(RINT " -R disable external recompression (decode)\n");
2949 P(RINT " -S [djw|fgk] disable/enable secondary compression\n"); 2947 P(RINT " -S [djw|fgk] disable/enable secondary compression\n");
2950 P(RINT " -A [apphead] disable/provide application header\n");
2951 P(RINT " -s source source file to copy from (if any)\n"); 2948 P(RINT " -s source source file to copy from (if any)\n");
2952 P(RINT " -B blksize source file block size\n"); 2949 P(RINT " -T use alternate code table (compatibility testing)\n");
2953 P(RINT " -W winsize input window buffer size\n");
2954 P(RINT " -v be verbose (max 2)\n"); 2950 P(RINT " -v be verbose (max 2)\n");
2955 P(RINT " -q be quiet\n");
2956 P(RINT " -h show help\n");
2957 P(RINT " -V show version\n"); 2951 P(RINT " -V show version\n");
2958 P(RINT " -P repeat count (for profiling)\n"); 2952 P(RINT " -W winsize input window buffer size\n");
2959 2953
2960 return EXIT_FAILURE; 2954 return EXIT_FAILURE;
2961} 2955}
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h
index 6ae43d7..d076656 100755
--- a/xdelta3/xdelta3-test.h
+++ b/xdelta3/xdelta3-test.h
@@ -2014,23 +2014,23 @@ test_string_matching (xd3_stream *stream, int ignore)
2014 xd3_init_config (& config, 0); 2014 xd3_init_config (& config, 0);
2015 2015
2016 config.smatch_cfg = XD3_SMATCH_SOFT; 2016 config.smatch_cfg = XD3_SMATCH_SOFT;
2017 config.large_look = 4; 2017 config.smatcher_soft.large_look = 4;
2018 config.large_step = 4; 2018 config.smatcher_soft.large_step = 4;
2019 config.small_look = 4; 2019 config.smatcher_soft.small_look = 4;
2020 config.small_chain = 10; 2020 config.smatcher_soft.small_chain = 10;
2021 config.small_lchain = 10; 2021 config.smatcher_soft.small_lchain = 10;
2022 config.max_lazy = 10; 2022 config.smatcher_soft.max_lazy = 10;
2023 config.long_enough = 10; 2023 config.smatcher_soft.long_enough = 10;
2024 config.ssmatch = (test->flags & SM_SSMATCH) && 1; 2024 config.smatcher_soft.ssmatch = (test->flags & SM_SSMATCH) && 1;
2025 config.try_lazy = (test->flags & SM_LAZY) && 1; 2025 config.smatcher_soft.try_lazy = (test->flags & SM_LAZY) && 1;
2026 config.promote = (test->flags & SM_PROMOTE) && 1; 2026 config.smatcher_soft.promote = (test->flags & SM_PROMOTE) && 1;
2027 2027
2028 if ((ret = xd3_config_stream (stream, & config))) { return ret; } 2028 if ((ret = xd3_config_stream (stream, & config))) { return ret; }
2029 if ((ret = xd3_encode_init (stream))) { return ret; } 2029 if ((ret = xd3_encode_init (stream))) { return ret; }
2030 2030
2031 xd3_avail_input (stream, (uint8_t*)test->input, len); 2031 xd3_avail_input (stream, (uint8_t*)test->input, len);
2032 2032
2033 if ((ret = stream->string_match (stream))) { return ret; } 2033 if ((ret = stream->smatcher.string_match (stream))) { return ret; }
2034 2034
2035 *rptr = 0; 2035 *rptr = 0;
2036 while (! xd3_rlist_empty (& stream->iopt.used)) 2036 while (! xd3_rlist_empty (& stream->iopt.used))
@@ -2093,16 +2093,16 @@ test_iopt_flush_instructions (xd3_stream *stream, int ignore)
2093 xd3_init_config (& config, 0); 2093 xd3_init_config (& config, 0);
2094 2094
2095 config.smatch_cfg = XD3_SMATCH_SOFT; 2095 config.smatch_cfg = XD3_SMATCH_SOFT;
2096 config.large_look = 16; 2096 config.smatcher_soft.large_look = 16;
2097 config.large_step = 16; 2097 config.smatcher_soft.large_step = 16;
2098 config.small_look = 4; 2098 config.smatcher_soft.small_look = 4;
2099 config.small_chain = 128; 2099 config.smatcher_soft.small_chain = 128;
2100 config.small_lchain = 16; 2100 config.smatcher_soft.small_lchain = 16;
2101 config.ssmatch = 0; 2101 config.smatcher_soft.ssmatch = 0;
2102 config.try_lazy = 1; 2102 config.smatcher_soft.try_lazy = 1;
2103 config.max_lazy = 8; 2103 config.smatcher_soft.max_lazy = 8;
2104 config.long_enough = 128; 2104 config.smatcher_soft.long_enough = 128;
2105 config.promote = 0; 2105 config.smatcher_soft.promote = 0;
2106 2106
2107 if ((ret = xd3_config_stream (stream, & config))) { return ret; } 2107 if ((ret = xd3_config_stream (stream, & config))) { return ret; }
2108 2108
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index c99ba6f..f7514e5 100755
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -478,10 +478,10 @@ IF_BUILD_SLOW(static const xd3_smatcher __smatcher_slow;)
478#if XD3_DEBUG 478#if XD3_DEBUG
479#define SMALL_HASH_DEBUG1(s,inp) \ 479#define SMALL_HASH_DEBUG1(s,inp) \
480 usize_t debug_hval = xd3_checksum_hash (& (s)->small_hash, \ 480 usize_t debug_hval = xd3_checksum_hash (& (s)->small_hash, \
481 xd3_scksum ((inp), (s)->small_look)) 481 xd3_scksum ((inp), (s)->smatcher.small_look))
482#define SMALL_HASH_DEBUG2(s,inp) \ 482#define SMALL_HASH_DEBUG2(s,inp) \
483 XD3_ASSERT (debug_hval == xd3_checksum_hash (& (s)->small_hash, \ 483 XD3_ASSERT (debug_hval == xd3_checksum_hash (& (s)->small_hash, \
484 xd3_scksum ((inp), (s)->small_look))) 484 xd3_scksum ((inp), (s)->smatcher.small_look)))
485#define SMALL_HASH_STATS(x) x 485#define SMALL_HASH_STATS(x) x
486#else 486#else
487#define SMALL_HASH_DEBUG1(s,inp) 487#define SMALL_HASH_DEBUG1(s,inp)
@@ -489,21 +489,6 @@ IF_BUILD_SLOW(static const xd3_smatcher __smatcher_slow;)
489#define SMALL_HASH_STATS(x) 489#define SMALL_HASH_STATS(x)
490#endif /* XD3_DEBUG */ 490#endif /* XD3_DEBUG */
491 491
492/* Config fields: three structures contain these variables, so this is non-typed. */
493#define XD3_COPY_CONFIG_FIELDS(dst,src) \
494 do { \
495 (dst)->large_look = (src)->large_look; \
496 (dst)->large_step = (src)->large_step; \
497 (dst)->small_look = (src)->small_look; \
498 (dst)->small_chain = (src)->small_chain; \
499 (dst)->small_lchain = (src)->small_lchain; \
500 (dst)->ssmatch = (src)->ssmatch; \
501 (dst)->try_lazy = (src)->try_lazy; \
502 (dst)->max_lazy = (src)->max_lazy; \
503 (dst)->long_enough = (src)->long_enough; \
504 (dst)->promote = (src)->promote; \
505 } while (0)
506
507/* Update the run-length state */ 492/* Update the run-length state */
508#define NEXTRUN(c) do { if ((c) == run_c) { run_l += 1; } else { run_c = (c); run_l = 1; } } while (0) 493#define NEXTRUN(c) do { if ((c) == run_c) { run_l += 1; } else { run_c = (c); run_l = 1; } } while (0)
509 494
@@ -1190,20 +1175,21 @@ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *cod
1190 1175
1191 /* Be exhaustive. */ 1176 /* Be exhaustive. */
1192 config.sprevsz = 1<<11; 1177 config.sprevsz = 1<<11;
1193 config.memsize = CODE_TABLE_STRING_SIZE * 10; 1178 config.memsize = CODE_TABLE_STRING_SIZE;
1194 1179 config.srcwin_size = CODE_TABLE_STRING_SIZE;
1195 config.large_look = 4; 1180 config.srcwin_maxsz = CODE_TABLE_STRING_SIZE;
1196 config.large_step = 1; 1181
1197 config.small_look = 4; 1182 config.smatch_cfg = XD3_SMATCH_SOFT;
1198 config.small_chain = CODE_TABLE_STRING_SIZE; 1183 config.smatcher_soft.large_look = 4;
1199 config.small_lchain = CODE_TABLE_STRING_SIZE; 1184 config.smatcher_soft.large_step = 1;
1200 config.ssmatch = 1; 1185 config.smatcher_soft.small_look = 4;
1201 config.try_lazy = 1; 1186 config.smatcher_soft.small_chain = CODE_TABLE_STRING_SIZE;
1202 config.max_lazy = CODE_TABLE_STRING_SIZE; 1187 config.smatcher_soft.small_lchain = CODE_TABLE_STRING_SIZE;
1203 config.long_enough = CODE_TABLE_STRING_SIZE; 1188 config.smatcher_soft.ssmatch = 1;
1204 config.promote = 1; 1189 config.smatcher_soft.try_lazy = 1;
1205 config.srcwin_size = CODE_TABLE_STRING_SIZE; 1190 config.smatcher_soft.max_lazy = CODE_TABLE_STRING_SIZE;
1206 config.srcwin_maxsz = CODE_TABLE_STRING_SIZE; 1191 config.smatcher_soft.long_enough = CODE_TABLE_STRING_SIZE;
1192 config.smatcher_soft.promote = 1;
1207 1193
1208 if ((ret = xd3_config_stream (& stream, & config))) { goto fail; } 1194 if ((ret = xd3_config_stream (& stream, & config))) { goto fail; }
1209 1195
@@ -2432,11 +2418,11 @@ xd3_rtype_to_string (xd3_rtype type, int print_mode)
2432 2418
2433int 2419int
2434xd3_config_stream(xd3_stream *stream, 2420xd3_config_stream(xd3_stream *stream,
2435 xd3_config *config) 2421 xd3_config *config)
2436{ 2422{
2437 int ret; 2423 int ret;
2438 xd3_config defcfg; 2424 xd3_config defcfg;
2439 const xd3_smatcher* smatcher; 2425 xd3_smatcher *smatcher = &stream->smatcher;
2440 2426
2441 if (config == NULL) 2427 if (config == NULL)
2442 { 2428 {
@@ -2450,17 +2436,16 @@ xd3_config_stream(xd3_stream *stream,
2450 stream->memsize = config->memsize ? config->memsize : XD3_DEFAULT_MEMSIZE; 2436 stream->memsize = config->memsize ? config->memsize : XD3_DEFAULT_MEMSIZE;
2451 stream->winsize = config->winsize ? config->winsize : XD3_DEFAULT_WINSIZE; 2437 stream->winsize = config->winsize ? config->winsize : XD3_DEFAULT_WINSIZE;
2452 stream->sprevsz = config->sprevsz ? config->sprevsz : XD3_DEFAULT_SPREVSZ; 2438 stream->sprevsz = config->sprevsz ? config->sprevsz : XD3_DEFAULT_SPREVSZ;
2453 stream->srcwin_size = config->srcwin_size ? config->srcwin_size : XD3_DEFAULT_START_CKSUM_ADVANCE;
2454 stream->srcwin_maxsz = config->srcwin_maxsz ? config->srcwin_maxsz : XD3_DEFAULT_MAX_CKSUM_ADVANCE;
2455 stream->iopt_size = config->iopt_size ? config->iopt_size : XD3_DEFAULT_IOPT_SIZE; 2439 stream->iopt_size = config->iopt_size ? config->iopt_size : XD3_DEFAULT_IOPT_SIZE;
2440 stream->srcwin_size = config->srcwin_size ? config->srcwin_size : XD3_DEFAULT_CKSUM_ADVANCE;
2441 stream->srcwin_maxsz = config->srcwin_maxsz ? config->srcwin_maxsz : XD3_DEFAULT_SRCWINSZ;
2442
2456 stream->getblk = config->getblk; 2443 stream->getblk = config->getblk;
2457 stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func; 2444 stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func;
2458 stream->free = config->freef ? config->freef : __xd3_free_func; 2445 stream->free = config->freef ? config->freef : __xd3_free_func;
2459 stream->opaque = config->opaque; 2446 stream->opaque = config->opaque;
2460 stream->flags = config->flags; 2447 stream->flags = config->flags;
2461 2448
2462 XD3_ASSERT (stream->winsize > 0);
2463
2464 /* Secondary setup. */ 2449 /* Secondary setup. */
2465 stream->sec_data = config->sec_data; 2450 stream->sec_data = config->sec_data;
2466 stream->sec_inst = config->sec_inst; 2451 stream->sec_inst = config->sec_inst;
@@ -2517,7 +2502,7 @@ xd3_config_stream(xd3_stream *stream,
2517 } 2502 }
2518 2503
2519 /* Check sprevsz */ 2504 /* Check sprevsz */
2520 if (config->small_chain == 1) 2505 if (smatcher->small_chain == 1)
2521 { 2506 {
2522 stream->sprevsz = 0; 2507 stream->sprevsz = 0;
2523 } 2508 }
@@ -2536,45 +2521,36 @@ xd3_config_stream(xd3_stream *stream,
2536 switch (config->smatch_cfg) 2521 switch (config->smatch_cfg)
2537 { 2522 {
2538 IF_BUILD_SOFT(case XD3_SMATCH_SOFT: 2523 IF_BUILD_SOFT(case XD3_SMATCH_SOFT:
2539 smatcher = & __smatcher_soft; break; 2524 {
2540 2525 *smatcher = config->smatcher_soft;
2541 if (config->large_look < MIN_MATCH || 2526 smatcher->string_match = __smatcher_soft.string_match;
2542 config->large_step < 1 || 2527 smatcher->name = __smatcher_soft.name;
2543 config->small_look < MIN_MATCH || 2528 if (smatcher->large_look < MIN_MATCH ||
2544 config->small_chain < 1 || 2529 smatcher->large_step < 1 ||
2545 config->large_look < config->small_look || 2530 smatcher->small_look < MIN_MATCH ||
2546 config->small_chain < config->small_lchain || 2531 smatcher->small_chain < 1 ||
2547 (config->small_lchain == 0 && config->try_lazy) || 2532 smatcher->large_look < smatcher->small_look ||
2548 config->srcwin_size < stream->large_look || 2533 smatcher->small_chain < smatcher->small_lchain ||
2549 config->srcwin_maxsz < stream->srcwin_size) 2534 (smatcher->small_lchain == 0 && smatcher->try_lazy))
2550 { 2535 {
2551 stream->msg = "invalid soft string-match config"; 2536 stream->msg = "invalid soft string-match config";
2552 return XD3_INTERNAL; 2537 return XD3_INTERNAL;
2553 } 2538 }
2554 break;) 2539 break;
2540 })
2555 2541
2556 IF_BUILD_SLOW(case XD3_SMATCH_DEFAULT:) 2542 IF_BUILD_SLOW(case XD3_SMATCH_DEFAULT:)
2557 IF_BUILD_SLOW(case XD3_SMATCH_SLOW: smatcher = & __smatcher_slow; break;) 2543 IF_BUILD_SLOW(case XD3_SMATCH_SLOW:
2558 IF_BUILD_FAST(case XD3_SMATCH_FAST: smatcher = & __smatcher_fast; break;) 2544 *smatcher = __smatcher_slow;
2545 break;)
2546 IF_BUILD_FAST(case XD3_SMATCH_FAST:
2547 *smatcher = __smatcher_fast;
2548 break;)
2559 default: 2549 default:
2560 stream->msg = "invalid string match config type"; 2550 stream->msg = "invalid string match config type";
2561 return XD3_INTERNAL; 2551 return XD3_INTERNAL;
2562 } 2552 }
2563 2553
2564 stream->string_match = smatcher->string_match;
2565 XD3_ASSERT(stream->string_match);
2566
2567 XD3_COPY_CONFIG_FIELDS (stream, smatcher);
2568
2569 /* If it is a soft config, the smatcher fields didn't set anything, copy from config
2570 * instead. */
2571 if (stream->large_look == 0)
2572 {
2573 XD3_COPY_CONFIG_FIELDS (stream, config);
2574 }
2575
2576 IF_DEBUG1 (P(RINT "[stream cfg] llook %u lstep %u slook %u\n",
2577 stream->large_look, stream->large_step, stream->small_look));
2578 return 0; 2554 return 0;
2579} 2555}
2580 2556
@@ -2638,7 +2614,7 @@ xd3_set_source (xd3_stream *stream,
2638 2614
2639 IF_DEBUG1 (P(RINT "[set source] size %"Q"u\n", src->size)); 2615 IF_DEBUG1 (P(RINT "[set source] size %"Q"u\n", src->size));
2640 2616
2641 if (src == NULL || src->size < stream->large_look) { return 0; } 2617 if (src == NULL || src->size < stream->smatcher.large_look) { return 0; }
2642 2618
2643 stream->src = src; 2619 stream->src = src;
2644 blk_num = src->size / src->blksize; 2620 blk_num = src->size / src->blksize;
@@ -3513,26 +3489,27 @@ xd3_encode_init (xd3_stream *stream)
3513 int i; 3489 int i;
3514 int large_comp = (stream->src != NULL); 3490 int large_comp = (stream->src != NULL);
3515 int small_comp = ! (stream->flags & XD3_NOCOMPRESS); 3491 int small_comp = ! (stream->flags & XD3_NOCOMPRESS);
3516 /*int small_prev = (stream->small_chain > 1);*/
3517 int space_fact = (large_comp + small_comp);
3518 int memsize = stream->memsize;
3519 3492
3520 /* Memory allocations for checksum tables are delayed until xd3_string_match_init in the 3493 /* Memory allocations for checksum tables are delayed until xd3_string_match_init in the
3521 * first call to string_match--that way identical or short inputs require no table 3494 * first call to string_match--that way identical or short inputs require no table
3522 * allocation. */ 3495 * allocation. */
3523 if (large_comp) 3496 if (large_comp)
3524 { 3497 {
3525 xd3_size_hashtable (stream, memsize / space_fact, & stream->large_hash); 3498 xd3_size_hashtable (stream, stream->memsize, & stream->large_hash);
3526 } 3499 }
3527 3500
3528 if (small_comp) 3501 if (small_comp)
3529 { 3502 {
3530 xd3_size_hashtable (stream, memsize / space_fact, & stream->small_hash); 3503 /* Keep table small because small matches become less efficient after long. */
3504 xd3_size_hashtable (stream,
3505 min(stream->winsize, XD3_DEFAULT_MEMSIZE),
3506 & stream->small_hash);
3531 } 3507 }
3532 3508
3533 for (i = 0; i < ENC_SECTS; i += 1) 3509 for (i = 0; i < ENC_SECTS; i += 1)
3534 { 3510 {
3535 if ((stream->enc_heads[i] = stream->enc_tails[i] = 3511 if ((stream->enc_heads[i] =
3512 stream->enc_tails[i] =
3536 xd3_alloc_output (stream, NULL)) == NULL) 3513 xd3_alloc_output (stream, NULL)) == NULL)
3537 { 3514 {
3538 goto fail; 3515 goto fail;
@@ -3735,7 +3712,7 @@ xd3_encode_input (xd3_stream *stream)
3735 3712
3736 /* String matching... */ 3713 /* String matching... */
3737 if (stream->avail_in != 0 && 3714 if (stream->avail_in != 0 &&
3738 (ret = stream->string_match (stream))) 3715 (ret = stream->smatcher.string_match (stream)))
3739 { 3716 {
3740 return ret; 3717 return ret;
3741 } 3718 }
@@ -3926,6 +3903,8 @@ xd3_string_match_init (xd3_stream *stream)
3926 if (stream->small_table != NULL) 3903 if (stream->small_table != NULL)
3927 { 3904 {
3928 /* The target hash table is reinitialized once per window. */ 3905 /* The target hash table is reinitialized once per window. */
3906 /* TODO: This would not have to be reinitialized if absolute offsets
3907 * were being stored. */
3929 if (stream->small_reset) 3908 if (stream->small_reset)
3930 { 3909 {
3931 stream->small_reset = 0; 3910 stream->small_reset = 0;
@@ -3935,17 +3914,21 @@ xd3_string_match_init (xd3_stream *stream)
3935 return 0; 3914 return 0;
3936 } 3915 }
3937 3916
3938 if ((stream->small_table = xd3_alloc0 (stream, stream->small_hash.size, sizeof (usize_t))) == NULL) 3917 if ((stream->small_table = xd3_alloc0 (stream,
3918 stream->small_hash.size,
3919 sizeof (usize_t))) == NULL)
3939 { 3920 {
3940 return ENOMEM; 3921 return ENOMEM;
3941 } 3922 }
3942 3923
3943 /* If there is a previous table needed. */ 3924 /* If there is a previous table needed. */
3944 if (stream->small_chain > 1) 3925 if (stream->smatcher.small_chain > 1)
3945 { 3926 {
3946 xd3_slist *p, *m; 3927 xd3_slist *p, *m;
3947 3928
3948 if ((stream->small_prev = xd3_alloc (stream, stream->sprevsz, sizeof (xd3_slist))) == NULL) 3929 if ((stream->small_prev = xd3_alloc (stream,
3930 stream->sprevsz,
3931 sizeof (xd3_slist))) == NULL)
3949 { 3932 {
3950 return ENOMEM; 3933 return ENOMEM;
3951 } 3934 }
@@ -4026,7 +4009,7 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4026 usize_t onblk = xd3_bytes_on_srcblk (stream->src, blkno); 4009 usize_t onblk = xd3_bytes_on_srcblk (stream->src, blkno);
4027 int ret; 4010 int ret;
4028 4011
4029 if (blkoff + stream->large_look > onblk) 4012 if (blkoff + stream->smatcher.large_look > onblk)
4030 { 4013 {
4031 /* Next block */ 4014 /* Next block */
4032 stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; 4015 stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize;
@@ -4042,19 +4025,19 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point)
4042 return ret; 4025 return ret;
4043 } 4026 }
4044 4027
4045 onblk -= stream->large_look; 4028 onblk -= stream->smatcher.large_look;
4046 int diff = logical_input_cksum_pos - stream->srcwin_cksum_pos; 4029 int diff = logical_input_cksum_pos - stream->srcwin_cksum_pos;
4047 onblk = min(blkoff + diff, onblk); 4030 onblk = min(blkoff + diff, onblk);
4048 4031
4049 while (blkoff <= onblk) 4032 while (blkoff <= onblk)
4050 { 4033 {
4051 uint32_t cksum = xd3_lcksum (stream->src->curblk + blkoff, stream->large_look); 4034 uint32_t cksum = xd3_lcksum (stream->src->curblk + blkoff, stream->smatcher.large_look);
4052 usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); 4035 usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum);
4053 4036
4054 stream->large_table[hval] = stream->srcwin_cksum_pos + HASH_CKOFFSET; 4037 stream->large_table[hval] = stream->srcwin_cksum_pos + HASH_CKOFFSET;
4055 4038
4056 blkoff += stream->large_step; 4039 blkoff += stream->smatcher.large_step;
4057 stream->srcwin_cksum_pos += stream->large_step; 4040 stream->srcwin_cksum_pos += stream->smatcher.large_step;
4058 4041
4059 IF_DEBUG (stream->large_ckcnt += 1); 4042 IF_DEBUG (stream->large_ckcnt += 1);
4060 } 4043 }
@@ -4543,7 +4526,7 @@ xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0,
4543/* When the hash table indicates a possible small string match, it calls this routine to 4526/* When the hash table indicates a possible small string match, it calls this routine to
4544 * find the best match. The first matching position is taken from the small_table, 4527 * find the best match. The first matching position is taken from the small_table,
4545 * HASH_CKOFFSET is subtracted to get the actual position. After checking that match, if 4528 * HASH_CKOFFSET is subtracted to get the actual position. After checking that match, if
4546 * previous linked lists are in use (because stream->small_chain > 1), previous matches 4529 * previous linked lists are in use (because stream->smatcher.small_chain > 1), previous matches
4547 * are tested searching for the longest match. If (stream->min_match > MIN_MATCH) then a lazy 4530 * are tested searching for the longest match. If (stream->min_match > MIN_MATCH) then a lazy
4548 * match is in effect. 4531 * match is in effect.
4549 * 4532 *
@@ -4563,8 +4546,8 @@ xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_off
4563 usize_t cmp_len; 4546 usize_t cmp_len;
4564 usize_t match_length = 0; 4547 usize_t match_length = 0;
4565 usize_t chain = (stream->min_match == MIN_MATCH ? 4548 usize_t chain = (stream->min_match == MIN_MATCH ?
4566 stream->small_chain : 4549 stream->smatcher.small_chain :
4567 stream->small_lchain); 4550 stream->smatcher.small_lchain);
4568 xd3_slist *current = NULL; 4551 xd3_slist *current = NULL;
4569 xd3_slist *first = NULL; 4552 xd3_slist *first = NULL;
4570 const uint8_t *inp_max = stream->next_in + stream->avail_in; 4553 const uint8_t *inp_max = stream->next_in + stream->avail_in;
@@ -4621,7 +4604,7 @@ xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_off
4621 (*match_offset) = base; 4604 (*match_offset) = base;
4622 4605
4623 /* Stop if we match the entire input or discover a long_enough match. */ 4606 /* Stop if we match the entire input or discover a long_enough match. */
4624 if (inp == inp_max || cmp_len >= stream->long_enough) 4607 if (inp == inp_max || cmp_len >= stream->smatcher.long_enough)
4625 { 4608 {
4626 goto done; 4609 goto done;
4627 } 4610 }
@@ -4661,7 +4644,7 @@ xd3_verify_small_state (xd3_stream *stream,
4661 const uint8_t *inp, 4644 const uint8_t *inp,
4662 uint32_t x_cksum) 4645 uint32_t x_cksum)
4663{ 4646{
4664 uint32_t cksum = xd3_scksum (inp, stream->small_look); 4647 uint32_t cksum = xd3_scksum (inp, stream->smatcher.small_look);
4665 4648
4666 XD3_ASSERT (cksum == x_cksum); 4649 XD3_ASSERT (cksum == x_cksum);
4667} 4650}
@@ -4671,7 +4654,7 @@ xd3_verify_large_state (xd3_stream *stream,
4671 const uint8_t *inp, 4654 const uint8_t *inp,
4672 uint32_t x_cksum) 4655 uint32_t x_cksum)
4673{ 4656{
4674 uint32_t cksum = xd3_lcksum (inp, stream->large_look); 4657 uint32_t cksum = xd3_lcksum (inp, stream->smatcher.large_look);
4675 4658
4676 XD3_ASSERT (cksum == x_cksum); 4659 XD3_ASSERT (cksum == x_cksum);
4677} 4660}
@@ -4682,7 +4665,7 @@ xd3_verify_run_state (xd3_stream *stream,
4682 int x_run_l, 4665 int x_run_l,
4683 uint8_t x_run_c) 4666 uint8_t x_run_c)
4684{ 4667{
4685 int slook = stream->small_look; 4668 int slook = stream->smatcher.small_look;
4686 uint8_t run_c; 4669 uint8_t run_c;
4687 int run_l = xd3_comprun (inp, slook, &run_c); 4670 int run_l = xd3_comprun (inp, slook, &run_c);
4688 4671
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h
index b538d77..90b2fd9 100755
--- a/xdelta3/xdelta3.h
+++ b/xdelta3/xdelta3.h
@@ -38,21 +38,9 @@
38#define XD3_DEFAULT_WINSIZE (1U << 18) 38#define XD3_DEFAULT_WINSIZE (1U << 18)
39#endif 39#endif
40 40
41/* The source block size. 41/* This is a unit of how far to advance the checksum position in one go. */
42 */ 42#ifndef XD3_DEFAULT_CKSUM_ADVANCE
43#ifndef XD3_DEFAULT_SRCBLKSZ 43#define XD3_DEFAULT_CKSUM_ADVANCE (1U << 14)
44#define XD3_DEFAULT_SRCBLKSZ (1U << 18)
45#endif
46
47/* The source window starts with only a few checksums, then doubles up to
48 * XD3_DEFAULT_MAX_CKSUM_ADVANCE. */
49#ifndef XD3_DEFAULT_START_CKSUM_ADVANCE
50#define XD3_DEFAULT_START_CKSUM_ADVANCE (1U << 14)
51#endif
52
53/* TODO: There is no command-line flag to set this value. */
54#ifndef XD3_DEFAULT_MAX_CKSUM_ADVANCE
55#define XD3_DEFAULT_MAX_CKSUM_ADVANCE (1U << 23)
56#endif 44#endif
57 45
58/* Default total size of the source window used in xdelta3-main.h */ 46/* Default total size of the source window used in xdelta3-main.h */
@@ -69,7 +57,7 @@
69/* When Xdelta requests a memory allocation for certain buffers, it rounds up to units of 57/* When Xdelta requests a memory allocation for certain buffers, it rounds up to units of
70 * at least this size. The code assumes (and asserts) that this is a power-of-two. */ 58 * at least this size. The code assumes (and asserts) that this is a power-of-two. */
71#ifndef XD3_ALLOCSIZE 59#ifndef XD3_ALLOCSIZE
72#define XD3_ALLOCSIZE (1U<<13) 60#define XD3_ALLOCSIZE (1U<<14)
73#endif 61#endif
74 62
75/* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect decoders against 63/* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect decoders against
@@ -506,9 +494,7 @@ struct _xd3_iopt_buf
506 xd3_rinst *buffer; 494 xd3_rinst *buffer;
507}; 495};
508 496
509/* This is the record of a pre-compiled configuration, a subset of xd3_config. Keep them 497/* This is the record of a pre-compiled configuration, a subset of xd3_config. */
510 * in sync! The user never sees this structure. Note: update XD3_SOFTCFG_VARCNT when
511 * changing. */
512struct _xd3_smatcher 498struct _xd3_smatcher
513{ 499{
514 const char *name; 500 const char *name;
@@ -577,7 +563,6 @@ struct _xd3_config
577 usize_t winsize; /* The encoder window size. */ 563 usize_t winsize; /* The encoder window size. */
578 usize_t sprevsz; /* How far back small string matching goes */ 564 usize_t sprevsz; /* How far back small string matching goes */
579 usize_t iopt_size; /* entries in the instruction-optimizing buffer */ 565 usize_t iopt_size; /* entries in the instruction-optimizing buffer */
580
581 usize_t srcwin_size; /* Initial size of the source-window lookahead */ 566 usize_t srcwin_size; /* Initial size of the source-window lookahead */
582 usize_t srcwin_maxsz; /* srcwin_size grows by a factor of 2 when no matches are found */ 567 usize_t srcwin_maxsz; /* srcwin_size grows by a factor of 2 when no matches are found */
583 568
@@ -594,16 +579,7 @@ struct _xd3_config
594 xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ 579 xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */
595 580
596 xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for soft config */ 581 xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for soft config */
597 uint large_look; /* large string lookahead (i.e., hashed chars) */ 582 xd3_smatcher smatcher_soft;
598 uint large_step; /* large string interval */
599 uint small_look; /* small string lookahead (i.e., hashed chars) */
600 uint small_chain; /* small string number of previous matches to try */
601 uint small_lchain; /* small string number of previous matches to try, when a lazy match */
602 uint ssmatch; /* boolean: insert checksums for matched strings */
603 uint try_lazy; /* boolean: whether lazy instruction optimization is attempted */
604 uint max_lazy; /* size of smallest match that will disable lazy matching */
605 uint long_enough; /* size of smallest match long enough to discontinue string matching. */
606 uint promote; /* whether to promote matches in the hash chain */
607}; 583};
608 584
609/* The primary source file object. You create one of these objects and initialize the 585/* The primary source file object. You create one of these objects and initialize the
@@ -661,6 +637,8 @@ struct _xd3_stream
661 usize_t sprevsz; /* small string, previous window size (power of 2) */ 637 usize_t sprevsz; /* small string, previous window size (power of 2) */
662 usize_t sprevmask; /* small string, previous window size mask */ 638 usize_t sprevmask; /* small string, previous window size mask */
663 uint iopt_size; 639 uint iopt_size;
640 uint srcwin_size;
641 uint srcwin_maxsz;
664 642
665 /* general configuration */ 643 /* general configuration */
666 xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */ 644 xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */
@@ -668,40 +646,24 @@ struct _xd3_stream
668 xd3_free_func *free; /* free function */ 646 xd3_free_func *free; /* free function */
669 void* opaque; /* private data object passed to alloc, free, and getblk */ 647 void* opaque; /* private data object passed to alloc, free, and getblk */
670 int flags; /* various options */ 648 int flags; /* various options */
671 int aborted;
672 649
673 /* secondary compressor configuration */ 650 /* secondary compressor configuration */
674 xd3_sec_cfg sec_data; /* Secondary compressor config: data */ 651 xd3_sec_cfg sec_data; /* Secondary compressor config: data */
675 xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ 652 xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */
676 xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ 653 xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */
677 654
678 /* fields common to xd3_stream_config, xd3_smatcher */ 655 xd3_smatcher smatcher;
679 uint large_look;
680 uint large_step;
681 uint small_look;
682 uint small_chain;
683 uint small_lchain;
684 uint ssmatch;
685 uint try_lazy;
686 uint max_lazy;
687 uint long_enough;
688 uint promote;
689 uint srcwin_size;
690 uint srcwin_maxsz;
691 int (*string_match) (xd3_stream *stream);
692 656
693 usize_t *large_table; /* table of large checksums */ 657 usize_t *large_table; /* table of large checksums */
694 xd3_hash_cfg large_hash; /* large hash config */ 658 xd3_hash_cfg large_hash; /* large hash config */
695 659
696 usize_t *small_table; /* table of small checksums */ 660 usize_t *small_table; /* table of small checksums */
697 xd3_slist *small_prev; /* table of previous offsets, circular linked list (no sentinel) */ 661 xd3_slist *small_prev; /* table of previous offsets, circular linked list */
698 int small_reset; /* true if small table should be reset */ 662 int small_reset; /* true if small table should be reset */
699
700 xd3_hash_cfg small_hash; /* small hash config */
701
702 xd3_addr_cache acache; /* the vcdiff address cache */
703 663
704 xd3_encode_state enc_state; /* state of the encoder */ 664 xd3_hash_cfg small_hash; /* small hash config */
665 xd3_addr_cache acache; /* the vcdiff address cache */
666 xd3_encode_state enc_state; /* state of the encoder */
705 667
706 usize_t taroff; /* base offset of the target input */ 668 usize_t taroff; /* base offset of the target input */
707 usize_t input_position; /* current input position */ 669 usize_t input_position; /* current input position */