diff options
Diffstat (limited to 'xdelta3')
-rwxr-xr-x | xdelta3/xdelta3-cfgs.h | 20 | ||||
-rwxr-xr-x | xdelta3/xdelta3-main.h | 196 | ||||
-rwxr-xr-x | xdelta3/xdelta3-test.h | 42 | ||||
-rwxr-xr-x | xdelta3/xdelta3.c | 169 | ||||
-rwxr-xr-x | xdelta3/xdelta3.h | 68 |
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 | ||
251 | static usize_t option_winsize = XD3_DEFAULT_WINSIZE; | 231 | static usize_t option_winsize = XD3_DEFAULT_WINSIZE; |
252 | static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; | 232 | static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; |
233 | static 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) | |||
2918 | static int | 2910 | static int |
2919 | main_help (void) | 2911 | main_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 | ||
2433 | int | 2419 | int |
2434 | xd3_config_stream(xd3_stream *stream, | 2420 | xd3_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. */ | ||
512 | struct _xd3_smatcher | 498 | struct _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 */ |