Algorithm-GDiffDelta
view release on metacpan or search on metacpan
GDiffDelta.xs view on Meta::CPAN
SV *ret;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(f);
PUTBACK;
n = call_method("tell", G_SCALAR);
assert(n == 0 || n == 1);
SPAGAIN;
offset = (Off_t) -1;
if (n) {
ret = POPs;
if (SvOK(ret))
offset = SvUV(ret);
}
PUTBACK;
FREETMPS;
LEAVE;
if (offset == (Off_t) -1)
croak("error getting position in %s: %s", from,
SvPV_nolen(get_sv("!", FALSE)));
}
else {
offset = PerlIO_tell(IoIFP(sv_2io(f)));
if (offset == (Off_t) -1)
croak("error getting position in %s: %s", from, strerror(errno));
}
return offset;
}
QEF_INLINE static size_t
read_ubyte (SV *f)
{
unsigned char buf;
careful_fread(&buf, 1, f, "delta");
return buf;
}
QEF_INLINE static size_t
read_ushort (SV *f)
{
unsigned char buf[2];
careful_fread(buf, 2, f, "delta");
return buf[0] * 0x100 + buf[1];
}
QEF_INLINE static size_t
read_int (SV *f)
{
unsigned char buf[4];
careful_fread(buf, 4, f, "delta");
if (buf[0] >= 0x7F)
croak("delta contains negative int value");
return buf[0] * 0x1000000 + buf[1] * 0x10000 +
buf[2] * 0x100 + buf[3];
}
/* The buffer is supplied by the parent so that we can avoid allocating
* it on the stack every time this is called, even though that probably
* wouldn't be very expensive in most implementations. */
static void
copy_data (SV *in, SV *out, size_t num_bytes, unsigned char *buf,
const char *from, const char *to)
{
assert(buf);
while (num_bytes >= QEF_BUFSZ) {
careful_fread(buf, QEF_BUFSZ, in, from);
careful_fwrite(buf, QEF_BUFSZ, out, to);
num_bytes -= QEF_BUFSZ;
}
careful_fread(buf, num_bytes, in, from);
careful_fwrite(buf, num_bytes, out, to);
}
/* Work out the size of the file by seeking to the end. */
static Off_t
file_size (SV *f, const char *from)
{
careful_fseek_whence(f, 0, from, SEEK_END);
return careful_ftell(f, from);
}
/* largest prime smaller than 65536 */
#define QEF_BASE 65521L
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define QEF_NMAX 5552
#define QEF_DO1(buf, i) { s1 += buf[i]; s2 += s1; }
#define QEF_DO2(buf, i) QEF_DO1(buf, i); QEF_DO1(buf, i + 1);
#define QEF_DO4(buf, i) QEF_DO2(buf, i); QEF_DO2(buf, i + 2);
#define QEF_DO8(buf, i) QEF_DO4(buf, i); QEF_DO4(buf, i + 4);
#define QEF_DO16(buf) QEF_DO8(buf, 0); QEF_DO8(buf, 8);
static U32
adler32(U32 adler, const unsigned char *buf, size_t len)
{
int k;
U32 s1 = adler & 0xffff;
U32 s2 = (adler >> 16) & 0xffff;
assert(buf);
while (len > 0) {
k = len < QEF_NMAX ? len : QEF_NMAX;
len -= k;
while (k >= 16) {
QEF_DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0)
do {
s1 += *buf++;
s2 += s1;
( run in 0.775 second using v1.01-cache-2.11-cpan-f0fbb3f571b )