comparison mercurial/cext/bdiff.c @ 36675:430fdb717549

bdiff: add a xdiffblocks method This is similar to `bdiff.blocks`, but uses xdiff as the backend. The indent heuristic is turned on by default since it has little overhead and improves diff quality significantly. Differential Revision: https://phab.mercurial-scm.org/D2602
author Jun Wu <quark@fb.com>
date Sat, 03 Mar 2018 12:39:14 -0800
parents 68026dd7c4f9
children 340e4b711df7
comparison
equal deleted inserted replaced
36674:c420792217c8 36675:430fdb717549
15 #include <stdlib.h> 15 #include <stdlib.h>
16 #include <string.h> 16 #include <string.h>
17 17
18 #include "bdiff.h" 18 #include "bdiff.h"
19 #include "bitmanipulation.h" 19 #include "bitmanipulation.h"
20 #include "thirdparty/xdiff/xdiff.h"
20 #include "util.h" 21 #include "util.h"
21 22
22 static PyObject *blocks(PyObject *self, PyObject *args) 23 static PyObject *blocks(PyObject *self, PyObject *args)
23 { 24 {
24 PyObject *sa, *sb, *rl = NULL, *m; 25 PyObject *sa, *sb, *rl = NULL, *m;
254 abort: 255 abort:
255 Py_XDECREF(result); 256 Py_XDECREF(result);
256 return NULL; 257 return NULL;
257 } 258 }
258 259
260 static int hunk_consumer(long a1, long a2, long b1, long b2, void *priv)
261 {
262 PyObject *rl = (PyObject *)priv;
263 PyObject *m = Py_BuildValue("llll", a1, a2, b1, b2);
264 if (!m)
265 return -1;
266 if (PyList_Append(rl, m) != 0) {
267 Py_DECREF(m);
268 return -1;
269 }
270 return 0;
271 }
272
273 static PyObject *xdiffblocks(PyObject *self, PyObject *args)
274 {
275 Py_ssize_t la, lb;
276 mmfile_t a, b;
277 PyObject *rl;
278
279 xpparam_t xpp = {
280 XDF_INDENT_HEURISTIC, /* flags */
281 NULL, /* anchors */
282 0, /* anchors_nr */
283 };
284 xdemitconf_t xecfg = {
285 0, /* ctxlen */
286 0, /* interhunkctxlen */
287 XDL_EMIT_BDIFFHUNK, /* flags */
288 NULL, /* find_func */
289 NULL, /* find_func_priv */
290 hunk_consumer, /* hunk_consume_func */
291 };
292 xdemitcb_t ecb = {
293 NULL, /* priv */
294 NULL, /* outf */
295 };
296
297 if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr,
298 &lb))
299 return NULL;
300
301 a.size = la;
302 b.size = lb;
303
304 rl = PyList_New(0);
305 if (!rl)
306 return PyErr_NoMemory();
307
308 ecb.priv = rl;
309
310 if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) {
311 Py_DECREF(rl);
312 return PyErr_NoMemory();
313 }
314
315 return rl;
316 }
317
259 static char mdiff_doc[] = "Efficient binary diff."; 318 static char mdiff_doc[] = "Efficient binary diff.";
260 319
261 static PyMethodDef methods[] = { 320 static PyMethodDef methods[] = {
262 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"}, 321 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"},
263 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"}, 322 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"},
264 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"}, 323 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"},
265 {"splitnewlines", splitnewlines, METH_VARARGS, 324 {"splitnewlines", splitnewlines, METH_VARARGS,
266 "like str.splitlines, but only split on newlines\n"}, 325 "like str.splitlines, but only split on newlines\n"},
326 {"xdiffblocks", xdiffblocks, METH_VARARGS,
327 "find a list of matching lines using xdiff algorithm\n"},
267 {NULL, NULL}, 328 {NULL, NULL},
268 }; 329 };
269 330
270 static const int version = 2; 331 static const int version = 3;
271 332
272 #ifdef IS_PY3K 333 #ifdef IS_PY3K
273 static struct PyModuleDef bdiff_module = { 334 static struct PyModuleDef bdiff_module = {
274 PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods, 335 PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods,
275 }; 336 };