summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)