Re: Implementing diff, was Re: git 0.99.7b doesn't build on Cygwin

From: Davide Libenzi <davidel@xmailserver.org>
Date: 2005-09-26 05:16:16
On Sun, 25 Sep 2005, Linus Torvalds wrote:

> On Sun, 25 Sep 2005, Davide Libenzi wrote:
>>
>> What you'd have to do, if you chose to use diffutils stuff, is to
>> transform the main() of diff in diff_main(), use setjmp/longjmp to capture
>> its exit()s, and make it use a proper allocator (if you want to avoid
>> leaks upon aborts).
>
> I'd love to use libxdiff instead since you say it can do it, but quite
> frankly, the man-page didn't much help me. Do you have an example of how
> to generate a uni-diff with it? Something that mortal men can read and say
> "oh"?

Ahh, you looked at the docs. Don't do that ;) Take a look at the 
test/xdiff_test.c for an example on how to use its most important APIs. 
There is also a regression test (xregression) that create random files, 
renadomly changes them, and then try that (A-B)+B=A and (B-A)+A=B (for 
both text and binary). I'm dropping inline an example on how to text-diff ...



- Davide



#include "xmacros.h"
#include "xdiff.h"

#define XDLT_STD_BLKSIZE (1024 * 8)

static int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode) {
         char cc;
         int fd;
         long size, bsize;
         char *blk;

         if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {

                 return -1;
         }
         if ((fd = open(fname, O_RDONLY)) == -1) {
                 perror(fname);
                 xdl_free_mmfile(mf);
                 return -1;
         }
         if ((size = bsize = lseek(fd, 0, SEEK_END)) > 0 && !binmode) {
                 if (lseek(fd, -1, SEEK_END) != (off_t) -1 &&
                     read(fd, &cc, 1) && cc != '\n')
                         bsize++;
         }
         lseek(fd, 0, SEEK_SET);
         if (!(blk = (char *) xdl_mmfile_writeallocate(mf, bsize))) {
                 xdl_free_mmfile(mf);
                 close(fd);
                 return -1;
         }
         if (read(fd, blk, (size_t) size) != (size_t) size) {
                 perror(fname);
                 xdl_free_mmfile(mf);
                 close(fd);
                 return -1;
         }
         close(fd);
         if (bsize > size)
                 blk[size] = '\n';
         return 0;
}

static int xdlt_outf(void *priv, mmbuffer_t *mb, int nbuf) {
         int i;

         for (i = 0; i < nbuf; i++)
                 if (!fwrite(mb[i].ptr, mb[i].size, 1, (FILE *) priv))
                         return -1;
         return 0;
}

static void *wrap_malloc(void *priv, unsigned int size) {

         return malloc(size);
}

static void wrap_free(void *priv, void *ptr) {

         free(ptr);
}

static void *wrap_realloc(void *priv, void *ptr, unsigned int size) {

         return realloc(ptr, size);
}

int sample_textdiff(char const *pre, char const *post, FILE *outf) {
         int error;
         memallocator_t malt;
         mmfile_t mf1, mf2;
         xpparam_t xpp;
         xdemitconf_t xecfg;
         xdemitcb_t ecb;

         malt.priv = NULL;
         malt.malloc = wrap_malloc;
         malt.free = wrap_free;
         malt.realloc = wrap_realloc;
         xdl_set_allocator(&malt);
         if (xdlt_load_mmfile(pre, &mf1, 0) < 0)
                 return -1;
         if (xdlt_load_mmfile(post, &mf2, 0) < 0) {
                 xdl_free_mmfile(&mf1);
                 return -1;
         }
         xpp.flags = 0;
         xecfg.ctxlen = 3;
         ecb.priv = outf;
         ecb.outf = xdlt_outf;
         error = xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
         xdl_free_mmfile(&mf2);
         xdl_free_mmfile(&mf1);

         return error;
}

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Mon Sep 26 05:15:12 2005

This archive was generated by hypermail 2.1.8 : 2005-09-26 05:15:15 EST