178 nomem: |
178 nomem: |
179 PyMem_Free(w); |
179 PyMem_Free(w); |
180 return result ? result : PyErr_NoMemory(); |
180 return result ? result : PyErr_NoMemory(); |
181 } |
181 } |
182 |
182 |
|
183 static bool sliceintolist(PyObject *list, Py_ssize_t destidx, |
|
184 const char *source, Py_ssize_t len) |
|
185 { |
|
186 PyObject *sliced = PyBytes_FromStringAndSize(source, len); |
|
187 if (sliced == NULL) |
|
188 return false; |
|
189 PyList_SET_ITEM(list, destidx, sliced); |
|
190 return true; |
|
191 } |
|
192 |
|
193 static PyObject *splitnewlines(PyObject *self, PyObject *args) |
|
194 { |
|
195 const char *text; |
|
196 Py_ssize_t nelts = 0, size, i, start = 0; |
|
197 PyObject *result = NULL; |
|
198 |
|
199 if (!PyArg_ParseTuple(args, "s#", &text, &size)) { |
|
200 goto abort; |
|
201 } |
|
202 if (!size) { |
|
203 return PyList_New(0); |
|
204 } |
|
205 /* This loops to size-1 because if the last byte is a newline, |
|
206 * we don't want to perform a split there. */ |
|
207 for (i = 0; i < size - 1; ++i) { |
|
208 if (text[i] == '\n') { |
|
209 ++nelts; |
|
210 } |
|
211 } |
|
212 if ((result = PyList_New(nelts + 1)) == NULL) |
|
213 goto abort; |
|
214 nelts = 0; |
|
215 for (i = 0; i < size - 1; ++i) { |
|
216 if (text[i] == '\n') { |
|
217 if (!sliceintolist(result, nelts++, text + start, |
|
218 i - start + 1)) |
|
219 goto abort; |
|
220 start = i + 1; |
|
221 } |
|
222 } |
|
223 if (!sliceintolist(result, nelts++, text + start, size - start)) |
|
224 goto abort; |
|
225 return result; |
|
226 abort: |
|
227 Py_XDECREF(result); |
|
228 return NULL; |
|
229 } |
|
230 |
183 static char mdiff_doc[] = "Efficient binary diff."; |
231 static char mdiff_doc[] = "Efficient binary diff."; |
184 |
232 |
185 static PyMethodDef methods[] = { |
233 static PyMethodDef methods[] = { |
186 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"}, |
234 {"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"}, |
187 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"}, |
235 {"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"}, |
188 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"}, |
236 {"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"}, |
|
237 {"splitnewlines", splitnewlines, METH_VARARGS, |
|
238 "like str.splitlines, but only split on newlines\n"}, |
189 {NULL, NULL}, |
239 {NULL, NULL}, |
190 }; |
240 }; |
191 |
241 |
192 static const int version = 1; |
242 static const int version = 2; |
193 |
243 |
194 #ifdef IS_PY3K |
244 #ifdef IS_PY3K |
195 static struct PyModuleDef bdiff_module = { |
245 static struct PyModuleDef bdiff_module = { |
196 PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods, |
246 PyModuleDef_HEAD_INIT, "bdiff", mdiff_doc, -1, methods, |
197 }; |
247 }; |