comparison mercurial/mpatch.c @ 29706:6b3a8d034b69

mpatch: provide things that will be exported later with a prefixed name For cffi a bunch of mpatch functions need to be visible through a .h file. This change renames them so it won't create potential c namespace conflicts.
author Maciej Fijalkowski <fijall@gmail.com>
date Mon, 18 Jul 2016 16:25:14 +0200
parents e9a0bcc9314d
children b9b9f9a92481
comparison
equal deleted inserted replaced
29705:e9a0bcc9314d 29706:6b3a8d034b69
30 #include "compat.h" 30 #include "compat.h"
31 31
32 static char mpatch_doc[] = "Efficient binary patching."; 32 static char mpatch_doc[] = "Efficient binary patching.";
33 static PyObject *mpatch_Error; 33 static PyObject *mpatch_Error;
34 34
35 struct frag { 35 struct mpatch_frag {
36 int start, end, len; 36 int start, end, len;
37 const char *data; 37 const char *data;
38 }; 38 };
39 39
40 struct flist { 40 struct mpatch_flist {
41 struct frag *base, *head, *tail; 41 struct mpatch_frag *base, *head, *tail;
42 }; 42 };
43 43
44 static struct flist *lalloc(ssize_t size) 44 static struct mpatch_flist *lalloc(ssize_t size)
45 { 45 {
46 struct flist *a = NULL; 46 struct mpatch_flist *a = NULL;
47 47
48 if (size < 1) 48 if (size < 1)
49 size = 1; 49 size = 1;
50 50
51 a = (struct flist *)malloc(sizeof(struct flist)); 51 a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist));
52 if (a) { 52 if (a) {
53 a->base = (struct frag *)malloc(sizeof(struct frag) * size); 53 a->base = (struct mpatch_frag *)malloc(sizeof(struct mpatch_frag) * size);
54 if (a->base) { 54 if (a->base) {
55 a->head = a->tail = a->base; 55 a->head = a->tail = a->base;
56 return a; 56 return a;
57 } 57 }
58 free(a); 58 free(a);
61 if (!PyErr_Occurred()) 61 if (!PyErr_Occurred())
62 PyErr_NoMemory(); 62 PyErr_NoMemory();
63 return NULL; 63 return NULL;
64 } 64 }
65 65
66 static void lfree(struct flist *a) 66 static void mpatch_lfree(struct mpatch_flist *a)
67 { 67 {
68 if (a) { 68 if (a) {
69 free(a->base); 69 free(a->base);
70 free(a); 70 free(a);
71 } 71 }
72 } 72 }
73 73
74 static ssize_t lsize(struct flist *a) 74 static ssize_t lsize(struct mpatch_flist *a)
75 { 75 {
76 return a->tail - a->head; 76 return a->tail - a->head;
77 } 77 }
78 78
79 /* move hunks in source that are less cut to dest, compensating 79 /* move hunks in source that are less cut to dest, compensating
80 for changes in offset. the last hunk may be split if necessary. 80 for changes in offset. the last hunk may be split if necessary.
81 */ 81 */
82 static int gather(struct flist *dest, struct flist *src, int cut, int offset) 82 static int gather(struct mpatch_flist *dest, struct mpatch_flist *src, int cut,
83 { 83 int offset)
84 struct frag *d = dest->tail, *s = src->head; 84 {
85 struct mpatch_frag *d = dest->tail, *s = src->head;
85 int postend, c, l; 86 int postend, c, l;
86 87
87 while (s != src->tail) { 88 while (s != src->tail) {
88 if (s->start + offset >= cut) 89 if (s->start + offset >= cut)
89 break; /* we've gone far enough */ 90 break; /* we've gone far enough */
122 src->head = s; 123 src->head = s;
123 return offset; 124 return offset;
124 } 125 }
125 126
126 /* like gather, but with no output list */ 127 /* like gather, but with no output list */
127 static int discard(struct flist *src, int cut, int offset) 128 static int discard(struct mpatch_flist *src, int cut, int offset)
128 { 129 {
129 struct frag *s = src->head; 130 struct mpatch_frag *s = src->head;
130 int postend, c, l; 131 int postend, c, l;
131 132
132 while (s != src->tail) { 133 while (s != src->tail) {
133 if (s->start + offset >= cut) 134 if (s->start + offset >= cut)
134 break; 135 break;
159 return offset; 160 return offset;
160 } 161 }
161 162
162 /* combine hunk lists a and b, while adjusting b for offset changes in a/ 163 /* combine hunk lists a and b, while adjusting b for offset changes in a/
163 this deletes a and b and returns the resultant list. */ 164 this deletes a and b and returns the resultant list. */
164 static struct flist *combine(struct flist *a, struct flist *b) 165 static struct mpatch_flist *combine(struct mpatch_flist *a,
165 { 166 struct mpatch_flist *b)
166 struct flist *c = NULL; 167 {
167 struct frag *bh, *ct; 168 struct mpatch_flist *c = NULL;
169 struct mpatch_frag *bh, *ct;
168 int offset = 0, post; 170 int offset = 0, post;
169 171
170 if (a && b) 172 if (a && b)
171 c = lalloc((lsize(a) + lsize(b)) * 2); 173 c = lalloc((lsize(a) + lsize(b)) * 2);
172 174
188 c->tail++; 190 c->tail++;
189 offset = post; 191 offset = post;
190 } 192 }
191 193
192 /* hold on to tail from a */ 194 /* hold on to tail from a */
193 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); 195 memcpy(c->tail, a->head, sizeof(struct mpatch_frag) * lsize(a));
194 c->tail += lsize(a); 196 c->tail += lsize(a);
195 } 197 }
196 198
197 lfree(a); 199 mpatch_lfree(a);
198 lfree(b); 200 mpatch_lfree(b);
199 return c; 201 return c;
200 } 202 }
201 203
202 /* decode a binary patch into a hunk list */ 204 /* decode a binary patch into a hunk list */
203 static struct flist *decode(const char *bin, ssize_t len) 205 static struct mpatch_flist *mpatch_decode(const char *bin, ssize_t len)
204 { 206 {
205 struct flist *l; 207 struct mpatch_flist *l;
206 struct frag *lt; 208 struct mpatch_frag *lt;
207 int pos = 0; 209 int pos = 0;
208 210
209 /* assume worst case size, we won't have many of these lists */ 211 /* assume worst case size, we won't have many of these lists */
210 l = lalloc(len / 12 + 1); 212 l = lalloc(len / 12 + 1);
211 if (!l) 213 if (!l)
225 } 227 }
226 228
227 if (pos != len) { 229 if (pos != len) {
228 if (!PyErr_Occurred()) 230 if (!PyErr_Occurred())
229 PyErr_SetString(mpatch_Error, "patch cannot be decoded"); 231 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
230 lfree(l); 232 mpatch_lfree(l);
231 return NULL; 233 return NULL;
232 } 234 }
233 235
234 l->tail = lt; 236 l->tail = lt;
235 return l; 237 return l;
236 } 238 }
237 239
238 /* calculate the size of resultant text */ 240 /* calculate the size of resultant text */
239 static ssize_t calcsize(ssize_t len, struct flist *l) 241 static ssize_t mpatch_calcsize(ssize_t len, struct mpatch_flist *l)
240 { 242 {
241 ssize_t outlen = 0, last = 0; 243 ssize_t outlen = 0, last = 0;
242 struct frag *f = l->head; 244 struct mpatch_frag *f = l->head;
243 245
244 while (f != l->tail) { 246 while (f != l->tail) {
245 if (f->start < last || f->end > len) { 247 if (f->start < last || f->end > len) {
246 if (!PyErr_Occurred()) 248 if (!PyErr_Occurred())
247 PyErr_SetString(mpatch_Error, 249 PyErr_SetString(mpatch_Error,
256 258
257 outlen += len - last; 259 outlen += len - last;
258 return outlen; 260 return outlen;
259 } 261 }
260 262
261 static int apply(char *buf, const char *orig, ssize_t len, struct flist *l) 263 static int mpatch_apply(char *buf, const char *orig, ssize_t len,
262 { 264 struct mpatch_flist *l)
263 struct frag *f = l->head; 265 {
266 struct mpatch_frag *f = l->head;
264 int last = 0; 267 int last = 0;
265 char *p = buf; 268 char *p = buf;
266 269
267 while (f != l->tail) { 270 while (f != l->tail) {
268 if (f->start < last || f->end > len) { 271 if (f->start < last || f->end > len) {
281 memcpy(p, orig + last, len - last); 284 memcpy(p, orig + last, len - last);
282 return 1; 285 return 1;
283 } 286 }
284 287
285 /* recursively generate a patch of all bins between start and end */ 288 /* recursively generate a patch of all bins between start and end */
286 static struct flist *fold(PyObject *bins, ssize_t start, ssize_t end) 289 static struct mpatch_flist *mpatch_fold(PyObject *bins, ssize_t start,
290 ssize_t end)
287 { 291 {
288 ssize_t len, blen; 292 ssize_t len, blen;
289 const char *buffer; 293 const char *buffer;
290 294
291 if (start + 1 == end) { 295 if (start + 1 == end) {
293 PyObject *tmp = PyList_GetItem(bins, start); 297 PyObject *tmp = PyList_GetItem(bins, start);
294 if (!tmp) 298 if (!tmp)
295 return NULL; 299 return NULL;
296 if (PyObject_AsCharBuffer(tmp, &buffer, &blen)) 300 if (PyObject_AsCharBuffer(tmp, &buffer, &blen))
297 return NULL; 301 return NULL;
298 return decode(buffer, blen); 302 return mpatch_decode(buffer, blen);
299 } 303 }
300 304
301 /* divide and conquer, memory management is elsewhere */ 305 /* divide and conquer, memory management is elsewhere */
302 len = (end - start) / 2; 306 len = (end - start) / 2;
303 return combine(fold(bins, start, start + len), 307 return combine(mpatch_fold(bins, start, start + len),
304 fold(bins, start + len, end)); 308 mpatch_fold(bins, start + len, end));
305 } 309 }
306 310
307 static PyObject * 311 static PyObject *
308 patches(PyObject *self, PyObject *args) 312 patches(PyObject *self, PyObject *args)
309 { 313 {
310 PyObject *text, *bins, *result; 314 PyObject *text, *bins, *result;
311 struct flist *patch; 315 struct mpatch_flist *patch;
312 const char *in; 316 const char *in;
313 char *out; 317 char *out;
314 Py_ssize_t len, outlen, inlen; 318 Py_ssize_t len, outlen, inlen;
315 319
316 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) 320 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins))
324 } 328 }
325 329
326 if (PyObject_AsCharBuffer(text, &in, &inlen)) 330 if (PyObject_AsCharBuffer(text, &in, &inlen))
327 return NULL; 331 return NULL;
328 332
329 patch = fold(bins, 0, len); 333 patch = mpatch_fold(bins, 0, len);
330 if (!patch) 334 if (!patch)
331 return NULL; 335 return NULL;
332 336
333 outlen = calcsize(inlen, patch); 337 outlen = mpatch_calcsize(inlen, patch);
334 if (outlen < 0) { 338 if (outlen < 0) {
335 result = NULL; 339 result = NULL;
336 goto cleanup; 340 goto cleanup;
337 } 341 }
338 result = PyBytes_FromStringAndSize(NULL, outlen); 342 result = PyBytes_FromStringAndSize(NULL, outlen);
339 if (!result) { 343 if (!result) {
340 result = NULL; 344 result = NULL;
341 goto cleanup; 345 goto cleanup;
342 } 346 }
343 out = PyBytes_AsString(result); 347 out = PyBytes_AsString(result);
344 if (!apply(out, in, inlen, patch)) { 348 if (!mpatch_apply(out, in, inlen, patch)) {
345 Py_DECREF(result); 349 Py_DECREF(result);
346 result = NULL; 350 result = NULL;
347 } 351 }
348 cleanup: 352 cleanup:
349 lfree(patch); 353 mpatch_lfree(patch);
350 return result; 354 return result;
351 } 355 }
352 356
353 /* calculate size of a patched file directly */ 357 /* calculate size of a patched file directly */
354 static PyObject * 358 static PyObject *