Переписан для обычного diff
This commit is contained in:
parent
ef491965f6
commit
e7d16e6969
7 changed files with 212 additions and 15 deletions
6
dub.json
6
dub.json
|
@ -12,9 +12,9 @@
|
||||||
"xdiff"
|
"xdiff"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"libxdiff": {
|
"xdiff": {
|
||||||
"repository": "git+https://git.zhirov.kz/dlang/libxdiff.git",
|
"repository": "git+https://git.zhirov.kz/dlang/xdiff.git",
|
||||||
"version": "143f39005c0e89cc57d564365e6ea61427928bc3"
|
"version": "e2396bc172eba813cdcd1a96c494e35d687f576a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"fileVersion": 1,
|
"fileVersion": 1,
|
||||||
"versions": {
|
"versions": {
|
||||||
"libxdiff": {"version":"143f39005c0e89cc57d564365e6ea61427928bc3","repository":"git+https://git.zhirov.kz/dlang/libxdiff.git"}
|
"libxdiff": {"version":"e2396bc172eba813cdcd1a96c494e35d687f576a","repository":"git+https://git.zhirov.kz/dlang/xdiff.git"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
source/app.d
25
source/app.d
|
@ -1,17 +1,20 @@
|
||||||
import std.stdio;
|
import libxdiff;
|
||||||
import libxdiff : MMFile;
|
|
||||||
|
import std.conv : to;
|
||||||
|
import std.stdio : writefln, writeln;
|
||||||
|
import std.file : read;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
auto a = MMFile.fromBytes(cast(ubyte[]) "hello world\n");
|
auto file1 = new MMFile(cast(const(ubyte)[]) read("/tmp/diff1.d"));
|
||||||
auto b = MMFile.fromBytes(cast(ubyte[]) "hello world!\n");
|
auto file2 = new MMFile(cast(const(ubyte)[]) read("/tmp/diff2.d"));
|
||||||
|
|
||||||
auto patch = a.computePatch(b);
|
auto patch = file1.computePatch(file2);
|
||||||
writeln("patch size: ", patch.size());
|
|
||||||
|
|
||||||
auto res = a.applyPatch(patch);
|
writeln(patch);
|
||||||
writeln("apply success: ", res.success);
|
|
||||||
writeln(res.patched.asSlice()); // печатаем результат
|
writefln(
|
||||||
// печатаем как есть (включая заголовок @@ и строки с '-'/'+' и '\n')
|
"file1: %s\nfile2: %s",
|
||||||
write(cast(string) MMFile.fromBlocksMoved(patch).asSlice());
|
file1.size, file2.size
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
70
source/libxdiff/init.d
Normal file
70
source/libxdiff/init.d
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
module libxdiff.init;
|
||||||
|
|
||||||
|
import xdiff;
|
||||||
|
|
||||||
|
import core.stdc.stdlib : malloc, free, realloc;
|
||||||
|
import std.exception : enforce;
|
||||||
|
import core.stdc.errno : errno;
|
||||||
|
import core.stdc.string : strerror;
|
||||||
|
import std.string : fromStringz;
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
private __gshared bool _allocatorReady = false;
|
||||||
|
package(libxdiff) alias ByteArray = const(ubyte)[];
|
||||||
|
|
||||||
|
extern (C)
|
||||||
|
{
|
||||||
|
private void* wrap_malloc(void*, uint size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void wrap_free(void*, void* p)
|
||||||
|
{
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void* wrap_realloc(void*, void* p, uint size)
|
||||||
|
{
|
||||||
|
return realloc(p, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAllocator()
|
||||||
|
{
|
||||||
|
if (_allocatorReady)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memallocator_t m = {null, &wrap_malloc, &wrap_free, &wrap_realloc};
|
||||||
|
|
||||||
|
enforce(xdl_set_allocator(&m) == 0,
|
||||||
|
"xdl_set_allocator failed: " ~ strerror(errno).fromStringz);
|
||||||
|
_allocatorReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmfile_t initMmfile(size_t len)
|
||||||
|
{
|
||||||
|
setAllocator();
|
||||||
|
mmfile_t mf;
|
||||||
|
enforce(xdl_init_mmfile(&mf, len.to!long, XDL_MMF_ATOMIC) == 0,
|
||||||
|
"xdl_init_mmfile failed: " ~ strerror(errno).fromStringz);
|
||||||
|
return mf;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MM
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
mmfile_t _inner;
|
||||||
|
public:
|
||||||
|
final @property size_t size()
|
||||||
|
{
|
||||||
|
return xdl_mmfile_size(&_inner).to!size_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка «компактности» — содержимое лежит в одном блоке
|
||||||
|
// (важно для бинарных функций, которым нужно сплошное непрерывное представление).
|
||||||
|
final bool isCompact() const
|
||||||
|
{
|
||||||
|
return xdl_mmfile_iscompact(cast(mmfile_t*)&_inner) != 0;
|
||||||
|
}
|
||||||
|
}
|
41
source/libxdiff/mmblocks.d
Normal file
41
source/libxdiff/mmblocks.d
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
module libxdiff.mmblocks;
|
||||||
|
|
||||||
|
import xdiff;
|
||||||
|
|
||||||
|
import libxdiff.init;
|
||||||
|
|
||||||
|
import std.exception : enforce;
|
||||||
|
import core.stdc.errno : errno;
|
||||||
|
import core.stdc.string : strerror;
|
||||||
|
import std.string : fromStringz;
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
private enum DEFAULT_BSIZE = 8 * 1024;
|
||||||
|
|
||||||
|
final class MMBlocks : MM
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
_inner = initMmfile(DEFAULT_BSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
package(libxdiff) mmfile_t* ptr() @trusted
|
||||||
|
{
|
||||||
|
return &_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
const(ubyte)[] asSlice() @trusted
|
||||||
|
{
|
||||||
|
enforce(isCompact(), "MMFile must be compact for asSliceConst");
|
||||||
|
auto h = _inner.head;
|
||||||
|
return h is null || h.size <= 0 ? [] : (cast(const(ubyte)*) h.ptr)[0 .. h.size.to!size_t];
|
||||||
|
}
|
||||||
|
|
||||||
|
override string toString() const @trusted
|
||||||
|
{
|
||||||
|
enforce(isCompact(), "MMFile must be compact for asSliceConst");
|
||||||
|
auto h = _inner.head;
|
||||||
|
return h is null || h.size <= 0 ? [] : fromStringz(cast(const char*) h.ptr).idup;
|
||||||
|
}
|
||||||
|
}
|
79
source/libxdiff/mmfile.d
Normal file
79
source/libxdiff/mmfile.d
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
module libxdiff.mmfile;
|
||||||
|
|
||||||
|
import xdiff;
|
||||||
|
|
||||||
|
import libxdiff.init;
|
||||||
|
import libxdiff.mmblocks;
|
||||||
|
|
||||||
|
import std.exception : enforce;
|
||||||
|
import core.stdc.errno : errno;
|
||||||
|
import core.stdc.string : strerror;
|
||||||
|
import std.string : fromStringz;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.string : join, representation;
|
||||||
|
|
||||||
|
final class MMFile : MM
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void _write(ByteArray data)
|
||||||
|
{
|
||||||
|
_inner = initMmfile(0);
|
||||||
|
|
||||||
|
if (data.length > 0)
|
||||||
|
{
|
||||||
|
auto length = data.length.to!long;
|
||||||
|
auto wrote = xdl_write_mmfile(&_inner, data.ptr, length);
|
||||||
|
enforce(wrote == length,
|
||||||
|
"xdl_write_mmfile wrote less than requested: " ~ strerror(errno).fromStringz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
this(ByteArray data)
|
||||||
|
{
|
||||||
|
_write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this(string data)
|
||||||
|
{
|
||||||
|
_write(data.representation);
|
||||||
|
}
|
||||||
|
|
||||||
|
this(string[] data)
|
||||||
|
{
|
||||||
|
_write(data.join('\n').representation);
|
||||||
|
}
|
||||||
|
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
if (_inner.head !is null)
|
||||||
|
xdl_free_mmfile(&_inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
MMBlocks computePatch(ref MMFile other, long ctxlen = 3)
|
||||||
|
{
|
||||||
|
auto patch = new MMBlocks();
|
||||||
|
|
||||||
|
extern (C) int emitToPatch(void* priv, mmbuffer_t* bufs, int num)
|
||||||
|
{
|
||||||
|
auto target = cast(MMBlocks) priv;
|
||||||
|
foreach (i; 0 .. num)
|
||||||
|
{
|
||||||
|
mmbuffer_t* buf = &bufs[i];
|
||||||
|
long written = xdl_writem_mmfile(target.ptr(), buf, 1);
|
||||||
|
if (written < 0 || written != buf.size)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpparam_t xpp = {0};
|
||||||
|
xdemitconf_t xec = {ctxlen};
|
||||||
|
xdemitcb_t ecb = {cast(void*) patch, &emitToPatch};
|
||||||
|
|
||||||
|
enforce(xdl_diff(&_inner, &other._inner, &xpp, &xec, &ecb) == 0,
|
||||||
|
"xdl_diff failed: " ~ strerror(errno).fromStringz);
|
||||||
|
|
||||||
|
return patch;
|
||||||
|
}
|
||||||
|
}
|
4
source/libxdiff/package.d
Normal file
4
source/libxdiff/package.d
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module libxdiff;
|
||||||
|
|
||||||
|
public import libxdiff.mmfile;
|
||||||
|
public import libxdiff.mmblocks;
|
Loading…
Add table
Add a link
Reference in a new issue