diff options
Diffstat (limited to 'xdiff-interface.c')
-rw-r--r-- | xdiff-interface.c | 34 |
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) |