##// END OF EJS Templates
mpatch: remove dependency on Python.h in mpatch.c...
Maciej Fijalkowski -
r29694:55dd1220 default
parent child Browse files
Show More
@@ -20,26 +20,15 b''
20 of the GNU General Public License, incorporated herein by reference.
20 of the GNU General Public License, incorporated herein by reference.
21 */
21 */
22
22
23 #define PY_SSIZE_T_CLEAN
24 #include <Python.h>
25 #include <stdlib.h>
23 #include <stdlib.h>
26 #include <string.h>
24 #include <string.h>
27
25
28 #include "util.h"
29 #include "bitmanipulation.h"
26 #include "bitmanipulation.h"
30 #include "compat.h"
27 #include "compat.h"
31
28 #include "mpatch.h"
32 static char mpatch_doc[] = "Efficient binary patching.";
33 static PyObject *mpatch_Error;
34
29
35 struct mpatch_frag {
30 char *mpatch_errors[] = {NULL, "invalid patch", "patch cannot be decoded",
36 int start, end, len;
31 "no memory"};
37 const char *data;
38 };
39
40 struct mpatch_flist {
41 struct mpatch_frag *base, *head, *tail;
42 };
43
32
44 struct mpatch_flist *lalloc(ssize_t size)
33 struct mpatch_flist *lalloc(ssize_t size)
45 {
34 {
@@ -56,10 +45,7 b' struct mpatch_flist *lalloc(ssize_t size'
56 return a;
45 return a;
57 }
46 }
58 free(a);
47 free(a);
59 a = NULL;
60 }
48 }
61 if (!PyErr_Occurred())
62 PyErr_NoMemory();
63 return NULL;
49 return NULL;
64 }
50 }
65
51
@@ -202,7 +188,7 b' static struct mpatch_flist *combine(stru'
202 }
188 }
203
189
204 /* decode a binary patch into a hunk list */
190 /* decode a binary patch into a hunk list */
205 struct mpatch_flist *mpatch_decode(const char *bin, ssize_t len)
191 int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist **res)
206 {
192 {
207 struct mpatch_flist *l;
193 struct mpatch_flist *l;
208 struct mpatch_frag *lt;
194 struct mpatch_frag *lt;
@@ -211,7 +197,7 b' struct mpatch_flist *mpatch_decode(const'
211 /* assume worst case size, we won't have many of these lists */
197 /* assume worst case size, we won't have many of these lists */
212 l = lalloc(len / 12 + 1);
198 l = lalloc(len / 12 + 1);
213 if (!l)
199 if (!l)
214 return NULL;
200 return MPATCH_ERR_NO_MEM;
215
201
216 lt = l->tail;
202 lt = l->tail;
217
203
@@ -227,14 +213,13 b' struct mpatch_flist *mpatch_decode(const'
227 }
213 }
228
214
229 if (pos != len) {
215 if (pos != len) {
230 if (!PyErr_Occurred())
231 PyErr_SetString(mpatch_Error, "patch cannot be decoded");
232 mpatch_lfree(l);
216 mpatch_lfree(l);
233 return NULL;
217 return MPATCH_ERR_CANNOT_BE_DECODED;
234 }
218 }
235
219
236 l->tail = lt;
220 l->tail = lt;
237 return l;
221 *res = l;
222 return 0;
238 }
223 }
239
224
240 /* calculate the size of resultant text */
225 /* calculate the size of resultant text */
@@ -245,10 +230,7 b' ssize_t mpatch_calcsize(ssize_t len, str'
245
230
246 while (f != l->tail) {
231 while (f != l->tail) {
247 if (f->start < last || f->end > len) {
232 if (f->start < last || f->end > len) {
248 if (!PyErr_Occurred())
233 return MPATCH_ERR_INVALID_PATCH;
249 PyErr_SetString(mpatch_Error,
250 "invalid patch");
251 return -1;
252 }
234 }
253 outlen += f->start - last;
235 outlen += f->start - last;
254 last = f->end;
236 last = f->end;
@@ -269,10 +251,7 b' int mpatch_apply(char *buf, const char *'
269
251
270 while (f != l->tail) {
252 while (f != l->tail) {
271 if (f->start < last || f->end > len) {
253 if (f->start < last || f->end > len) {
272 if (!PyErr_Occurred())
254 return MPATCH_ERR_INVALID_PATCH;
273 PyErr_SetString(mpatch_Error,
274 "invalid patch");
275 return 0;
276 }
255 }
277 memcpy(p, orig + last, f->start - last);
256 memcpy(p, orig + last, f->start - last);
278 p += f->start - last;
257 p += f->start - last;
@@ -282,29 +261,24 b' int mpatch_apply(char *buf, const char *'
282 f++;
261 f++;
283 }
262 }
284 memcpy(p, orig + last, len - last);
263 memcpy(p, orig + last, len - last);
285 return 1;
264 return 0;
286 }
265 }
287
266
288 /* recursively generate a patch of all bins between start and end */
267 /* recursively generate a patch of all bins between start and end */
289 struct mpatch_flist *mpatch_fold(PyObject *bins, ssize_t start,
268 struct mpatch_flist *mpatch_fold(void *bins,
290 ssize_t end)
269 struct mpatch_flist* (*get_next_item)(void*, ssize_t),
270 ssize_t start, ssize_t end)
291 {
271 {
292 ssize_t len, blen;
272 ssize_t len;
293 const char *buffer;
294
273
295 if (start + 1 == end) {
274 if (start + 1 == end) {
296 /* trivial case, output a decoded list */
275 /* trivial case, output a decoded list */
297 PyObject *tmp = PyList_GetItem(bins, start);
276 return get_next_item(bins, start);
298 if (!tmp)
299 return NULL;
300 if (PyObject_AsCharBuffer(tmp, &buffer, &blen))
301 return NULL;
302 return mpatch_decode(buffer, blen);
303 }
277 }
304
278
305 /* divide and conquer, memory management is elsewhere */
279 /* divide and conquer, memory management is elsewhere */
306 len = (end - start) / 2;
280 len = (end - start) / 2;
307 return combine(mpatch_fold(bins, start, start + len),
281 return combine(mpatch_fold(bins, get_next_item, start, start + len),
308 mpatch_fold(bins, start + len, end));
282 mpatch_fold(bins, get_next_item, start + len, end));
309 }
283 }
310
284
@@ -1,6 +1,12 b''
1 #ifndef _HG_MPATCH_H_
1 #ifndef _HG_MPATCH_H_
2 #define _HG_MPATCH_H_
2 #define _HG_MPATCH_H_
3
3
4 extern char *mpatch_errors[];
5
6 #define MPATCH_ERR_NO_MEM -3
7 #define MPATCH_ERR_CANNOT_BE_DECODED -2
8 #define MPATCH_ERR_INVALID_PATCH -1
9
4 struct mpatch_frag {
10 struct mpatch_frag {
5 int start, end, len;
11 int start, end, len;
6 const char *data;
12 const char *data;
@@ -15,6 +21,8 b' ssize_t mpatch_calcsize(ssize_t len, str'
15 void mpatch_lfree(struct mpatch_flist *a);
21 void mpatch_lfree(struct mpatch_flist *a);
16 int mpatch_apply(char *buf, const char *orig, ssize_t len,
22 int mpatch_apply(char *buf, const char *orig, ssize_t len,
17 struct mpatch_flist *l);
23 struct mpatch_flist *l);
18 struct mpatch_flist *mpatch_fold(void *bins, ssize_t start, ssize_t end);
24 struct mpatch_flist *mpatch_fold(void *bins,
25 struct mpatch_flist* (*get_next_item)(void*, ssize_t),
26 ssize_t start, ssize_t end);
19
27
20 #endif
28 #endif
@@ -33,12 +33,33 b''
33 static char mpatch_doc[] = "Efficient binary patching.";
33 static char mpatch_doc[] = "Efficient binary patching.";
34 static PyObject *mpatch_Error;
34 static PyObject *mpatch_Error;
35
35
36 struct mpatch_flist *cpygetitem(void *bins, ssize_t pos)
37 {
38 const char *buffer;
39 struct mpatch_flist *res;
40 ssize_t blen;
41 int r;
42
43 PyObject *tmp = PyList_GetItem((PyObject*)bins, pos);
44 if (!tmp)
45 return NULL;
46 if (PyObject_AsCharBuffer(tmp, &buffer, (Py_ssize_t*)&blen))
47 return NULL;
48 if ((r = mpatch_decode(buffer, blen, &res)) < 0) {
49 if (!PyErr_Occurred())
50 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
51 return NULL;
52 }
53 return res;
54 }
55
36 static PyObject *
56 static PyObject *
37 patches(PyObject *self, PyObject *args)
57 patches(PyObject *self, PyObject *args)
38 {
58 {
39 PyObject *text, *bins, *result;
59 PyObject *text, *bins, *result;
40 struct mpatch_flist *patch;
60 struct mpatch_flist *patch;
41 const char *in;
61 const char *in;
62 int r;
42 char *out;
63 char *out;
43 Py_ssize_t len, outlen, inlen;
64 Py_ssize_t len, outlen, inlen;
44
65
@@ -55,12 +76,16 b' patches(PyObject *self, PyObject *args)'
55 if (PyObject_AsCharBuffer(text, &in, &inlen))
76 if (PyObject_AsCharBuffer(text, &in, &inlen))
56 return NULL;
77 return NULL;
57
78
58 patch = mpatch_fold(bins, 0, len);
79 patch = mpatch_fold(bins, cpygetitem, 0, len);
59 if (!patch)
80 if (!patch) { /* error already set or memory error */
81 if (!PyErr_Occurred())
82 PyErr_NoMemory();
60 return NULL;
83 return NULL;
84 }
61
85
62 outlen = mpatch_calcsize(inlen, patch);
86 outlen = mpatch_calcsize(inlen, patch);
63 if (outlen < 0) {
87 if (outlen < 0) {
88 r = (int)outlen;
64 result = NULL;
89 result = NULL;
65 goto cleanup;
90 goto cleanup;
66 }
91 }
@@ -70,12 +95,14 b' patches(PyObject *self, PyObject *args)'
70 goto cleanup;
95 goto cleanup;
71 }
96 }
72 out = PyBytes_AsString(result);
97 out = PyBytes_AsString(result);
73 if (!mpatch_apply(out, in, inlen, patch)) {
98 if ((r = mpatch_apply(out, in, inlen, patch)) < 0) {
74 Py_DECREF(result);
99 Py_DECREF(result);
75 result = NULL;
100 result = NULL;
76 }
101 }
77 cleanup:
102 cleanup:
78 mpatch_lfree(patch);
103 mpatch_lfree(patch);
104 if (!result && !PyErr_Occurred())
105 PyErr_SetString(mpatch_Error, mpatch_errors[-r]);
79 return result;
106 return result;
80 }
107 }
81
108
General Comments 0
You need to be logged in to leave comments. Login now