mercurial/cffi/bdiff.py
branchstable
changeset 33572 857876ebaed4
parent 30346 9cc438bf7d9a
parent 32513 25b37900d6e0
child 43076 2372284d9457
equal deleted inserted replaced
33202:c1994c986d77 33572:857876ebaed4
       
     1 # bdiff.py - CFFI implementation of bdiff.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 import struct
     4 import os
       
     5 
    11 
     6 ffi = cffi.FFI()
    12 from ..pure.bdiff import *
     7 ffi.set_source("_bdiff_cffi",
    13 from . import _bdiff
     8     open(os.path.join(os.path.join(os.path.dirname(__file__), '..'),
       
     9         'bdiff.c')).read(), include_dirs=['mercurial'])
       
    10 ffi.cdef("""
       
    11 struct bdiff_line {
       
    12     int hash, n, e;
       
    13     ssize_t len;
       
    14     const char *l;
       
    15 };
       
    16 
    14 
    17 struct bdiff_hunk;
    15 ffi = _bdiff.ffi
    18 struct bdiff_hunk {
    16 lib = _bdiff.lib
    19     int a1, a2, b1, b2;
       
    20     struct bdiff_hunk *next;
       
    21 };
       
    22 
    17 
    23 int bdiff_splitlines(const char *a, ssize_t len, struct bdiff_line **lr);
    18 def blocks(sa, sb):
    24 int bdiff_diff(struct bdiff_line *a, int an, struct bdiff_line *b, int bn,
    19     a = ffi.new("struct bdiff_line**")
    25     struct bdiff_hunk *base);
    20     b = ffi.new("struct bdiff_line**")
    26 void bdiff_freehunks(struct bdiff_hunk *l);
    21     ac = ffi.new("char[]", str(sa))
    27 void free(void*);
    22     bc = ffi.new("char[]", str(sb))
    28 """)
    23     l = ffi.new("struct bdiff_hunk*")
       
    24     try:
       
    25         an = lib.bdiff_splitlines(ac, len(sa), a)
       
    26         bn = lib.bdiff_splitlines(bc, len(sb), b)
       
    27         if not a[0] or not b[0]:
       
    28             raise MemoryError
       
    29         count = lib.bdiff_diff(a[0], an, b[0], bn, l)
       
    30         if count < 0:
       
    31             raise MemoryError
       
    32         rl = [None] * count
       
    33         h = l.next
       
    34         i = 0
       
    35         while h:
       
    36             rl[i] = (h.a1, h.a2, h.b1, h.b2)
       
    37             h = h.next
       
    38             i += 1
       
    39     finally:
       
    40         lib.free(a[0])
       
    41         lib.free(b[0])
       
    42         lib.bdiff_freehunks(l.next)
       
    43     return rl
    29 
    44 
    30 if __name__ == '__main__':
    45 def bdiff(sa, sb):
    31     ffi.compile()
    46     a = ffi.new("struct bdiff_line**")
       
    47     b = ffi.new("struct bdiff_line**")
       
    48     ac = ffi.new("char[]", str(sa))
       
    49     bc = ffi.new("char[]", str(sb))
       
    50     l = ffi.new("struct bdiff_hunk*")
       
    51     try:
       
    52         an = lib.bdiff_splitlines(ac, len(sa), a)
       
    53         bn = lib.bdiff_splitlines(bc, len(sb), b)
       
    54         if not a[0] or not b[0]:
       
    55             raise MemoryError
       
    56         count = lib.bdiff_diff(a[0], an, b[0], bn, l)
       
    57         if count < 0:
       
    58             raise MemoryError
       
    59         rl = []
       
    60         h = l.next
       
    61         la = lb = 0
       
    62         while h:
       
    63             if h.a1 != la or h.b1 != lb:
       
    64                 lgt = (b[0] + h.b1).l - (b[0] + lb).l
       
    65                 rl.append(struct.pack(">lll", (a[0] + la).l - a[0].l,
       
    66                                       (a[0] + h.a1).l - a[0].l, lgt))
       
    67                 rl.append(str(ffi.buffer((b[0] + lb).l, lgt)))
       
    68             la = h.a2
       
    69             lb = h.b2
       
    70             h = h.next
       
    71 
       
    72     finally:
       
    73         lib.free(a[0])
       
    74         lib.free(b[0])
       
    75         lib.bdiff_freehunks(l.next)
       
    76     return "".join(rl)