mercurial/cffi/mpatch.py
branchstable
changeset 33572 857876ebaed4
parent 30346 9cc438bf7d9a
parent 32513 25b37900d6e0
child 43076 2372284d9457
equal deleted inserted replaced
33202:c1994c986d77 33572:857876ebaed4
       
     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 
     1 from __future__ import absolute_import
     8 from __future__ import absolute_import
     2 
     9 
     3 import cffi
    10 from ..pure.mpatch import *
     4 import os
    11 from ..pure.mpatch import mpatchError  # silence pyflakes
       
    12 from . import _mpatch
     5 
    13 
     6 ffi = cffi.FFI()
    14 ffi = _mpatch.ffi
     7 mpatch_c = os.path.join(os.path.join(os.path.dirname(__file__), '..',
    15 lib = _mpatch.lib
     8                                      'mpatch.c'))
       
     9 ffi.set_source("_mpatch_cffi", open(mpatch_c).read(),
       
    10                include_dirs=["mercurial"])
       
    11 ffi.cdef("""
       
    12 
    16 
    13 struct mpatch_frag {
    17 @ffi.def_extern()
    14        int start, end, len;
    18 def cffi_get_next_item(arg, pos):
    15        const char *data;
    19     all, bins = ffi.from_handle(arg)
    16 };
    20     container = ffi.new("struct mpatch_flist*[1]")
       
    21     to_pass = ffi.new("char[]", str(bins[pos]))
       
    22     all.append(to_pass)
       
    23     r = lib.mpatch_decode(to_pass, len(to_pass) - 1, container)
       
    24     if r < 0:
       
    25         return ffi.NULL
       
    26     return container[0]
    17 
    27 
    18 struct mpatch_flist {
    28 def patches(text, bins):
    19        struct mpatch_frag *base, *head, *tail;
    29     lgt = len(bins)
    20 };
    30     all = []
    21 
    31     if not lgt:
    22 extern "Python" struct mpatch_flist* cffi_get_next_item(void*, ssize_t);
    32         return text
    23 
    33     arg = (all, bins)
    24 int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist** res);
    34     patch = lib.mpatch_fold(ffi.new_handle(arg),
    25 ssize_t mpatch_calcsize(size_t len, struct mpatch_flist *l);
    35                             lib.cffi_get_next_item, 0, lgt)
    26 void mpatch_lfree(struct mpatch_flist *a);
    36     if not patch:
    27 static int mpatch_apply(char *buf, const char *orig, size_t len,
    37         raise mpatchError("cannot decode chunk")
    28                         struct mpatch_flist *l);
    38     outlen = lib.mpatch_calcsize(len(text), patch)
    29 struct mpatch_flist *mpatch_fold(void *bins,
    39     if outlen < 0:
    30                        struct mpatch_flist* (*get_next_item)(void*, ssize_t),
    40         lib.mpatch_lfree(patch)
    31                        ssize_t start, ssize_t end);
    41         raise mpatchError("inconsistency detected")
    32 """)
    42     buf = ffi.new("char[]", outlen)
    33 
    43     if lib.mpatch_apply(buf, text, len(text), patch) < 0:
    34 if __name__ == '__main__':
    44         lib.mpatch_lfree(patch)
    35     ffi.compile()
    45         raise mpatchError("error applying patches")
       
    46     res = ffi.buffer(buf, outlen)[:]
       
    47     lib.mpatch_lfree(patch)
       
    48     return res