37 struct frag *base, *head, *tail; |
37 struct frag *base, *head, *tail; |
38 }; |
38 }; |
39 |
39 |
40 static struct flist *lalloc(int size) |
40 static struct flist *lalloc(int size) |
41 { |
41 { |
42 struct flist *a; |
42 struct flist *a = NULL; |
43 |
43 |
44 a = malloc(sizeof(struct flist)); |
44 a = malloc(sizeof(struct flist)); |
45 a->head = a->tail = a->base = malloc(sizeof(struct frag) * size); |
45 if (a) { |
|
46 a->base = malloc(sizeof(struct frag) * size); |
|
47 if (!a->base) |
|
48 free(a); |
|
49 else |
|
50 a->head = a->tail = a->base; |
|
51 } |
46 return a; |
52 return a; |
47 } |
53 } |
48 |
54 |
49 static void lfree(struct flist *a) |
55 static void lfree(struct flist *a) |
50 { |
56 { |
51 free(a->base); |
57 if (a) { |
52 free(a); |
58 free(a->base); |
|
59 free(a); |
|
60 } |
53 } |
61 } |
54 |
62 |
55 static int lsize(struct flist *a) |
63 static int lsize(struct flist *a) |
56 { |
64 { |
57 return a->tail - a->head; |
65 return a->tail - a->head; |
142 |
150 |
143 /* combine hunk lists a and b, while adjusting b for offset changes in a/ |
151 /* combine hunk lists a and b, while adjusting b for offset changes in a/ |
144 this deletes a and b and returns the resultant list. */ |
152 this deletes a and b and returns the resultant list. */ |
145 static struct flist *combine(struct flist *a, struct flist *b) |
153 static struct flist *combine(struct flist *a, struct flist *b) |
146 { |
154 { |
147 struct flist *c; |
155 struct flist *c = NULL; |
148 struct frag *bh = b->head, *ct; |
156 struct frag *bh, *ct; |
149 int offset = 0, post; |
157 int offset = 0, post; |
150 |
158 |
151 c = lalloc((lsize(a) + lsize(b)) * 2); |
159 if (a && b) |
152 |
160 c = lalloc((lsize(a) + lsize(b)) * 2); |
153 while (bh != b->tail) { |
161 |
154 /* save old hunks */ |
162 if (c) { |
155 offset = gather(c, a, bh->start, offset); |
163 |
156 |
164 for (bh = b->head; bh != b->tail; bh++) { |
157 /* discard replaced hunks */ |
165 /* save old hunks */ |
158 post = discard(a, bh->end, offset); |
166 offset = gather(c, a, bh->start, offset); |
159 |
167 |
160 /* insert new hunk */ |
168 /* discard replaced hunks */ |
161 ct = c->tail; |
169 post = discard(a, bh->end, offset); |
162 ct->start = bh->start - offset; |
170 |
163 ct->end = bh->end - post; |
171 /* insert new hunk */ |
164 ct->len = bh->len; |
172 ct = c->tail; |
165 ct->data = bh->data; |
173 ct->start = bh->start - offset; |
166 c->tail++; |
174 ct->end = bh->end - post; |
167 bh++; |
175 ct->len = bh->len; |
168 offset = post; |
176 ct->data = bh->data; |
169 } |
177 c->tail++; |
170 |
178 offset = post; |
171 /* hold on to tail from a */ |
179 } |
172 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); |
180 |
173 c->tail += lsize(a); |
181 /* hold on to tail from a */ |
|
182 memcpy(c->tail, a->head, sizeof(struct frag) * lsize(a)); |
|
183 c->tail += lsize(a); |
|
184 } |
|
185 |
174 lfree(a); |
186 lfree(a); |
175 lfree(b); |
187 lfree(b); |
176 return c; |
188 return c; |
177 } |
189 } |
178 |
190 |
240 int len; |
252 int len; |
241 |
253 |
242 if (start + 1 == end) { |
254 if (start + 1 == end) { |
243 /* trivial case, output a decoded list */ |
255 /* trivial case, output a decoded list */ |
244 PyObject *tmp = PyList_GetItem(bins, start); |
256 PyObject *tmp = PyList_GetItem(bins, start); |
|
257 if (!tmp) |
|
258 return NULL; |
245 return decode(PyString_AsString(tmp), PyString_Size(tmp)); |
259 return decode(PyString_AsString(tmp), PyString_Size(tmp)); |
246 } |
260 } |
247 |
261 |
248 /* divide and conquer, memory management is elsewhere */ |
262 /* divide and conquer, memory management is elsewhere */ |
249 len = (end - start) / 2; |
263 len = (end - start) / 2; |
257 PyObject *text, *bins, *result; |
271 PyObject *text, *bins, *result; |
258 struct flist *patch; |
272 struct flist *patch; |
259 char *in, *out; |
273 char *in, *out; |
260 int len, outlen; |
274 int len, outlen; |
261 |
275 |
262 if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) |
276 if (!PyArg_ParseTuple(args, "SO:mpatch", &text, &bins)) |
263 return NULL; |
277 return NULL; |
264 |
278 |
265 len = PyList_Size(bins); |
279 len = PyList_Size(bins); |
266 if (!len) { |
280 if (!len) { |
267 /* nothing to do */ |
281 /* nothing to do */ |
268 Py_INCREF(text); |
282 Py_INCREF(text); |
269 return text; |
283 return text; |
270 } |
284 } |
271 |
285 |
272 patch = fold(bins, 0, len); |
286 patch = fold(bins, 0, len); |
|
287 if (!patch) |
|
288 return PyErr_NoMemory(); |
|
289 |
273 outlen = calcsize(PyString_Size(text), patch); |
290 outlen = calcsize(PyString_Size(text), patch); |
274 result = PyString_FromStringAndSize(NULL, outlen); |
291 result = PyString_FromStringAndSize(NULL, outlen); |
275 in = PyString_AsString(text); |
292 if (result) { |
276 out = PyString_AsString(result); |
293 in = PyString_AsString(text); |
277 apply(out, in, PyString_Size(text), patch); |
294 out = PyString_AsString(result); |
|
295 apply(out, in, PyString_Size(text), patch); |
|
296 } |
|
297 |
278 lfree(patch); |
298 lfree(patch); |
279 |
|
280 return result; |
299 return result; |
281 } |
300 } |
282 |
301 |
283 static PyMethodDef methods[] = { |
302 static PyMethodDef methods[] = { |
284 {"patches", patches, METH_VARARGS, "apply a series of patches\n"}, |
303 {"patches", patches, METH_VARARGS, "apply a series of patches\n"}, |