"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "xdelta3.c" between
xdelta3-3.0.11.tar.gz and xdelta3-3.1.0.tar.gz

About: xdelta is a tool and library for differential compression (supports VCDIFF encoding and decoding). Beta version.

xdelta3.c  (xdelta3-3.0.11):xdelta3.c  (xdelta3-3.1.0)
skipping to change at line 353 skipping to change at line 353
* listed here. */ * listed here. */
ADDR_SECTION ADDR_SECTION
} xd3_section_type; } xd3_section_type;
typedef unsigned int xd3_rtype; typedef unsigned int xd3_rtype;
/***********************************************************************/ /***********************************************************************/
#include "xdelta3-list.h" #include "xdelta3-list.h"
#if XD3_ENCODER
XD3_MAKELIST(xd3_rlist, xd3_rinst, link); XD3_MAKELIST(xd3_rlist, xd3_rinst, link);
#endif
/***********************************************************************/ /***********************************************************************/
#define SECONDARY_MIN_SAVINGS 2 /* Secondary compression has to save #define SECONDARY_MIN_SAVINGS 2 /* Secondary compression has to save
at least this many bytes. */ at least this many bytes. */
#define SECONDARY_MIN_INPUT 10 /* Secondary compression needs at #define SECONDARY_MIN_INPUT 10 /* Secondary compression needs at
least this many bytes. */ least this many bytes. */
#define VCDIFF_MAGIC1 0xd6 /* 1st file byte */ #define VCDIFF_MAGIC1 0xd6 /* 1st file byte */
#define VCDIFF_MAGIC2 0xc3 /* 2nd file byte */ #define VCDIFF_MAGIC2 0xc3 /* 2nd file byte */
#define VCDIFF_MAGIC3 0xc4 /* 3rd file byte */ #define VCDIFF_MAGIC3 0xc4 /* 3rd file byte */
#define VCDIFF_VERSION 0x00 /* 4th file byte */ #define VCDIFF_VERSION 0x00 /* 4th file byte */
#define VCD_SELF 0 /* 1st address mode */ #define VCD_SELF 0 /* 1st address mode */
#define VCD_HERE 1 /* 2nd address mode */ #define VCD_HERE 1 /* 2nd address mode */
#define CODE_TABLE_STRING_SIZE (6 * 256) /* Should fit a code table string. */
#define CODE_TABLE_VCDIFF_SIZE (6 * 256) /* Should fit a compressed code
* table string */
#define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK || SECONDARY_LZMA) #define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK || SECONDARY_LZMA)
#define ALPHABET_SIZE 256 /* Used in test code--size of the secondary #define ALPHABET_SIZE 256 /* Used in test code--size of the secondary
* compressor alphabet. */ * compressor alphabet. */
#define HASH_PERMUTE 1 /* The input is permuted by random nums */
#define ADLER_LARGE_CKSUM 1 /* Adler checksum vs. RK checksum */
#define HASH_CKOFFSET 1U /* Table entries distinguish "no-entry" from #define HASH_CKOFFSET 1U /* Table entries distinguish "no-entry" from
* offset 0 using this offset. */ * offset 0 using this offset. */
#define MIN_SMALL_LOOK 2U /* Match-optimization stuff. */
#define MIN_LARGE_LOOK 2U
#define MIN_MATCH_OFFSET 1U
#define MAX_MATCH_SPLIT 18U /* VCDIFF code table: 18 is the default limit #define MAX_MATCH_SPLIT 18U /* VCDIFF code table: 18 is the default limit
* for direct-coded ADD sizes */ * for direct-coded ADD sizes */
#define LEAST_MATCH_INCR 0 /* The least number of bytes an overlapping #define LEAST_MATCH_INCR 0 /* The least number of bytes an overlapping
* match must beat the preceding match by. This * match must beat the preceding match by. This
* is a bias for the lazy match optimization. A * is a bias for the lazy match optimization. A
* non-zero value means that an adjacent match * non-zero value means that an adjacent match
* has to be better by more than the step * has to be better by more than the step
* between them. 0. */ * between them. 0. */
#define MIN_MATCH 4U /* VCDIFF code table: MIN_MATCH=4 */ #define MIN_MATCH 4U /* VCDIFF code table: MIN_MATCH=4 */
#define MIN_ADD 1U /* 1 */
#define MIN_RUN 8U /* The shortest run, if it is shorter than this #define MIN_RUN 8U /* The shortest run, if it is shorter than this
* an immediate add/copy will be just as good. * an immediate add/copy will be just as good.
* ADD1/COPY6 = 1I+1D+1A bytes, RUN18 = * ADD1/COPY6 = 1I+1D+1A bytes, RUN18 =
* 1I+1D+1A. */ * 1I+1D+1A. */
#define MAX_MODES 9 /* Maximum number of nodes used for #define MAX_MODES 9 /* Maximum number of nodes used for
* compression--does not limit decompression. */ * compression--does not limit decompression. */
#define ENC_SECTS 4 /* Number of separate output sections. */ #define ENC_SECTS 4 /* Number of separate output sections. */
#define HDR_TAIL(s) ((s)->enc_tails[0]) #define HDR_TAIL(s) ((s)->enc_tails[0])
#define DATA_TAIL(s) ((s)->enc_tails[1]) #define DATA_TAIL(s) ((s)->enc_tails[1])
#define INST_TAIL(s) ((s)->enc_tails[2]) #define INST_TAIL(s) ((s)->enc_tails[2])
#define ADDR_TAIL(s) ((s)->enc_tails[3]) #define ADDR_TAIL(s) ((s)->enc_tails[3])
#define HDR_HEAD(s) ((s)->enc_heads[0]) #define HDR_HEAD(s) ((s)->enc_heads[0])
#define DATA_HEAD(s) ((s)->enc_heads[1]) #define DATA_HEAD(s) ((s)->enc_heads[1])
#define INST_HEAD(s) ((s)->enc_heads[2]) #define INST_HEAD(s) ((s)->enc_heads[2])
#define ADDR_HEAD(s) ((s)->enc_heads[3]) #define ADDR_HEAD(s) ((s)->enc_heads[3])
#define TOTAL_MODES(x) (2+(x)->acache.s_same+(x)->acache.s_near)
/* Template instances. */ /* Template instances. */
#if XD3_BUILD_SLOW #if XD3_BUILD_SLOW
#define IF_BUILD_SLOW(x) x #define IF_BUILD_SLOW(x) x
#else #else
#define IF_BUILD_SLOW(x) #define IF_BUILD_SLOW(x)
#endif #endif
#if XD3_BUILD_FAST #if XD3_BUILD_FAST
#define IF_BUILD_FAST(x) x #define IF_BUILD_FAST(x) x
#else #else
#define IF_BUILD_FAST(x) #define IF_BUILD_FAST(x)
skipping to change at line 478 skipping to change at line 467
static void* xd3_alloc0 (xd3_stream *stream, static void* xd3_alloc0 (xd3_stream *stream,
usize_t elts, usize_t elts,
usize_t size); usize_t size);
static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts); static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts);
static void xd3_free_output (xd3_stream *stream, static void xd3_free_output (xd3_stream *stream,
xd3_output *output); xd3_output *output);
static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first,
xd3_rinst *second, usize_t code); xd3_rinst *second, uint8_t code);
static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single,
usize_t code); uint8_t code);
static usize_t xd3_sizeof_output (xd3_output *output); static usize_t xd3_sizeof_output (xd3_output *output);
static void xd3_encode_reset (xd3_stream *stream); static void xd3_encode_reset (xd3_stream *stream);
static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos); static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos);
static int xd3_source_extend_match (xd3_stream *stream); static int xd3_source_extend_match (xd3_stream *stream);
static int xd3_srcwin_setup (xd3_stream *stream); static int xd3_srcwin_setup (xd3_stream *stream);
static usize_t xd3_iopt_last_matched (xd3_stream *stream); static usize_t xd3_iopt_last_matched (xd3_stream *stream);
static int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, static int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output,
uint32_t num); uint32_t num);
skipping to change at line 505 skipping to change at line 494
usize_t *match_offset); usize_t *match_offset);
static int xd3_string_match_init (xd3_stream *stream); static int xd3_string_match_init (xd3_stream *stream);
static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg, static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg,
const usize_t ln); const usize_t ln);
static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp); static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp);
static int xd3_srcwin_move_point (xd3_stream *stream, static int xd3_srcwin_move_point (xd3_stream *stream,
usize_t *next_move_point); usize_t *next_move_point);
static int xd3_emit_run (xd3_stream *stream, usize_t pos, static int xd3_emit_run (xd3_stream *stream, usize_t pos,
usize_t size, uint8_t *run_c); usize_t size, uint8_t *run_c);
static usize_t xd3_checksum_hash (const xd3_hash_cfg *cfg,
const usize_t cksum);
static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low); static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low);
static void xd3_scksum_insert (xd3_stream *stream, static void xd3_scksum_insert (xd3_stream *stream,
usize_t inx, usize_t inx,
usize_t scksum, usize_t scksum,
usize_t pos); usize_t pos);
#if XD3_DEBUG #if XD3_DEBUG
static void xd3_verify_run_state (xd3_stream *stream, static void xd3_verify_run_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
usize_t x_run_l, usize_t x_run_l,
uint8_t *x_run_c); uint8_t *x_run_c);
static void xd3_verify_large_state (xd3_stream *stream, static void xd3_verify_large_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
uint32_t x_cksum); usize_t x_cksum);
static void xd3_verify_small_state (xd3_stream *stream, static void xd3_verify_small_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
uint32_t x_cksum); uint32_t x_cksum);
#endif /* XD3_DEBUG */ #endif /* XD3_DEBUG */
#endif /* XD3_ENCODER */ #endif /* XD3_ENCODER */
static int xd3_decode_allocate (xd3_stream *stream, usize_t size, static int xd3_decode_allocate (xd3_stream *stream, usize_t size,
uint8_t **copied1, usize_t *alloc1); uint8_t **copied1, usize_t *alloc1);
static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size); static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size);
static void xd3_free (xd3_stream *stream, void *ptr); static void xd3_free (xd3_stream *stream, void *ptr);
static int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp,
const uint8_t *max, uint32_t *valp);
#if REGRESSION_TEST
static int xd3_selftest (void);
#endif
/***********************************************************************/
const char* xd3_strerror (int ret) const char* xd3_strerror (int ret)
{ {
switch (ret) switch (ret)
{ {
case XD3_INPUT: return "XD3_INPUT"; case XD3_INPUT: return "XD3_INPUT";
case XD3_OUTPUT: return "XD3_OUTPUT"; case XD3_OUTPUT: return "XD3_OUTPUT";
case XD3_GETSRCBLK: return "XD3_GETSRCBLK"; case XD3_GETSRCBLK: return "XD3_GETSRCBLK";
case XD3_GOTHEADER: return "XD3_GOTHEADER"; case XD3_GOTHEADER: return "XD3_GOTHEADER";
case XD3_WINSTART: return "XD3_WINSTART"; case XD3_WINSTART: return "XD3_WINSTART";
case XD3_WINFINISH: return "XD3_WINFINISH"; case XD3_WINFINISH: return "XD3_WINFINISH";
skipping to change at line 571 skipping to change at line 549
} }
/***********************************************************************/ /***********************************************************************/
#define xd3_sec_data(s) ((s)->sec_stream_d) #define xd3_sec_data(s) ((s)->sec_stream_d)
#define xd3_sec_inst(s) ((s)->sec_stream_i) #define xd3_sec_inst(s) ((s)->sec_stream_i)
#define xd3_sec_addr(s) ((s)->sec_stream_a) #define xd3_sec_addr(s) ((s)->sec_stream_a)
struct _xd3_sec_type struct _xd3_sec_type
{ {
int id; uint8_t id;
const char *name; const char *name;
xd3_secondary_flags flags; xd3_secondary_flags flags;
/* xd3_sec_stream is opaque to the generic code */ /* xd3_sec_stream is opaque to the generic code */
xd3_sec_stream* (*alloc) (xd3_stream *stream); xd3_sec_stream* (*alloc) (xd3_stream *stream);
void (*destroy) (xd3_stream *stream, void (*destroy) (xd3_stream *stream,
xd3_sec_stream *sec); xd3_sec_stream *sec);
int (*init) (xd3_stream *stream, int (*init) (xd3_stream *stream,
xd3_sec_stream *sec_stream, xd3_sec_stream *sec_stream,
int is_encode); int is_encode);
skipping to change at line 603 skipping to change at line 581
xd3_sec_cfg *cfg); xd3_sec_cfg *cfg);
#endif #endif
}; };
#define BIT_STATE_ENCODE_INIT { 0, 1 } #define BIT_STATE_ENCODE_INIT { 0, 1 }
#define BIT_STATE_DECODE_INIT { 0, 0x100 } #define BIT_STATE_DECODE_INIT { 0, 0x100 }
typedef struct _bit_state bit_state; typedef struct _bit_state bit_state;
struct _bit_state struct _bit_state
{ {
usize_t cur_byte; uint8_t cur_byte;
usize_t cur_mask; usize_t cur_mask;
}; };
#if SECONDARY_ANY == 0 #if SECONDARY_ANY == 0
#define IF_SEC(x) #define IF_SEC(x)
#define IF_NSEC(x) x #define IF_NSEC(x) x
#else /* yuck */ #else /* yuck */
#define IF_SEC(x) x #define IF_SEC(x) x
#define IF_NSEC(x) #define IF_NSEC(x)
static int static int
skipping to change at line 748 skipping to change at line 726
#include "xdelta3-main.h" #include "xdelta3-main.h"
#endif #endif
#if REGRESSION_TEST #if REGRESSION_TEST
#include "xdelta3-test.h" #include "xdelta3-test.h"
#endif #endif
#endif /* __XDELTA3_C_HEADER_PASS__ */ #endif /* __XDELTA3_C_HEADER_PASS__ */
#ifdef __XDELTA3_C_INLINE_PASS__ #ifdef __XDELTA3_C_INLINE_PASS__
const uint16_t __single_hash[256] =
{
/* Random numbers generated using SLIB's pseudo-random number generator.
* This hashes the input alphabet. */
0xbcd1, 0xbb65, 0x42c2, 0xdffe, 0x9666, 0x431b, 0x8504, 0xeb46,
0x6379, 0xd460, 0xcf14, 0x53cf, 0xdb51, 0xdb08, 0x12c8, 0xf602,
0xe766, 0x2394, 0x250d, 0xdcbb, 0xa678, 0x02af, 0xa5c6, 0x7ea6,
0xb645, 0xcb4d, 0xc44b, 0xe5dc, 0x9fe6, 0x5b5c, 0x35f5, 0x701a,
0x220f, 0x6c38, 0x1a56, 0x4ca3, 0xffc6, 0xb152, 0x8d61, 0x7a58,
0x9025, 0x8b3d, 0xbf0f, 0x95a3, 0xe5f4, 0xc127, 0x3bed, 0x320b,
0xb7f3, 0x6054, 0x333c, 0xd383, 0x8154, 0x5242, 0x4e0d, 0x0a94,
0x7028, 0x8689, 0x3a22, 0x0980, 0x1847, 0xb0f1, 0x9b5c, 0x4176,
0xb858, 0xd542, 0x1f6c, 0x2497, 0x6a5a, 0x9fa9, 0x8c5a, 0x7743,
0xa8a9, 0x9a02, 0x4918, 0x438c, 0xc388, 0x9e2b, 0x4cad, 0x01b6,
0xab19, 0xf777, 0x365f, 0x1eb2, 0x091e, 0x7bf8, 0x7a8e, 0x5227,
0xeab1, 0x2074, 0x4523, 0xe781, 0x01a3, 0x163d, 0x3b2e, 0x287d,
0x5e7f, 0xa063, 0xb134, 0x8fae, 0x5e8e, 0xb7b7, 0x4548, 0x1f5a,
0xfa56, 0x7a24, 0x900f, 0x42dc, 0xcc69, 0x02a0, 0x0b22, 0xdb31,
0x71fe, 0x0c7d, 0x1732, 0x1159, 0xcb09, 0xe1d2, 0x1351, 0x52e9,
0xf536, 0x5a4f, 0xc316, 0x6bf9, 0x8994, 0xb774, 0x5f3e, 0xf6d6,
0x3a61, 0xf82c, 0xcc22, 0x9d06, 0x299c, 0x09e5, 0x1eec, 0x514f,
0x8d53, 0xa650, 0x5c6e, 0xc577, 0x7958, 0x71ac, 0x8916, 0x9b4f,
0x2c09, 0x5211, 0xf6d8, 0xcaaa, 0xf7ef, 0x287f, 0x7a94, 0xab49,
0xfa2c, 0x7222, 0xe457, 0xd71a, 0x00c3, 0x1a76, 0xe98c, 0xc037,
0x8208, 0x5c2d, 0xdfda, 0xe5f5, 0x0b45, 0x15ce, 0x8a7e, 0xfcad,
0xaa2d, 0x4b5c, 0xd42e, 0xb251, 0x907e, 0x9a47, 0xc9a6, 0xd93f,
0x085e, 0x35ce, 0xa153, 0x7e7b, 0x9f0b, 0x25aa, 0x5d9f, 0xc04d,
0x8a0e, 0x2875, 0x4a1c, 0x295f, 0x1393, 0xf760, 0x9178, 0x0f5b,
0xfa7d, 0x83b4, 0x2082, 0x721d, 0x6462, 0x0368, 0x67e2, 0x8624,
0x194d, 0x22f6, 0x78fb, 0x6791, 0xb238, 0xb332, 0x7276, 0xf272,
0x47ec, 0x4504, 0xa961, 0x9fc8, 0x3fdc, 0xb413, 0x007a, 0x0806,
0x7458, 0x95c6, 0xccaa, 0x18d6, 0xe2ae, 0x1b06, 0xf3f6, 0x5050,
0xc8e8, 0xf4ac, 0xc04c, 0xf41c, 0x992f, 0xae44, 0x5f1b, 0x1113,
0x1738, 0xd9a8, 0x19ea, 0x2d33, 0x9698, 0x2fe9, 0x323f, 0xcde2,
0x6d71, 0xe37d, 0xb697, 0x2c4f, 0x4373, 0x9102, 0x075d, 0x8e25,
0x1672, 0xec28, 0x6acb, 0x86cc, 0x186e, 0x9414, 0xd674, 0xd1a5
};
/**************************************************************** /****************************************************************
Instruction tables Instruction tables
*****************************************************************/ *****************************************************************/
/* The following code implements a parametrized description of the /* The following code implements a parametrized description of the
* code table given above for a few reasons. It is not necessary for * code table given above for a few reasons. It is not necessary for
* implementing the standard, to support compression with variable * implementing the standard, to support compression with variable
* tables, so an implementation is only required to know the default * tables, so an implementation is only required to know the default
* code table to begin decompression. (If the encoder uses an * code table to begin decompression. (If the encoder uses an
* alternate table, the table is included in compressed form inside * alternate table, the table is included in compressed form inside
skipping to change at line 842 skipping to change at line 782
uint8_t offset; uint8_t offset;
uint8_t mult; uint8_t mult;
}; };
/* This contains a complete description of a code table. */ /* This contains a complete description of a code table. */
struct _xd3_code_table_desc struct _xd3_code_table_desc
{ {
/* Assumes a single RUN instruction */ /* Assumes a single RUN instruction */
/* Assumes that MIN_MATCH is 4 */ /* Assumes that MIN_MATCH is 4 */
uint8_t add_sizes; /* Number of immediate-size single adds (default uint8_t add_sizes; /* Number of immediate-size single
17) */ adds (default 17) */
uint8_t near_modes; /* Number of near copy modes (default 4) */ uint8_t near_modes; /* Number of near copy modes (default 4) */
uint8_t same_modes; /* Number of same copy modes (default 3) */ uint8_t same_modes; /* Number of same copy modes (default 3) */
uint8_t cpy_sizes; /* Number of immediate-size single copies (defau uint8_t cpy_sizes; /* Number of immediate-size single
lt 15) */ copies (default 15) */
uint8_t addcopy_add_max; /* Maximum add size for an add-copy double instr uint8_t addcopy_add_max; /* Maximum add size for an add-copy
uction, double instruction, all modes
all modes (default 4) */ (default 4) */
uint8_t addcopy_near_cpy_max; /* Maximum cpy size for an add-copy double instr uint8_t addcopy_near_cpy_max; /* Maximum cpy size for an add-copy
uction, double instruction, up through
up through VCD_NEAR modes (default 6) */ VCD_NEAR modes (default 6) */
uint8_t addcopy_same_cpy_max; /* Maximum cpy size for an add-copy double instr uint8_t addcopy_same_cpy_max; /* Maximum cpy size for an add-copy
uction, double instruction, VCD_SAME modes
VCD_SAME modes (default 4) */ (default 4) */
uint8_t copyadd_add_max; /* Maximum add size for a copy-add double instru uint8_t copyadd_add_max; /* Maximum add size for a copy-add
ction, double instruction, all modes
all modes (default 1) */ (default 1) */
uint8_t copyadd_near_cpy_max; /* Maximum cpy size for a copy-add double instru uint8_t copyadd_near_cpy_max; /* Maximum cpy size for a copy-add
ction, double instruction, up through
up through VCD_NEAR modes (default 4) */ VCD_NEAR modes (default 4) */
uint8_t copyadd_same_cpy_max; /* Maximum cpy size for a copy-add double instru uint8_t copyadd_same_cpy_max; /* Maximum cpy size for a copy-add
ction, double instruction, VCD_SAME modes
VCD_SAME modes (default 4) */ (default 4) */
xd3_code_table_sizes addcopy_max_sizes[MAX_MODES]; xd3_code_table_sizes addcopy_max_sizes[MAX_MODES];
xd3_code_table_sizes copyadd_max_sizes[MAX_MODES]; xd3_code_table_sizes copyadd_max_sizes[MAX_MODES];
}; };
/* The rfc3284 code table is represented: */ /* The rfc3284 code table is represented: */
static const xd3_code_table_desc __rfc3284_code_table_desc = { static const xd3_code_table_desc __rfc3284_code_table_desc = {
17, /* add sizes */ 17, /* add sizes */
4, /* near modes */ 4, /* near modes */
3, /* same modes */ 3, /* same modes */
skipping to change at line 881 skipping to change at line 829
4, /* add-copy max add */ 4, /* add-copy max add */
6, /* add-copy max cpy, near */ 6, /* add-copy max cpy, near */
4, /* add-copy max cpy, same */ 4, /* add-copy max cpy, same */
1, /* copy-add max add */ 1, /* copy-add max add */
4, /* copy-add max cpy, near */ 4, /* copy-add max cpy, near */
4, /* copy-add max cpy, same */ 4, /* copy-add max cpy, same */
/* addcopy */ /* addcopy */
{ {6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{4,235,1},{4,239 { {6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},
,1},{4,243,1} }, {4,235,1},{4,239,1},{4,243,1} },
/* copyadd */ /* copyadd */
{ {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},{4,253,1},{4,254 { {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},
,1},{4,255,1} }, {4,253,1},{4,254,1},{4,255,1} },
}; };
/* Computes code table entries of TBL using the specified description. */ /* Computes code table entries of TBL using the specified description. */
static void static void
xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl) xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl)
{ {
usize_t size1, size2, mode; uint8_t size1, size2;
usize_t cpy_modes = 2 + desc->near_modes + desc->same_modes; uint8_t mode;
usize_t cpy_modes = 2U + desc->near_modes + desc->same_modes;
xd3_dinst *d = tbl; xd3_dinst *d = tbl;
(d++)->type1 = XD3_RUN; (d++)->type1 = XD3_RUN;
(d++)->type1 = XD3_ADD; (d++)->type1 = XD3_ADD;
for (size1 = 1; size1 <= desc->add_sizes; size1 += 1, d += 1) for (size1 = 1; size1 <= desc->add_sizes; size1 += 1, d += 1)
{ {
d->type1 = XD3_ADD; d->type1 = XD3_ADD;
d->size1 = size1; d->size1 = size1;
} }
for (mode = 0; mode < cpy_modes; mode += 1) for (mode = 0; mode < cpy_modes; mode += 1)
{ {
(d++)->type1 = XD3_CPY + mode; (d++)->type1 = XD3_CPY + mode;
for (size1 = MIN_MATCH; size1 < MIN_MATCH + desc->cpy_sizes; size1 += 1, d for (size1 = MIN_MATCH; size1 < MIN_MATCH + desc->cpy_sizes;
+= 1) size1 += 1, d += 1)
{ {
d->type1 = XD3_CPY + mode; d->type1 = XD3_CPY + mode;
d->size1 = size1; d->size1 = size1;
} }
} }
for (mode = 0; mode < cpy_modes; mode += 1) for (mode = 0; mode < cpy_modes; mode += 1)
{ {
for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1) for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1)
{ {
skipping to change at line 999 skipping to change at line 951
(prev->type >= XD3_CPY) ) (prev->type >= XD3_CPY) )
{ {
prev->code2 = 247 + (prev->type - XD3_CPY); prev->code2 = 247 + (prev->type - XD3_CPY);
} }
} }
break; break;
default: default:
{ {
int mode = inst->type - XD3_CPY; uint8_t mode = inst->type - XD3_CPY;
XD3_ASSERT (inst->type >= XD3_CPY && inst->type < 12); XD3_ASSERT (inst->type >= XD3_CPY && inst->type < 12);
inst->code1 = 19 + 16 * mode; inst->code1 = 19 + 16 * mode;
if (inst->size <= 18 && inst->size >= 4) if (inst->size <= 18 && inst->size >= 4)
{ {
inst->code1 += inst->size - 3; inst->code1 += inst->size - 3;
if ( (prev != NULL) && if ( (prev != NULL) &&
(prev->type == XD3_ADD) && (prev->type == XD3_ADD) &&
(prev->size <= 4) ) (prev->size <= 4) )
{ {
if ( (inst->size <= 6) && if ( (inst->size <= 6) &&
(mode <= 5) ) (mode <= 5) )
{ {
prev->code2 = 163 + (mode * 12) + (3 * (prev->size - 1)) + (i prev->code2 = (uint8_t)(163 + (mode * 12) +
nst->size - 4); (3 * (prev->size - 1)) +
(inst->size - 4));
XD3_ASSERT (prev->code2 <= 234); XD3_ASSERT (prev->code2 <= 234);
} }
else if ( (inst->size == 4) && else if ( (inst->size == 4) &&
(mode >= 6) ) (mode >= 6) )
{ {
prev->code2 = 235 + ((mode - 6) * 4) + (prev->size - 1); prev->code2 = 235 + ((mode - 6) * 4) + (prev->size - 1);
XD3_ASSERT (prev->code2 <= 246); XD3_ASSERT (prev->code2 <= 246);
} }
} }
skipping to change at line 1078 skipping to change at line 1031
{ {
if (x == value) if (x == value)
{ {
return 0; return 0;
} }
} }
return XD3_INTERNAL; return XD3_INTERNAL;
} }
size_t usize_t
xd3_pow2_roundup (size_t x) xd3_pow2_roundup (usize_t x)
{ {
size_t i = 1; usize_t i = 1;
while (x > i) { while (x > i) {
i <<= 1U; i <<= 1U;
} }
return i; return i;
} }
static xoff_t static xoff_t
xd3_xoff_roundup (xoff_t x) xd3_xoff_roundup (xoff_t x)
{ {
xoff_t i = 1; xoff_t i = 1;
skipping to change at line 1123 skipping to change at line 1076
} }
return sz + (blksz - mod); return sz + (blksz - mod);
} }
/*********************************************************************** /***********************************************************************
Adler32 stream function: code copied from Zlib, defined in RFC1950 Adler32 stream function: code copied from Zlib, defined in RFC1950
***********************************************************************/ ***********************************************************************/
#define A32_BASE 65521L /* Largest prime smaller than 2^16 */ #define A32_BASE 65521L /* Largest prime smaller than 2^16 */
#define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(B #define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2
ASE-1) <= 2^32-1 */ + (n+1)(BASE-1) <= 2^32-1 */
#define A32_DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define A32_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define A32_DO2(buf,i) A32_DO1(buf,i); A32_DO1(buf,i+1); #define A32_DO2(buf,i) A32_DO1(buf,i); A32_DO1(buf,i+1);
#define A32_DO4(buf,i) A32_DO2(buf,i); A32_DO2(buf,i+2); #define A32_DO4(buf,i) A32_DO2(buf,i); A32_DO2(buf,i+2);
#define A32_DO8(buf,i) A32_DO4(buf,i); A32_DO4(buf,i+4); #define A32_DO8(buf,i) A32_DO4(buf,i); A32_DO4(buf,i+4);
#define A32_DO16(buf) A32_DO8(buf,0); A32_DO8(buf,8); #define A32_DO16(buf) A32_DO8(buf,0); A32_DO8(buf,8);
static unsigned long adler32 (unsigned long adler, const uint8_t *buf, static uint32_t adler32 (uint32_t adler, const uint8_t *buf, usize_t len)
usize_t len)
{ {
unsigned long s1 = adler & 0xffff; uint32_t s1 = adler & 0xffffU;
unsigned long s2 = (adler >> 16) & 0xffff; uint32_t s2 = (adler >> 16) & 0xffffU;
int k; int k;
while (len > 0) while (len > 0)
{ {
k = (len < A32_NMAX) ? len : A32_NMAX; k = (len < A32_NMAX) ? len : A32_NMAX;
len -= k; len -= k;
while (k >= 16) while (k >= 16)
{ {
A32_DO16(buf); A32_DO16(buf);
skipping to change at line 1330 skipping to change at line 1283
#if XD3_ENCODER #if XD3_ENCODER
/* OPT: this gets called a lot, can it be optimized? */ /* OPT: this gets called a lot, can it be optimized? */
static int static int
xd3_encode_address (xd3_stream *stream, xd3_encode_address (xd3_stream *stream,
usize_t addr, usize_t addr,
usize_t here, usize_t here,
uint8_t* mode) uint8_t* mode)
{ {
usize_t d, bestd; usize_t d, bestd;
usize_t i, bestm, ret; usize_t i, bestm;
int ret;
xd3_addr_cache* acache = & stream->acache; xd3_addr_cache* acache = & stream->acache;
#define SMALLEST_INT(x) do { if (((x) & ~127U) == 0) { goto good; } } while (0) #define SMALLEST_INT(x) do { if (((x) & ~127U) == 0) { goto good; } } while (0)
/* Attempt to find the address mode that yields the smallest integer value /* Attempt to find the address mode that yields the smallest integer value
* for "d", the encoded address value, thereby minimizing the encoded size * for "d", the encoded address value, thereby minimizing the encoded size
* of the address. */ * of the address. */
bestd = addr; bestd = addr;
bestm = VCD_SELF; bestm = VCD_SELF;
skipping to change at line 1404 skipping to change at line 1358
(*mode) += bestm; (*mode) += bestm;
return 0; return 0;
} }
#endif #endif
static int static int
xd3_decode_address (xd3_stream *stream, usize_t here, xd3_decode_address (xd3_stream *stream, usize_t here,
usize_t mode, const uint8_t **inpp, usize_t mode, const uint8_t **inpp,
const uint8_t *max, uint32_t *valp) const uint8_t *max, usize_t *valp)
{ {
int ret; int ret;
usize_t same_start = 2 + stream->acache.s_near; usize_t same_start = 2 + stream->acache.s_near;
if (mode < same_start) if (mode < same_start)
{ {
if ((ret = xd3_read_size (stream, inpp, max, valp))) { return ret; } if ((ret = xd3_read_size (stream, inpp, max, valp))) { return ret; }
switch (mode) switch (mode)
{ {
skipping to change at line 1471 skipping to change at line 1425
static void* static void*
xd3_alloc (xd3_stream *stream, xd3_alloc (xd3_stream *stream,
usize_t elts, usize_t elts,
usize_t size) usize_t size)
{ {
void *a = stream->alloc (stream->opaque, elts, size); void *a = stream->alloc (stream->opaque, elts, size);
if (a != NULL) if (a != NULL)
{ {
IF_DEBUG (stream->alloc_cnt += 1); IF_DEBUG (stream->alloc_cnt += 1);
IF_DEBUG2 (DP(RINT "[stream %p malloc] size %u ptr %p\n", IF_DEBUG2 (DP(RINT "[stream %p malloc] size %"W"u ptr %p\n",
stream, elts * size, a)); (void*)stream, elts * size, a));
} }
else else
{ {
stream->msg = "out of memory"; stream->msg = "out of memory";
} }
return a; return a;
} }
static void static void
xd3_free (xd3_stream *stream, xd3_free (xd3_stream *stream,
void *ptr) void *ptr)
{ {
if (ptr != NULL) if (ptr != NULL)
{ {
IF_DEBUG (stream->free_cnt += 1); IF_DEBUG (stream->free_cnt += 1);
XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt);
IF_DEBUG2 (DP(RINT "[stream %p free] %p\n", IF_DEBUG2 (DP(RINT "[stream %p free] %p\n",
stream, ptr)); (void*)stream, ptr));
stream->free (stream->opaque, ptr); stream->free (stream->opaque, ptr);
} }
} }
#if XD3_ENCODER #if XD3_ENCODER
static void* static void*
xd3_alloc0 (xd3_stream *stream, xd3_alloc0 (xd3_stream *stream,
usize_t elts, usize_t elts,
usize_t size) usize_t size)
{ {
skipping to change at line 1621 skipping to change at line 1575
xd3_iopt_buflist *blist = stream->iopt_alloc; xd3_iopt_buflist *blist = stream->iopt_alloc;
while (blist != NULL) while (blist != NULL)
{ {
xd3_iopt_buflist *tmp = blist; xd3_iopt_buflist *tmp = blist;
blist = blist->next; blist = blist->next;
xd3_free (stream, tmp->buffer); xd3_free (stream, tmp->buffer);
xd3_free (stream, tmp); xd3_free (stream, tmp);
} }
#if XD3_ENCODER
xd3_free (stream, stream->large_table); xd3_free (stream, stream->large_table);
xd3_free (stream, stream->small_table); xd3_free (stream, stream->small_table);
xd3_free (stream, stream->large_hash.powers);
xd3_free (stream, stream->small_hash.powers);
xd3_free (stream, stream->small_prev); xd3_free (stream, stream->small_prev);
#if XD3_ENCODER
{ {
int i; int i;
for (i = 0; i < ENC_SECTS; i += 1) for (i = 0; i < ENC_SECTS; i += 1)
{ {
xd3_free_output (stream, stream->enc_heads[i]); xd3_free_output (stream, stream->enc_heads[i]);
} }
xd3_free_output (stream, stream->enc_free); xd3_free_output (stream, stream->enc_free);
} }
#endif #endif
skipping to change at line 1934 skipping to change at line 1890
ret = stream->getblk (stream, source, blkno); ret = stream->getblk (stream, source, blkno);
if (ret != 0) if (ret != 0)
{ {
IF_DEBUG2 (DP(RINT "[getblk] app error blkno %"Q"u: %s\n", IF_DEBUG2 (DP(RINT "[getblk] app error blkno %"Q"u: %s\n",
blkno, xd3_strerror (ret))); blkno, xd3_strerror (ret)));
return ret; return ret;
} }
IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk " IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk "
"%u blksize %u max_blkno %"Q"u\n", blkno, source->onblk, "%"W"u blksize %"W"u max_blkno %"Q"u\n", blkno, source->onblk ,
source->blksize, source->max_blkno)); source->blksize, source->max_blkno));
} }
if (blkno > source->max_blkno) if (blkno > source->max_blkno)
{ {
source->max_blkno = blkno; source->max_blkno = blkno;
if (source->onblk == source->blksize) if (source->onblk == source->blksize)
{ {
IF_DEBUG1 (DP(RINT "[getblk] full source blkno %"Q"u: " IF_DEBUG1 (DP(RINT "[getblk] full source blkno %"Q"u: "
"source length unknown %"Q"u\n", "source length unknown %"Q"u\n",
blkno, blkno,
xd3_source_eof (source))); xd3_source_eof (source)));
} }
else if (!source->eof_known) else if (!source->eof_known)
{ {
IF_DEBUG1 (DP(RINT "[getblk] eof block has %d bytes; " IF_DEBUG1 (DP(RINT "[getblk] eof block has %"W"u bytes; "
"source length known %"Q"u\n", "source length known %"Q"u\n",
xd3_bytes_on_srcblk (source, blkno), xd3_bytes_on_srcblk (source, blkno),
xd3_source_eof (source))); xd3_source_eof (source)));
source->eof_known = 1; source->eof_known = 1;
} }
} }
XD3_ASSERT (source->curblk != NULL); XD3_ASSERT (source->curblk != NULL);
if (blkno == source->max_blkno) if (blkno == source->max_blkno)
skipping to change at line 1990 skipping to change at line 1946
stream->src = src; stream->src = src;
src->srclen = 0; src->srclen = 0;
src->srcbase = 0; src->srcbase = 0;
/* Enforce power-of-two blocksize so that source-block number /* Enforce power-of-two blocksize so that source-block number
* calculations are cheap. */ * calculations are cheap. */
if (xd3_check_pow2 (src->blksize, &shiftby) != 0) if (xd3_check_pow2 (src->blksize, &shiftby) != 0)
{ {
src->blksize = xd3_pow2_roundup(src->blksize); src->blksize = xd3_pow2_roundup(src->blksize);
xd3_check_pow2 (src->blksize, &shiftby); xd3_check_pow2 (src->blksize, &shiftby);
IF_DEBUG1 (DP(RINT "raising src_blksz to %u\n", src->blksize)); IF_DEBUG1 (DP(RINT "raising src_blksz to %"W"u\n", src->blksize));
} }
src->shiftby = shiftby; src->shiftby = shiftby;
src->maskby = (1 << shiftby) - 1; src->maskby = (1ULL << shiftby) - 1ULL;
if (xd3_check_pow2 (src->max_winsize, NULL) != 0) if (xd3_check_pow2 (src->max_winsize, NULL) != 0)
{ {
src->max_winsize = xd3_xoff_roundup(src->max_winsize); src->max_winsize = xd3_xoff_roundup(src->max_winsize);
IF_DEBUG1 (DP(RINT "raising src_maxsize to %u\n", src->blksize)); IF_DEBUG1 (DP(RINT "raising src_maxsize to %"W"u\n", src->blksize));
} }
src->max_winsize = xd3_max (src->max_winsize, XD3_ALLOCSIZE); src->max_winsize = xd3_max (src->max_winsize, XD3_ALLOCSIZE);
return 0; return 0;
} }
int int
xd3_set_source_and_size (xd3_stream *stream, xd3_set_source_and_size (xd3_stream *stream,
xd3_source *user_source, xd3_source *user_source,
xoff_t source_size) { xoff_t source_size) {
int ret = xd3_set_source (stream, user_source); int ret = xd3_set_source (stream, user_source);
if (ret == 0) if (ret == 0)
{ {
stream->src->eof_known = 1; stream->src->eof_known = 1;
IF_DEBUG2 (DP(RINT "[set source] size known %"Q"u\n",
source_size));
xd3_blksize_div(source_size, xd3_blksize_div(source_size,
stream->src, stream->src,
&stream->src->max_blkno, &stream->src->max_blkno,
&stream->src->onlastblk); &stream->src->onlastblk);
IF_DEBUG1 (DP(RINT "[set source] size known %"Q"u max_blkno %"Q"u\n", IF_DEBUG1 (DP(RINT "[set source] size known %"Q"u max_blkno %"Q"u\n",
source_size, stream->src->max_blkno)); source_size, stream->src->max_blkno));
} }
return ret; return ret;
} }
skipping to change at line 2193 skipping to change at line 2150
(stream->srcwin_cksum_pos < (stream->srcwin_cksum_pos <
xd3_source_eof (stream->src))); xd3_source_eof (stream->src)));
} }
/* xtra field indicates the copy is from the source */ /* xtra field indicates the copy is from the source */
if (inst->xtra) if (inst->xtra)
{ {
XD3_ASSERT (inst->addr >= src->srcbase); XD3_ASSERT (inst->addr >= src->srcbase);
XD3_ASSERT (inst->addr + inst->size <= XD3_ASSERT (inst->addr + inst->size <=
src->srcbase + src->srclen); src->srcbase + src->srclen);
addr = (usize_t)(inst->addr - src->srcbase); addr = inst->addr - src->srcbase;
stream->n_scpy += 1; stream->n_scpy += 1;
stream->l_scpy += (xoff_t) inst->size; stream->l_scpy += inst->size;
} }
else else
{ {
/* with source window: target copy address is offset /* with source window: target copy address is offset
* by taroff. */ * by taroff. */
addr = stream->taroff + (usize_t) inst->addr; addr = stream->taroff + inst->addr;
stream->n_tcpy += 1; stream->n_tcpy += 1;
stream->l_tcpy += (xoff_t) inst->size; stream->l_tcpy += inst->size;
} }
} }
else else
{ {
addr = (usize_t) inst->addr; addr = inst->addr;
stream->n_tcpy += 1; stream->n_tcpy += 1;
stream->l_tcpy += inst->size; stream->l_tcpy += inst->size;
} }
/* Note: used to assert inst->size >= MIN_MATCH, but not true /* Note: used to assert inst->size >= MIN_MATCH, but not true
* for merge operations & identical match heuristics. */ * for merge operations & identical match heuristics. */
/* the "here" position is always offset by taroff */ /* the "here" position is always offset by taroff */
if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff,
& inst->type))) & inst->type)))
{ {
return ret; return ret;
} }
IF_DEBUG2 ({ IF_DEBUG2 ({
static int cnt; static int cnt;
DP(RINT "[iopt copy:%d] pos %"Q"u-%"Q"u addr %"Q"u-%"Q"u size %u\n", DP(RINT "[iopt copy:%d] pos %"Q"u-%"Q"u addr %"Q"u-%"Q"u size %"W"u\n",
cnt++, cnt++,
stream->total_in + inst->pos, stream->total_in + inst->pos,
stream->total_in + inst->pos + inst->size, stream->total_in + inst->pos + inst->size,
inst->addr, inst->addr + inst->size, inst->size); inst->addr, inst->addr + inst->size, inst->size);
}); });
break; break;
} }
case XD3_RUN: case XD3_RUN:
{ {
if ((ret = xd3_emit_byte (stream, & DATA_TAIL (stream), inst->xtra))) { r eturn ret; } if ((ret = xd3_emit_byte (stream, & DATA_TAIL (stream), inst->xtra))) { r eturn ret; }
stream->n_run += 1; stream->n_run += 1;
stream->l_run += inst->size; stream->l_run += inst->size;
IF_DEBUG2 ({ IF_DEBUG2 ({
static int cnt; static int cnt;
DP(RINT "[iopt run:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); DP(RINT "[iopt run:%d] pos %"Q"u size %"W"u\n", cnt++, stream->total_in + inst->pos, inst->size);
}); });
break; break;
} }
case XD3_ADD: case XD3_ADD:
{ {
if ((ret = xd3_emit_bytes (stream, & DATA_TAIL (stream), if ((ret = xd3_emit_bytes (stream, & DATA_TAIL (stream),
stream->next_in + inst->pos, inst->size))) { r eturn ret; } stream->next_in + inst->pos, inst->size))) { r eturn ret; }
stream->n_add += 1; stream->n_add += 1;
stream->l_add += inst->size; stream->l_add += inst->size;
IF_DEBUG2 ({ IF_DEBUG2 ({
static int cnt; static int cnt;
DP(RINT "[iopt add:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); DP(RINT "[iopt add:%d] pos %"Q"u size %"W"u\n", cnt++, stream->total_in + inst->pos, inst->size);
}); });
break; break;
} }
} }
/* This is the only place stream->unencoded_offset is incremented. */ /* This is the only place stream->unencoded_offset is incremented. */
XD3_ASSERT (stream->unencoded_offset == inst->pos); XD3_ASSERT (stream->unencoded_offset == inst->pos);
stream->unencoded_offset += inst->size; stream->unencoded_offset += inst->size;
inst->code2 = 0; inst->code2 = 0;
XD3_CHOOSE_INSTRUCTION (stream, stream->iout, inst); XD3_CHOOSE_INSTRUCTION (stream, stream->iout, inst);
if (stream->iout != NULL) if (stream->iout != NULL)
{ {
if (stream->iout->code2 != 0) if (stream->iout->code2 != 0)
{ {
if ((ret = xd3_emit_double (stream, stream->iout, inst, stream->iout->c if ((ret = xd3_emit_double (stream, stream->iout, inst,
ode2))) { return ret; } stream->iout->code2))) { return ret; }
xd3_iopt_free_nonadd (stream, stream->iout); xd3_iopt_free_nonadd (stream, stream->iout);
xd3_iopt_free_nonadd (stream, inst); xd3_iopt_free_nonadd (stream, inst);
stream->iout = NULL; stream->iout = NULL;
return 0; return 0;
} }
else else
{ {
if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1)) ) { return ret; } if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1)) ) { return ret; }
skipping to change at line 2631 skipping to change at line 2589
r = xd3_rlist_back (& stream->iopt_used); r = xd3_rlist_back (& stream->iopt_used);
return r->pos + r->size; return r->pos + r->size;
} }
/********************************************************* /*********************************************************
Emit routines Emit routines
***********************************************************/ ***********************************************************/
static int static int
xd3_emit_single (xd3_stream *stream, xd3_rinst *single, usize_t code) xd3_emit_single (xd3_stream *stream, xd3_rinst *single, uint8_t code)
{ {
int has_size = stream->code_table[code].size1 == 0; int has_size = stream->code_table[code].size1 == 0;
int ret; int ret;
IF_DEBUG2 (DP(RINT "[emit1] %u %s (%u) code %u\n", IF_DEBUG2 (DP(RINT "[emit1] %"W"u %s (%"W"u) code %u\n",
single->pos, single->pos,
xd3_rtype_to_string ((xd3_rtype) single->type, 0), xd3_rtype_to_string ((xd3_rtype) single->type, 0),
single->size, single->size,
code)); code));
if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code)))
{ {
return ret; return ret;
} }
if (has_size) if (has_size)
{ {
if ((ret = xd3_emit_size (stream, & INST_TAIL (stream), single->size))) if ((ret = xd3_emit_size (stream, & INST_TAIL (stream), single->size)))
{ {
return ret; return ret;
} }
} }
return 0; return 0;
} }
static int static int
xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_emit_double (xd3_stream *stream, xd3_rinst *first,
xd3_rinst *second, usize_t code) xd3_rinst *second, uint8_t code)
{ {
int ret; int ret;
/* All double instructions use fixed sizes, so all we need to do is /* All double instructions use fixed sizes, so all we need to do is
* output the instruction code, no sizes. */ * output the instruction code, no sizes. */
XD3_ASSERT (stream->code_table[code].size1 != 0 && XD3_ASSERT (stream->code_table[code].size1 != 0 &&
stream->code_table[code].size2 != 0); stream->code_table[code].size2 != 0);
if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code)))
{ {
return ret; return ret;
} }
IF_DEBUG2 (DP(RINT "[emit2]: %u %s (%u) %s (%u) code %u\n", IF_DEBUG2 (DP(RINT "[emit2]: %"W"u %s (%"W"u) %s (%"W"u) code %u\n",
first->pos, first->pos,
xd3_rtype_to_string ((xd3_rtype) first->type, 0), xd3_rtype_to_string ((xd3_rtype) first->type, 0),
first->size, first->size,
xd3_rtype_to_string ((xd3_rtype) second->type, 0), xd3_rtype_to_string ((xd3_rtype) second->type, 0),
second->size, second->size,
code)); code));
return 0; return 0;
} }
/* This enters a potential run instruction into the iopt buffer. The /* This enters a potential run instruction into the iopt buffer. The
* position argument is relative to the target window. */ * position argument is relative to the target window. */
static int static int
xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c) xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c)
{ {
xd3_rinst* ri; xd3_rinst* ri;
skipping to change at line 2730 skipping to change at line 2688
return 0; return 0;
} }
static int static int
xd3_emit_hdr (xd3_stream *stream) xd3_emit_hdr (xd3_stream *stream)
{ {
int ret; int ret;
int use_secondary = stream->sec_type != NULL; int use_secondary = stream->sec_type != NULL;
int use_adler32 = stream->flags & (XD3_ADLER32 | XD3_ADLER32_RECODE); int use_adler32 = stream->flags & (XD3_ADLER32 | XD3_ADLER32_RECODE);
int vcd_source = xd3_encoder_used_source (stream); int vcd_source = xd3_encoder_used_source (stream);
usize_t win_ind = 0; uint8_t win_ind = 0;
usize_t del_ind = 0; uint8_t del_ind = 0;
usize_t enc_len; usize_t enc_len;
usize_t tgt_len; usize_t tgt_len;
usize_t data_len; usize_t data_len;
usize_t inst_len; usize_t inst_len;
usize_t addr_len; usize_t addr_len;
if (stream->current_window == 0) if (stream->current_window == 0)
{ {
usize_t hdr_ind = 0; uint8_t hdr_ind = 0;
int use_appheader = stream->enc_appheader != NULL; int use_appheader = stream->enc_appheader != NULL;
if (use_secondary) { hdr_ind |= VCD_SECONDARY; } if (use_secondary) { hdr_ind |= VCD_SECONDARY; }
if (use_appheader) { hdr_ind |= VCD_APPHEADER; } if (use_appheader) { hdr_ind |= VCD_APPHEADER; }
if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
VCDIFF_MAGIC1)) != 0 || VCDIFF_MAGIC1)) != 0 ||
(ret = xd3_emit_byte (stream, & HDR_TAIL (stream), (ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
VCDIFF_MAGIC2)) != 0 || VCDIFF_MAGIC2)) != 0 ||
(ret = xd3_emit_byte (stream, & HDR_TAIL (stream), (ret = xd3_emit_byte (stream, & HDR_TAIL (stream),
skipping to change at line 2838 skipping to change at line 2796
stream->src->srclen)) || stream->src->srclen)) ||
(ret = xd3_emit_offset (stream, & HDR_TAIL (stream), (ret = xd3_emit_offset (stream, & HDR_TAIL (stream),
stream->src->srcbase))) { return ret; } stream->src->srcbase))) { return ret; }
} }
tgt_len = stream->avail_in; tgt_len = stream->avail_in;
data_len = xd3_sizeof_output (DATA_HEAD (stream)); data_len = xd3_sizeof_output (DATA_HEAD (stream));
inst_len = xd3_sizeof_output (INST_HEAD (stream)); inst_len = xd3_sizeof_output (INST_HEAD (stream));
addr_len = xd3_sizeof_output (ADDR_HEAD (stream)); addr_len = xd3_sizeof_output (ADDR_HEAD (stream));
/* The enc_len field is a redundency for future extensions.*/ /* The enc_len field is a redundency for future extensions. */
enc_len = (1 + (xd3_sizeof_size (tgt_len) + enc_len = (1 + (xd3_sizeof_size (tgt_len) +
xd3_sizeof_size (data_len) + xd3_sizeof_size (data_len) +
xd3_sizeof_size (inst_len) + xd3_sizeof_size (inst_len) +
xd3_sizeof_size (addr_len)) + xd3_sizeof_size (addr_len)) +
data_len + data_len +
inst_len + inst_len +
addr_len + addr_len +
(use_adler32 ? 4 : 0)); (use_adler32 ? 4 : 0));
if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), enc_len)) || if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), enc_len)) ||
skipping to change at line 2912 skipping to change at line 2870
} }
IF_DEBUG2 (DP(RINT "[leftover] flush?=%s\n", (stream->flags & XD3_FLUSH) ? "ye s" : "no")); IF_DEBUG2 (DP(RINT "[leftover] flush?=%s\n", (stream->flags & XD3_FLUSH) ? "ye s" : "no"));
/* Take leftover input first. */ /* Take leftover input first. */
if (stream->buf_leftover != NULL) if (stream->buf_leftover != NULL)
{ {
XD3_ASSERT (stream->buf_avail == 0); XD3_ASSERT (stream->buf_avail == 0);
XD3_ASSERT (stream->buf_leftavail < stream->winsize); XD3_ASSERT (stream->buf_leftavail < stream->winsize);
IF_DEBUG2 (DP(RINT "[leftover] previous %u avail %u\n", stream->buf_leftav IF_DEBUG2 (DP(RINT "[leftover] previous %"W"u avail %"W"u\n",
ail, stream->avail_in)); stream->buf_leftavail, stream->avail_in));
memcpy (stream->buf_in, stream->buf_leftover, stream->buf_leftavail); memcpy (stream->buf_in, stream->buf_leftover, stream->buf_leftavail);
stream->buf_leftover = NULL; stream->buf_leftover = NULL;
stream->buf_avail = stream->buf_leftavail; stream->buf_avail = stream->buf_leftavail;
} }
/* Copy into the buffer. */ /* Copy into the buffer. */
room = stream->winsize - stream->buf_avail; room = stream->winsize - stream->buf_avail;
take = xd3_min (room, stream->avail_in); take = xd3_min (room, stream->avail_in);
skipping to change at line 2937 skipping to change at line 2896
if (take < stream->avail_in) if (take < stream->avail_in)
{ {
/* Buffer is full */ /* Buffer is full */
stream->buf_leftover = stream->next_in + take; stream->buf_leftover = stream->next_in + take;
stream->buf_leftavail = stream->avail_in - take; stream->buf_leftavail = stream->avail_in - take;
} }
else if ((stream->buf_avail < stream->winsize) && !(stream->flags & XD3_FLUSH) ) else if ((stream->buf_avail < stream->winsize) && !(stream->flags & XD3_FLUSH) )
{ {
/* Buffer has space */ /* Buffer has space */
IF_DEBUG2 (DP(RINT "[leftover] emptied %u\n", take)); IF_DEBUG2 (DP(RINT "[leftover] emptied %"W"u\n", take));
return XD3_INPUT; return XD3_INPUT;
} }
/* Use the buffer: */ /* Use the buffer: */
IF_DEBUG2 (DP(RINT "[leftover] take %u remaining %u\n", take, stream->buf_left avail)); IF_DEBUG2 (DP(RINT "[leftover] take %"W"u remaining %"W"u\n", take, stream->bu f_leftavail));
stream->next_in = stream->buf_in; stream->next_in = stream->buf_in;
stream->avail_in = stream->buf_avail; stream->avail_in = stream->buf_avail;
stream->buf_avail = 0; stream->buf_avail = 0;
return 0; return 0;
} }
/* Allocates one block of xd3_rlist elements */ /* Allocates one block of xd3_rlist elements */
static int static int
xd3_alloc_iopt (xd3_stream *stream, usize_t elts) xd3_alloc_iopt (xd3_stream *stream, usize_t elts)
skipping to change at line 2979 skipping to change at line 2938
xd3_rlist_push_back (& stream->iopt_free, & last->buffer[i]); xd3_rlist_push_back (& stream->iopt_free, & last->buffer[i]);
} }
return 0; return 0;
} }
/* This function allocates all memory initially used by the encoder. */ /* This function allocates all memory initially used by the encoder. */
static int static int
xd3_encode_init (xd3_stream *stream, int full_init) xd3_encode_init (xd3_stream *stream, int full_init)
{ {
int ret;
int i; int i;
if (full_init) if (full_init)
{ {
int large_comp = (stream->src != NULL); int large_comp = (stream->src != NULL);
int small_comp = ! (stream->flags & XD3_NOCOMPRESS); int small_comp = ! (stream->flags & XD3_NOCOMPRESS);
/* Memory allocations for checksum tables are delayed until /* Memory allocations for checksum tables are delayed until
* xd3_string_match_init in the first call to string_match--that way * xd3_string_match_init in the first call to string_match--that way
* identical or short inputs require no table allocation. */ * identical or short inputs require no table allocation. */
if (large_comp) if (large_comp)
{ {
/* TODO Need to check for overflow here. */
usize_t hash_values = stream->src->max_winsize / usize_t hash_values = stream->src->max_winsize /
stream->smatcher.large_step; stream->smatcher.large_step;
xd3_size_hashtable (stream, if ((ret = xd3_size_hashtable (stream,
hash_values, hash_values,
& stream->large_hash); stream->smatcher.large_look,
& stream->large_hash)))
{
return ret;
}
} }
if (small_comp) if (small_comp)
{ {
/* TODO: This is under devel: used to have min (sprevsz) here, which so rt /* TODO: This is under devel: used to have min (sprevsz) here, which so rt
* of makes sense, but observed fast performance w/ larger tables, whic h * of makes sense, but observed fast performance w/ larger tables, whic h
* also sort of makes sense. @@@ */ * also sort of makes sense. @@@ */
usize_t hash_values = stream->winsize; usize_t hash_values = stream->winsize;
xd3_size_hashtable (stream, if ((ret = xd3_size_hashtable (stream,
hash_values, hash_values,
& stream->small_hash); stream->smatcher.small_look,
& stream->small_hash)))
{
return ret;
}
} }
} }
/* data buffers */ /* data buffers */
for (i = 0; i < ENC_SECTS; i += 1) for (i = 0; i < ENC_SECTS; i += 1)
{ {
if ((stream->enc_heads[i] = if ((stream->enc_heads[i] =
stream->enc_tails[i] = stream->enc_tails[i] =
xd3_alloc_output (stream, NULL)) == NULL) xd3_alloc_output (stream, NULL)) == NULL)
{ {
skipping to change at line 3157 skipping to change at line 3126
/* Initalize the address cache before each window. */ /* Initalize the address cache before each window. */
xd3_init_cache (& stream->acache); xd3_init_cache (& stream->acache);
stream->input_position = 0; stream->input_position = 0;
stream->min_match = MIN_MATCH; stream->min_match = MIN_MATCH;
stream->unencoded_offset = 0; stream->unencoded_offset = 0;
stream->enc_state = ENC_SEARCH; stream->enc_state = ENC_SEARCH;
IF_DEBUG2 (DP(RINT "[WINSTART:%"Q"u] input bytes %u offset %"Q"u\n", IF_DEBUG2 (DP(RINT "[WINSTART:%"Q"u] input bytes %"W"u offset %"Q"u\n",
stream->current_window, stream->avail_in, stream->current_window, stream->avail_in,
stream->total_in)); stream->total_in));
return XD3_WINSTART; return XD3_WINSTART;
case ENC_SEARCH: case ENC_SEARCH:
IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %u %s\n", IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %"W"u %s\n",
stream->match_state, stream->avail_in, stream->match_state, stream->avail_in,
stream->src ? "source" : "no source")); stream->src ? "source" : "no source"));
/* Reentrant matching. */ /* Reentrant matching. */
if (stream->src != NULL) if (stream->src != NULL)
{ {
switch (stream->match_state) switch (stream->match_state)
{ {
case MATCH_TARGET: case MATCH_TARGET:
/* Try matching forward at the start of the target. /* Try matching forward at the start of the target.
skipping to change at line 3271 skipping to change at line 3240
{ {
stream->enc_tails[i-1]->next_page = stream->enc_heads[i]; stream->enc_tails[i-1]->next_page = stream->enc_heads[i];
stream->enc_heads[i] = NULL; stream->enc_heads[i] = NULL;
} }
enc_output: enc_output:
stream->enc_state = ENC_POSTOUT; stream->enc_state = ENC_POSTOUT;
stream->next_out = stream->enc_current->base; stream->next_out = stream->enc_current->base;
stream->avail_out = stream->enc_current->next; stream->avail_out = stream->enc_current->next;
stream->total_out += (xoff_t) stream->avail_out; stream->total_out += stream->avail_out;
/* If there is any output in this buffer, return it, otherwise /* If there is any output in this buffer, return it, otherwise
* fall through to handle the next buffer or finish the window * fall through to handle the next buffer or finish the window
* after all buffers have been output. */ * after all buffers have been output. */
if (stream->avail_out > 0) if (stream->avail_out > 0)
{ {
/* This is the only place xd3_encode returns XD3_OUTPUT */ /* This is the only place xd3_encode returns XD3_OUTPUT */
return XD3_OUTPUT; return XD3_OUTPUT;
} }
skipping to change at line 3296 skipping to change at line 3265
stream->msg = "missed call to consume output"; stream->msg = "missed call to consume output";
return XD3_INTERNAL; return XD3_INTERNAL;
} }
/* Continue outputting one buffer at a time, until the next is NULL. */ /* Continue outputting one buffer at a time, until the next is NULL. */
if ((stream->enc_current = stream->enc_current->next_page) != NULL) if ((stream->enc_current = stream->enc_current->next_page) != NULL)
{ {
goto enc_output; goto enc_output;
} }
stream->total_in += (xoff_t) stream->avail_in; stream->total_in += stream->avail_in;
stream->enc_state = ENC_POSTWIN; stream->enc_state = ENC_POSTWIN;
IF_DEBUG2 (DP(RINT "[WINFINISH:%"Q"u] in=%"Q"u\n", IF_DEBUG2 (DP(RINT "[WINFINISH:%"Q"u] in=%"Q"u\n",
stream->current_window, stream->current_window,
stream->total_in)); stream->total_in));
return XD3_WINFINISH; return XD3_WINFINISH;
case ENC_POSTWIN: case ENC_POSTWIN:
xd3_encode_reset (stream); xd3_encode_reset (stream);
skipping to change at line 3606 skipping to change at line 3575
sizeof (xd3_slist))) == NULL) sizeof (xd3_slist))) == NULL)
{ {
return ENOMEM; return ENOMEM;
} }
} }
} }
return 0; return 0;
} }
#if XD3_USE_LARGEFILE64 #if XD3_USE_LARGEFILE64 && !XD3_USE_LARGESIZET
/* This function handles the 32/64bit ambiguity -- file positions are 64bit /* This function handles the 32/64bit ambiguity -- file positions are 64bit
* but the hash table for source-offsets is 32bit. */ * but the hash table for source-offsets is 32bit. */
static xoff_t static xoff_t
xd3_source_cksum_offset(xd3_stream *stream, usize_t low) xd3_source_cksum_offset(xd3_stream *stream, usize_t low)
{ {
xoff_t scp = stream->srcwin_cksum_pos; xoff_t scp = stream->srcwin_cksum_pos;
xoff_t s0 = scp >> 32; xoff_t s0 = scp >> 32;
usize_t sr = (usize_t) scp; usize_t sr = (usize_t) scp;
skipping to change at line 3633 skipping to change at line 3602
if (low > sr) { if (low > sr) {
return (--s0 << 32) | low; return (--s0 << 32) | low;
} }
return (s0 << 32) | low; return (s0 << 32) | low;
} }
#else #else
static xoff_t static xoff_t
xd3_source_cksum_offset(xd3_stream *stream, usize_t low) xd3_source_cksum_offset(xd3_stream *stream, usize_t low)
{ {
return (xoff_t) low; return low;
} }
#endif #endif
/* This function sets up the stream->src fields srcbase, srclen. The /* This function sets up the stream->src fields srcbase, srclen. The
* call is delayed until these values are needed to encode a copy * call is delayed until these values are needed to encode a copy
* address. At this point the decision has to be made. */ * address. At this point the decision has to be made. */
static int static int
xd3_srcwin_setup (xd3_stream *stream) xd3_srcwin_setup (xd3_stream *stream)
{ {
xd3_source *src = stream->src; xd3_source *src = stream->src;
skipping to change at line 3667 skipping to change at line 3636
if (stream->enc_state == ENC_INSTR && stream->match_maxaddr == 0) if (stream->enc_state == ENC_INSTR && stream->match_maxaddr == 0)
{ {
goto done; goto done;
} }
/* Check for overflow, srclen is usize_t - this can't happen unless /* Check for overflow, srclen is usize_t - this can't happen unless
* XD3_DEFAULT_SRCBACK and related parameters are extreme - should * XD3_DEFAULT_SRCBACK and related parameters are extreme - should
* use smaller windows. */ * use smaller windows. */
length = stream->match_maxaddr - stream->match_minaddr; length = stream->match_maxaddr - stream->match_minaddr;
x = (xoff_t) USIZE_T_MAX; x = USIZE_T_MAX;
if (length > x) if (length > x)
{ {
stream->msg = "source window length overflow (not 64bit)"; stream->msg = "source window length overflow (not 64bit)";
return XD3_INTERNAL; return XD3_INTERNAL;
} }
/* If ENC_INSTR, then we know the exact source window to use because /* If ENC_INSTR, then we know the exact source window to use because
* no more copies can be issued. */ * no more copies can be issued. */
if (stream->enc_state == ENC_INSTR) if (stream->enc_state == ENC_INSTR)
{ {
src->srcbase = stream->match_minaddr; src->srcbase = stream->match_minaddr;
src->srclen = (usize_t) length; src->srclen = (usize_t) length;
XD3_ASSERT (src->srclen); XD3_ASSERT (src->srclen);
goto done; goto done;
} }
/* Otherwise, we have to make a guess. More copies may still be /* Otherwise, we have to make a guess. More copies may still be
* issued, but we have to decide the source window base and length * issued, but we have to decide the source window base and length
* now. */ * now.
/* TODO: This may not working well in practice, more testing needed. */ * TODO: This may not working well in practice, more testing needed. */
src->srcbase = stream->match_minaddr; src->srcbase = stream->match_minaddr;
src->srclen = xd3_max ((usize_t) length, src->srclen = xd3_max ((usize_t) length,
stream->avail_in + (stream->avail_in >> 2)); stream->avail_in + (stream->avail_in >> 2));
if (src->eof_known) if (src->eof_known)
{ {
/* Note: if the source size is known, we must reduce srclen or /* Note: if the source size is known, we must reduce srclen or
* code that expects to pass a single block w/ getblk == NULL * code that expects to pass a single block w/ getblk == NULL
* will not function, as the code will return GETSRCBLK asking * will not function, as the code will return GETSRCBLK asking
* for the second block. */ * for the second block. */
src->srclen = xd3_min (src->srclen, xd3_source_eof(src) - src->srcbase); src->srclen = xd3_min (src->srclen, xd3_source_eof(src) - src->srcbase);
} }
IF_DEBUG1 (DP(RINT "[srcwin_setup_constrained] base %"Q"u len %"W"u\n",
IF_DEBUG1 (DP(RINT "[srcwin_setup_constrained] base %"Q"u len %u\n",
src->srcbase, src->srclen)); src->srcbase, src->srclen));
XD3_ASSERT (src->srclen); XD3_ASSERT (src->srclen);
done: done:
/* Set the taroff. This convenience variable is used even when /* Set the taroff. This convenience variable is used even when
stream->src == NULL. */ stream->src == NULL. */
stream->taroff = src->srclen; stream->taroff = src->srclen;
return 0; return 0;
} }
skipping to change at line 3767 skipping to change at line 3735
* will experience XD3_TOOFARBACK at the first xd3_getblk call * will experience XD3_TOOFARBACK at the first xd3_getblk call
* because the input may have advanced up to one block beyond the * because the input may have advanced up to one block beyond the
* actual EOF. */ * actual EOF. */
IF_DEBUG2(DP(RINT "[match_setup] %"Q"u srcpos %"Q"u, " IF_DEBUG2(DP(RINT "[match_setup] %"Q"u srcpos %"Q"u, "
"src->max_winsize %"Q"u\n", "src->max_winsize %"Q"u\n",
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
srcpos, src->max_winsize)); srcpos, src->max_winsize));
/* Going backwards, the 1.5-pass algorithm allows some /* Going backwards, the 1.5-pass algorithm allows some
* already-matched input may be covered by a longer source match. * already-matched input may be covered by a longer source match.
* The greedy algorithm does not allow this. */ * The greedy algorithm does not allow this.
* TODO: Measure this. */
if (stream->flags & XD3_BEGREEDY) if (stream->flags & XD3_BEGREEDY)
{ {
/* The greedy algorithm allows backward matching to the last /* The greedy algorithm allows backward matching to the last
matched position. */ * matched position. */
greedy_or_not = xd3_iopt_last_matched (stream); greedy_or_not = xd3_iopt_last_matched (stream);
} }
else else
{ {
/* The 1.5-pass algorithm allows backward matching to go back as /* The 1.5-pass algorithm allows backward matching to go back as
* far as the unencoded offset, which is updated as instructions * far as the unencoded offset, which is updated as instructions
* pass out of the iopt buffer. If this (default) is chosen, it * pass out of the iopt buffer. If this (default) is chosen, it
* means xd3_iopt_erase may be called to eliminate instructions * means xd3_iopt_erase may be called to eliminate instructions
* when a covering source match is found. */ * when a covering source match is found. */
greedy_or_not = stream->unencoded_offset; greedy_or_not = stream->unencoded_offset;
skipping to change at line 3800 skipping to change at line 3769
stream->match_maxfwd = stream->avail_in - stream->input_position; stream->match_maxfwd = stream->avail_in - stream->input_position;
/* Now we take the source position into account. It depends whether /* Now we take the source position into account. It depends whether
* the srclen/srcbase have been decided yet. */ * the srclen/srcbase have been decided yet. */
if (stream->srcwin_decided == 0) if (stream->srcwin_decided == 0)
{ {
/* Unrestricted case: the match can cover the entire source, /* Unrestricted case: the match can cover the entire source,
* 0--src->size. We compare the usize_t * 0--src->size. We compare the usize_t
* match_maxfwd/match_maxback against the xoff_t * match_maxfwd/match_maxback against the xoff_t
* src->size/srcpos values and take the min. */ * src->size/srcpos values and take the min. */
if (srcpos < (xoff_t) stream->match_maxback) /* TODO #if XD3_USE_LARGESIZET ? */
if (srcpos < stream->match_maxback)
{ {
stream->match_maxback = (usize_t) srcpos; stream->match_maxback = (usize_t) srcpos;
} }
if (src->eof_known) if (src->eof_known)
{ {
xoff_t srcavail = xd3_source_eof (src) - srcpos; xoff_t srcavail = xd3_source_eof (src) - srcpos;
if (srcavail < (xoff_t) stream->match_maxfwd) if (srcavail < stream->match_maxfwd)
{ {
stream->match_maxfwd = (usize_t) srcavail; stream->match_maxfwd = (usize_t) srcavail;
} }
} }
IF_DEBUG2(DP(RINT IF_DEBUG2(DP(RINT
"[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) "
"unrestricted maxback %u maxfwd %u\n", "unrestricted maxback %"W"u maxfwd %"W"u\n",
srcpos, srcpos,
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
stream->match_maxback, stream->match_maxback,
stream->match_maxfwd)); stream->match_maxfwd));
goto good; goto good;
} }
/* Decided some source window. */ /* Decided some source window. */
XD3_ASSERT (src->srclen > 0); XD3_ASSERT (src->srclen > 0);
/* Restricted case: fail if the srcpos lies outside the source window */ /* Restricted case: fail if the srcpos lies outside the source window */
if ((srcpos < src->srcbase) || if ((srcpos < src->srcbase) ||
(srcpos > (src->srcbase + (xoff_t) src->srclen))) (srcpos > (src->srcbase + src->srclen)))
{ {
IF_DEBUG1(DP(RINT "[match_setup] restricted source window failure\n")); IF_DEBUG1(DP(RINT "[match_setup] restricted source window failure\n"));
goto bad; goto bad;
} }
else else
{ {
usize_t srcavail; usize_t srcavail;
srcavail = (usize_t) (srcpos - src->srcbase); srcavail = (usize_t) (srcpos - src->srcbase);
if (srcavail < stream->match_maxback) if (srcavail < stream->match_maxback)
{ {
stream->match_maxback = srcavail; stream->match_maxback = srcavail;
} }
srcavail = (usize_t) (src->srcbase + (xoff_t) src->srclen - srcpos); srcavail = src->srcbase + src->srclen - srcpos;
if (srcavail < stream->match_maxfwd) if (srcavail < stream->match_maxfwd)
{ {
stream->match_maxfwd = srcavail; stream->match_maxfwd = srcavail;
} }
IF_DEBUG2(DP(RINT IF_DEBUG2(DP(RINT
"[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) "
"restricted maxback %u maxfwd %u\n", "restricted maxback %"W"u maxfwd %"W"u\n",
srcpos, srcpos,
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
stream->match_maxback, stream->match_maxback,
stream->match_maxfwd)); stream->match_maxfwd));
goto good; goto good;
} }
good: good:
stream->match_state = MATCH_BACKWARD; stream->match_state = MATCH_BACKWARD;
stream->match_srcpos = srcpos; stream->match_srcpos = srcpos;
stream->match_last_srcpos = srcpos; stream->match_last_srcpos = srcpos;
return 0; return 0;
bad: bad:
stream->match_state = MATCH_SEARCHING; stream->match_state = MATCH_SEARCHING;
stream->match_last_srcpos = srcpos; stream->match_last_srcpos = srcpos;
return 1; return 1;
} }
static inline int static inline usize_t
xd3_forward_match(const uint8_t *s1c, const uint8_t *s2c, int n) xd3_forward_match(const uint8_t *s1c, const uint8_t *s2c, usize_t n)
{ {
int i = 0; usize_t i = 0;
#if UNALIGNED_OK #if UNALIGNED_OK
int nint = n / sizeof(int); usize_t nint = n / sizeof(int);
if (nint >> 3) if (nint >> 3)
{ {
int j = 0; usize_t j = 0;
const int *s1 = (const int*)s1c; const int *s1 = (const int*)s1c;
const int *s2 = (const int*)s2c; const int *s2 = (const int*)s2c;
int nint_8 = nint - 8; usize_t nint_8 = nint - 8;
while (i <= nint_8 && while (i <= nint_8 &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++] && s1[i++] == s2[j++] &&
s1[i++] == s2[j++]) { } s1[i++] == s2[j++]) { }
skipping to change at line 3932 skipping to change at line 3902
xoff_t matchoff; /* matchoff is the current right/left-boundary of xoff_t matchoff; /* matchoff is the current right/left-boundary of
the source match being tested. */ the source match being tested. */
usize_t streamoff; /* streamoff is the current right/left-boundary usize_t streamoff; /* streamoff is the current right/left-boundary
of the input match being tested. */ of the input match being tested. */
xoff_t tryblk; /* tryblk, tryoff are the block, offset position xoff_t tryblk; /* tryblk, tryoff are the block, offset position
of matchoff */ of matchoff */
usize_t tryoff; usize_t tryoff;
usize_t tryrem; /* tryrem is the number of matchable bytes */ usize_t tryrem; /* tryrem is the number of matchable bytes */
usize_t matched; usize_t matched;
IF_DEBUG2(DP(RINT "[extend match] srcpos %"Q"u\n",
stream->match_srcpos));
XD3_ASSERT (src != NULL); XD3_ASSERT (src != NULL);
/* Does it make sense to compute backward match AFTER forward match? */ /* Does it make sense to compute backward match AFTER forward match? */
if (stream->match_state == MATCH_BACKWARD) if (stream->match_state == MATCH_BACKWARD)
{ {
/* Note: this code is practically duplicated below, substituting /* Note: this code is practically duplicated below, substituting
* match_fwd/match_back and direction. */ * match_fwd/match_back and direction. */
matchoff = stream->match_srcpos - stream->match_back; matchoff = stream->match_srcpos - stream->match_back;
streamoff = stream->input_position - stream->match_back; streamoff = stream->input_position - stream->match_back;
xd3_blksize_div (matchoff, src, &tryblk, &tryoff); xd3_blksize_div (matchoff, src, &tryblk, &tryoff);
skipping to change at line 3957 skipping to change at line 3930
if (tryoff == 0) if (tryoff == 0)
{ {
tryoff = src->blksize; tryoff = src->blksize;
tryblk -= 1; tryblk -= 1;
} }
if ((ret = xd3_getblk (stream, tryblk))) if ((ret = xd3_getblk (stream, tryblk)))
{ {
if (ret == XD3_TOOFARBACK) if (ret == XD3_TOOFARBACK)
{ {
IF_DEBUG2(DP(RINT "[maxback] %"Q"u TOOFARBACK: %u INP %"Q"u CKS UM %"Q"u\n", IF_DEBUG2(DP(RINT "[maxback] %"Q"u TOOFARBACK: %"W"u INP %"Q"u CKSUM %"Q"u\n",
tryblk, stream->match_back, tryblk, stream->match_back,
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
stream->srcwin_cksum_pos)); stream->srcwin_cksum_pos));
/* the starting position is too far back. */ /* the starting position is too far back. */
if (stream->match_back == 0) if (stream->match_back == 0)
{ {
XD3_ASSERT(stream->match_fwd == 0); XD3_ASSERT(stream->match_fwd == 0);
goto donefwd; goto donefwd;
} }
skipping to change at line 3979 skipping to change at line 3952
/* search went too far back, continue forward. */ /* search went too far back, continue forward. */
goto doneback; goto doneback;
} }
/* could be a XD3_GETSRCBLK failure. */ /* could be a XD3_GETSRCBLK failure. */
return ret; return ret;
} }
tryrem = xd3_min (tryoff, stream->match_maxback - stream->match_back); tryrem = xd3_min (tryoff, stream->match_maxback - stream->match_back);
IF_DEBUG2(DP(RINT "[maxback] maxback %u trysrc %"Q"u/%u tgt %u tryrem % u\n", IF_DEBUG2(DP(RINT "[maxback] maxback %"W"u trysrc %"Q"u/%"W"u tgt %"W"u tryrem %"W"u\n",
stream->match_maxback, tryblk, tryoff, streamoff, tryrem)) ; stream->match_maxback, tryblk, tryoff, streamoff, tryrem)) ;
/* TODO: This code can be optimized similar to xd3_match_forward() */ /* TODO: This code can be optimized similar to xd3_match_forward() */
for (; tryrem != 0; tryrem -= 1, stream->match_back += 1) for (; tryrem != 0; tryrem -= 1, stream->match_back += 1)
{ {
if (src->curblk[tryoff-1] != stream->next_in[streamoff-1]) if (src->curblk[tryoff-1] != stream->next_in[streamoff-1])
{ {
goto doneback; goto doneback;
} }
skipping to change at line 4018 skipping to change at line 3991
if (tryoff == src->blksize) if (tryoff == src->blksize)
{ {
tryoff = 0; tryoff = 0;
tryblk += 1; tryblk += 1;
} }
if ((ret = xd3_getblk (stream, tryblk))) if ((ret = xd3_getblk (stream, tryblk)))
{ {
if (ret == XD3_TOOFARBACK) if (ret == XD3_TOOFARBACK)
{ {
IF_DEBUG2(DP(RINT "[maxfwd] %"Q"u TOOFARBACK: %u INP %"Q"u CKSUM %" Q"u\n", IF_DEBUG2(DP(RINT "[maxfwd] %"Q"u TOOFARBACK: %"W"u INP %"Q"u CKSUM %"Q"u\n",
tryblk, stream->match_fwd, tryblk, stream->match_fwd,
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
stream->srcwin_cksum_pos)); stream->srcwin_cksum_pos));
goto donefwd; goto donefwd;
} }
/* could be a XD3_GETSRCBLK failure. */ /* could be a XD3_GETSRCBLK failure. */
return ret; return ret;
} }
skipping to change at line 4057 skipping to change at line 4030
if (tryrem != matched) if (tryrem != matched)
{ {
break; break;
} }
} }
donefwd: donefwd:
stream->match_state = MATCH_SEARCHING; stream->match_state = MATCH_SEARCHING;
IF_DEBUG2(DP(RINT "[extend match] input %"Q"u srcpos %"Q"u len %u\n", IF_DEBUG2(DP(RINT "[extend match] input %"Q"u srcpos %"Q"u len %"W"u\n",
stream->input_position + stream->total_in, stream->input_position + stream->total_in,
stream->match_srcpos, stream->match_srcpos,
stream->match_fwd)); stream->match_fwd));
/* If the match ends short of the last instruction end, we probably /* If the match ends short of the last instruction end, we probably
* don't want it. There is the possibility that a copy ends short * don't want it. There is the possibility that a copy ends short
* of the last copy but also goes further back, in which case we * of the last copy but also goes further back, in which case we
* might want it. This code does not implement such: if so we would * might want it. This code does not implement such: if so we would
* need more complicated xd3_iopt_erase logic. */ * need more complicated xd3_iopt_erase logic. */
if (stream->match_fwd < stream->min_match) if (stream->match_fwd < stream->min_match)
skipping to change at line 4113 skipping to change at line 4086
} }
if (match_end > stream->maxsrcaddr) if (match_end > stream->maxsrcaddr)
{ {
/* Note: across windows */ /* Note: across windows */
stream->maxsrcaddr = match_end; stream->maxsrcaddr = match_end;
} }
IF_DEBUG2 ({ IF_DEBUG2 ({
static int x = 0; static int x = 0;
DP(RINT "[source match:%d] length %u <inp %"Q"u %"Q"u> <src %"Q"u %"Q"u> (%s) [ %u bytes ]\n", DP(RINT "[source match:%d] length %"W"u <inp %"Q"u %"Q"u> <src %"Q"u %"Q "u> (%s)\n",
x++, x++,
match_length, match_length,
stream->total_in + target_position, stream->total_in + target_position,
stream->total_in + target_position + match_length, stream->total_in + target_position + match_length,
match_position, match_position,
match_position + match_length, match_position + match_length,
(stream->total_in + target_position == match_position) ? "same" : "dif (stream->total_in + target_position == match_position) ? "same" : "dif
f", f");
match_length);
}); });
if ((ret = xd3_found_match (stream, if ((ret = xd3_found_match (stream,
/* decoder position */ target_position, /* decoder position */ target_position,
/* length */ match_length, /* length */ match_length,
/* address */ match_position, /* address */ match_position,
/* is_source */ 1))) /* is_source */ 1)))
{ {
return ret; return ret;
} }
skipping to change at line 4219 skipping to change at line 4191
const uint8_t *ref; const uint8_t *ref;
SMALL_HASH_DEBUG1 (stream, stream->next_in + stream->input_position); SMALL_HASH_DEBUG1 (stream, stream->next_in + stream->input_position);
XD3_ASSERT (stream->min_match + stream->input_position <= stream->avail_in); XD3_ASSERT (stream->min_match + stream->input_position <= stream->avail_in);
base -= HASH_CKOFFSET; base -= HASH_CKOFFSET;
again: again:
IF_DEBUG2 (DP(RINT "smatch at base=%u inp=%u cksum=%u\n", base, IF_DEBUG2 (DP(RINT "smatch at base=%"W"u inp=%"W"u cksum=%"W"u\n", base,
stream->input_position, scksum)); stream->input_position, scksum));
/* For small matches, we can always go to the end-of-input because /* For small matches, we can always go to the end-of-input because
* the matching position must be less than the input position. */ * the matching position must be less than the input position. */
XD3_ASSERT (base < stream->input_position); XD3_ASSERT (base < stream->input_position);
ref = stream->next_in + base; ref = stream->next_in + base;
inp = stream->next_in + stream->input_position; inp = stream->next_in + stream->input_position;
SMALL_HASH_DEBUG2 (stream, ref); SMALL_HASH_DEBUG2 (stream, ref);
skipping to change at line 4320 skipping to change at line 4292
/* It's unlikely that a window is large enough for the (match_length == 6 && /* It's unlikely that a window is large enough for the (match_length == 6 &&
* address >= 2^28) check */ * address >= 2^28) check */
return match_length; return match_length;
} }
#if XD3_DEBUG #if XD3_DEBUG
static void static void
xd3_verify_small_state (xd3_stream *stream, xd3_verify_small_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
uint32_t x_cksum) uint32_t x_cksum)
{ {
uint32_t state; uint32_t state;
uint32_t cksum = xd3_scksum (&state, inp, stream->smatcher.small_look); uint32_t cksum = xd3_scksum (&state, inp, stream->smatcher.small_look);
XD3_ASSERT (cksum == x_cksum); XD3_ASSERT (cksum == x_cksum);
} }
static void static void
xd3_verify_large_state (xd3_stream *stream, xd3_verify_large_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
uint32_t x_cksum) usize_t x_cksum)
{ {
uint32_t cksum = xd3_lcksum (inp, stream->smatcher.large_look); usize_t cksum = xd3_large_cksum (&stream->large_hash, inp, stream->smatcher.la rge_look);
XD3_ASSERT (cksum == x_cksum); XD3_ASSERT (cksum == x_cksum);
} }
static void static void
xd3_verify_run_state (xd3_stream *stream, xd3_verify_run_state (xd3_stream *stream,
const uint8_t *inp, const uint8_t *inp,
usize_t x_run_l, usize_t x_run_l,
uint8_t *x_run_c) uint8_t *x_run_c)
{ {
usize_t slook = stream->smatcher.small_look; usize_t slook = stream->smatcher.small_look;
uint8_t run_c; uint8_t run_c;
skipping to change at line 4459 skipping to change at line 4431
stream->srcwin_cksum_pos, stream->srcwin_cksum_pos,
target_cksum_pos, target_cksum_pos,
xd3_source_eof (stream->src), xd3_source_eof (stream->src),
stream->src->eof_known ? "known" : "unknown")); stream->src->eof_known ? "known" : "unknown"));
blkpos = xd3_bytes_on_srcblk (stream->src, blkno); blkpos = xd3_bytes_on_srcblk (stream->src, blkno);
if (blkpos < (ssize_t) stream->smatcher.large_look) if (blkpos < (ssize_t) stream->smatcher.large_look)
{ {
stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize;
IF_DEBUG2 (DP(RINT "[srcwin_move_point] continue (end-of-block): %"Q"u\ n", blkpos)); IF_DEBUG2 (DP(RINT "[srcwin_move_point] continue (end-of-block): %"Z"d\ n", blkpos));
continue; continue;
} }
/* This inserts checksums for the entire block, in reverse, /* This inserts checksums for the entire block, in reverse,
* starting from the end of the block. This logic does not test * starting from the end of the block. This logic does not test
* stream->srcwin_cksum_pos because it always advances it to the * stream->srcwin_cksum_pos because it always advances it to the
* start of the next block. * start of the next block.
* *
* oldpos is the srcwin_cksum_pos within this block. blkpos is * oldpos is the srcwin_cksum_pos within this block. blkpos is
* the number of bytes available. Each iteration inspects * the number of bytes available. Each iteration inspects
* large_look bytes then steps back large_step bytes. The * large_look bytes then steps back large_step bytes. The
* if-stmt above ensures at least one large_look of data. */ * if-stmt above ensures at least one large_look of data. */
blkpos -= stream->smatcher.large_look; blkpos -= stream->smatcher.large_look;
blkbaseoffset = stream->src->blksize * blkno; blkbaseoffset = stream->src->blksize * blkno;
do do
{ {
uint32_t cksum = xd3_lcksum (stream->src->curblk + blkpos, /* TODO: This would be significantly faster if the compiler
stream->smatcher.large_look); * knew stream->smatcher.large_look (which the template for
* xd3_string_match_* allows). */
usize_t cksum = xd3_large_cksum (&stream->large_hash,
stream->src->curblk + blkpos,
stream->smatcher.large_look);
usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum);
stream->large_table[hval] = stream->large_table[hval] =
(usize_t) (blkbaseoffset + (usize_t) (blkbaseoffset +
(xoff_t)(blkpos + HASH_CKOFFSET)); (xoff_t)(blkpos + HASH_CKOFFSET));
IF_DEBUG (stream->large_ckcnt += 1); IF_DEBUG (stream->large_ckcnt += 1);
blkpos -= stream->smatcher.large_step; blkpos -= stream->smatcher.large_step;
} }
while (blkpos >= oldpos); while (blkpos >= oldpos);
stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize;
} }
IF_DEBUG1 (DP(RINT
"[srcwin_move_point] exited loop T=%"Q"u "
"S=%"Q"u EOF=%"Q"u %s\n",
stream->total_in + stream->input_position,
stream->srcwin_cksum_pos,
xd3_source_eof (stream->src),
stream->src->eof_known ? "known" : "unknown"));
if (stream->src->eof_known) if (stream->src->eof_known)
{ {
xoff_t source_size = xd3_source_eof (stream->src); xoff_t source_size = xd3_source_eof (stream->src);
if (stream->srcwin_cksum_pos >= source_size) if (stream->srcwin_cksum_pos >= source_size)
{ {
/* This invariant is needed for xd3_source_cksum_offset() */ /* This invariant is needed for xd3_source_cksum_offset() */
stream->srcwin_cksum_pos = source_size; stream->srcwin_cksum_pos = source_size;
*next_move_point = USIZE_T_MAX; *next_move_point = USIZE_T_MAX;
IF_DEBUG1 (DP(RINT IF_DEBUG1 (DP(RINT
"[srcwin_move_point] finished with source input\n")); "[srcwin_move_point] finished with source input\n"));
skipping to change at line 4517 skipping to change at line 4501
/* How long until this function should be called again. */ /* How long until this function should be called again. */
XD3_ASSERT(stream->srcwin_cksum_pos >= target_cksum_pos); XD3_ASSERT(stream->srcwin_cksum_pos >= target_cksum_pos);
*next_move_point = stream->input_position + *next_move_point = stream->input_position +
stream->src->blksize - stream->src->blksize -
((stream->srcwin_cksum_pos - target_cksum_pos) & stream->src->maskby); ((stream->srcwin_cksum_pos - target_cksum_pos) & stream->src->maskby);
IF_DEBUG2 (DP(RINT IF_DEBUG2 (DP(RINT
"[srcwin_move_point] finished T=%"Q"u " "[srcwin_move_point] finished T=%"Q"u "
"S=%"Q"u L=%"Q"u EOF=%"Q"u %s again in %u\n", "S=%"Q"u L=%"Q"u EOF=%"Q"u %s again in %"W"u\n",
stream->total_in + stream->input_position, stream->total_in + stream->input_position,
stream->srcwin_cksum_pos, stream->srcwin_cksum_pos,
target_cksum_pos, target_cksum_pos,
xd3_source_eof (stream->src), xd3_source_eof (stream->src),
stream->src->eof_known ? "known" : "unknown", stream->src->eof_known ? "known" : "unknown",
*next_move_point - stream->input_position)); *next_move_point - stream->input_position));
return 0; return 0;
} }
skipping to change at line 4573 skipping to change at line 4557
static int static int
XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream)
{ {
const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS); const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS);
const int DO_LARGE = (stream->src != NULL); const int DO_LARGE = (stream->src != NULL);
const int DO_RUN = (1); const int DO_RUN = (1);
const uint8_t *inp; const uint8_t *inp;
uint32_t scksum = 0; uint32_t scksum = 0;
uint32_t scksum_state = 0; uint32_t scksum_state = 0;
uint32_t lcksum = 0; usize_t lcksum = 0;
usize_t sinx; usize_t sinx;
usize_t linx; usize_t linx;
uint8_t run_c; uint8_t run_c;
usize_t run_l; usize_t run_l;
int ret; int ret;
usize_t match_length; usize_t match_length;
usize_t match_offset = 0; usize_t match_offset = 0;
usize_t next_move_point; usize_t next_move_point = 0;
IF_DEBUG2(DP(RINT "[string_match] initial entry %u\n", stream->input_position) ); IF_DEBUG2(DP(RINT "[string_match] initial entry %"W"u\n", stream->input_positi on));
/* If there will be no compression due to settings or short input, /* If there will be no compression due to settings or short input,
* skip it entirely. */ * skip it entirely. */
if (! (DO_SMALL || DO_LARGE || DO_RUN) || if (! (DO_SMALL || DO_LARGE || DO_RUN) ||
stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; }
if ((ret = xd3_string_match_init (stream))) { return ret; } if ((ret = xd3_string_match_init (stream))) { return ret; }
/* The restartloop label is reached when the incremental loop state /* The restartloop label is reached when the incremental loop state
* needs to be reset. */ * needs to be reset. */
restartloop: restartloop:
IF_DEBUG2(DP(RINT "[string_match] restartloop %u\n", stream->input_position)); IF_DEBUG2(DP(RINT "[string_match] restartloop %"W"u\n", stream->input_position ));
/* If there is not enough input remaining for any kind of match, /* If there is not enough input remaining for any kind of match,
skip it. */ skip it. */
if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; }
/* Now reset the incremental loop state: */ /* Now reset the incremental loop state: */
/* The min_match variable is updated to avoid matching the same lazy /* The min_match variable is updated to avoid matching the same lazy
* match over and over again. For example, if you find a (small) * match over and over again. For example, if you find a (small)
* match of length 9 at one position, you will likely find a match * match of length 9 at one position, you will likely find a match
skipping to change at line 4649 skipping to change at line 4633
/* Source window: next_move_point is the point that /* Source window: next_move_point is the point that
* stream->input_position must reach before computing more * stream->input_position must reach before computing more
* source checksum. Note: this is called unconditionally * source checksum. Note: this is called unconditionally
* the first time after reentry, subsequent calls will be * the first time after reentry, subsequent calls will be
* avoided if next_move_point is > input_position */ * avoided if next_move_point is > input_position */
if ((ret = xd3_srcwin_move_point (stream, & next_move_point))) if ((ret = xd3_srcwin_move_point (stream, & next_move_point)))
{ {
return ret; return ret;
} }
lcksum = xd3_lcksum (inp, LLOOK); lcksum = xd3_large_cksum (&stream->large_hash, inp, LLOOK);
} }
/* TRYLAZYLEN: True if a certain length match should be followed by /* TRYLAZYLEN: True if a certain length match should be followed by
* lazy search. This checks that LEN is shorter than MAXLAZY and * lazy search. This checks that LEN is shorter than MAXLAZY and
* that there is enough leftover data to consider lazy matching. * that there is enough leftover data to consider lazy matching.
* "Enough" is set to 2 since the next match will start at the next * "Enough" is set to 2 since the next match will start at the next
* offset, it must match two extra characters. */ * offset, it must match two extra characters. */
#define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) \ #define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) \
&& (POS) + (LEN) <= (MAX) - 2) && (POS) + (LEN) <= (MAX) - 2)
skipping to change at line 4769 skipping to change at line 4753
} }
/* Insert a hash for this string. */ /* Insert a hash for this string. */
xd3_scksum_insert (stream, sinx, scksum, stream->input_position); xd3_scksum_insert (stream, sinx, scksum, stream->input_position);
/* Maybe output a COPY instruction */ /* Maybe output a COPY instruction */
if (match_length >= stream->min_match) if (match_length >= stream->min_match)
{ {
IF_DEBUG2 ({ IF_DEBUG2 ({
static int x = 0; static int x = 0;
DP(RINT "[target match:%d] <inp %u %u> <cpy %u %u> " DP(RINT "[target match:%d] <inp %"W"u %"W"u> <cpy %"W"u %"W"u> "
"(-%d) [ %u bytes ]\n", "(-%"W"d) [ %"W"u bytes ]\n",
x++, x++,
stream->input_position, stream->input_position,
stream->input_position + match_length, stream->input_position + match_length,
match_offset, match_offset,
match_offset + match_length, match_offset + match_length,
stream->input_position - match_offset, stream->input_position - match_offset,
match_length); match_length);
}); });
if ((ret = xd3_found_match (stream, if ((ret = xd3_found_match (stream,
skipping to change at line 4825 skipping to change at line 4809
NEXTRUN (inp[SLOOK]); NEXTRUN (inp[SLOOK]);
} }
if (DO_SMALL) if (DO_SMALL)
{ {
scksum = xd3_small_cksum_update (&scksum_state, inp, SLOOK); scksum = xd3_small_cksum_update (&scksum_state, inp, SLOOK);
} }
if (DO_LARGE && (stream->input_position + LLOOK < stream->avail_in)) if (DO_LARGE && (stream->input_position + LLOOK < stream->avail_in))
{ {
lcksum = xd3_large_cksum_update (lcksum, inp, LLOOK); lcksum = xd3_large_cksum_update (&stream->large_hash, lcksum, inp, LLOO K);
} }
} }
loopnomore: loopnomore:
return 0; return 0;
} }
#endif /* XD3_ENCODER */ #endif /* XD3_ENCODER */
#endif /* __XDELTA3_C_TEMPLATE_PASS__ */ #endif /* __XDELTA3_C_TEMPLATE_PASS__ */
 End of changes. 112 change blocks. 
207 lines changed or deleted 176 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS