bdiff.py
104 lines
| 2.8 KiB
| text/x-python
|
PythonLexer
Yuya Nishihara
|
r32512 | # 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. | ||||
Matt Harbison
|
r52756 | from __future__ import annotations | ||
Yuya Nishihara
|
r32512 | |||
import struct | ||||
Matt Harbison
|
r52827 | import typing | ||
Yuya Nishihara
|
r32512 | |||
Matt Harbison
|
r50493 | from typing import ( | ||
List, | ||||
Matt Harbison
|
r52827 | Optional, | ||
Matt Harbison
|
r50493 | Tuple, | ||
) | ||||
Yuya Nishihara
|
r32512 | from ..pure.bdiff import * | ||
Matt Harbison
|
r52827 | |||
from ..interfaces import ( | ||||
modules as intmod, | ||||
) | ||||
Matt Harbison
|
r47543 | from . import _bdiff # pytype: disable=import-error | ||
Yuya Nishihara
|
r32512 | |||
ffi = _bdiff.ffi | ||||
lib = _bdiff.lib | ||||
Augie Fackler
|
r43346 | |||
Matt Harbison
|
r50493 | def blocks(sa: bytes, sb: bytes) -> List[Tuple[int, int, int, int]]: | ||
Manuel Jacob
|
r52683 | a = ffi.new("struct bdiff_line**") | ||
b = ffi.new("struct bdiff_line**") | ||||
Manuel Jacob
|
r52685 | ac = ffi.new("char[]", bytes(sa)) | ||
bc = ffi.new("char[]", bytes(sb)) | ||||
Manuel Jacob
|
r52683 | l = ffi.new("struct bdiff_hunk*") | ||
Yuya Nishihara
|
r32513 | 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 | ||||
Matt Harbison
|
r50492 | rl = [(0, 0, 0, 0)] * count | ||
Yuya Nishihara
|
r32513 | 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 | ||||
Yuya Nishihara
|
r32512 | |||
Augie Fackler
|
r43346 | |||
Matt Harbison
|
r50493 | def bdiff(sa: bytes, sb: bytes) -> bytes: | ||
Manuel Jacob
|
r52683 | a = ffi.new("struct bdiff_line**") | ||
b = ffi.new("struct bdiff_line**") | ||||
Manuel Jacob
|
r52685 | ac = ffi.new("char[]", bytes(sa)) | ||
bc = ffi.new("char[]", bytes(sb)) | ||||
Manuel Jacob
|
r52683 | l = ffi.new("struct bdiff_hunk*") | ||
Yuya Nishihara
|
r32513 | 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 | ||||
Augie Fackler
|
r43346 | rl.append( | ||
struct.pack( | ||||
Augie Fackler
|
r43347 | b">lll", | ||
Augie Fackler
|
r43346 | (a[0] + la).l - a[0].l, | ||
(a[0] + h.a1).l - a[0].l, | ||||
lgt, | ||||
) | ||||
) | ||||
Manuel Jacob
|
r52684 | rl.append(bytes(ffi.buffer((b[0] + lb).l, lgt))) | ||
Yuya Nishihara
|
r32513 | la = h.a2 | ||
lb = h.b2 | ||||
h = h.next | ||||
Yuya Nishihara
|
r32512 | |||
Yuya Nishihara
|
r32513 | finally: | ||
lib.free(a[0]) | ||||
lib.free(b[0]) | ||||
lib.bdiff_freehunks(l.next) | ||||
Augie Fackler
|
r43347 | return b"".join(rl) | ||
Matt Harbison
|
r52827 | |||
# In order to adhere to the module protocol, these functions must be visible to | ||||
# the type checker, though they aren't actually implemented by this | ||||
# implementation of the module protocol. Callers are responsible for | ||||
# checking that the implementation is available before using them. | ||||
if typing.TYPE_CHECKING: | ||||
xdiffblocks: Optional[intmod.BDiffBlocksFnc] = None | ||||