Algorithm-GDiffDelta
view release on metacpan or search on metacpan
GDiffDelta.xs view on Meta::CPAN
chunk_sz = QEF_MIN(QEF_BUFSZ, size);
careful_fread(buf, chunk_sz, f, from);
adler = adler32(adler, buf, chunk_sz);
size -= chunk_sz;
}
return adler;
}
static void
prepare_bdfile (SV *orig, Off_t orig_size, QefBDFile *bdf)
{
unsigned int fphbits;
Off_t hsize, offset;
U32 i;
QefBDRecord *brec;
QefBDRecord **fphash;
fphbits = hashbits(orig_size / QEF_BLK_SIZE + 1);
hsize = (Off_t) 1 << fphbits;
New(0, fphash, hsize, QefBDRecord *);
for (i = 0; i < hsize; ++i)
fphash[i] = 0;
qef_cha_init(&bdf->cha, sizeof(QefBDRecord), hsize / 4 + 1);
if (orig_size == 0)
bdf->size = 0;
else {
offset = 0;
bdf->size = orig_size;
/* Start by looking at the last (possibly incomplete) block */
if ((offset = (orig_size / QEF_BLK_SIZE) * QEF_BLK_SIZE) == orig_size)
offset -= QEF_BLK_SIZE;
while (1) {
brec = qef_cha_alloc(&bdf->cha);
brec->fp = adler32_file(orig, 0, offset,
QEF_MIN(QEF_BLK_SIZE, orig_size - offset),
"original");
brec->offset = offset;
i = QEF_HASHLONG(brec->fp, fphbits);
brec->next = fphash[i];
fphash[i] = brec;
if (offset < QEF_BLK_SIZE)
break;
offset -= QEF_BLK_SIZE;
}
assert(offset == 0);
}
bdf->fphbits = fphbits;
bdf->fphash = fphash;
}
/* Output a GDIFF DATA operation. */
static void
data_op (SV *changed, SV *delta, Off_t offset, Off_t size, unsigned char *buf)
{
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");
}
/* Output a GDIFF COPY operation. */
static void
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) {
( run in 0.851 second using v1.01-cache-2.11-cpan-140bd7fdf52 )