sdiff/source/sdiff/mmfile.d

77 lines
1.4 KiB
D

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)
{
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;
}
}