quickerNES/extern/xdelta3/xdelta3-internal.h

373 lines
14 KiB
C

/* xdelta3 - delta compression tools and library
* Copyright (C) 2011, 2012, 2013, 2014, 2015 Joshua P. MacDonald
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef XDELTA3_INTERNAL_H__
#define XDELTA3_INTERNAL_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 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);
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);
uint32_t xd3_large_cksum_update (uint32_t cksum,
const uint8_t *base,
usize_t look);
int xd3_emit_byte (xd3_stream *stream,
xd3_output **outputp,
uint8_t code);
int xd3_emit_bytes (xd3_stream *stream,
xd3_output **outputp,
const uint8_t *base,
usize_t size);
xd3_output* xd3_alloc_output (xd3_stream *stream,
xd3_output *old_output);
int xd3_encode_init_full (xd3_stream *stream);
size_t xd3_pow2_roundup (size_t x);
int xd3_process_stream (int is_encode,
xd3_stream *stream,
int (*func) (xd3_stream *),
int close_stream,
const uint8_t *input,
usize_t input_size,
uint8_t *output,
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
/* 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 */
};
#ifdef _WIN32
#define vsnprintf_func _vsnprintf
#define snprintf_func _snprintf
#else
#define vsnprintf_func vsnprintf
#define snprintf_func snprintf
#endif
#define short_sprintf(sb,fmt,...) \
snprintf_func((sb).buf,sizeof((sb).buf),fmt,__VA_ARGS__)
/* Type used for short snprintf calls. */
typedef struct {
char buf[48];
} shortbuf;
/* Prior to SVN 303 this function was only defined in DJGPP and WIN32
* environments and other platforms would use the builtin snprintf()
* with an arrangement of macros below. In OS X 10.6, Apply made
* snprintf() a macro, which defeated those macros (since snprintf
* would be evaluated before its argument macros were expanded,
* therefore always define xsnprintf_func. */
#undef PRINTF_ATTRIBUTE
#ifdef __GNUC__
/* Let's just assume no one uses gcc 2.x! */
#define PRINTF_ATTRIBUTE(x,y) __attribute__ ((__format__ (__printf__, x, y)))
#else
#define PRINTF_ATTRIBUTE(x,y)
#endif
/* Underlying xprintf() */
int xsnprintf_func (char *str, int 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 ""
#ifndef UINT32_MAX
#define UINT32_MAX 4294967295U
#endif
#ifndef UINT64_MAX
#define UINT64_MAX 18446744073709551615ULL
#endif
#define UINT32_OFLOW_MASK 0xfe000000U
#define UINT64_OFLOW_MASK 0xfe00000000000000ULL
/*********************************************************************
Integer encoder/decoder functions
**********************************************************************/
/* Consume N bytes of input, only used by the decoder. */
#define DECODE_INPUT(n) \
do { \
stream->total_in += (xoff_t) (n); \
stream->avail_in -= (n); \
stream->next_in += (n); \
} while (0)
#define DECODE_INTEGER_TYPE(PART,OFLOW) \
while (stream->avail_in != 0) \
{ \
usize_t next = stream->next_in[0]; \
\
DECODE_INPUT(1); \
\
if (PART & OFLOW) \
{ \
stream->msg = "overflow in decode_integer"; \
return XD3_INVALID_INPUT; \
} \
\
PART = (PART << 7) | (next & 127); \
\
if ((next & 128) == 0) \
{ \
(*val) = PART; \
PART = 0; \
return 0; \
} \
} \
\
stream->msg = "further input required"; \
return XD3_INPUT
#define READ_INTEGER_TYPE(TYPE, OFLOW) \
TYPE val = 0; \
const uint8_t *inp = (*inpp); \
usize_t next; \
\
do \
{ \
if (inp == maxp) \
{ \
stream->msg = "end-of-input in read_integer"; \
return XD3_INVALID_INPUT; \
} \
\
if (val & OFLOW) \
{ \
stream->msg = "overflow in read_intger"; \
return XD3_INVALID_INPUT; \
} \
\
next = (*inp++); \
val = (val << 7) | (next & 127); \
} \
while (next & 128); \
\
(*valp) = val; \
(*inpp) = inp; \
\
return 0
#define EMIT_INTEGER_TYPE() \
/* max 64-bit value in base-7 encoding is 9.1 bytes */ \
uint8_t buf[10]; \
usize_t bufi = 10; \
\
/* This loop performs division and turns on all MSBs. */ \
do \
{ \
buf[--bufi] = (num & 127) | 128; \
num >>= 7U; \
} \
while (num != 0); \
\
/* Turn off MSB of the last byte. */ \
buf[9] &= 127; \
\
return xd3_emit_bytes (stream, output, buf + bufi, 10 - bufi)
#define IF_SIZEOF32(x) if (num < (1U << (7 * (x)))) return (x);
#define IF_SIZEOF64(x) if (num < (1ULL << (7 * (x)))) return (x);
#if USE_UINT32
static inline uint32_t
xd3_sizeof_uint32_t (uint32_t num)
{
IF_SIZEOF32(1);
IF_SIZEOF32(2);
IF_SIZEOF32(3);
IF_SIZEOF32(4);
return 5;
}
static inline int
xd3_decode_uint32_t (xd3_stream *stream, uint32_t *val)
{ DECODE_INTEGER_TYPE (stream->dec_32part, UINT32_OFLOW_MASK); }
static inline int
xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp,
const uint8_t *maxp, uint32_t *valp)
{ READ_INTEGER_TYPE (uint32_t, UINT32_OFLOW_MASK); }
#if XD3_ENCODER
static inline int
xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, uint32_t num)
{ EMIT_INTEGER_TYPE (); }
#endif
#endif
#if USE_UINT64
static inline int
xd3_decode_uint64_t (xd3_stream *stream, uint64_t *val)
{ DECODE_INTEGER_TYPE (stream->dec_64part, UINT64_OFLOW_MASK); }
#if XD3_ENCODER
static inline int
xd3_emit_uint64_t (xd3_stream *stream, xd3_output **output, uint64_t num)
{ EMIT_INTEGER_TYPE (); }
#endif
/* These are tested but not used */
#if REGRESSION_TEST
static int
xd3_read_uint64_t (xd3_stream *stream, const uint8_t **inpp,
const uint8_t *maxp, uint64_t *valp)
{ READ_INTEGER_TYPE (uint64_t, UINT64_OFLOW_MASK); }
static uint32_t
xd3_sizeof_uint64_t (uint64_t num)
{
IF_SIZEOF64(1);
IF_SIZEOF64(2);
IF_SIZEOF64(3);
IF_SIZEOF64(4);
IF_SIZEOF64(5);
IF_SIZEOF64(6);
IF_SIZEOF64(7);
IF_SIZEOF64(8);
IF_SIZEOF64(9);
return 10;
}
#endif
#endif
#if SIZEOF_USIZE_T == 4
#define USIZE_T_MAX UINT32_MAX
#define USIZE_T_MAXBLKSZ 0x80000000U
#define xd3_decode_size xd3_decode_uint32_t
#define xd3_emit_size xd3_emit_uint32_t
#define xd3_sizeof_size xd3_sizeof_uint32_t
#define xd3_read_size xd3_read_uint32_t
#elif SIZEOF_USIZE_T == 8
#define USIZE_T_MAX UINT64_MAX
#define USIZE_T_MAXBLKSZ 0x8000000000000000ULL
#define xd3_decode_size xd3_decode_uint64_t
#define xd3_emit_size xd3_emit_uint64_t
#define xd3_sizeof_size xd3_sizeof_uint64_t
#define xd3_read_size xd3_read_uint64_t
#endif
#if SIZEOF_XOFF_T == 4
#define XOFF_T_MAX UINT32_MAX
#define xd3_emit_offset xd3_emit_uint32_t
static inline int
xd3_decode_offset (xd3_stream *stream, xoff_t *val)
{
return xd3_decode_uint32_t (stream, (uint32_t*) val);
}
#elif SIZEOF_XOFF_T == 8
#define XOFF_T_MAX UINT64_MAX
#define xd3_emit_offset xd3_emit_uint64_t
static inline int
xd3_decode_offset (xd3_stream *stream, xoff_t *val)
{
return xd3_decode_uint64_t (stream, (uint64_t*) val);
}
#endif
#define USIZE_T_OVERFLOW(a,b) ((USIZE_T_MAX - (usize_t) (a)) < (usize_t) (b))
#define XOFF_T_OVERFLOW(a,b) ((XOFF_T_MAX - (xoff_t) (a)) < (xoff_t) (b))
#define MAX_LRU_SIZE 32U
#define XD3_MINSRCWINSZ (XD3_ALLOCSIZE * MAX_LRU_SIZE)
#define XD3_MAXSRCWINSZ (1ULL << 31)
#endif // XDELTA3_INTERNAL_H__