Algorithm-GDiffDelta
view release on metacpan or search on metacpan
GDiffDelta.xs view on Meta::CPAN
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(f);
/* TODO - possibly use newSVpvn_share to avoid the memcpy
* and extra allocation for buf? */
XPUSHs(sv_2mortal(buf = newSVpvn("", 0)));
XPUSHs(sv_2mortal(newSVuv(size)));
PUTBACK;
n = call_method("read", G_SCALAR);
assert(n == 0 || n == 1);
SPAGAIN;
ret = n ? POPs : &PL_sv_undef;
if (!SvOK(ret))
croak("error reading from %s: %s", from,
SvPV_nolen(get_sv("!", FALSE)));
if (SvUV(ret) != size)
croak("%s ends unexpectedly", from);
if (!SvPOK(buf) || SvCUR(buf) != size)
croak("'read' method left buffer badly set up", from);
str = SvPV(buf, len);
assert(len == size);
memcpy(ptr, str, size);
PUTBACK;
FREETMPS;
LEAVE;
}
else {
int r = PerlIO_read(IoIFP(sv_2io(f)), ptr, size);
if (r < 0)
croak("error reading from %s: %s", from, strerror(errno));
else if ((size_t) r != size)
croak("%s ends unexpectedly", from);
}
GDiffDelta.xs view on Meta::CPAN
#endif
if (sv_isobject(f)) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(f);
XPUSHs(sv_2mortal(newSVpvn(ptr, size)));
XPUSHs(sv_2mortal(newSVuv(size)));
PUTBACK;
n = call_method("write", G_SCALAR);
assert(n == 0 || n == 1);
SPAGAIN;
ret = n ? POPs : &PL_sv_no;
n = SvTRUE(ret);
PUTBACK;
FREETMPS;
LEAVE;
if (!n)
croak("error writing to %s: %s", to,
SvPV_nolen(get_sv("!", FALSE)));
}
else {
if ((size_t) PerlIO_write(IoIFP(sv_2io(f)), ptr, size) != size)
croak("error writing to %s: %s", to, strerror(errno));
}
GDiffDelta.xs view on Meta::CPAN
I32 n;
SV *ret;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(f);
XPUSHs(sv_2mortal(newSVuv(offset)));
XPUSHs(sv_2mortal(newSVuv(whence)));
PUTBACK;
n = call_method("seek", G_SCALAR);
assert(n == 0 || n == 1);
SPAGAIN;
ret = n ? POPs : &PL_sv_undef;
n = SvTRUE(ret);
PUTBACK;
FREETMPS;
LEAVE;
if (!n)
croak("error seeking in %s: %s", from,
SvPV_nolen(get_sv("!", FALSE)));
}
else {
if (PerlIO_seek(IoIFP(sv_2io(f)), offset, whence))
croak("error seeking in %s: %s", from, strerror(errno));
}
GDiffDelta.xs view on Meta::CPAN
if (sv_isobject(f)) {
I32 n;
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));
GDiffDelta.xs view on Meta::CPAN
size_t headsz = 0;
assert(size > 0);
assert(size <= QEF_INT_MAX);
assert(buf);
if (size <= 246)
buf[headsz++] = size;
else if (size <= QEF_USHORT_MAX) {
buf[headsz++] = 247;
QEF_BE16_PUT(buf, headsz, size);
}
else {
buf[headsz++] = 248;
QEF_BE32_PUT(buf, headsz, size);
}
/* Write the opcode and size argument (if any). */
careful_fwrite(buf, headsz, delta, "delta");
/* Copy the actual data to be inserted into the delta. */
careful_fseek(changed, offset, "changed file");
copy_data(changed, delta, size, buf, "changed file", "delta");
}
GDiffDelta.xs view on Meta::CPAN
copy_op (SV *delta, Off_t offset, Off_t size)
{
unsigned char buf[QEF_COPY_MAX];
size_t headsz = 0;
assert(size > 0);
if (offset <= QEF_USHORT_MAX) {
if (size <= QEF_UBYTE_MAX) {
buf[headsz++] = 249;
QEF_BE16_PUT(buf, headsz, offset);
buf[headsz++] = size;
}
else if (size <= QEF_USHORT_MAX) {
buf[headsz++] = 250;
QEF_BE16_PUT(buf, headsz, offset);
QEF_BE16_PUT(buf, headsz, size);
}
else if (size <= QEF_INT_MAX) {
buf[headsz++] = 251;
QEF_BE16_PUT(buf, headsz, offset);
QEF_BE32_PUT(buf, headsz, size);
}
else {
/* TODO - break copy ops for bigger than 2Gb into smaller ones */
assert(0);
}
}
else if (offset <= QEF_INT_MAX) {
if (size <= QEF_UBYTE_MAX) {
buf[headsz++] = 252;
QEF_BE32_PUT(buf, headsz, offset);
buf[headsz++] = size;
}
else if (size <= QEF_USHORT_MAX) {
buf[headsz++] = 253;
QEF_BE32_PUT(buf, headsz, offset);
QEF_BE16_PUT(buf, headsz, size);
}
else if (size <= QEF_INT_MAX) {
buf[headsz++] = 254;
QEF_BE32_PUT(buf, headsz, offset);
QEF_BE32_PUT(buf, headsz, size);
}
else {
/* TODO - break copy ops for bigger than 2Gb into smaller ones */
assert(0);
}
}
else {
/* TODO - allow 64bit offsets */
assert(0);
}
GDiffDelta.xs view on Meta::CPAN
U32
qefgdiff_gdiff_adler32 (U32 init, SV *s)
PREINIT:
STRLEN len;
const unsigned char *buf;
CODE:
buf = (unsigned char *) SvPV(s, len);
RETVAL = adler32(init, buf, len);
OUTPUT:
RETVAL
void
qefgdiff_gdiff_delta (SV *orig, SV *changed, SV *delta)
CODE:
careful_fwrite("\xD1\xFF\xD1\xFF\x04", 5, delta, "delta");
do_delta(orig, changed, delta);
careful_fwrite("\0", 1, delta, "delta");
#define QEF_UBYTE_MAX 0xFFUL
/* Maximum value of a GDIFF ushort (unsigned 16 bit value). */
#define QEF_USHORT_MAX 0xFFFFUL
/* Maximum value of a GDIFF int (signed 32 bit value). */
#define QEF_INT_MAX 0x7FFFFFFFUL
/* Copy a number into a buffer in big-endian format, using a counter as an
* index into the buffer and moving it along the right number of bytes. */
#define QEF_BE16_PUT(buf, idx, num) \
do { \
buf[idx++] = ((num) >> 8) & 0xFF; \
buf[idx++] = (num) & 0xFF; \
} while (0)
#define QEF_BE32_PUT(buf, idx, num) \
do { \
buf[idx++] = ((num) >> 24) & 0xFF; \
buf[idx++] = ((num) >> 16) & 0xFF; \
buf[idx++] = ((num) >> 8) & 0xFF; \
buf[idx++] = (num) & 0xFF; \
} while (0)
/* Data structures for the hashes of the original file. */
struct QefChaNode {
( run in 0.489 second using v1.01-cache-2.11-cpan-d6f9594c0a5 )