Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/mpatch.c @ 5444:a0952e4e52eb
mpatch: allow buffer objects for input
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 11 Oct 2007 00:46:45 -0500 |
parents | 4759da3e4dc8 |
children | cd1a6e7216c5 b0e5f44fdeb3 |
comparison
equal
deleted
inserted
replaced
5443:58496354773f | 5444:a0952e4e52eb |
---|---|
53 static char mpatch_doc[] = "Efficient binary patching."; | 53 static char mpatch_doc[] = "Efficient binary patching."; |
54 static PyObject *mpatch_Error; | 54 static PyObject *mpatch_Error; |
55 | 55 |
56 struct frag { | 56 struct frag { |
57 int start, end, len; | 57 int start, end, len; |
58 char *data; | 58 const char *data; |
59 }; | 59 }; |
60 | 60 |
61 struct flist { | 61 struct flist { |
62 struct frag *base, *head, *tail; | 62 struct frag *base, *head, *tail; |
63 }; | 63 }; |
219 lfree(b); | 219 lfree(b); |
220 return c; | 220 return c; |
221 } | 221 } |
222 | 222 |
223 /* decode a binary patch into a hunk list */ | 223 /* decode a binary patch into a hunk list */ |
224 static struct flist *decode(char *bin, int len) | 224 static struct flist *decode(const char *bin, int len) |
225 { | 225 { |
226 struct flist *l; | 226 struct flist *l; |
227 struct frag *lt; | 227 struct frag *lt; |
228 char *data = bin + 12, *end = bin + len; | 228 const char *data = bin + 12, *end = bin + len; |
229 char decode[12]; /* for dealing with alignment issues */ | 229 char decode[12]; /* for dealing with alignment issues */ |
230 | 230 |
231 /* assume worst case size, we won't have many of these lists */ | 231 /* assume worst case size, we won't have many of these lists */ |
232 l = lalloc(len / 12); | 232 l = lalloc(len / 12); |
233 if (!l) | 233 if (!l) |
282 | 282 |
283 outlen += len - last; | 283 outlen += len - last; |
284 return outlen; | 284 return outlen; |
285 } | 285 } |
286 | 286 |
287 static int apply(char *buf, char *orig, int len, struct flist *l) | 287 static int apply(char *buf, const char *orig, int len, struct flist *l) |
288 { | 288 { |
289 struct frag *f = l->head; | 289 struct frag *f = l->head; |
290 int last = 0; | 290 int last = 0; |
291 char *p = buf; | 291 char *p = buf; |
292 | 292 |
310 | 310 |
311 /* recursively generate a patch of all bins between start and end */ | 311 /* recursively generate a patch of all bins between start and end */ |
312 static struct flist *fold(PyObject *bins, int start, int end) | 312 static struct flist *fold(PyObject *bins, int start, int end) |
313 { | 313 { |
314 int len; | 314 int len; |
315 ssize_t blen; | |
316 const char *buffer; | |
315 | 317 |
316 if (start + 1 == end) { | 318 if (start + 1 == end) { |
317 /* trivial case, output a decoded list */ | 319 /* trivial case, output a decoded list */ |
318 PyObject *tmp = PyList_GetItem(bins, start); | 320 PyObject *tmp = PyList_GetItem(bins, start); |
319 if (!tmp) | 321 if (!tmp) |
320 return NULL; | 322 return NULL; |
321 return decode(PyString_AsString(tmp), PyString_Size(tmp)); | 323 if (PyObject_AsCharBuffer(tmp, &buffer, &blen)) |
324 return NULL; | |
325 return decode(buffer, blen); | |
322 } | 326 } |
323 | 327 |
324 /* divide and conquer, memory management is elsewhere */ | 328 /* divide and conquer, memory management is elsewhere */ |
325 len = (end - start) / 2; | 329 len = (end - start) / 2; |
326 return combine(fold(bins, start, start + len), | 330 return combine(fold(bins, start, start + len), |
330 static PyObject * | 334 static PyObject * |
331 patches(PyObject *self, PyObject *args) | 335 patches(PyObject *self, PyObject *args) |
332 { | 336 { |
333 PyObject *text, *bins, *result; | 337 PyObject *text, *bins, *result; |
334 struct flist *patch; | 338 struct flist *patch; |
335 char *in, *out; | 339 const char *in; |
340 char *out; | |
336 int len, outlen; | 341 int len, outlen; |
337 | 342 ssize_t inlen; |
338 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins)) | 343 |
344 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) | |
339 return NULL; | 345 return NULL; |
340 | 346 |
341 len = PyList_Size(bins); | 347 len = PyList_Size(bins); |
342 if (!len) { | 348 if (!len) { |
343 /* nothing to do */ | 349 /* nothing to do */ |
344 Py_INCREF(text); | 350 Py_INCREF(text); |
345 return text; | 351 return text; |
346 } | 352 } |
347 | 353 |
354 if (PyObject_AsCharBuffer(text, &in, &inlen)) | |
355 return NULL; | |
356 | |
348 patch = fold(bins, 0, len); | 357 patch = fold(bins, 0, len); |
349 if (!patch) | 358 if (!patch) |
350 return NULL; | 359 return NULL; |
351 | 360 |
352 outlen = calcsize(PyString_Size(text), patch); | 361 outlen = calcsize(inlen, patch); |
353 if (outlen < 0) { | 362 if (outlen < 0) { |
354 result = NULL; | 363 result = NULL; |
355 goto cleanup; | 364 goto cleanup; |
356 } | 365 } |
357 result = PyString_FromStringAndSize(NULL, outlen); | 366 result = PyString_FromStringAndSize(NULL, outlen); |
358 if (!result) { | 367 if (!result) { |
359 result = NULL; | 368 result = NULL; |
360 goto cleanup; | 369 goto cleanup; |
361 } | 370 } |
362 in = PyString_AsString(text); | |
363 out = PyString_AsString(result); | 371 out = PyString_AsString(result); |
364 if (!apply(out, in, PyString_Size(text), patch)) { | 372 if (!apply(out, in, inlen, patch)) { |
365 Py_DECREF(result); | 373 Py_DECREF(result); |
366 result = NULL; | 374 result = NULL; |
367 } | 375 } |
368 cleanup: | 376 cleanup: |
369 lfree(patch); | 377 lfree(patch); |