Files
harbour-core/harbour/contrib/hbxdiff/3rd/libxdiff/xbdiff.c
Petr Chornyj 8d26624109 2010-02-01 11:10 UTC+0200 Petr Chornyj (myorg63 at mail.ru)
* contrib/hbmxml
  * contrib/hbmxml/3rd
  * contrib/hbmxml/3rd/minixml
  * contrib/hbmxml/3rd/minixml/config.h
  * contrib/hbmxml/3rd/minixml/COPYING
  * contrib/hbmxml/3rd/minixml/mxml-private.h
  * contrib/hbmxml/3rd/minixml/mxml.h
  * contrib/hbmxml/3rd/minixml/mxml.hbc
  * contrib/hbmxml/3rd/minixml/mxml.hbp
  * contrib/hbmxml/3rd/minixml/mxml_att.c
  * contrib/hbmxml/3rd/minixml/mxml_ent.c
  * contrib/hbmxml/3rd/minixml/mxml_fil.c
  * contrib/hbmxml/3rd/minixml/mxml_ind.c
  * contrib/hbmxml/3rd/minixml/mxml_nod.c
  * contrib/hbmxml/3rd/minixml/mxml_pri.c
  * contrib/hbmxml/3rd/minixml/mxml_pri.h
  * contrib/hbmxml/3rd/minixml/mxml_sea.c
  * contrib/hbmxml/3rd/minixml/mxml_set.c
  * contrib/hbmxml/3rd/minixml/mxml_str.c
  * contrib/hbmxml/hbmxml.c
  * contrib/hbmxml/hbmxml.ch
  * contrib/hbmxml/hbmxml.hbc
  * contrib/hbmxml/hbmxml.hbp
  * contrib/hbmxml/tests
  * contrib/hbmxml/tests/hbmk.hbm
  * contrib/hbmxml/tests/test.prg
  * contrib/hbmxml/tests/test.xml
    + added wrapper to miniXML library.
      Not finished yet, work in progress
  * contrib/hbxdiff
  * contrib/hbxdiff/3rd
  * contrib/hbxdiff/3rd/libxdiff
  * contrib/hbxdiff/3rd/libxdiff/AUTHORS
  * contrib/hbxdiff/3rd/libxdiff/config.h
  * contrib/hbxdiff/3rd/libxdiff/COPYING
  * contrib/hbxdiff/3rd/libxdiff/xadler32.c
  * contrib/hbxdiff/3rd/libxdiff/xadler32.h
  * contrib/hbxdiff/3rd/libxdiff/xalloc.c
  * contrib/hbxdiff/3rd/libxdiff/xbdiff.c
  * contrib/hbxdiff/3rd/libxdiff/xbdiff.h
  * contrib/hbxdiff/3rd/libxdiff/xbpatchi.c
  * contrib/hbxdiff/3rd/libxdiff/xdiff.h
  * contrib/hbxdiff/3rd/libxdiff/xdiff.hbc
  * contrib/hbxdiff/3rd/libxdiff/xdiff.hbp
  * contrib/hbxdiff/3rd/libxdiff/xdiff.txt
  * contrib/hbxdiff/3rd/libxdiff/xdiffi.c
  * contrib/hbxdiff/3rd/libxdiff/xdiffi.h
  * contrib/hbxdiff/3rd/libxdiff/xemit.c
  * contrib/hbxdiff/3rd/libxdiff/xemit.h
  * contrib/hbxdiff/3rd/libxdiff/xinclude.h
  * contrib/hbxdiff/3rd/libxdiff/xmacros.h
  * contrib/hbxdiff/3rd/libxdiff/xmerge3.c
  * contrib/hbxdiff/3rd/libxdiff/xmissing.c
  * contrib/hbxdiff/3rd/libxdiff/xmissing.h
  * contrib/hbxdiff/3rd/libxdiff/xpatchi.c
  * contrib/hbxdiff/3rd/libxdiff/xprepare.c
  * contrib/hbxdiff/3rd/libxdiff/xprepare.h
  * contrib/hbxdiff/3rd/libxdiff/xrabdiff.c
  * contrib/hbxdiff/3rd/libxdiff/xrabply.c
  * contrib/hbxdiff/3rd/libxdiff/xtypes.h
  * contrib/hbxdiff/3rd/libxdiff/xutils.c
  * contrib/hbxdiff/3rd/libxdiff/xutils.h
  * contrib/hbxdiff/3rd/libxdiff/xversion.c
  * contrib/hbxdiff/hbxdiff.c
  * contrib/hbxdiff/hbxdiff.ch
  * contrib/hbxdiff/hbxdiff.hbc
  * contrib/hbxdiff/hbxdiff.hbp
  * contrib/hbxdiff/tests
  * contrib/hbxdiff/tests/hbmk.hbm
  * contrib/hbxdiff/tests/test.prg
  * contrib/hbxdiff/tests/test2.prg
  * contrib/hbxdiff/tests/test3.prg
    + added wrapper to libxdiff library.
      Not finished yet, work in progress
2011-01-02 09:15:19 +00:00

316 lines
7.1 KiB
C

/*
* LibXDiff by Davide Libenzi ( File Differential Library )
* Copyright (C) 2003 Davide Libenzi
*
* This library is free software; you can redistribute it and/or
* 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.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Davide Libenzi <davidel@xmailserver.org>
*
*/
#include "xinclude.h"
typedef struct s_bdrecord {
struct s_bdrecord *next;
unsigned long fp;
char const *ptr;
} bdrecord_t;
typedef struct s_bdfile {
char const *data, *top;
chastore_t cha;
unsigned int fphbits;
bdrecord_t **fphash;
} bdfile_t;
static int xdl_prepare_bdfile(mmbuffer_t *mmb, long fpbsize, bdfile_t *bdf) {
unsigned int fphbits;
long i, size, hsize;
char const *base, *data, *top;
bdrecord_t *brec;
bdrecord_t **fphash;
fphbits = xdl_hashbits((unsigned int) (mmb->size / fpbsize) + 1);
hsize = 1 << fphbits;
if (!(fphash = (bdrecord_t **) xdl_malloc(hsize * sizeof(bdrecord_t *)))) {
return -1;
}
for (i = 0; i < hsize; i++)
fphash[i] = NULL;
if (xdl_cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1) < 0) {
xdl_free(fphash);
return -1;
}
if (!(size = mmb->size)) {
bdf->data = bdf->top = NULL;
} else {
bdf->data = data = base = mmb->ptr;
bdf->top = top = mmb->ptr + mmb->size;
if ((data += (size / fpbsize) * fpbsize) == top)
data -= fpbsize;
for (; data >= base; data -= fpbsize) {
if (!(brec = (bdrecord_t *) xdl_cha_alloc(&bdf->cha))) {
xdl_cha_free(&bdf->cha);
xdl_free(fphash);
return -1;
}
brec->fp = xdl_adler32(0, (unsigned char const *) data,
XDL_MIN(fpbsize, (long) (top - data)));
brec->ptr = data;
i = (long) XDL_HASHLONG(brec->fp, fphbits);
brec->next = fphash[i];
fphash[i] = brec;
}
}
bdf->fphbits = fphbits;
bdf->fphash = fphash;
return 0;
}
static void xdl_free_bdfile(bdfile_t *bdf) {
xdl_free(bdf->fphash);
xdl_cha_free(&bdf->cha);
}
unsigned long xdl_mmb_adler32(mmbuffer_t *mmb) {
return mmb->size ? xdl_adler32(0, (unsigned char const *) mmb->ptr, mmb->size): 0;
}
unsigned long xdl_mmf_adler32(mmfile_t *mmf) {
unsigned long fp = 0;
long size;
char const *blk;
if ((blk = (char const *) xdl_mmfile_first(mmf, &size)) != NULL) {
do {
fp = xdl_adler32(fp, (unsigned char const *) blk, size);
} while ((blk = (char const *) xdl_mmfile_next(mmf, &size)) != NULL);
}
return fp;
}
int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb) {
long i, rsize, size, bsize, csize, msize, moff;
unsigned long fp;
char const *blk, *base, *data, *top, *ptr1, *ptr2;
bdrecord_t *brec;
bdfile_t bdf;
mmbuffer_t mb[2];
unsigned char cpybuf[32];
if ((bsize = bdp->bsize) < XDL_MIN_BLKSIZE)
bsize = XDL_MIN_BLKSIZE;
if (xdl_prepare_bdfile(mmb1, bsize, &bdf) < 0) {
return -1;
}
/*
* Prepare and emit the binary patch file header. It will be used
* to verify that that file being patched matches in size and fingerprint
* the one that generated the patch.
*/
fp = xdl_mmb_adler32(mmb1);
size = mmb1->size;
XDL_LE32_PUT(cpybuf, fp);
XDL_LE32_PUT(cpybuf + 4, size);
mb[0].ptr = (char *) cpybuf;
mb[0].size = 4 + 4;
if (ecb->outf(ecb->priv, mb, 1) < 0) {
xdl_free_bdfile(&bdf);
return -1;
}
if ((blk = (char const *) mmb2->ptr) != NULL) {
size = mmb2->size;
for (base = data = blk, top = data + size; data < top;) {
rsize = XDL_MIN(bsize, (long) (top - data));
fp = xdl_adler32(0, (unsigned char const *) data, rsize);
i = (long) XDL_HASHLONG(fp, bdf.fphbits);
for (msize = 0, brec = bdf.fphash[i]; brec; brec = brec->next)
if (brec->fp == fp) {
csize = XDL_MIN((long) (top - data), (long) (bdf.top - brec->ptr));
for (ptr1 = brec->ptr, ptr2 = data; csize && *ptr1 == *ptr2;
csize--, ptr1++, ptr2++);
if ((csize = (long) (ptr1 - brec->ptr)) > msize) {
moff = (long) (brec->ptr - bdf.data);
msize = csize;
}
}
if (msize < XDL_COPYOP_SIZE) {
data++;
} else {
if (data > base) {
i = (long) (data - base);
if (i > 255) {
cpybuf[0] = XDL_BDOP_INSB;
XDL_LE32_PUT(cpybuf + 1, i);
mb[0].ptr = (char *) cpybuf;
mb[0].size = XDL_INSBOP_SIZE;
} else {
cpybuf[0] = XDL_BDOP_INS;
cpybuf[1] = (unsigned char) i;
mb[0].ptr = (char *) cpybuf;
mb[0].size = 2;
}
mb[1].ptr = (char *) base;
mb[1].size = i;
if (ecb->outf(ecb->priv, mb, 2) < 0) {
xdl_free_bdfile(&bdf);
return -1;
}
}
data += msize;
cpybuf[0] = XDL_BDOP_CPY;
XDL_LE32_PUT(cpybuf + 1, moff);
XDL_LE32_PUT(cpybuf + 5, msize);
mb[0].ptr = (char *) cpybuf;
mb[0].size = XDL_COPYOP_SIZE;
if (ecb->outf(ecb->priv, mb, 1) < 0) {
xdl_free_bdfile(&bdf);
return -1;
}
base = data;
}
}
if (data > base) {
i = (long) (data - base);
if (i > 255) {
cpybuf[0] = XDL_BDOP_INSB;
XDL_LE32_PUT(cpybuf + 1, i);
mb[0].ptr = (char *) cpybuf;
mb[0].size = XDL_INSBOP_SIZE;
} else {
cpybuf[0] = XDL_BDOP_INS;
cpybuf[1] = (unsigned char) i;
mb[0].ptr = (char *) cpybuf;
mb[0].size = 2;
}
mb[1].ptr = (char *) base;
mb[1].size = i;
if (ecb->outf(ecb->priv, mb, 2) < 0) {
xdl_free_bdfile(&bdf);
return -1;
}
}
}
xdl_free_bdfile(&bdf);
return 0;
}
int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb) {
mmbuffer_t mmb1, mmb2;
if (!xdl_mmfile_iscompact(mmf1) || !xdl_mmfile_iscompact(mmf2)) {
return -1;
}
if ((mmb1.ptr = (char *) xdl_mmfile_first(mmf1, &mmb1.size)) == NULL)
mmb1.size = 0;
if ((mmb2.ptr = (char *) xdl_mmfile_first(mmf2, &mmb2.size)) == NULL)
mmb2.size = 0;
return xdl_bdiff_mb(&mmb1, &mmb2, bdp, ecb);
}
long xdl_bdiff_tgsize(mmfile_t *mmfp) {
long tgsize = 0, size, off, csize;
char const *blk;
unsigned char const *data, *top;
if ((blk = (char const *) xdl_mmfile_first(mmfp, &size)) == NULL ||
size < XDL_BPATCH_HDR_SIZE) {
return -1;
}
blk += XDL_BPATCH_HDR_SIZE;
size -= XDL_BPATCH_HDR_SIZE;
do {
for (data = (unsigned char const *) blk, top = data + size;
data < top;) {
if (*data == XDL_BDOP_INS) {
data++;
csize = (long) *data++;
tgsize += csize;
data += csize;
} else if (*data == XDL_BDOP_INSB) {
data++;
XDL_LE32_GET(data, csize);
data += 4;
tgsize += csize;
data += csize;
} else if (*data == XDL_BDOP_CPY) {
data++;
XDL_LE32_GET(data, off);
data += 4;
XDL_LE32_GET(data, csize);
data += 4;
tgsize += csize;
} else {
return -1;
}
}
} while ((blk = (char const *) xdl_mmfile_next(mmfp, &size)) != NULL);
return tgsize;
}