Algorithm-GDiffDelta

 view release on metacpan or  search on metacpan

GDiffDelta.pm  view on Meta::CPAN

=head1 SYNOPSIS

    use Algorithm::GDiffDelta qw(
        gdiff_adler32 gdiff_delta gdiff_apply
    );

    # Pass in two file handles for reading from and one to
    # writing the GDIFF binary delta to:
    gdiff_delta($orig, $changed, $delta);

    # Pass in file handles of original file and GDIFF delta
    # to read from, and file to write reconstructed changed
    # file to:
    gdiff_apply($orig, $delta, $changed);

    # A fast adler32 digest implementation is also available:
    my $adler32 = gdiff_adler32(1, 'some data');
    $adler32 = gdiff_adler32($adler32, 'some more data');

=head1 DESCRIPTION

GDiffDelta.xs  view on Meta::CPAN


        /* 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;
        }

GDiffDelta.xs  view on Meta::CPAN

    QefBDFile bdf;
    QefBDRecord *brec;
    unsigned char insbuf[QEF_BUFSZ], buf1[QEF_BUFSZ], buf2[QEF_BUFSZ];
    size_t pos, sz1, sz2, minsz;
    Off_t ins_offset, ins_size;
    int stop;

    changed_size = file_size(changed, "changed file");
    if (changed_size == 0)
        return;
    orig_size = file_size(orig, "original");

    prepare_bdfile(orig, orig_size, &bdf);

    ins_size = 0;
    changed_offset = 0;
    while (changed_offset < changed_size) {
        rsize = QEF_MIN(QEF_BLK_SIZE, changed_size - changed_offset);
        fp = adler32_file(changed, 0, changed_offset, rsize, "changed file");

        brec = bdf.fphash[QEF_HASHLONG(fp, bdf.fphbits)];

GDiffDelta.xs  view on Meta::CPAN

                newmsize = 0;
                newmoff = off1;
                stop = 0;
                while (!stop) {
                    sz1 = QEF_MIN(QEF_BUFSZ, orig_size - off1);
                    sz2 = QEF_MIN(QEF_BUFSZ, changed_size - off2);
                    minsz = QEF_MIN(sz1, sz2);
                    if (minsz == 0)
                        break;
                    /* TODO - is there a better way to buffer these? */
                    careful_fseek(orig, off1, "original");
                    careful_fread(buf1, minsz, orig, "original");
                    careful_fseek(changed, off2, "changed file");
                    careful_fread(buf2, minsz, changed, "changed file");
                    for (pos = 0; pos < minsz; ++pos) {
                        if (buf1[pos] != buf2[pos]) {
                            stop = 1;
                            break;
                        }
                    }
                    newmsize += pos;
                    off1 += minsz;

GDiffDelta.xs  view on Meta::CPAN

                        s = read_ushort(delta);
                        copy_data(delta, output, s, buf, "delta", "output");
                        break;
                    case 248: /* int, <n> bytes - append <n> data bytes */
                        s = read_int(delta);
                        copy_data(delta, output, s, buf, "delta", "output");
                        break;
                    case 249: /* ushort, ubyte - copy <position>, <length> */
                        r = read_ushort(delta);
                        s = read_ubyte(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 250: /* ushort, ushort - copy <position>, <length> */
                        r = read_ushort(delta);
                        s = read_ushort(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 251: /* ushort, int - copy <position>, <length> */
                        r = read_ushort(delta);
                        s = read_int(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 252: /* int, ubyte - copy <position>, <length> */
                        r = read_int(delta);
                        s = read_ubyte(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 253: /* int, ushort - copy <position>, <length> */
                        r = read_int(delta);
                        s = read_ushort(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 254: /* int, int - copy <position>, <length> */
                        r = read_int(delta);
                        s = read_int(delta);
                        careful_fseek(orig, r, "original");
                        copy_data(orig, output, s, buf, "original", "output");
                        break;
                    case 255: /* long, int - copy <position>, <length> */
                        /* TODO - 64 seeking */
                        assert(0);
                        break;
                    default: assert(0);
                }
            }
        }

t/20apply.t  view on Meta::CPAN

my $orig_bak = $orig;
my $new = 'ABXYCDBCDE';
my $delta = "\xD1\xFF\xD1\xFF\x04" .
            "\xF9\0\0\x02\x02XY\xF9\0\x02\x02\xF9\0\x01\x04\0";
my $delta_bak = $delta;
my $ios_orig_file = IO::Scalar->new(\$orig);
my $ios_delta_file = IO::Scalar->new(\$delta);
my $ios_new_file = IO::Scalar->new;
gdiff_apply($ios_orig_file, $ios_delta_file, $ios_new_file);
is("$ios_orig_file", $orig_bak,
   'make sure original data in IO::Scalar still OK');
is("$ios_delta_file", $delta_bak,
   'make sure delta in IO::Scalar still OK');
is("$ios_new_file", $new, 'apply example delta using IO::Scalar');

# Now test with real files, using sample data in 't/data'.
for (1 .. 2) {
    my $orig_filename = catfile($data_dir, "$_.orig");
    my $delta_filename = catfile($data_dir, "$_.gdiff");
    my $new_filename = catfile($data_dir, "$_.new");

t/30delta.t  view on Meta::CPAN

# Test generating deltas of predefined files.  Make sure that the output can
# be applied to the original file to get the changed one (i.e., that it is
# a correct delta) and also that the delta is as small as I'd expect.

use strict;
use warnings;
use Test::More tests => 6 + 2 * 3;
use IO::Scalar;
use Algorithm::GDiffDelta qw( gdiff_delta gdiff_apply );
use File::Spec::Functions;
use File::Temp qw( tmpnam );

t/30delta.t  view on Meta::CPAN

my $orig_bak = $orig;
my $new = 'ABXYCDBCDE';
my $new_bak = $new;
my $delta = "\xD1\xFF\xD1\xFF\x04" .
            "\xF9\0\0\x02\x02XY\xF9\0\x02\x02\xF9\0\x01\x04\0";
my $ios_orig_file = IO::Scalar->new(\$orig);
my $ios_new_file = IO::Scalar->new(\$new);
my $ios_delta_file = IO::Scalar->new;
gdiff_delta($ios_orig_file, $ios_new_file, $ios_delta_file);
is("$ios_orig_file", $orig_bak,
   'make sure original data in IO::Scalar still OK');
is("$ios_new_file", $new_bak,
   'make sure new data in IO::Scalar still OK');
is(length "$ios_delta_file", 17,
   'check delta produced with IO::Scalar is right length');
like("$ios_delta_file", qr/^\xD1\xFF\xD1\xFF\x04/, 'GDIFF header is right');
like("$ios_delta_file", qr/\x00\z/, 'GDIFF delta ends in EOF opcode');
$ios_orig_file = IO::Scalar->new(\$orig);
$ios_delta_file = IO::Scalar->new(\"$ios_delta_file");
$ios_new_file = IO::Scalar->new;
gdiff_apply($ios_orig_file, $ios_delta_file, $ios_new_file);

util.h  view on Meta::CPAN

    } 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 {
    struct QefChaNode *next;
    long icurr;
};
typedef struct QefChaNode QefChaNode;

struct QefChaStore {
    QefChaNode *head, *tail;
    long isize, nsize;
    QefChaNode *ancur;



( run in 0.255 second using v1.01-cache-2.11-cpan-1c8d708658b )