mercurial/cffi/bdiff.py
changeset 32512 0e8b0b9a7acc
parent 32506 2dcb3d52ef41
child 32513 25b37900d6e0
equal deleted inserted replaced
32511:2e431fb98c6b 32512:0e8b0b9a7acc
       
     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 
       
     8 from __future__ import absolute_import
       
     9 
       
    10 import struct
       
    11 
       
    12 from ..pure.bdiff import *
       
    13 from . import _bdiff
       
    14 
       
    15 ffi = _bdiff.ffi
       
    16 lib = _bdiff.lib
       
    17 
       
    18 if True:
       
    19     if True:
       
    20         def blocks(sa, sb):
       
    21             a = ffi.new("struct bdiff_line**")
       
    22             b = ffi.new("struct bdiff_line**")
       
    23             ac = ffi.new("char[]", str(sa))
       
    24             bc = ffi.new("char[]", str(sb))
       
    25             l = ffi.new("struct bdiff_hunk*")
       
    26             try:
       
    27                 an = lib.bdiff_splitlines(ac, len(sa), a)
       
    28                 bn = lib.bdiff_splitlines(bc, len(sb), b)
       
    29                 if not a[0] or not b[0]:
       
    30                     raise MemoryError
       
    31                 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
       
    32                 if count < 0:
       
    33                     raise MemoryError
       
    34                 rl = [None] * count
       
    35                 h = l.next
       
    36                 i = 0
       
    37                 while h:
       
    38                     rl[i] = (h.a1, h.a2, h.b1, h.b2)
       
    39                     h = h.next
       
    40                     i += 1
       
    41             finally:
       
    42                 lib.free(a[0])
       
    43                 lib.free(b[0])
       
    44                 lib.bdiff_freehunks(l.next)
       
    45             return rl
       
    46 
       
    47         def bdiff(sa, sb):
       
    48             a = ffi.new("struct bdiff_line**")
       
    49             b = ffi.new("struct bdiff_line**")
       
    50             ac = ffi.new("char[]", str(sa))
       
    51             bc = ffi.new("char[]", str(sb))
       
    52             l = ffi.new("struct bdiff_hunk*")
       
    53             try:
       
    54                 an = lib.bdiff_splitlines(ac, len(sa), a)
       
    55                 bn = lib.bdiff_splitlines(bc, len(sb), b)
       
    56                 if not a[0] or not b[0]:
       
    57                     raise MemoryError
       
    58                 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
       
    59                 if count < 0:
       
    60                     raise MemoryError
       
    61                 rl = []
       
    62                 h = l.next
       
    63                 la = lb = 0
       
    64                 while h:
       
    65                     if h.a1 != la or h.b1 != lb:
       
    66                         lgt = (b[0] + h.b1).l - (b[0] + lb).l
       
    67                         rl.append(struct.pack(">lll", (a[0] + la).l - a[0].l,
       
    68                             (a[0] + h.a1).l - a[0].l, lgt))
       
    69                         rl.append(str(ffi.buffer((b[0] + lb).l, lgt)))
       
    70                     la = h.a2
       
    71                     lb = h.b2
       
    72                     h = h.next
       
    73 
       
    74             finally:
       
    75                 lib.free(a[0])
       
    76                 lib.free(b[0])
       
    77                 lib.bdiff_freehunks(l.next)
       
    78             return "".join(rl)