##// END OF EJS Templates
diffhelpers: verify hline was created before using it...
Augie Fackler -
r23959:c8e7fa41 stable
parent child Browse files
Show More
@@ -1,197 +1,199
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 if (!hline) {
38 return NULL;
39 }
37 40
38 41 if (c == ' ' || c == '+') {
39 42 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
40 43 PyList_SetItem(b, blen-1, rline);
41 44 }
42 45 if (c == ' ' || c == '-') {
43 46 Py_INCREF(hline);
44 47 PyList_SetItem(a, alen-1, hline);
45 48 }
46 49 PyList_SetItem(hunk, hunksz-1, hline);
47 50 }
48 51
49 52 /* python callable form of _fix_newline */
50 53 static PyObject *
51 54 fix_newline(PyObject *self, PyObject *args)
52 55 {
53 56 PyObject *hunk, *a, *b;
54 57 if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
55 58 return NULL;
56 59 _fix_newline(hunk, a, b);
57 60 return Py_BuildValue("l", 0);
58 61 }
59 62
60 63 #if (PY_VERSION_HEX < 0x02050000)
61 64 static const char *addlines_format = "OOiiOO";
62 65 #else
63 66 static const char *addlines_format = "OOnnOO";
64 67 #endif
65 68
66 69 /*
67 70 * read lines from fp into the hunk. The hunk is parsed into two arrays
68 71 * a and b. a gets the old state of the text, b gets the new state
69 72 * The control char from the hunk is saved when inserting into a, but not b
70 73 * (for performance while deleting files)
71 74 */
72 75 static PyObject *
73 76 addlines(PyObject *self, PyObject *args)
74 77 {
75 78
76 79 PyObject *fp, *hunk, *a, *b, *x;
77 80 Py_ssize_t i;
78 81 Py_ssize_t lena, lenb;
79 82 Py_ssize_t num;
80 83 Py_ssize_t todoa, todob;
81 84 char *s, c;
82 85 PyObject *l;
83 86 if (!PyArg_ParseTuple(args, addlines_format,
84 87 &fp, &hunk, &lena, &lenb, &a, &b))
85 88 return NULL;
86 89
87 90 while (1) {
88 91 todoa = lena - PyList_Size(a);
89 92 todob = lenb - PyList_Size(b);
90 93 num = todoa > todob ? todoa : todob;
91 94 if (num == 0)
92 95 break;
93 96 for (i = 0; i < num; i++) {
94 97 x = PyFile_GetLine(fp, 0);
95 98 s = PyBytes_AsString(x);
96 99 c = *s;
97 100 if (strcmp(s, "\\ No newline at end of file\n") == 0) {
98 101 _fix_newline(hunk, a, b);
99 102 continue;
100 103 }
101 104 if (c == '\n') {
102 105 /* Some patches may be missing the control char
103 106 * on empty lines. Supply a leading space. */
104 107 Py_DECREF(x);
105 108 x = PyBytes_FromString(" \n");
106 109 }
107 110 PyList_Append(hunk, x);
108 111 if (c == '+') {
109 112 l = PyBytes_FromString(s + 1);
110 113 PyList_Append(b, l);
111 114 Py_DECREF(l);
112 115 } else if (c == '-') {
113 116 PyList_Append(a, x);
114 117 } else {
115 118 l = PyBytes_FromString(s + 1);
116 119 PyList_Append(b, l);
117 120 Py_DECREF(l);
118 121 PyList_Append(a, x);
119 122 }
120 123 Py_DECREF(x);
121 124 }
122 125 }
123 126 return Py_BuildValue("l", 0);
124 127 }
125 128
126 129 /*
127 130 * compare the lines in a with the lines in b. a is assumed to have
128 131 * a control char at the start of each line, this char is ignored in the
129 132 * compare
130 133 */
131 134 static PyObject *
132 135 testhunk(PyObject *self, PyObject *args)
133 136 {
134 137
135 138 PyObject *a, *b;
136 139 long bstart;
137 140 Py_ssize_t alen, blen;
138 141 Py_ssize_t i;
139 142 char *sa, *sb;
140 143
141 144 if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
142 145 return NULL;
143 146 alen = PyList_Size(a);
144 147 blen = PyList_Size(b);
145 148 if (alen > blen - bstart || bstart < 0) {
146 149 return Py_BuildValue("l", -1);
147 150 }
148 151 for (i = 0; i < alen; i++) {
149 152 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
150 153 sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
151 154 if (strcmp(sa + 1, sb) != 0)
152 155 return Py_BuildValue("l", -1);
153 156 }
154 157 return Py_BuildValue("l", 0);
155 158 }
156 159
157 160 static PyMethodDef methods[] = {
158 161 {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
159 162 {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
160 163 {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
161 164 {NULL, NULL}
162 165 };
163 166
164 167 #ifdef IS_PY3K
165 168 static struct PyModuleDef diffhelpers_module = {
166 169 PyModuleDef_HEAD_INIT,
167 170 "diffhelpers",
168 171 diffhelpers_doc,
169 172 -1,
170 173 methods
171 174 };
172 175
173 176 PyMODINIT_FUNC PyInit_diffhelpers(void)
174 177 {
175 178 PyObject *m;
176 179
177 180 m = PyModule_Create(&diffhelpers_module);
178 181 if (m == NULL)
179 182 return NULL;
180 183
181 184 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
182 185 NULL, NULL);
183 186 Py_INCREF(diffhelpers_Error);
184 187 PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
185 188
186 189 return m;
187 190 }
188 191 #else
189 192 PyMODINIT_FUNC
190 193 initdiffhelpers(void)
191 194 {
192 195 Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
193 196 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
194 197 NULL, NULL);
195 198 }
196 199 #endif
197
General Comments 0
You need to be logged in to leave comments. Login now