diff mercurial/pure/bdiff.py @ 29833:a8933d992a71

bdiff: implement cffi version of blocks
author Maciej Fijalkowski <fijall@gmail.com>
date Thu, 28 Jul 2016 14:17:08 +0200
parents 9ab45fbe045e
children 1ea77b75d266
line wrap: on
line diff
--- a/mercurial/pure/bdiff.py	Fri Aug 19 13:30:40 2016 -0700
+++ b/mercurial/pure/bdiff.py	Thu Jul 28 14:17:08 2016 +0200
@@ -12,6 +12,10 @@
 import re
 import struct
 
+from . import policy
+policynocffi = policy.policynocffi
+modulepolicy = policy.policy
+
 def splitnewlines(text):
     '''like str.splitlines, but only split on newlines.'''
     lines = [l + '\n' for l in text.split('\n')]
@@ -96,3 +100,37 @@
         text = re.sub('[ \t\r]+', ' ', text)
         text = text.replace(' \n', '\n')
     return text
+
+if modulepolicy not in policynocffi:
+    try:
+        from _bdiff_cffi import ffi, lib
+    except ImportError:
+        if modulepolicy == 'cffi': # strict cffi import
+            raise
+    else:
+        def blocks(sa, sb):
+            a = ffi.new("struct bdiff_line**")
+            b = ffi.new("struct bdiff_line**")
+            ac = ffi.new("char[]", sa)
+            bc = ffi.new("char[]", sb)
+            try:
+                an = lib.bdiff_splitlines(ac, len(sa), a)
+                bn = lib.bdiff_splitlines(bc, len(sb), b)
+                if not a[0] or not b[0]:
+                    raise MemoryError
+                l = ffi.new("struct bdiff_hunk*")
+                count = lib.bdiff_diff(a[0], an, b[0], bn, l)
+                if count < 0:
+                    raise MemoryError
+                rl = [None] * count
+                h = l.next
+                i = 0
+                while h:
+                    rl[i] = (h.a1, h.a2, h.b1, h.b2)
+                    h = h.next
+                    i += 1
+            finally:
+                lib.free(a[0])
+                lib.free(b[0])
+                lib.bdiff_freehunks(l.next)
+            return rl