Переписан для обычного 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