view mercurial/cffi/bdiff.py @ 36160:9fd8c2a3db5a

narrowspec: move module into core Having support for parsing the narrow specification in core is necessary for moving many other parts of narrow to core. We do still want to harmonize the narrow spec with the sparse spec. And the format needs to be documented. But this shouldn't hold up the code moving to core. Differential Revision: https://phab.mercurial-scm.org/D2201
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 12 Feb 2018 16:21:34 -0800
parents 857876ebaed4
children 2372284d9457
line wrap: on
line source

# bdiff.py - CFFI implementation of bdiff.c
#
# Copyright 2016 Maciej Fijalkowski <fijall@gmail.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

import struct

from ..pure.bdiff import *
from . import _bdiff

ffi = _bdiff.ffi
lib = _bdiff.lib

def blocks(sa, sb):
    a = ffi.new("struct bdiff_line**")
    b = ffi.new("struct bdiff_line**")
    ac = ffi.new("char[]", str(sa))
    bc = ffi.new("char[]", str(sb))
    l = ffi.new("struct bdiff_hunk*")
    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
        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

def bdiff(sa, sb):
    a = ffi.new("struct bdiff_line**")
    b = ffi.new("struct bdiff_line**")
    ac = ffi.new("char[]", str(sa))
    bc = ffi.new("char[]", str(sb))
    l = ffi.new("struct bdiff_hunk*")
    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
        count = lib.bdiff_diff(a[0], an, b[0], bn, l)
        if count < 0:
            raise MemoryError
        rl = []
        h = l.next
        la = lb = 0
        while h:
            if h.a1 != la or h.b1 != lb:
                lgt = (b[0] + h.b1).l - (b[0] + lb).l
                rl.append(struct.pack(">lll", (a[0] + la).l - a[0].l,
                                      (a[0] + h.a1).l - a[0].l, lgt))
                rl.append(str(ffi.buffer((b[0] + lb).l, lgt)))
            la = h.a2
            lb = h.b2
            h = h.next

    finally:
        lib.free(a[0])
        lib.free(b[0])
        lib.bdiff_freehunks(l.next)
    return "".join(rl)