|
1 # mpatch.py - CFFI implementation of mpatch.c |
|
2 # |
|
3 # Copyright 2016 Maciej Fijalkowski <fijall@gmail.com> |
|
4 # |
|
5 # This software may be used and distributed according to the terms of the |
|
6 # GNU General Public License version 2 or any later version. |
|
7 |
|
8 from __future__ import absolute_import |
|
9 |
|
10 from ..pure.mpatch import * |
|
11 from ..pure.mpatch import mpatchError # silence pyflakes |
|
12 from . import _mpatch |
|
13 |
|
14 ffi = _mpatch.ffi |
|
15 lib = _mpatch.lib |
|
16 |
|
17 if True: |
|
18 if True: |
|
19 @ffi.def_extern() |
|
20 def cffi_get_next_item(arg, pos): |
|
21 all, bins = ffi.from_handle(arg) |
|
22 container = ffi.new("struct mpatch_flist*[1]") |
|
23 to_pass = ffi.new("char[]", str(bins[pos])) |
|
24 all.append(to_pass) |
|
25 r = lib.mpatch_decode(to_pass, len(to_pass) - 1, container) |
|
26 if r < 0: |
|
27 return ffi.NULL |
|
28 return container[0] |
|
29 |
|
30 def patches(text, bins): |
|
31 lgt = len(bins) |
|
32 all = [] |
|
33 if not lgt: |
|
34 return text |
|
35 arg = (all, bins) |
|
36 patch = lib.mpatch_fold(ffi.new_handle(arg), |
|
37 lib.cffi_get_next_item, 0, lgt) |
|
38 if not patch: |
|
39 raise mpatchError("cannot decode chunk") |
|
40 outlen = lib.mpatch_calcsize(len(text), patch) |
|
41 if outlen < 0: |
|
42 lib.mpatch_lfree(patch) |
|
43 raise mpatchError("inconsistency detected") |
|
44 buf = ffi.new("char[]", outlen) |
|
45 if lib.mpatch_apply(buf, text, len(text), patch) < 0: |
|
46 lib.mpatch_lfree(patch) |
|
47 raise mpatchError("error applying patches") |
|
48 res = ffi.buffer(buf, outlen)[:] |
|
49 lib.mpatch_lfree(patch) |
|
50 return res |