Revert "(xdelta3) Slim down on dependency"

This reverts commit d7d659147c15394f72c3e53953bfb4291bd8c982.
This commit is contained in:
libretroadmin 2022-12-19 03:25:15 +01:00
parent 910db94e9f
commit 91f3611fdd
8 changed files with 1085 additions and 11 deletions

View File

@ -162,6 +162,9 @@ xd3_decode_allocate (xd3_stream *stream,
uint8_t **buf_ptr,
usize_t *buf_alloc)
{
IF_DEBUG2 (DP(RINT "[xd3_decode_allocate] size %"W"u alloc %"W"u\n",
size, *buf_alloc));
if (*buf_ptr != NULL && *buf_alloc < size)
{
xd3_free (stream, *buf_ptr);
@ -187,6 +190,9 @@ xd3_decode_section (xd3_stream *stream,
xd3_decode_state nstate,
int copy)
{
XD3_ASSERT (section->pos <= section->size);
XD3_ASSERT (stream->dec_state != nstate);
if (section->pos < section->size)
{
usize_t sect_take;
@ -201,6 +207,8 @@ xd3_decode_section (xd3_stream *stream,
/* No allocation/copy needed */
section->buf = stream->next_in;
sect_take = section->size;
IF_DEBUG1 (DP(RINT "[xd3_decode_section] zerocopy %"W"u @ %"W"u avail %"W"u\n",
sect_take, section->pos, stream->avail_in));
}
else
{
@ -217,11 +225,17 @@ xd3_decode_section (xd3_stream *stream,
section->size,
& section->copied1,
& section->alloc1)))
{
return ret;
}
section->buf = section->copied1;
}
IF_DEBUG2 (DP(RINT "[xd3_decode_section] take %"W"u @ %"W"u [need %"W"u] avail %"W"u\n",
sect_take, section->pos, sect_need, stream->avail_in));
XD3_ASSERT (section->pos + sect_take <= section->alloc1);
memcpy (section->copied1 + section->pos,
stream->next_in,
sect_take);
@ -236,10 +250,14 @@ xd3_decode_section (xd3_stream *stream,
if (section->pos < section->size)
{
IF_DEBUG1 (DP(RINT "[xd3_decode_section] further input required %"W"u\n",
section->size - section->pos));
stream->msg = "further input required";
return XD3_INPUT;
}
XD3_ASSERT (section->pos == section->size);
stream->dec_state = nstate;
section->buf_max = section->buf + section->size;
section->pos = 0;
@ -269,13 +287,27 @@ xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst)
/* For copy instructions, read address. */
if (inst->type >= XD3_CPY)
{
IF_DEBUG2 ({
static int cnt = 0;
XPR(NT "DECODE:%u: COPY at %"Q"u (winoffset %"W"u) "
"size %"W"u winaddr %"W"u\n",
cnt++,
stream->total_out + (stream->dec_position -
stream->dec_cpylen),
(stream->dec_position - stream->dec_cpylen),
inst->size,
inst->addr);
});
if ((ret = xd3_decode_address (stream,
stream->dec_position,
inst->type - XD3_CPY,
& stream->addr_sect.buf,
stream->addr_sect.buf_max,
& inst->addr)))
{
return ret;
}
/* Cannot copy an address before it is filled-in. */
if (inst->addr >= stream->dec_position)
@ -293,6 +325,30 @@ xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst)
return XD3_INVALID_INPUT;
}
}
else
{
IF_DEBUG2 ({
if (inst->type == XD3_ADD)
{
static int cnt;
XPR(NT "DECODE:%d: ADD at %"Q"u (winoffset %"W"u) size %"W"u\n",
cnt++,
(stream->total_out + stream->dec_position - stream->dec_cpylen),
stream->dec_position - stream->dec_cpylen,
inst->size);
}
else
{
static int cnt;
XD3_ASSERT (inst->type == XD3_RUN);
XPR(NT "DECODE:%d: RUN at %"Q"u (winoffset %"W"u) size %"W"u\n",
cnt++,
stream->total_out + stream->dec_position - stream->dec_cpylen,
stream->dec_position - stream->dec_cpylen,
inst->size);
}
});
}
/* Check: The instruction will not overflow the output buffer. */
if (stream->dec_position + inst->size > stream->dec_maxpos)
@ -360,6 +416,8 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst)
return XD3_INVALID_INPUT;
}
XD3_ASSERT (inst->type != XD3_NOOP);
switch (inst->type)
{
case XD3_RUN:
@ -449,6 +507,7 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst)
int ret;
xd3_blksize_add (&block, &blkoff, source, inst->addr);
XD3_ASSERT (blkoff < blksize);
if ((ret = xd3_getblk (stream, block)))
{
@ -468,10 +527,18 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst)
if ((source->onblk != blksize) &&
(blkoff + take > source->onblk))
{
IF_DEBUG1 (XPR(NT "[srcfile] short at blkno %"Q"u onblk "
"%"W"u blksize %"W"u blkoff %"W"u take %"W"u\n",
block,
source->onblk,
blksize,
blkoff,
take));
stream->msg = "source file too short";
return XD3_INVALID_INPUT;
}
XD3_ASSERT (blkoff != blksize);
/* Check if we have enough data on this block to
* finish the instruction. */
@ -485,6 +552,9 @@ xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst)
take = blksize - blkoff;
inst->size -= take;
inst->addr += take;
/* because (blkoff + take > blksize), above */
XD3_ASSERT (inst->size != 0);
}
}
}
@ -592,6 +662,9 @@ xd3_decode_sections (xd3_stream *stream)
}
need += stream->data_sect.size;
/* The window may be entirely processed. */
XD3_ASSERT (stream->dec_winbytes <= need);
/* Compute how much more input is needed. */
more = (need - stream->dec_winbytes);
@ -636,6 +709,8 @@ xd3_decode_sections (xd3_stream *stream)
DEC_EMIT, copy))) { return ret; }
}
XD3_ASSERT (stream->dec_winbytes == need);
if ((ret = xd3_decode_secondary_sections (stream))) { return ret; }
if (stream->flags & XD3_SKIP_EMIT)
@ -656,6 +731,19 @@ xd3_decode_emit (xd3_stream *stream)
{
int ret;
/* Produce output: originally structured to allow reentrant code
* that fills as much of the output buffer as possible, but VCDIFF
* semantics allows to copy from anywhere from the target window, so
* instead allocate a sufficiently sized buffer after the target
* window length is decoded.
*
* This code still needs to be reentrant to allow XD3_GETSRCBLK to
* return control. This is handled by setting the
* stream->dec_currentN instruction types to XD3_NOOP after they
* have been processed. */
XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT));
XD3_ASSERT (stream->dec_tgtlen <= stream->space_out);
while (stream->inst_sect.buf != stream->inst_sect.buf_max ||
stream->dec_current1.type != XD3_NOOP ||
stream->dec_current2.type != XD3_NOOP)
@ -685,6 +773,8 @@ xd3_decode_emit (xd3_stream *stream)
if (stream->avail_out != stream->dec_tgtlen)
{
IF_DEBUG2 (DP(RINT "AVAIL_OUT(%"W"u) != DEC_TGTLEN(%"W"u)\n",
stream->avail_out, stream->dec_tgtlen));
stream->msg = "wrong window length";
return XD3_INVALID_INPUT;
}
@ -919,6 +1009,9 @@ xd3_decode_input (xd3_stream *stream)
if ((ret = xd3_decode_init_window (stream))) { return ret; }
stream->dec_state = DEC_CPYLEN;
IF_DEBUG2 (DP(RINT "--------- TARGET WINDOW %"Q"u -----------\n",
stream->current_window));
}
case DEC_CPYLEN:
@ -1072,6 +1165,16 @@ xd3_decode_input (xd3_stream *stream)
xd3_blksize_div(stream->dec_cpyoff, src,
&src->cpyoff_blocks,
&src->cpyoff_blkoff);
IF_DEBUG2(DP(RINT
"[decode_cpyoff] %"Q"u "
"cpyblkno %"Q"u "
"cpyblkoff %"W"u "
"blksize %"W"u\n",
stream->dec_cpyoff,
src->cpyoff_blocks,
src->cpyoff_blkoff,
src->blksize));
}
/* xd3_decode_emit returns XD3_OUTPUT on every success. */
@ -1116,4 +1219,4 @@ xd3_decode_input (xd3_stream *stream)
}
}
#endif /* _XDELTA3_DECODE_H_*/
#endif /* _XDELTA3_DECODE_H_*/

View File

@ -305,6 +305,21 @@ heap_extract (usize_t *heap, const djw_heapen *ents, usize_t heap_last)
return (djw_heapen*) & ents[smallest];
}
#if XD3_DEBUG
static void
heap_check (usize_t *heap, djw_heapen *ents, usize_t heap_last)
{
usize_t i;
for (i = 1; i <= heap_last; i += 1)
{
/* Heap property: child not less than parent */
XD3_ASSERT (! heap_less (& ents[heap[i]], & ents[heap[i/2]]));
IF_DEBUG2 (DP(RINT "heap[%"W"u] = %u\n", i, ents[heap[i]].freq));
}
}
#endif
/*********************************************************************/
/* MTF, 1/2 */
/*********************************************************************/
@ -380,9 +395,15 @@ djw_build_prefix (const djw_weight *freq, uint8_t *clen, usize_t asize, usize_t
usize_t total_bits;
usize_t i;
IF_DEBUG (usize_t first_bits = 0);
/* Insert real symbol frequences. */
for (i = 0; i < asize; i += 1)
{
ents[i+1].freq = freq[i];
IF_DEBUG2 (DP(RINT "ents[%"W"i] = freq[%"W"u] = %d\n",
i+1, i, freq[i]));
}
again:
@ -410,6 +431,11 @@ djw_build_prefix (const djw_weight *freq, uint8_t *clen, usize_t asize, usize_t
}
}
IF_DEBUG (heap_check (heap, ents, heap_last));
/* Must be at least one symbol, or else we can't get here. */
XD3_ASSERT (heap_last != 0);
/* If there is only one symbol, fake a second to prevent zero-length
* codes. */
if (heap_last == 1)
@ -435,6 +461,8 @@ djw_build_prefix (const djw_weight *freq, uint8_t *clen, usize_t asize, usize_t
heap_insert (heap, ents, ++heap_last, ents_size++);
}
IF_DEBUG (heap_check (heap, ents, heap_last));
/* Now compute prefix code lengths, counting parents. */
for (i = 1; i < asize+1; i += 1)
{
@ -452,11 +480,21 @@ djw_build_prefix (const djw_weight *freq, uint8_t *clen, usize_t asize, usize_t
}
/* clen is 0-origin, unlike ents. */
IF_DEBUG2 (DP(RINT "clen[%"W"u] = %"W"u\n", i-1, b));
clen[i-1] = b;
}
IF_DEBUG (if (first_bits == 0) first_bits = total_bits);
if (! overflow)
{
IF_DEBUG2 (if (first_bits != total_bits)
{
DP(RINT "code length overflow changed %"W"u bits\n",
total_bits - first_bits);
});
return total_bits;
}
/* OPT: There is a non-looping way to fix overflow shown in zlib, but this
* is easier (for now), as done in bzip2. */
@ -487,6 +525,8 @@ djw_build_codes (usize_t *codes, const uint8_t *clen, usize_t asize, usize_t abs
max_clen = xd3_max (max_clen, (usize_t) clen[i]);
}
XD3_ASSERT (max_clen <= abs_max);
/* Generate a code for each symbol with the appropriate length. */
for (l = min_clen; l <= max_clen; l += 1)
{
@ -500,6 +540,13 @@ djw_build_codes (usize_t *codes, const uint8_t *clen, usize_t asize, usize_t abs
code <<= 1;
}
IF_DEBUG2 ({
for (i = 0; i < asize; i += 1)
{
DP(RINT "code[%"W"u] = %"W"u\n", i, codes[i]);
}
});
}
/*********************************************************************/
@ -528,6 +575,8 @@ djw_compute_mtf_1_2 (djw_prefix *prefix,
for (j = 0; mtf[j] != sym; j += 1) { }
XD3_ASSERT (j <= nsym);
for (k = j; k >= 1; k -= 1) { mtf[k] = mtf[k-1]; }
mtf[0] = sym;
@ -579,6 +628,14 @@ djw_count_freqs (djw_weight *freq, xd3_output *input)
while (++p < p_max);
}
IF_DEBUG2 ({int i;
DP(RINT "freqs: ");
for (i = 0; i < ALPHABET_SIZE; i += 1)
{
DP(RINT "%u ", freq[i]);
}
DP(RINT "\n");});
return size;
}
@ -643,6 +700,7 @@ djw_encode_prefix (xd3_stream *stream,
{
num_to_encode -= 1;
}
XD3_ASSERT (num_to_encode - DJW_EXTRA_12OFFSET < (1 << DJW_EXTRA_CODE_BITS));
/* Encode: # of extra codes */
if ((ret = xd3_encode_bits (stream, output, bstate, DJW_EXTRA_CODE_BITS,
@ -789,6 +847,11 @@ xd3_encode_howmany_groups (xd3_stream *stream,
(*ret_groups) = cfg_groups;
(*ret_sector_size) = cfg_sector_size;
XD3_ASSERT (cfg_groups > 0 && cfg_groups <= DJW_MAX_GROUPS);
XD3_ASSERT (cfg_groups == 1 ||
(cfg_sector_size >= DJW_SECTORSZ_MULT &&
cfg_sector_size <= DJW_SECTORSZ_MAX));
return 0;
}
@ -814,6 +877,8 @@ xd3_encode_huff (xd3_stream *stream,
input_bytes = djw_count_freqs (real_freq, input);
input_bits = input_bytes * 8;
XD3_ASSERT (input_bytes > 0);
if ((ret = xd3_encode_howmany_groups (stream, cfg, input_bytes,
& groups, & sector_size)))
{
@ -877,12 +942,18 @@ xd3_encode_huff (xd3_stream *stream,
usize_t sym = *p++;
usize_t bits = clen[sym];
IF_DEBUG (output_bits -= bits);
if ((ret = xd3_encode_bits (stream, & output,
& bstate, bits, code[sym])))
{
goto failure;
}
}
while (p < p_max);
}
XD3_ASSERT (output_bits == 0);
}
else
{
@ -902,6 +973,7 @@ xd3_encode_huff (xd3_stream *stream,
usize_t gbest_no;
usize_t gpcnt;
const uint8_t *p;
IF_DEBUG2 (usize_t gcount[DJW_MAX_GROUPS]);
/* Encode: sector size (5 bits) */
if ((ret = xd3_encode_bits (stream, & output, & bstate,
@ -938,19 +1010,32 @@ xd3_encode_huff (xd3_stream *stream,
djw_weight sum = 0;
djw_weight goal = left / (groups - gp);
IF_DEBUG2 (usize_t nz = 0);
/* Due to the single-code granularity of this distribution, it may
* be that we can't generate a distribution for each group. In that
* case subtract one group and try again. If (inefficient), we're
* testing group behavior, so don't mess things up. */
if (goal == 0 && !cfg->inefficient)
{
IF_DEBUG2 (DP(RINT "too many groups (%"W"u), dropping one\n",
groups));
groups -= 1;
goto regroup;
}
/* Sum == goal is possible when (cfg->inefficient)... */
while (sum < goal)
{
XD3_ASSERT (sym2 < ALPHABET_SIZE);
IF_DEBUG2 (nz += real_freq[sym2] != 0);
sum += real_freq[sym2++];
}
IF_DEBUG2(DP(RINT "group %"W"u has symbols %"W"u..%"W"u (%"W"u non-zero) "
"(%u/%"W"u = %.3f)\n",
gp, sym1, sym2, nz, sum,
input_bytes, sum / (double)input_bytes););
for (s = 0; s < ALPHABET_SIZE; s += 1)
{
@ -966,6 +1051,7 @@ xd3_encode_huff (xd3_stream *stream,
niter += 1;
gbest_no = 0;
memset (evolve_freq, 0, sizeof (evolve_freq[0]) * groups);
IF_DEBUG2 (memset (gcount, 0, sizeof (gcount[0]) * groups));
/* For each input page (loop is irregular to allow non-pow2-size group
* size. */
@ -1015,7 +1101,9 @@ xd3_encode_huff (xd3_stream *stream,
}
}
XD3_ASSERT(gbest_no < gbest_max);
gbest[gbest_no++] = winner;
IF_DEBUG2 (gcount[winner] += 1);
p = p0;
in = in0;
@ -1030,6 +1118,8 @@ xd3_encode_huff (xd3_stream *stream,
}
while (in != NULL);
XD3_ASSERT (gbest_no == gbest_max);
/* Recompute code lengths. */
output_bits = 0;
for (gp = 0; gp < groups; gp += 1)
@ -1065,14 +1155,29 @@ xd3_encode_huff (xd3_stream *stream,
* for the (output_bits==0) assert after all bits are output. */
if (any_zeros)
{
IF_DEBUG2 (usize_t save_total = output_bits);
for (i = 0; i < ALPHABET_SIZE; i += 1)
{
if (evolve_zero[i]) { output_bits -= evolve_clen[gp][i]; }
}
IF_DEBUG2 (DP(RINT "evolve_zero reduced %"W"u bits in group %"W"u\n",
save_total - output_bits, gp));
}
}
IF_DEBUG2(
DP(RINT "pass %"W"u total bits: %"W"u group uses: ", niter, output_bits);
for (gp = 0; gp < groups; gp += 1) { DP(RINT "%"W"u ", gcount[gp]); }
DP(RINT "\n");
);
/* End iteration. */
IF_DEBUG2 (if (niter > 1 && best_bits < output_bits) {
DP(RINT "iteration lost %"W"u bits\n", output_bits - best_bits); });
if (niter == 1 || (niter < DJW_MAX_ITER &&
(best_bits - output_bits) >= DJW_MIN_IMPROVEMENT))
{
@ -1086,6 +1191,9 @@ xd3_encode_huff (xd3_stream *stream,
goto nosecond;
}
IF_DEBUG2 (DP(RINT "djw compression: %"W"u -> %0.3f\n",
input_bytes, output_bits / 8.0));
/* Encode: prefix */
{
uint8_t prefix_symbol[DJW_MAX_GROUPS * ALPHABET_SIZE];
@ -1136,10 +1244,18 @@ xd3_encode_huff (xd3_stream *stream,
usize_t gp_sel_bits = gbest_clen[gp_mtf];
usize_t gp_sel_code = gbest_code[gp_mtf];
XD3_ASSERT (gp_mtf < groups+1);
if ((ret = xd3_encode_bits (stream, & output, & bstate,
gp_sel_bits, gp_sel_code)))
{
goto failure;
}
IF_DEBUG (select_bits -= gp_sel_bits);
}
XD3_ASSERT (select_bits == 0);
}
/* Efficiency check. */
@ -1172,6 +1288,8 @@ xd3_encode_huff (xd3_stream *stream,
usize_t *gp_codes = evolve_code[gp_best];
uint8_t *gp_clens = evolve_clen[gp_best];
XD3_ASSERT (sector < gbest_no);
sector += 1;
/* Encode the sector data. */
@ -1181,14 +1299,21 @@ xd3_encode_huff (xd3_stream *stream,
usize_t bits = gp_clens[sym];
usize_t code = gp_codes[sym];
IF_DEBUG (output_bits -= bits);
if ((ret = xd3_encode_bits (stream, & output, & bstate,
bits, code)))
{
goto failure;
}
GP_PAGE ();
}
}
while (in != NULL);
XD3_ASSERT (select_bits == 0);
XD3_ASSERT (output_bits == 0);
}
}
@ -1231,6 +1356,9 @@ djw_build_decoder (xd3_stream *stream,
usize_t min_clen;
usize_t max_clen;
/* Assumption: the two temporary arrays are large enough to hold abs_max. */
XD3_ASSERT (abs_max <= DJW_MAX_CODELEN);
/* This looks something like the start of zlib's inftrees.c */
memset (nr_clen, 0, sizeof (nr_clen[0]) * (abs_max+1));
@ -1239,6 +1367,13 @@ djw_build_decoder (xd3_stream *stream,
ci = clen;
do
{
/* Caller _must_ check that values are in-range. Most of the time the
* caller decodes a specific number of bits, which imply the max value,
* and the other time the caller decodes a huffman value, which must be
* in-range. Therefore, its an assertion and this function cannot
* otherwise fail. */
XD3_ASSERT (*ci <= abs_max);
nr_clen[*ci++]++;
}
while (--i != 0);
@ -1333,6 +1468,7 @@ djw_decode_symbol (xd3_stream *stream,
if (offset <= max_sym)
{
IF_DEBUG2 (DP(RINT "(j) %"W"u ", code));
*sym = inorder[offset];
return 0;
}
@ -1384,6 +1520,9 @@ djw_decode_clclen (xd3_stream *stream,
/* Set the rest to zero. */
for (; i < DJW_TOTAL_CODES; i += 1) { cl_clen[i] = 0; }
/* No need to check for in-range clen values, because: */
XD3_ASSERT (1 << DJW_CLCLEN_BITS == DJW_MAX_CLCLEN + 1);
/* Build the code-length decoder. */
djw_build_decoder (stream, DJW_TOTAL_CODES, DJW_MAX_CLCLEN,
cl_clen, cl_inorder, cl_base,
@ -1645,6 +1784,8 @@ xd3_decode_huff (xd3_stream *stream,
{
gp = sel_group[c];
XD3_ASSERT (gp < groups);
gp_inorder = inorder[gp];
gp_base = base[gp];
gp_limit = limit[gp];
@ -1682,6 +1823,10 @@ xd3_decode_huff (xd3_stream *stream,
}
}
IF_REGRESSION (if ((ret = xd3_test_clean_bits (stream, & bstate)))
{ goto fail; });
XD3_ASSERT (ret == 0);
fail:
xd3_free (stream, sel_group);

View File

@ -204,8 +204,12 @@ static int fgk_init (xd3_stream *stream, fgk_stream *h, int is_encode)
fgk_factor_remaining(h); /* set ZFE and ZFR */
fgk_factor_remaining(h); /* set ZFDB according to prev state */
IF_DEBUG (memset (h->alphabet, 0, sizeof (h->alphabet[0]) * h->total_nodes));
for (ui = 0; ui < h->total_blocks-1; ui += 1)
{
h->block_array[ui].block_freeptr = &h->block_array[ui + 1];
}
h->block_array[h->total_blocks - 1].block_freeptr = NULL;
h->free_block = h->block_array;
@ -234,6 +238,8 @@ static usize_t fgk_encode_data (fgk_stream* h, usize_t n)
{
fgk_node *target_ptr = h->alphabet + n;
XD3_ASSERT (n < h->alphabet_size);
h->coded_depth = 0;
/* First encode the binary representation of the nth remaining
@ -290,6 +296,8 @@ static usize_t fgk_encode_data (fgk_stream* h, usize_t n)
*/
static INLINE fgk_bit fgk_get_encoded_bit (fgk_stream *h)
{
XD3_ASSERT (h->coded_depth > 0);
return h->coded_bits[--h->coded_depth];
}
@ -412,6 +420,9 @@ static void fgk_promote (fgk_stream *h, fgk_node *node)
node->left_child &&
node->left_child->weight == 0)
{
XD3_ASSERT (node->left_child == h->remaining_zeros);
XD3_ASSERT (node->right_child->weight == (node->weight+1)); /* child weight was already incremented */
if (node->weight == (my_right->weight - 1) && my_right != h->root_node)
{
fgk_free_block (h, cur_block);
@ -613,6 +624,8 @@ static fgk_block* fgk_make_block (fgk_stream *h, fgk_node* lead)
{
fgk_block *ret = h->free_block;
XD3_ASSERT (h->free_block != NULL);
h->free_block = h->free_block->block_freeptr;
ret->block_leader = lead;
@ -652,6 +665,8 @@ static void fgk_factor_remaining (fgk_stream *h)
*/
static INLINE int fgk_decode_bit (fgk_stream* h, fgk_bit b)
{
XD3_ASSERT (b == 1 || b == 0);
if (IS_ADAPTIVE && h->decode_ptr->weight == 0)
{
usize_t bitsreq;
@ -827,6 +842,13 @@ xd3_decode_fgk (xd3_stream *stream,
if (output == output_max)
{
/* During regression testing: */
IF_REGRESSION ({
int ret;
bstate.cur_mask <<= 1;
if ((ret = xd3_test_clean_bits (stream, & bstate))) { return ret; }
});
(*output_pos) = output;
(*input_pos) = input;
return 0;

View File

@ -20,6 +20,19 @@
#include "retro_inline.h"
#include "xdelta3-internal.h"
#if XD3_DEBUG
#define SMALL_HASH_DEBUG1(s,inp) \
uint32_t debug_state; \
uint32_t debug_hval = xd3_checksum_hash (& (s)->small_hash, \
xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look))
#define SMALL_HASH_DEBUG2(s,inp) \
XD3_ASSERT (debug_hval == xd3_checksum_hash (& (s)->small_hash, \
xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look)))
#else
#define SMALL_HASH_DEBUG1(s,inp)
#define SMALL_HASH_DEBUG2(s,inp)
#endif /* XD3_DEBUG */
#if UNALIGNED_OK
#define UNALIGNED_READ32(dest,src) (*(dest)) = (*(uint32_t*)(src))
#else

View File

@ -20,6 +20,31 @@
#include "retro_inline.h"
#include "xdelta3.h"
typedef struct _main_file main_file;
typedef struct _main_extcomp main_extcomp;
void main_buffree (void *ptr);
void* main_bufalloc (size_t size);
void main_file_init (main_file *xfile);
int main_file_close (main_file *xfile);
void main_file_cleanup (main_file *xfile);
int main_file_isopen (main_file *xfile);
int main_file_open (main_file *xfile, const char* name, int mode);
int main_file_exists (main_file *xfile);
int main_file_stat (main_file *xfile, xoff_t *size);
int xd3_whole_append_window (xd3_stream *stream);
int xd3_main_cmdline (int argc, char **argv);
int main_file_read (main_file *ifile,
uint8_t *buf,
size_t size,
size_t *nread,
const char *msg);
int main_file_write (main_file *ofile, uint8_t *buf,
usize_t size, const char *msg);
void* main_malloc (size_t size);
void main_free (void *ptr);
int test_compare_files (const char* f0, const char* f1);
usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno);
xoff_t xd3_source_eof(const xd3_source *src);
@ -39,6 +64,7 @@ xd3_output* xd3_alloc_output (xd3_stream *stream,
int xd3_encode_init_full (xd3_stream *stream);
usize_t xd3_pow2_roundup (usize_t x);
long get_millisecs_now (void);
int xd3_process_stream (int is_encode,
xd3_stream *stream,
int (*func) (xd3_stream *),
@ -49,6 +75,67 @@ int xd3_process_stream (int is_encode,
usize_t *output_size,
usize_t output_size_max);
#if PYTHON_MODULE || SWIG_MODULE || NOT_MAIN
int xd3_main_cmdline (int argc, char **argv);
#endif
#if REGRESSION_TEST
int xd3_selftest (void);
#endif
/* main_file->mode values */
typedef enum
{
XO_READ = 0,
XO_WRITE = 1
} main_file_modes;
#ifndef XD3_POSIX
#define XD3_POSIX 0
#endif
#ifndef XD3_STDIO
#define XD3_STDIO 0
#endif
#ifndef XD3_WIN32
#define XD3_WIN32 0
#endif
#ifndef NOT_MAIN
#define NOT_MAIN 0
#endif
/* If none are set, default to posix. */
#if (XD3_POSIX + XD3_STDIO + XD3_WIN32) == 0
#undef XD3_POSIX
#define XD3_POSIX 1
#endif
struct _main_file
{
#if XD3_WIN32
HANDLE file;
#elif XD3_STDIO
FILE *file;
#elif XD3_POSIX
int file;
#endif
int mode; /* XO_READ and XO_WRITE */
const char *filename; /* File name or /dev/stdin,
* /dev/stdout, /dev/stderr. */
char *filename_copy; /* File name or /dev/stdin,
* /dev/stdout, /dev/stderr. */
const char *realname; /* File name or /dev/stdin,
* /dev/stdout, /dev/stderr. */
const main_extcomp *compressor; /* External compression struct. */
int flags; /* RD_FIRST, RD_NONEXTERNAL, ... */
xoff_t nread; /* for input position */
xoff_t nwrite; /* for output position */
uint8_t *snprintf_buf; /* internal snprintf() use */
int size_known; /* Set by main_set_souze */
xoff_t source_position; /* for avoiding seek in getblk_func */
int seek_failed; /* after seek fails once, try FIFO */
};
#ifndef UINT32_MAX
#define UINT32_MAX 4294967295U
#endif

View File

@ -65,10 +65,32 @@ static INLINE int xd3_decode_bits (xd3_stream *stream,
done:
IF_DEBUG2 (DP(RINT "(d) %"W"u ", value));
(*valuep) = value;
return 0;
}
#if REGRESSION_TEST
/* There may be extra bits at the end of secondary decompression, this macro
* checks for non-zero bits. This is overly strict, but helps pass the
* single-bit-error regression test. */
static int
xd3_test_clean_bits (xd3_stream *stream, bit_state *bits)
{
for (; bits->cur_mask != 0x100; bits->cur_mask <<= 1)
{
if (bits->cur_byte & bits->cur_mask)
{
stream->msg = "secondary decoder garbage";
return XD3_INTERNAL;
}
}
return 0;
}
#endif
static int
xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp,
int is_encode)
@ -198,15 +220,23 @@ static INLINE int xd3_encode_bits (xd3_stream *stream,
int ret;
usize_t mask = 1 << nbits;
XD3_ASSERT (nbits > 0);
XD3_ASSERT (nbits < sizeof (usize_t) * 8);
XD3_ASSERT (value < mask);
do
{
mask >>= 1;
if ((ret = xd3_encode_bit (stream, output, bits, value & mask)))
{
return ret;
}
}
while (mask != 1);
IF_DEBUG2 (DP(RINT "(e) %"W"u ", value));
return 0;
}
@ -260,8 +290,18 @@ xd3_encode_secondary (xd3_stream *stream,
comp_size += tmp_tail->next;
}
XD3_ASSERT (comp_size == xd3_sizeof_output (tmp_head));
XD3_ASSERT (tmp_tail != NULL);
if (comp_size < (orig_size - SECONDARY_MIN_SAVINGS) || cfg->inefficient)
{
if (comp_size < orig_size)
{
IF_DEBUG1(DP(RINT "[encode_secondary] saved %"W"u bytes: %"W"u -> %"W"u (%0.2f%%)\n",
orig_size - comp_size, orig_size, comp_size,
100.0 * (double) comp_size / (double) orig_size));
}
xd3_free_output (stream, *head);
*head = tmp_head;

500
deps/xdelta3/xdelta3.c vendored

File diff suppressed because it is too large Load Diff

184
deps/xdelta3/xdelta3.h vendored
View File

@ -22,11 +22,21 @@
#ifndef _XDELTA3_H_
#define _XDELTA3_H_
#define _POSIX_SOURCE 200112L
#define _ISOC99_SOURCE
#define _C99_SOURCE
/* To include RetroArch's INLINE macro */
#include <retro_inline.h>
#include "retro_inline.h"
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@ -106,9 +116,46 @@
#ifndef _WIN32
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif /* _WIN32 defined */
#include <stdint.h>
#else /* WIN32 case */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef WINVER
#if XD3_USE_LARGEFILE64
/* 64 bit file offsets: uses GetFileSizeEx and SetFilePointerEx. */
#define WINVER 0x0500
#define _WIN32_WINNT 0x0500
#else /* xoff_t is 32bit */
/* 32 bit file offsets: uses GetFileSize and SetFilePointer. */
#define WINVER 0x0400
#define _WIN32_WINNT 0x0400
#endif /* if XD3_USE_LARGEFILE64 */
#endif /* ifndef WINVER */
#include <windows.h>
/* _MSV_VER is defined by Microsoft tools, not by Mingw32 */
#ifdef _MSC_VER
typedef signed int ssize_t;
typedef int pid_t;
#if _MSC_VER < 1600
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef ULONGLONG uint64_t;
#else /* _MSC_VER >= 1600 */
/* For MSVC10 and above */
#include <stdint.h>
#define inline __inline
#endif /* _MSC_VER < 1600 */
#else /* _MSC_VER not defined */
/* Mingw32 */
#include <stdint.h>
#endif /* _MSC_VER defined */
#endif /* _WIN32 defined */
#if SIZE_MAX == UINT64_MAX
#define SIZEOF_SIZE_T 8
@ -149,6 +196,12 @@
#define _FILE_OFFSET_BITS 64
#endif
_Static_assert(SIZEOF_SIZE_T == sizeof(size_t), "SIZEOF_SIZE_T not correctly set");
#ifdef SIZEOF_UNSIGNED_LONG_LONG
_Static_assert(SIZEOF_UNSIGNED_LONG_LONG == sizeof(unsigned long long), "SIZEOF_UNSIGNED_LONG_LONG not correctly set");
#endif
/* Set a xoff_t typedef and the "Q" printf insert. */
#if defined(_WIN32)
typedef uint64_t xoff_t;
@ -229,8 +282,10 @@ typedef uint32_t usize_t;
#error Bad configure script
#endif /* size_t printf flags */
#define USE_UINT32 (SIZEOF_USIZE_T == 4 || SIZEOF_XOFF_T == 4 )
#define USE_UINT64 (SIZEOF_USIZE_T == 8 || SIZEOF_XOFF_T == 8 )
#define USE_UINT32 (SIZEOF_USIZE_T == 4 || \
SIZEOF_XOFF_T == 4 || REGRESSION_TEST)
#define USE_UINT64 (SIZEOF_USIZE_T == 8 || \
SIZEOF_XOFF_T == 8 || REGRESSION_TEST)
#ifndef UNALIGNED_OK
#ifdef HAVE_ALIGNED_ACCESS_REQUIRED
@ -248,6 +303,37 @@ typedef uint32_t usize_t;
#define XD3_ENCODER 1
#endif
/* The code returned when main() fails, also defined in system
includes. */
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
/* REGRESSION TEST enables the "xdelta3 test" command, which runs a
series of self-tests. */
#ifndef REGRESSION_TEST
#define REGRESSION_TEST 0
#endif
/* XD3_DEBUG=1 enables assertions and various statistics. Levels > 1
* enable some additional output only useful during development and
* debugging. */
#ifndef XD3_DEBUG
#define XD3_DEBUG 0
#endif
#ifndef PYTHON_MODULE
#define PYTHON_MODULE 0
#endif
#ifndef SWIG_MODULE
#define SWIG_MODULE 0
#endif
#ifndef NOT_MAIN
#define NOT_MAIN 0
#endif
/* There are three string matching functions supplied: one fast, one
* slow (default), and one soft-configurable. To disable any of
* these, use the following definitions. */
@ -270,6 +356,10 @@ typedef uint32_t usize_t;
#define XD3_BUILD_DEFAULT 1
#endif
#if XD3_DEBUG
#include <stdio.h>
#endif
typedef struct _xd3_stream xd3_stream;
typedef struct _xd3_source xd3_source;
typedef struct _xd3_hash_cfg xd3_hash_cfg;
@ -310,6 +400,52 @@ typedef int (xd3_getblk_func) (xd3_stream *stream,
typedef const xd3_dinst* (xd3_code_table_func) (void);
#ifdef _WIN32
#define vsnprintf_func _vsnprintf
#define snprintf_func _snprintf
#else
#define vsnprintf_func vsnprintf
#define snprintf_func snprintf
#endif
/* Type used for short snprintf calls. */
typedef struct {
char buf[48];
} shortbuf;
#ifndef PRINTF_ATTRIBUTE
#ifdef __GNUC__
#define PRINTF_ATTRIBUTE(x,y) __attribute__ ((__format__ (__printf__, x, y)))
#else
#define PRINTF_ATTRIBUTE(x,y)
#endif
#endif
/* Underlying xprintf() */
int xsnprintf_func (char *str, size_t n, const char *fmt, ...)
PRINTF_ATTRIBUTE(3,4);
/* XPR(NT "", ...) (used by main) prefixes an "xdelta3: " to the output. */
void xprintf(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
#define XPR xprintf
#define NT "xdelta3: "
#define NTR ""
/* DP(RINT ...) */
#define DP xprintf
#define RINT ""
#if XD3_DEBUG
#define XD3_ASSERT(x) \
do { \
if (! (x)) { \
DP(RINT "%s:%d: XD3 assertion failed: %s\n", \
__FILE__, __LINE__, #x); \
abort (); } } while (0)
#else
#define XD3_ASSERT(x) (void)0
#endif /* XD3_DEBUG */
#define xd3_max(x,y) ((x) < (y) ? (y) : (x))
#define xd3_min(x,y) ((x) < (y) ? (x) : (y))
@ -990,6 +1126,14 @@ struct _xd3_stream
xoff_t l_run;
usize_t i_slots_used;
#if XD3_DEBUG
usize_t large_ckcnt;
/* memory usage */
usize_t alloc_cnt;
usize_t free_cnt;
#endif
};
/**************************************************************************
@ -1244,6 +1388,14 @@ void xd3_avail_input (xd3_stream *stream,
const uint8_t *idata,
usize_t isize)
{
/* Even if isize is zero, the code expects a non-NULL idata. Why?
* It uses this value to determine whether xd3_avail_input has ever
* been called. If xd3_encode_input is called before
* xd3_avail_input it will return XD3_INPUT right away without
* allocating a stream->winsize buffer. This is to avoid an
* unwanted allocation. */
XD3_ASSERT (idata != NULL || isize == 0);
stream->next_in = idata;
stream->avail_in = isize;
}
@ -1274,6 +1426,9 @@ usize_t xd3_encoder_srclen (xd3_stream *stream) {
static INLINE
void xd3_set_flags (xd3_stream *stream, uint32_t flags)
{
/* The bitwise difference should contain only XD3_FLUSH or
XD3_SKIP_WINDOW */
XD3_ASSERT(((flags ^ stream->flags) & ~(XD3_FLUSH | XD3_SKIP_WINDOW)) == 0);
stream->flags = flags;
}
@ -1296,6 +1451,7 @@ void xd3_blksize_div (const xoff_t offset,
usize_t *blkoff) {
*blkno = offset >> source->shiftby;
*blkoff = offset & source->maskby;
XD3_ASSERT (*blkoff < source->blksize);
}
static INLINE
@ -1315,6 +1471,8 @@ void xd3_blksize_add (xoff_t *blkno,
*blkno += blkdiff;
*blkoff &= source->maskby;
}
XD3_ASSERT (*blkoff < source->blksize);
}
#ifdef __cplusplus
@ -1327,6 +1485,22 @@ void xd3_blksize_add (xoff_t *blkno,
#define XD3_CPY 3U /* XD3_CPY rtypes are represented as (XD3_CPY +
* copy-mode value) */
#if XD3_DEBUG
#define IF_DEBUG(x) x
#else
#define IF_DEBUG(x)
#endif
#if XD3_DEBUG > 1
#define IF_DEBUG1(x) x
#else
#define IF_DEBUG1(x)
#endif
#if XD3_DEBUG > 2
#define IF_DEBUG2(x) x
#else
#define IF_DEBUG2(x)
#endif
#define SIZEOF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
#endif /* _XDELTA3_H_ */