##// END OF EJS Templates
diffhelpers: use Py_ssize_t in addlines()...
Adrian Buehlmann -
r16694:797b7620 default
parent child Browse files
Show More
@@ -1,190 +1,197
1 1 /*
2 2 * diffhelpers.c - helper routines for mpatch
3 3 *
4 4 * Copyright 2007 Chris Mason <chris.mason@oracle.com>
5 5 *
6 6 * This software may be used and distributed according to the terms
7 7 * of the GNU General Public License v2, incorporated herein by reference.
8 8 */
9 9
10 10 #include <Python.h>
11 11 #include <stdlib.h>
12 12 #include <string.h>
13 13
14 14 #include "util.h"
15 15
16 16 static char diffhelpers_doc[] = "Efficient diff parsing";
17 17 static PyObject *diffhelpers_Error;
18 18
19 19
20 20 /* fixup the last lines of a and b when the patch has no newline at eof */
21 21 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
22 22 {
23 23 Py_ssize_t hunksz = PyList_Size(hunk);
24 24 PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
25 25 char *l = PyBytes_AsString(s);
26 26 Py_ssize_t alen = PyList_Size(a);
27 27 Py_ssize_t blen = PyList_Size(b);
28 28 char c = l[0];
29 29 PyObject *hline;
30 30 Py_ssize_t sz = PyBytes_GET_SIZE(s);
31 31
32 32 if (sz > 1 && l[sz-2] == '\r')
33 33 /* tolerate CRLF in last line */
34 34 sz -= 1;
35 35
36 36 hline = PyBytes_FromStringAndSize(l, sz-1);
37 37
38 38 if (c == ' ' || c == '+') {
39 39 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
40 40 PyList_SetItem(b, blen-1, rline);
41 41 }
42 42 if (c == ' ' || c == '-') {
43 43 Py_INCREF(hline);
44 44 PyList_SetItem(a, alen-1, hline);
45 45 }
46 46 PyList_SetItem(hunk, hunksz-1, hline);
47 47 }
48 48
49 49 /* python callable form of _fix_newline */
50 50 static PyObject *
51 51 fix_newline(PyObject *self, PyObject *args)
52 52 {
53 53 PyObject *hunk, *a, *b;
54 54 if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
55 55 return NULL;
56 56 _fix_newline(hunk, a, b);
57 57 return Py_BuildValue("l", 0);
58 58 }
59 59
60 #if (PY_VERSION_HEX < 0x02050000)
61 static const char *addlines_format = "OOiiOO";
62 #else
63 static const char *addlines_format = "OOnnOO";
64 #endif
65
60 66 /*
61 67 * read lines from fp into the hunk. The hunk is parsed into two arrays
62 68 * a and b. a gets the old state of the text, b gets the new state
63 69 * The control char from the hunk is saved when inserting into a, but not b
64 70 * (for performance while deleting files)
65 71 */
66 72 static PyObject *
67 73 addlines(PyObject *self, PyObject *args)
68 74 {
69 75
70 76 PyObject *fp, *hunk, *a, *b, *x;
71 int i;
72 int lena, lenb;
73 int num;
74 int todoa, todob;
77 Py_ssize_t i;
78 Py_ssize_t lena, lenb;
79 Py_ssize_t num;
80 Py_ssize_t todoa, todob;
75 81 char *s, c;
76 82 PyObject *l;
77 if (!PyArg_ParseTuple(args, "OOiiOO", &fp, &hunk, &lena, &lenb, &a, &b))
83 if (!PyArg_ParseTuple(args, addlines_format,
84 &fp, &hunk, &lena, &lenb, &a, &b))
78 85 return NULL;
79 86
80 87 while (1) {
81 88 todoa = lena - PyList_Size(a);
82 89 todob = lenb - PyList_Size(b);
83 90 num = todoa > todob ? todoa : todob;
84 91 if (num == 0)
85 92 break;
86 93 for (i = 0; i < num; i++) {
87 94 x = PyFile_GetLine(fp, 0);
88 95 s = PyBytes_AsString(x);
89 96 c = *s;
90 97 if (strcmp(s, "\\ No newline at end of file\n") == 0) {
91 98 _fix_newline(hunk, a, b);
92 99 continue;
93 100 }
94 101 if (c == '\n') {
95 102 /* Some patches may be missing the control char
96 103 * on empty lines. Supply a leading space. */
97 104 Py_DECREF(x);
98 105 x = PyBytes_FromString(" \n");
99 106 }
100 107 PyList_Append(hunk, x);
101 108 if (c == '+') {
102 109 l = PyBytes_FromString(s + 1);
103 110 PyList_Append(b, l);
104 111 Py_DECREF(l);
105 112 } else if (c == '-') {
106 113 PyList_Append(a, x);
107 114 } else {
108 115 l = PyBytes_FromString(s + 1);
109 116 PyList_Append(b, l);
110 117 Py_DECREF(l);
111 118 PyList_Append(a, x);
112 119 }
113 120 Py_DECREF(x);
114 121 }
115 122 }
116 123 return Py_BuildValue("l", 0);
117 124 }
118 125
119 126 /*
120 127 * compare the lines in a with the lines in b. a is assumed to have
121 128 * a control char at the start of each line, this char is ignored in the
122 129 * compare
123 130 */
124 131 static PyObject *
125 132 testhunk(PyObject *self, PyObject *args)
126 133 {
127 134
128 135 PyObject *a, *b;
129 136 long bstart;
130 137 int alen, blen;
131 138 int i;
132 139 char *sa, *sb;
133 140
134 141 if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
135 142 return NULL;
136 143 alen = PyList_Size(a);
137 144 blen = PyList_Size(b);
138 145 if (alen > blen - bstart || bstart < 0) {
139 146 return Py_BuildValue("l", -1);
140 147 }
141 148 for (i = 0; i < alen; i++) {
142 149 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
143 150 sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
144 151 if (strcmp(sa + 1, sb) != 0)
145 152 return Py_BuildValue("l", -1);
146 153 }
147 154 return Py_BuildValue("l", 0);
148 155 }
149 156
150 157 static PyMethodDef methods[] = {
151 158 {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
152 159 {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
153 160 {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
154 161 {NULL, NULL}
155 162 };
156 163
157 164 #ifdef IS_PY3K
158 165 static struct PyModuleDef diffhelpers_module = {
159 166 PyModuleDef_HEAD_INIT,
160 167 "diffhelpers",
161 168 diffhelpers_doc,
162 169 -1,
163 170 methods
164 171 };
165 172
166 173 PyMODINIT_FUNC PyInit_diffhelpers(void)
167 174 {
168 175 PyObject *m;
169 176
170 177 m = PyModule_Create(&diffhelpers_module);
171 178 if (m == NULL)
172 179 return NULL;
173 180
174 181 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
175 182 NULL, NULL);
176 183 Py_INCREF(diffhelpers_Error);
177 184 PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
178 185
179 186 return m;
180 187 }
181 188 #else
182 189 PyMODINIT_FUNC
183 190 initdiffhelpers(void)
184 191 {
185 192 Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
186 193 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
187 194 NULL, NULL);
188 195 }
189 196 #endif
190 197
General Comments 0
You need to be logged in to leave comments. Login now