Merge branch 'np/delta'

* np/delta:
  update diff-delta.c copyright
  improve delta long block matching with big files
maint
Junio C Hamano 2007-05-29 00:49:23 -07:00
commit 41ffe5cdf5
1 changed files with 63 additions and 64 deletions

View File

@ -1,21 +1,14 @@
/* /*
* diff-delta.c: generate a delta between two buffers * diff-delta.c: generate a delta between two buffers
* *
* Many parts of this file have been lifted from LibXDiff version 0.10. * This code was greatly inspired by parts of LibXDiff from Davide Libenzi
* http://www.xmailserver.org/xdiff-lib.html * http://www.xmailserver.org/xdiff-lib.html
* *
* LibXDiff was written by Davide Libenzi <davidel@xmailserver.org> * Rewritten for GIT by Nicolas Pitre <nico@cam.org>, (C) 2005-2007
* Copyright (C) 2003 Davide Libenzi
* *
* Many mods for GIT usage by Nicolas Pitre <nico@cam.org>, (C) 2005. * This code is free software; you can redistribute it and/or modify
* * it under the terms of the GNU General Public License version 2 as
* This file is free software; you can redistribute it and/or * published by the Free Software Foundation.
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Use of this within git automatically means that the LGPL
* licensing gets turned into GPLv2 within this project.
*/ */


#include "git-compat-util.h" #include "git-compat-util.h"
@ -246,7 +239,7 @@ create_delta(const struct delta_index *index,
const void *trg_buf, unsigned long trg_size, const void *trg_buf, unsigned long trg_size,
unsigned long *delta_size, unsigned long max_size) unsigned long *delta_size, unsigned long max_size)
{ {
unsigned int i, outpos, outsize, val; unsigned int i, outpos, outsize, moff, msize, val;
int inscnt; int inscnt;
const unsigned char *ref_data, *ref_top, *data, *top; const unsigned char *ref_data, *ref_top, *data, *top;
unsigned char *out; unsigned char *out;
@ -291,30 +284,33 @@ create_delta(const struct delta_index *index,
} }
inscnt = i; inscnt = i;


moff = 0;
msize = 0;
while (data < top) { while (data < top) {
unsigned int moff = 0, msize = 0; if (msize < 4096) {
struct index_entry *entry; struct index_entry *entry;
val ^= U[data[-RABIN_WINDOW]]; val ^= U[data[-RABIN_WINDOW]];
val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT]; val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
i = val & index->hash_mask; i = val & index->hash_mask;
for (entry = index->hash[i]; entry; entry = entry->next) { for (entry = index->hash[i]; entry; entry = entry->next) {
const unsigned char *ref = entry->ptr; const unsigned char *ref = entry->ptr;
const unsigned char *src = data; const unsigned char *src = data;
unsigned int ref_size = ref_top - ref; unsigned int ref_size = ref_top - ref;
if (entry->val != val) if (entry->val != val)
continue; continue;
if (ref_size > top - src) if (ref_size > top - src)
ref_size = top - src; ref_size = top - src;
if (ref_size > 0x10000) if (ref_size <= msize)
ref_size = 0x10000; break;
if (ref_size <= msize) while (ref_size-- && *src++ == *ref)
break; ref++;
while (ref_size-- && *src++ == *ref) if (msize < ref - entry->ptr) {
ref++; /* this is our best match so far */
if (msize < ref - entry->ptr) { msize = ref - entry->ptr;
/* this is our best match so far */ moff = entry->ptr - ref_data;
msize = ref - entry->ptr; if (msize >= 4096) /* good enough */
moff = entry->ptr - ref_data; break;
}
} }
} }


@ -327,27 +323,13 @@ create_delta(const struct delta_index *index,
out[outpos - inscnt - 1] = inscnt; out[outpos - inscnt - 1] = inscnt;
inscnt = 0; inscnt = 0;
} }
msize = 0;
} else { } else {
unsigned int left;
unsigned char *op; unsigned char *op;


if (msize >= RABIN_WINDOW) {
const unsigned char *sk;
sk = data + msize - RABIN_WINDOW;
val = 0;
for (i = 0; i < RABIN_WINDOW; i++)
val = ((val << 8) | *sk++) ^ T[val >> RABIN_SHIFT];
} else {
const unsigned char *sk = data + 1;
for (i = 1; i < msize; i++) {
val ^= U[sk[-RABIN_WINDOW]];
val = ((val << 8) | *sk++) ^ T[val >> RABIN_SHIFT];
}
}

if (inscnt) { if (inscnt) {
while (moff && ref_data[moff-1] == data[-1]) { while (moff && ref_data[moff-1] == data[-1]) {
if (msize == 0x10000)
break;
/* we can match one byte back */ /* we can match one byte back */
msize++; msize++;
moff--; moff--;
@ -363,23 +345,40 @@ create_delta(const struct delta_index *index,
inscnt = 0; inscnt = 0;
} }


data += msize; /* A copy op is currently limited to 64KB (pack v2) */
left = (msize < 0x10000) ? 0 : (msize - 0x10000);
msize -= left;

op = out + outpos++; op = out + outpos++;
i = 0x80; i = 0x80;


if (moff & 0xff) { out[outpos++] = moff; i |= 0x01; } if (moff & 0x000000ff)
moff >>= 8; out[outpos++] = moff >> 0, i |= 0x01;
if (moff & 0xff) { out[outpos++] = moff; i |= 0x02; } if (moff & 0x0000ff00)
moff >>= 8; out[outpos++] = moff >> 8, i |= 0x02;
if (moff & 0xff) { out[outpos++] = moff; i |= 0x04; } if (moff & 0x00ff0000)
moff >>= 8; out[outpos++] = moff >> 16, i |= 0x04;
if (moff & 0xff) { out[outpos++] = moff; i |= 0x08; } if (moff & 0xff000000)
out[outpos++] = moff >> 24, i |= 0x08;


if (msize & 0xff) { out[outpos++] = msize; i |= 0x10; } if (msize & 0x00ff)
msize >>= 8; out[outpos++] = msize >> 0, i |= 0x10;
if (msize & 0xff) { out[outpos++] = msize; i |= 0x20; } if (msize & 0xff00)
out[outpos++] = msize >> 8, i |= 0x20;


*op = i; *op = i;

data += msize;
moff += msize;
msize = left;

if (msize < 4096) {
int j;
val = 0;
for (j = -RABIN_WINDOW; j < 0; j++)
val = ((val << 8) | data[j])
^ T[val >> RABIN_SHIFT];
}
} }


if (outpos >= outsize - MAX_OP_SIZE) { if (outpos >= outsize - MAX_OP_SIZE) {