dxdiff/source/xdiff_mmblocks.d
2025-08-31 16:47:55 +03:00

108 lines
3.3 KiB
D
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module xdiff_mmblocks;
import std.exception : enforce;
import xdiff_init : ensureInit, initMmfile;
import xdiff;
final class MMBlocks
{
private:
mmfile_t _inner;
bool _owned = true; // владеем ли блоками?
enum DEFAULT_BSIZE = 8 * 1024;
// Глубокая копия: читаем все блоки и записываем в dst
static void deepCopyAll(mmfile_t* src, MMBlocks dst)
{
enforce(xdl_seek_mmfile(src, 0) == 0, "seek(0) failed");
long sz = 0;
auto p = xdl_mmfile_first(src, &sz);
while (p !is null && sz > 0)
{
auto wrote = xdl_write_mmfile(dst.mmfilePtr(), p, sz);
enforce(wrote == sz, "write failed during deep copy");
p = xdl_mmfile_next(src, &sz);
}
}
public:
this()
{
_inner = initMmfile(DEFAULT_BSIZE);
}
static MMBlocks fromBytes(const(ubyte)[] data)
{
auto b = new MMBlocks;
if (data.length > 0)
{
auto wrote = xdl_write_mmfile(&b._inner, data.ptr, cast(long)data.length);
enforce(wrote == cast(long)data.length, "xdl_write_mmfile wrote less than requested");
}
return b;
}
~this()
{
if (_owned && _inner.head !is null)
xdl_free_mmfile(&_inner);
// обнулим на всякий случай
_inner.head = null; _inner.tail = null;
_inner.rcur = null; _inner.wcur = null;
_inner.fsize = 0; _inner.bsize = 0;
}
// доступ к внутреннему mmfile_t*
mmfile_t* mmfilePtr() @trusted { return &_inner; }
size_t size() { return cast(size_t)xdl_mmfile_size(&_inner); }
bool isCompact() const { return xdl_mmfile_iscompact(cast(mmfile_t*)&_inner) != 0; }
int writeBuf(const(ubyte)[] buf)
{
auto wrote = xdl_write_mmfile(&_inner, buf.ptr, cast(long)buf.length);
return (wrote == cast(long)buf.length) ? 0 : -1;
}
/// Глубокая копия (новое владение)
MMBlocks clone() const
{
auto dst = new MMBlocks;
// deepCopyAll принимает mmfile_t*, поэтому аккуратно снимаем const с заголовка:
deepCopyAll(cast(mmfile_t*)&_inner, dst);
return dst;
}
/// Компактизация через пересборку содержимого
void toCompact()
{
if (isCompact()) return;
auto dst = new MMBlocks;
deepCopyAll(&_inner, dst);
// перехватываем владение содержимым dst
if (_owned && _inner.head !is null)
xdl_free_mmfile(&_inner);
_inner = *dst.mmfilePtr();
dst._owned = false; // dst больше не владеет
dst._inner.head = null; // чтобы финалайзер dst ничего не освободил
dst._inner.tail = null;
dst._inner.rcur = null;
dst._inner.wcur = null;
dst._inner.fsize = 0;
dst._inner.bsize = 0;
}
/// Снять владение (используется при move в MMFile)
void disarm()
{
_owned = false;
_inner.head = null; _inner.tail = null;
_inner.rcur = null; _inner.wcur = null;
_inner.fsize = 0; _inner.bsize = 0;
}
}