init
This commit is contained in:
commit
8c388b1123
11 changed files with 347 additions and 0 deletions
56
source/sdiff/init.d
Normal file
56
source/sdiff/init.d
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
module sdiff.init;
|
||||
|
||||
import xdiff;
|
||||
|
||||
import core.stdc.stdlib : malloc, free, realloc;
|
||||
import std.exception : enforce;
|
||||
import std.conv : to;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
shared static this()
|
||||
{
|
||||
memallocator_t m = {null, &wrap_malloc, &wrap_free, &wrap_realloc};
|
||||
auto rc = xdl_set_allocator(&m);
|
||||
enforce(rc == 0, "xdl_set_allocator failed (rc=" ~ rc.to!string ~ ")");
|
||||
}
|
||||
|
||||
mmfile_t initMmfile(size_t blockSize)
|
||||
{
|
||||
mmfile_t mf;
|
||||
auto rc = xdl_init_mmfile(&mf, blockSize.to!long, XDL_MMF_ATOMIC);
|
||||
enforce(rc == 0, "xdl_init_mmfile failed (rc=" ~ rc.to!string ~ ")");
|
||||
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;
|
||||
}
|
||||
}
|
||||
42
source/sdiff/mmblocks.d
Normal file
42
source/sdiff/mmblocks.d
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
module sdiff.mmblocks;
|
||||
|
||||
import xdiff;
|
||||
|
||||
import sdiff.init;
|
||||
|
||||
import std.exception : enforce;
|
||||
import std.conv : to;
|
||||
|
||||
private enum DEFAULT_BSIZE = 64 * 1024;
|
||||
|
||||
final class MMBlocks : MM
|
||||
{
|
||||
public:
|
||||
this()
|
||||
{
|
||||
_inner = initMmfile(DEFAULT_BSIZE);
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
if (_inner.head !is null)
|
||||
xdl_free_mmfile(&_inner);
|
||||
}
|
||||
|
||||
package(sdiff) mmfile_t* ptr() @trusted
|
||||
{
|
||||
return &_inner;
|
||||
}
|
||||
|
||||
const(ubyte)[] slice() const @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
|
||||
{
|
||||
return cast(string) slice();
|
||||
}
|
||||
}
|
||||
79
source/sdiff/mmfile.d
Normal file
79
source/sdiff/mmfile.d
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
module sdiff.mmfile;
|
||||
|
||||
import xdiff;
|
||||
|
||||
import sdiff.init;
|
||||
import sdiff.mmblocks;
|
||||
|
||||
import std.exception : enforce;
|
||||
import std.conv : to;
|
||||
import std.string : join, representation;
|
||||
|
||||
final class MMFile : MM
|
||||
{
|
||||
private:
|
||||
void _write(const(ubyte)[] 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 (rc=" ~ wrote.to!string ~ ")");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
this(const(ubyte)[] 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 diff(const scope 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)
|
||||
{
|
||||
auto buf = &bufs[i];
|
||||
auto rc = xdl_writem_mmfile(target.ptr(), buf, 1);
|
||||
if (rc < 0 || rc != buf.size)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
xpparam_t xpp = xpparam_t.init;
|
||||
|
||||
xdemitconf_t xec = xdemitconf_t.init;
|
||||
xec.ctxlen = ctxlen;
|
||||
|
||||
xdemitcb_t ecb = {cast(void*) patch, &emitToPatch};
|
||||
|
||||
auto rc = xdl_diff(&_inner, cast(mmfile_t*)&other._inner, &xpp, &xec, &ecb);
|
||||
enforce(rc == 0, "xdl_diff failed (rc=" ~ rc.to!string ~ ")");
|
||||
|
||||
return patch;
|
||||
}
|
||||
}
|
||||
4
source/sdiff/package.d
Normal file
4
source/sdiff/package.d
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
module sdiff;
|
||||
|
||||
public import sdiff.mmfile;
|
||||
public import sdiff.mmblocks;
|
||||
23
source/sdiff/unittests.d
Normal file
23
source/sdiff/unittests.d
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
module sdiff.unittests;
|
||||
|
||||
import sdiff;
|
||||
|
||||
import std.conv : to;
|
||||
import std.stdio;
|
||||
|
||||
unittest
|
||||
{
|
||||
auto data = new MMFile("hello world\n");
|
||||
auto data2 = new MMFile("hello world!\n");
|
||||
|
||||
auto patch = data.diff(data2);
|
||||
|
||||
writeln(patch);
|
||||
|
||||
assert(
|
||||
patch.to!string ==
|
||||
"@@ -1,1 +1,1 @@\n" ~
|
||||
"-hello world\n" ~
|
||||
"+hello world!\n"
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue