summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2007-12-13 14:24:18 -0800
committerJunio C Hamano <gitster@pobox.com>2007-12-13 23:04:26 -0800
commit913b45f51b151d8e29f86df67d3e10853d831470 (patch)
tree8c081b6a2a505d3c202a200c71aab055d4f24e4f
parentc279d7e9869740a6d64b0d1d70f7968af68d2071 (diff)
downloadgit-913b45f51b151d8e29f86df67d3e10853d831470.tar.gz
xdi_diff: trim common trailing lines
This implements earlier Linus's optimization to trim common lines at the end before passing them down to low level xdiff interface for all of our xdiff users. We could later enhance this to also trim common leading lines, but that would need tweaking the output function to add the number of lines trimmed at the beginning to line numbers that appear in the hunk headers. Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--xdiff-interface.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 69a022c134..f2cd488de0 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -103,9 +103,41 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
return 0;
}
+/*
+ * Trim down common substring at the end of the buffers,
+ * but leave at least ctx lines at the end.
+ */
+static void trim_common_tail(mmfile_t *a, mmfile_t *b, int ctx)
+{
+ const int blk = 1024;
+ long trimmed = 0, recovered = 0;
+ int i;
+ char *ap = a->ptr + a->size;
+ char *bp = b->ptr + b->size;
+ long smaller = (a->size < b->size) ? a->size : b->size;
+
+ while (blk + trimmed <= smaller && !memcmp(ap - blk, bp - blk, blk)) {
+ trimmed += blk;
+ ap -= blk;
+ bp -= blk;
+ }
+
+ for (i = 0, recovered = 0; recovered < trimmed && i <= ctx; i++) {
+ while (recovered < trimmed && ap[recovered] != '\n')
+ recovered++;
+ }
+ a->size -= (trimmed - recovered);
+ b->size -= (trimmed - recovered);
+}
+
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb)
{
- return xdl_diff(mf1, mf2, xpp, xecfg, xecb);
+ mmfile_t a = *mf1;
+ mmfile_t b = *mf2;
+
+ trim_common_tail(&a, &b, xecfg->ctxlen);
+
+ return xdl_diff(&a, &b, xpp, xecfg, xecb);
}
int read_mmfile(mmfile_t *ptr, const char *filename)