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 )