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