27 struct bdiff_hunk l, *h; |
27 struct bdiff_hunk l, *h; |
28 int an, bn, count, pos = 0; |
28 int an, bn, count, pos = 0; |
29 |
29 |
30 l.next = NULL; |
30 l.next = NULL; |
31 |
31 |
32 if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb)) |
32 if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb)) { |
33 return NULL; |
33 return NULL; |
|
34 } |
34 |
35 |
35 an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a); |
36 an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a); |
36 bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b); |
37 bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b); |
37 |
38 |
38 if (!a || !b) |
39 if (!a || !b) { |
39 goto nomem; |
40 goto nomem; |
|
41 } |
40 |
42 |
41 count = bdiff_diff(a, an, b, bn, &l); |
43 count = bdiff_diff(a, an, b, bn, &l); |
42 if (count < 0) |
44 if (count < 0) { |
43 goto nomem; |
45 goto nomem; |
|
46 } |
44 |
47 |
45 rl = PyList_New(count); |
48 rl = PyList_New(count); |
46 if (!rl) |
49 if (!rl) { |
47 goto nomem; |
50 goto nomem; |
|
51 } |
48 |
52 |
49 for (h = l.next; h; h = h->next) { |
53 for (h = l.next; h; h = h->next) { |
50 m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2); |
54 m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2); |
51 PyList_SetItem(rl, pos, m); |
55 PyList_SetItem(rl, pos, m); |
52 pos++; |
56 pos++; |
70 Py_ssize_t len = 0, la, lb, li = 0, lcommon = 0, lmax; |
74 Py_ssize_t len = 0, la, lb, li = 0, lcommon = 0, lmax; |
71 PyThreadState *_save = NULL; |
75 PyThreadState *_save = NULL; |
72 |
76 |
73 l.next = NULL; |
77 l.next = NULL; |
74 |
78 |
75 if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, &bb)) |
79 if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, |
|
80 &bb)) { |
76 return NULL; |
81 return NULL; |
|
82 } |
77 |
83 |
78 if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) { |
84 if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) { |
79 PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous"); |
85 PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous"); |
80 goto cleanup; |
86 goto cleanup; |
81 } |
87 } |
96 _save = PyEval_SaveThread(); |
102 _save = PyEval_SaveThread(); |
97 |
103 |
98 lmax = la > lb ? lb : la; |
104 lmax = la > lb ? lb : la; |
99 for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib; |
105 for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib; |
100 ++li, ++ia, ++ib) { |
106 ++li, ++ia, ++ib) { |
101 if (*ia == '\n') |
107 if (*ia == '\n') { |
102 lcommon = li + 1; |
108 lcommon = li + 1; |
|
109 } |
103 } |
110 } |
104 /* we can almost add: if (li == lmax) lcommon = li; */ |
111 /* we can almost add: if (li == lmax) lcommon = li; */ |
105 |
112 |
106 an = bdiff_splitlines((char *)ba.buf + lcommon, la - lcommon, &al); |
113 an = bdiff_splitlines((char *)ba.buf + lcommon, la - lcommon, &al); |
107 bn = bdiff_splitlines((char *)bb.buf + lcommon, lb - lcommon, &bl); |
114 bn = bdiff_splitlines((char *)bb.buf + lcommon, lb - lcommon, &bl); |
117 } |
124 } |
118 |
125 |
119 /* calculate length of output */ |
126 /* calculate length of output */ |
120 la = lb = 0; |
127 la = lb = 0; |
121 for (h = l.next; h; h = h->next) { |
128 for (h = l.next; h; h = h->next) { |
122 if (h->a1 != la || h->b1 != lb) |
129 if (h->a1 != la || h->b1 != lb) { |
123 len += 12 + bl[h->b1].l - bl[lb].l; |
130 len += 12 + bl[h->b1].l - bl[lb].l; |
|
131 } |
124 la = h->a2; |
132 la = h->a2; |
125 lb = h->b2; |
133 lb = h->b2; |
126 } |
134 } |
127 PyEval_RestoreThread(_save); |
135 PyEval_RestoreThread(_save); |
128 _save = NULL; |
136 _save = NULL; |
129 |
137 |
130 result = PyBytes_FromStringAndSize(NULL, len); |
138 result = PyBytes_FromStringAndSize(NULL, len); |
131 |
139 |
132 if (!result) |
140 if (!result) { |
133 goto cleanup; |
141 goto cleanup; |
|
142 } |
134 |
143 |
135 /* build binary patch */ |
144 /* build binary patch */ |
136 rb = PyBytes_AsString(result); |
145 rb = PyBytes_AsString(result); |
137 la = lb = 0; |
146 la = lb = 0; |
138 |
147 |
172 char allws, c; |
182 char allws, c; |
173 const char *r; |
183 const char *r; |
174 Py_ssize_t i, rlen, wlen = 0; |
184 Py_ssize_t i, rlen, wlen = 0; |
175 char *w; |
185 char *w; |
176 |
186 |
177 if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws)) |
187 if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws)) { |
178 return NULL; |
188 return NULL; |
|
189 } |
179 r = PyBytes_AsString(s); |
190 r = PyBytes_AsString(s); |
180 rlen = PyBytes_Size(s); |
191 rlen = PyBytes_Size(s); |
181 |
192 |
182 w = (char *)PyMem_Malloc(rlen ? rlen : 1); |
193 w = (char *)PyMem_Malloc(rlen ? rlen : 1); |
183 if (!w) |
194 if (!w) { |
184 goto nomem; |
195 goto nomem; |
|
196 } |
185 |
197 |
186 for (i = 0; i != rlen; i++) { |
198 for (i = 0; i != rlen; i++) { |
187 c = r[i]; |
199 c = r[i]; |
188 if (c == ' ' || c == '\t' || c == '\r') { |
200 if (c == ' ' || c == '\t' || c == '\r') { |
189 if (!allws && (wlen == 0 || w[wlen - 1] != ' ')) |
201 if (!allws && (wlen == 0 || w[wlen - 1] != ' ')) { |
190 w[wlen++] = ' '; |
202 w[wlen++] = ' '; |
|
203 } |
191 } else if (c == '\n' && !allws && wlen > 0 && |
204 } else if (c == '\n' && !allws && wlen > 0 && |
192 w[wlen - 1] == ' ') { |
205 w[wlen - 1] == ' ') { |
193 w[wlen - 1] = '\n'; |
206 w[wlen - 1] = '\n'; |
194 } else { |
207 } else { |
195 w[wlen++] = c; |
208 w[wlen++] = c; |
205 |
218 |
206 static bool sliceintolist(PyObject *list, Py_ssize_t destidx, |
219 static bool sliceintolist(PyObject *list, Py_ssize_t destidx, |
207 const char *source, Py_ssize_t len) |
220 const char *source, Py_ssize_t len) |
208 { |
221 { |
209 PyObject *sliced = PyBytes_FromStringAndSize(source, len); |
222 PyObject *sliced = PyBytes_FromStringAndSize(source, len); |
210 if (sliced == NULL) |
223 if (sliced == NULL) { |
211 return false; |
224 return false; |
|
225 } |
212 PyList_SET_ITEM(list, destidx, sliced); |
226 PyList_SET_ITEM(list, destidx, sliced); |
213 return true; |
227 return true; |
214 } |
228 } |
215 |
229 |
216 static PyObject *splitnewlines(PyObject *self, PyObject *args) |
230 static PyObject *splitnewlines(PyObject *self, PyObject *args) |
230 for (i = 0; i < size - 1; ++i) { |
244 for (i = 0; i < size - 1; ++i) { |
231 if (text[i] == '\n') { |
245 if (text[i] == '\n') { |
232 ++nelts; |
246 ++nelts; |
233 } |
247 } |
234 } |
248 } |
235 if ((result = PyList_New(nelts + 1)) == NULL) |
249 if ((result = PyList_New(nelts + 1)) == NULL) { |
236 goto abort; |
250 goto abort; |
|
251 } |
237 nelts = 0; |
252 nelts = 0; |
238 for (i = 0; i < size - 1; ++i) { |
253 for (i = 0; i < size - 1; ++i) { |
239 if (text[i] == '\n') { |
254 if (text[i] == '\n') { |
240 if (!sliceintolist(result, nelts++, text + start, |
255 if (!sliceintolist(result, nelts++, text + start, |
241 i - start + 1)) |
256 i - start + 1)) { |
242 goto abort; |
257 goto abort; |
|
258 } |
243 start = i + 1; |
259 start = i + 1; |
244 } |
260 } |
245 } |
261 } |
246 if (!sliceintolist(result, nelts++, text + start, size - start)) |
262 if (!sliceintolist(result, nelts++, text + start, size - start)) { |
247 goto abort; |
263 goto abort; |
|
264 } |
248 return result; |
265 return result; |
249 abort: |
266 abort: |
250 Py_XDECREF(result); |
267 Py_XDECREF(result); |
251 return NULL; |
268 return NULL; |
252 } |
269 } |
255 void *priv) |
272 void *priv) |
256 { |
273 { |
257 PyObject *rl = (PyObject *)priv; |
274 PyObject *rl = (PyObject *)priv; |
258 PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2); |
275 PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2); |
259 int r; |
276 int r; |
260 if (!m) |
277 if (!m) { |
261 return -1; |
278 return -1; |
|
279 } |
262 r = PyList_Append(rl, m); |
280 r = PyList_Append(rl, m); |
263 Py_DECREF(m); |
281 Py_DECREF(m); |
264 return r; |
282 return r; |
265 } |
283 } |
266 |
284 |
280 xdemitcb_t ecb = { |
298 xdemitcb_t ecb = { |
281 NULL, /* priv */ |
299 NULL, /* priv */ |
282 }; |
300 }; |
283 |
301 |
284 if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr, |
302 if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr, |
285 &lb)) |
303 &lb)) { |
286 return NULL; |
304 return NULL; |
|
305 } |
287 |
306 |
288 a.size = la; |
307 a.size = la; |
289 b.size = lb; |
308 b.size = lb; |
290 |
309 |
291 rl = PyList_New(0); |
310 rl = PyList_New(0); |
292 if (!rl) |
311 if (!rl) { |
293 return PyErr_NoMemory(); |
312 return PyErr_NoMemory(); |
|
313 } |
294 |
314 |
295 ecb.priv = rl; |
315 ecb.priv = rl; |
296 |
316 |
297 if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) { |
317 if (xdl_diff(&a, &b, &xpp, &xecfg, &ecb) != 0) { |
298 Py_DECREF(rl); |
318 Py_DECREF(rl); |