mercurial/cext/diffhelpers.c
changeset 36095 7f8338b87c88
parent 32409 017ad85e5ac8
equal deleted inserted replaced
36094:44cb058bc0d3 36095:7f8338b87c88
    14 #include "util.h"
    14 #include "util.h"
    15 
    15 
    16 static char diffhelpers_doc[] = "Efficient diff parsing";
    16 static char diffhelpers_doc[] = "Efficient diff parsing";
    17 static PyObject *diffhelpers_Error;
    17 static PyObject *diffhelpers_Error;
    18 
    18 
    19 
       
    20 /* fixup the last lines of a and b when the patch has no newline at eof */
    19 /* fixup the last lines of a and b when the patch has no newline at eof */
    21 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
    20 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
    22 {
    21 {
    23 	Py_ssize_t hunksz = PyList_Size(hunk);
    22 	Py_ssize_t hunksz = PyList_Size(hunk);
    24 	PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
    23 	PyObject *s = PyList_GET_ITEM(hunk, hunksz - 1);
    25 	char *l = PyBytes_AsString(s);
    24 	char *l = PyBytes_AsString(s);
    26 	Py_ssize_t alen = PyList_Size(a);
    25 	Py_ssize_t alen = PyList_Size(a);
    27 	Py_ssize_t blen = PyList_Size(b);
    26 	Py_ssize_t blen = PyList_Size(b);
    28 	char c = l[0];
    27 	char c = l[0];
    29 	PyObject *hline;
    28 	PyObject *hline;
    30 	Py_ssize_t sz = PyBytes_GET_SIZE(s);
    29 	Py_ssize_t sz = PyBytes_GET_SIZE(s);
    31 
    30 
    32 	if (sz > 1 && l[sz-2] == '\r')
    31 	if (sz > 1 && l[sz - 2] == '\r')
    33 		/* tolerate CRLF in last line */
    32 		/* tolerate CRLF in last line */
    34 		sz -= 1;
    33 		sz -= 1;
    35 
    34 
    36 	hline = PyBytes_FromStringAndSize(l, sz-1);
    35 	hline = PyBytes_FromStringAndSize(l, sz - 1);
    37 	if (!hline) {
    36 	if (!hline) {
    38 		return;
    37 		return;
    39 	}
    38 	}
    40 
    39 
    41 	if (c == ' ' || c == '+') {
    40 	if (c == ' ' || c == '+') {
    42 		PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
    41 		PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
    43 		PyList_SetItem(b, blen-1, rline);
    42 		PyList_SetItem(b, blen - 1, rline);
    44 	}
    43 	}
    45 	if (c == ' ' || c == '-') {
    44 	if (c == ' ' || c == '-') {
    46 		Py_INCREF(hline);
    45 		Py_INCREF(hline);
    47 		PyList_SetItem(a, alen-1, hline);
    46 		PyList_SetItem(a, alen - 1, hline);
    48 	}
    47 	}
    49 	PyList_SetItem(hunk, hunksz-1, hline);
    48 	PyList_SetItem(hunk, hunksz - 1, hline);
    50 }
    49 }
    51 
    50 
    52 /* python callable form of _fix_newline */
    51 /* python callable form of _fix_newline */
    53 static PyObject *
    52 static PyObject *fix_newline(PyObject *self, PyObject *args)
    54 fix_newline(PyObject *self, PyObject *args)
       
    55 {
    53 {
    56 	PyObject *hunk, *a, *b;
    54 	PyObject *hunk, *a, *b;
    57 	if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
    55 	if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
    58 		return NULL;
    56 		return NULL;
    59 	_fix_newline(hunk, a, b);
    57 	_fix_newline(hunk, a, b);
    70  * read lines from fp into the hunk.  The hunk is parsed into two arrays
    68  * read lines from fp into the hunk.  The hunk is parsed into two arrays
    71  * a and b.  a gets the old state of the text, b gets the new state
    69  * a and b.  a gets the old state of the text, b gets the new state
    72  * The control char from the hunk is saved when inserting into a, but not b
    70  * The control char from the hunk is saved when inserting into a, but not b
    73  * (for performance while deleting files)
    71  * (for performance while deleting files)
    74  */
    72  */
    75 static PyObject *
    73 static PyObject *addlines(PyObject *self, PyObject *args)
    76 addlines(PyObject *self, PyObject *args)
       
    77 {
    74 {
    78 
    75 
    79 	PyObject *fp, *hunk, *a, *b, *x;
    76 	PyObject *fp, *hunk, *a, *b, *x;
    80 	Py_ssize_t i;
    77 	Py_ssize_t i;
    81 	Py_ssize_t lena, lenb;
    78 	Py_ssize_t lena, lenb;
    82 	Py_ssize_t num;
    79 	Py_ssize_t num;
    83 	Py_ssize_t todoa, todob;
    80 	Py_ssize_t todoa, todob;
    84 	char *s, c;
    81 	char *s, c;
    85 	PyObject *l;
    82 	PyObject *l;
    86 	if (!PyArg_ParseTuple(args, addlines_format,
    83 	if (!PyArg_ParseTuple(args, addlines_format, &fp, &hunk, &lena, &lenb,
    87 			      &fp, &hunk, &lena, &lenb, &a, &b))
    84 	                      &a, &b))
    88 		return NULL;
    85 		return NULL;
    89 
    86 
    90 	while (1) {
    87 	while (1) {
    91 		todoa = lena - PyList_Size(a);
    88 		todoa = lena - PyList_Size(a);
    92 		todob = lenb - PyList_Size(b);
    89 		todob = lenb - PyList_Size(b);
    93 		num = todoa > todob ? todoa : todob;
    90 		num = todoa > todob ? todoa : todob;
    94 		if (num == 0)
    91 		if (num == 0)
    95 		    break;
    92 			break;
    96 		for (i = 0; i < num; i++) {
    93 		for (i = 0; i < num; i++) {
    97 			x = PyFile_GetLine(fp, 0);
    94 			x = PyFile_GetLine(fp, 0);
    98 			s = PyBytes_AsString(x);
    95 			s = PyBytes_AsString(x);
    99 			c = *s;
    96 			c = *s;
   100 			if (strcmp(s, "\\ No newline at end of file\n") == 0) {
    97 			if (strcmp(s, "\\ No newline at end of file\n") == 0) {
   129 /*
   126 /*
   130  * compare the lines in a with the lines in b.  a is assumed to have
   127  * compare the lines in a with the lines in b.  a is assumed to have
   131  * a control char at the start of each line, this char is ignored in the
   128  * a control char at the start of each line, this char is ignored in the
   132  * compare
   129  * compare
   133  */
   130  */
   134 static PyObject *
   131 static PyObject *testhunk(PyObject *self, PyObject *args)
   135 testhunk(PyObject *self, PyObject *args)
       
   136 {
   132 {
   137 
   133 
   138 	PyObject *a, *b;
   134 	PyObject *a, *b;
   139 	long bstart;
   135 	long bstart;
   140 	Py_ssize_t alen, blen;
   136 	Py_ssize_t alen, blen;
   156 	}
   152 	}
   157 	return Py_BuildValue("l", 0);
   153 	return Py_BuildValue("l", 0);
   158 }
   154 }
   159 
   155 
   160 static PyMethodDef methods[] = {
   156 static PyMethodDef methods[] = {
   161 	{"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
   157     {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
   162 	{"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
   158     {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
   163 	{"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
   159     {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
   164 	{NULL, NULL}
   160     {NULL, NULL}};
   165 };
       
   166 
   161 
   167 static const int version = 1;
   162 static const int version = 1;
   168 
   163 
   169 #ifdef IS_PY3K
   164 #ifdef IS_PY3K
   170 static struct PyModuleDef diffhelpers_module = {
   165 static struct PyModuleDef diffhelpers_module = {
   171 	PyModuleDef_HEAD_INIT,
   166     PyModuleDef_HEAD_INIT, "diffhelpers", diffhelpers_doc, -1, methods,
   172 	"diffhelpers",
       
   173 	diffhelpers_doc,
       
   174 	-1,
       
   175 	methods
       
   176 };
   167 };
   177 
   168 
   178 PyMODINIT_FUNC PyInit_diffhelpers(void)
   169 PyMODINIT_FUNC PyInit_diffhelpers(void)
   179 {
   170 {
   180 	PyObject *m;
   171 	PyObject *m;
   181 
   172 
   182 	m = PyModule_Create(&diffhelpers_module);
   173 	m = PyModule_Create(&diffhelpers_module);
   183 	if (m == NULL)
   174 	if (m == NULL)
   184 		return NULL;
   175 		return NULL;
   185 
   176 
   186 	diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
   177 	diffhelpers_Error =
   187 											NULL, NULL);
   178 	    PyErr_NewException("diffhelpers.diffhelpersError", NULL, NULL);
   188 	Py_INCREF(diffhelpers_Error);
   179 	Py_INCREF(diffhelpers_Error);
   189 	PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
   180 	PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
   190 	PyModule_AddIntConstant(m, "version", version);
   181 	PyModule_AddIntConstant(m, "version", version);
   191 
   182 
   192 	return m;
   183 	return m;
   193 }
   184 }
   194 #else
   185 #else
   195 PyMODINIT_FUNC
   186 PyMODINIT_FUNC initdiffhelpers(void)
   196 initdiffhelpers(void)
       
   197 {
   187 {
   198 	PyObject *m;
   188 	PyObject *m;
   199 	m = Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
   189 	m = Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
   200 	diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
   190 	diffhelpers_Error =
   201 	                                        NULL, NULL);
   191 	    PyErr_NewException("diffhelpers.diffhelpersError", NULL, NULL);
   202 	PyModule_AddIntConstant(m, "version", version);
   192 	PyModule_AddIntConstant(m, "version", version);
   203 }
   193 }
   204 #endif
   194 #endif