213 char *end = bin + len; |
217 char *end = bin + len; |
214 char decode[12]; /* for dealing with alignment issues */ |
218 char decode[12]; /* for dealing with alignment issues */ |
215 |
219 |
216 /* assume worst case size, we won't have many of these lists */ |
220 /* assume worst case size, we won't have many of these lists */ |
217 l = lalloc(len / 12); |
221 l = lalloc(len / 12); |
|
222 if (!l) |
|
223 return NULL; |
|
224 |
218 lt = l->tail; |
225 lt = l->tail; |
219 |
226 |
220 while (bin < end) { |
227 while (bin < end) { |
221 memcpy(decode, bin, 12); |
228 memcpy(decode, bin, 12); |
222 lt->start = ntohl(*(uint32_t *)decode); |
229 lt->start = ntohl(*(uint32_t *)decode); |
236 { |
250 { |
237 int outlen = 0, last = 0; |
251 int outlen = 0, last = 0; |
238 struct frag *f = l->head; |
252 struct frag *f = l->head; |
239 |
253 |
240 while (f != l->tail) { |
254 while (f != l->tail) { |
|
255 if (f->start < last || f->end > len) { |
|
256 if (!PyErr_Occurred()) |
|
257 PyErr_SetString(mpatch_Error, |
|
258 "invalid patch"); |
|
259 return -1; |
|
260 } |
241 outlen += f->start - last; |
261 outlen += f->start - last; |
242 last = f->end; |
262 last = f->end; |
243 outlen += f->len; |
263 outlen += f->len; |
244 f++; |
264 f++; |
245 } |
265 } |
246 |
266 |
247 outlen += len - last; |
267 outlen += len - last; |
248 return outlen; |
268 return outlen; |
249 } |
269 } |
250 |
270 |
251 static void apply(char *buf, char *orig, int len, struct flist *l) |
271 static int apply(char *buf, char *orig, int len, struct flist *l) |
252 { |
272 { |
253 struct frag *f = l->head; |
273 struct frag *f = l->head; |
254 int last = 0; |
274 int last = 0; |
255 char *p = buf; |
275 char *p = buf; |
256 |
276 |
257 while (f != l->tail) { |
277 while (f != l->tail) { |
|
278 if (f->start < last || f->end > len) { |
|
279 if (!PyErr_Occurred()) |
|
280 PyErr_SetString(mpatch_Error, |
|
281 "invalid patch"); |
|
282 return 0; |
|
283 } |
258 memcpy(p, orig + last, f->start - last); |
284 memcpy(p, orig + last, f->start - last); |
259 p += f->start - last; |
285 p += f->start - last; |
260 memcpy(p, f->data, f->len); |
286 memcpy(p, f->data, f->len); |
261 last = f->end; |
287 last = f->end; |
262 p += f->len; |
288 p += f->len; |
263 f++; |
289 f++; |
264 } |
290 } |
265 memcpy(p, orig + last, len - last); |
291 memcpy(p, orig + last, len - last); |
|
292 return 1; |
266 } |
293 } |
267 |
294 |
268 /* recursively generate a patch of all bins between start and end */ |
295 /* recursively generate a patch of all bins between start and end */ |
269 static struct flist *fold(PyObject *bins, int start, int end) |
296 static struct flist *fold(PyObject *bins, int start, int end) |
270 { |
297 { |
302 return text; |
329 return text; |
303 } |
330 } |
304 |
331 |
305 patch = fold(bins, 0, len); |
332 patch = fold(bins, 0, len); |
306 if (!patch) |
333 if (!patch) |
307 return PyErr_NoMemory(); |
334 return NULL; |
308 |
335 |
309 outlen = calcsize(PyString_Size(text), patch); |
336 outlen = calcsize(PyString_Size(text), patch); |
|
337 if (outlen < 0) { |
|
338 result = NULL; |
|
339 goto cleanup; |
|
340 } |
310 result = PyString_FromStringAndSize(NULL, outlen); |
341 result = PyString_FromStringAndSize(NULL, outlen); |
311 if (result) { |
342 if (!result) { |
312 in = PyString_AsString(text); |
343 result = NULL; |
313 out = PyString_AsString(result); |
344 goto cleanup; |
314 apply(out, in, PyString_Size(text), patch); |
345 } |
315 } |
346 in = PyString_AsString(text); |
316 |
347 out = PyString_AsString(result); |
|
348 if (!apply(out, in, PyString_Size(text), patch)) { |
|
349 Py_DECREF(result); |
|
350 result = NULL; |
|
351 } |
|
352 cleanup: |
317 lfree(patch); |
353 lfree(patch); |
318 return result; |
354 return result; |
319 } |
355 } |
320 |
356 |
321 static PyMethodDef methods[] = { |
357 static PyMethodDef methods[] = { |