init
This commit is contained in:
		
						commit
						e9952bacf2
					
				
					 6 changed files with 392 additions and 0 deletions
				
			
		
							
								
								
									
										17
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					.dub
 | 
				
			||||||
 | 
					docs.json
 | 
				
			||||||
 | 
					__dummy.html
 | 
				
			||||||
 | 
					docs/
 | 
				
			||||||
 | 
					/dxdiff
 | 
				
			||||||
 | 
					dxdiff.so
 | 
				
			||||||
 | 
					dxdiff.dylib
 | 
				
			||||||
 | 
					dxdiff.dll
 | 
				
			||||||
 | 
					dxdiff.a
 | 
				
			||||||
 | 
					dxdiff.lib
 | 
				
			||||||
 | 
					dxdiff-test-*
 | 
				
			||||||
 | 
					*.exe
 | 
				
			||||||
 | 
					*.pdb
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					*.obj
 | 
				
			||||||
 | 
					*.lst
 | 
				
			||||||
 | 
					/bin
 | 
				
			||||||
							
								
								
									
										17
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Используйте IntelliSense, чтобы узнать о возможных атрибутах.
 | 
				
			||||||
 | 
						// Наведите указатель мыши, чтобы просмотреть описания существующих атрибутов.
 | 
				
			||||||
 | 
						// Для получения дополнительной информации посетите: https://go.microsoft.com/fwlink/?linkid=830387
 | 
				
			||||||
 | 
						"version": "0.2.0",
 | 
				
			||||||
 | 
						"configurations": [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"type": "code-d",
 | 
				
			||||||
 | 
								"request": "launch",
 | 
				
			||||||
 | 
								"dubBuild": true,
 | 
				
			||||||
 | 
								"name": "Build & Debug DUB project",
 | 
				
			||||||
 | 
								"cwd": "${command:dubWorkingDirectory}",
 | 
				
			||||||
 | 
								"program": "bin/${command:dubTarget}",
 | 
				
			||||||
 | 
								"args": []
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								.vscode/settings.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						"editor.insertSpaces": false,
 | 
				
			||||||
 | 
						"editor.tabSize": 4,
 | 
				
			||||||
 | 
						"editor.detectIndentation": false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					# dxdiff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Тестовый пример использования библиотеки LibXDiff.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					use: ./bin/dxdiff diff   [-C N]  FROM TO
 | 
				
			||||||
 | 
					     ./bin/dxdiff patch           ORIG PATCH
 | 
				
			||||||
 | 
					     ./bin/dxdiff bdiff  [-B N]   FROM TO
 | 
				
			||||||
 | 
					     ./bin/dxdiff rabdiff         FROM TO
 | 
				
			||||||
 | 
					     ./bin/dxdiff bpatch          ORIG PATCH
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										20
									
								
								dub.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								dub.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						"authors": [
 | 
				
			||||||
 | 
							"alexander"
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						"copyright": "Copyright © 2025, alexander",
 | 
				
			||||||
 | 
						"description": "A minimal D application.",
 | 
				
			||||||
 | 
						"license": "proprietary",
 | 
				
			||||||
 | 
						"name": "dxdiff",
 | 
				
			||||||
 | 
						"targetPath": "bin",
 | 
				
			||||||
 | 
						"targetType": "executable",
 | 
				
			||||||
 | 
						"libs": [
 | 
				
			||||||
 | 
							"xdiff"
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						"dependencies": {
 | 
				
			||||||
 | 
							"xdiff": {
 | 
				
			||||||
 | 
								"repository": "git+https://git.zhirov.kz/dlang/xdiff.git",
 | 
				
			||||||
 | 
								"version": "e2396bc172eba813cdcd1a96c494e35d687f576a"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										322
									
								
								source/app.d
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								source/app.d
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,322 @@
 | 
				
			||||||
 | 
					import std.stdio : writeln, stderr, File;
 | 
				
			||||||
 | 
					import std.getopt;
 | 
				
			||||||
 | 
					import std.file : read, exists;
 | 
				
			||||||
 | 
					import std.exception : enforce, collectException;
 | 
				
			||||||
 | 
					import core.stdc.stdlib : malloc, free, realloc;
 | 
				
			||||||
 | 
					import core.stdc.string : memcpy;
 | 
				
			||||||
 | 
					import core.sys.posix.unistd : posix_write = write;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import xdiff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// RAII для mmfile_t
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					struct MmFile
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mmfile_t mf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// фабрика вместо конструктора по умолчанию
 | 
				
			||||||
 | 
						static MmFile create(long bsize = 8 * 1024, ulong flags = XDL_MMF_ATOMIC)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							MmFile m;
 | 
				
			||||||
 | 
							enforce(xdl_init_mmfile(&m.mf, bsize, flags) == 0, "xdl_init_mmfile failed");
 | 
				
			||||||
 | 
							return m;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void deinit()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							xdl_free_mmfile(&mf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// Коллбэки вывода
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					extern (C) int mmfileOut(void* priv, mmbuffer_t* mb, int nbuf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto mmfOut = cast(mmfile_t*) priv;
 | 
				
			||||||
 | 
						return xdl_writem_mmfile(mmfOut, mb, nbuf) < 0 ? -1 : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern (C) int fdOut(void* priv, mmbuffer_t* mb, int nbuf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const fd = cast(int) cast(size_t) priv; // 1=stdout, 2=stderr
 | 
				
			||||||
 | 
						foreach (i; 0 .. nbuf)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto ptr = mb[i].ptr;
 | 
				
			||||||
 | 
							auto left = cast(size_t) mb[i].size;
 | 
				
			||||||
 | 
							while (left)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto n = posix_write(fd, ptr, left);
 | 
				
			||||||
 | 
								if (n < 0)
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								ptr += n;
 | 
				
			||||||
 | 
								left -= cast(size_t) n;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// Загрузка/выгрузка
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					void loadMmFile(ref MmFile m, string path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						try
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							enforce(exists(path), "no such file: " ~ path);
 | 
				
			||||||
 | 
							auto data = cast(const(char)[]) read(path); // читает весь файл
 | 
				
			||||||
 | 
							auto dst = cast(char*) xdl_mmfile_writeallocate(&m.mf, data.length);
 | 
				
			||||||
 | 
							enforce(dst !is null, "xdl_mmfile_writeallocate failed (null)");
 | 
				
			||||||
 | 
							if (data.length)
 | 
				
			||||||
 | 
								memcpy(dst, data.ptr, data.length);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch (Exception e)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// пробрасываем с контекстом пути
 | 
				
			||||||
 | 
							throw new Exception("loadMmFile(" ~ path ~ "): " ~ e.msg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dumpMmFile(const ref MmFile m, string path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						File f = File(path, "wb");
 | 
				
			||||||
 | 
						scope (exit)
 | 
				
			||||||
 | 
							f.close();
 | 
				
			||||||
 | 
						long sz = 0;
 | 
				
			||||||
 | 
						auto blk = cast(char*) xdl_mmfile_first(cast(mmfile_t*)&m.mf, &sz);
 | 
				
			||||||
 | 
						while (blk !is null)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							f.rawWrite(blk[0 .. cast(size_t) sz]);
 | 
				
			||||||
 | 
							blk = cast(char*) xdl_mmfile_next(cast(mmfile_t*)&m.mf, &sz);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// Аллокатор
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					extern (C) void* wrap_malloc(void*, uint size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return malloc(size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern (C) void wrap_free(void*, void* ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						free(ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern (C) void* wrap_realloc(void*, void* ptr, uint size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return realloc(ptr, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void installAllocator()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memallocator_t malt;
 | 
				
			||||||
 | 
						malt.priv = null;
 | 
				
			||||||
 | 
						malt.malloc = &wrap_malloc;
 | 
				
			||||||
 | 
						malt.free = &wrap_free;
 | 
				
			||||||
 | 
						malt.realloc = &wrap_realloc;
 | 
				
			||||||
 | 
						enforce(xdl_set_allocator(&malt) == 0, "xdl_set_allocator failed");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// Команды
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					int doDiff(ref MmFile a, ref MmFile b, long ctxlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xpparam_t xpp;
 | 
				
			||||||
 | 
						xpp.flags = 0;
 | 
				
			||||||
 | 
						xdemitconf_t xecfg;
 | 
				
			||||||
 | 
						xecfg.ctxlen = ctxlen;
 | 
				
			||||||
 | 
						xdemitcb_t ecb;
 | 
				
			||||||
 | 
						ecb.priv = cast(void*) cast(size_t) 1;
 | 
				
			||||||
 | 
						ecb.outf = &fdOut;
 | 
				
			||||||
 | 
						return xdl_diff(&a.mf, &b.mf, &xpp, &xecfg, &ecb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int doPatch(ref MmFile orig, ref MmFile patch, int mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xdemitcb_t outcb;
 | 
				
			||||||
 | 
						outcb.priv = cast(void*) cast(size_t) 1;
 | 
				
			||||||
 | 
						outcb.outf = &fdOut;
 | 
				
			||||||
 | 
						xdemitcb_t rejcb;
 | 
				
			||||||
 | 
						rejcb.priv = cast(void*) cast(size_t) 2;
 | 
				
			||||||
 | 
						rejcb.outf = &fdOut;
 | 
				
			||||||
 | 
						return xdl_patch(&orig.mf, &patch.mf, mode, &outcb, &rejcb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int doBDiff(ref MmFile a, ref MmFile b, long bsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bdiffparam_t bdp;
 | 
				
			||||||
 | 
						bdp.bsize = bsize;
 | 
				
			||||||
 | 
						xdemitcb_t ecb;
 | 
				
			||||||
 | 
						ecb.priv = cast(void*) cast(size_t) 1;
 | 
				
			||||||
 | 
						ecb.outf = &fdOut;
 | 
				
			||||||
 | 
						return xdl_bdiff(&a.mf, &b.mf, &bdp, &ecb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int doRaBDiff(ref MmFile a, ref MmFile b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xdemitcb_t ecb;
 | 
				
			||||||
 | 
						ecb.priv = cast(void*) cast(size_t) 1;
 | 
				
			||||||
 | 
						ecb.outf = &fdOut;
 | 
				
			||||||
 | 
						return xdl_rabdiff(&a.mf, &b.mf, &ecb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int doBPatch(ref MmFile base, ref MmFile binPatch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xdemitcb_t ecb;
 | 
				
			||||||
 | 
						ecb.priv = cast(void*) cast(size_t) 1;
 | 
				
			||||||
 | 
						ecb.outf = &fdOut;
 | 
				
			||||||
 | 
						return xdl_bpatch(&base.mf, &binPatch.mf, &ecb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					// CLI
 | 
				
			||||||
 | 
					// ------------------------------
 | 
				
			||||||
 | 
					enum Cmd
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						diff,
 | 
				
			||||||
 | 
						patch,
 | 
				
			||||||
 | 
						bdiff,
 | 
				
			||||||
 | 
						rabdiff,
 | 
				
			||||||
 | 
						bpatch
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private Cmd parseCmd(string s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						final switch (s)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case "diff":
 | 
				
			||||||
 | 
							return Cmd.diff;
 | 
				
			||||||
 | 
						case "patch":
 | 
				
			||||||
 | 
							return Cmd.patch;
 | 
				
			||||||
 | 
						case "bdiff":
 | 
				
			||||||
 | 
							return Cmd.bdiff;
 | 
				
			||||||
 | 
						case "rabdiff":
 | 
				
			||||||
 | 
							return Cmd.rabdiff;
 | 
				
			||||||
 | 
						case "bpatch":
 | 
				
			||||||
 | 
							return Cmd.bpatch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Короткая справка
 | 
				
			||||||
 | 
					void printUsage(string prg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stderr.writefln(
 | 
				
			||||||
 | 
							"use: %1$s diff   [-C N]  FROM TO\n" ~
 | 
				
			||||||
 | 
								"     %1$s patch           ORIG PATCH\n" ~
 | 
				
			||||||
 | 
								"     %1$s bdiff  [-B N]   FROM TO\n" ~
 | 
				
			||||||
 | 
								"     %1$s rabdiff         FROM TO\n" ~
 | 
				
			||||||
 | 
								"     %1$s bpatch          ORIG PATCH\n",
 | 
				
			||||||
 | 
								prg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Парсинг подкоманды + её опций. Возвращаем уже «очищенный» список позиционных.
 | 
				
			||||||
 | 
					struct Parsed
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Cmd cmd;
 | 
				
			||||||
 | 
						long ctxlen = 3; // для diff
 | 
				
			||||||
 | 
						long bsize = 16; // для bdiff
 | 
				
			||||||
 | 
						string[] positional; // оставшиеся позиционные (пути)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Parsed parseArgs(string[] args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enforce(args.length >= 2, "no subcommand");
 | 
				
			||||||
 | 
						auto sub = args[1];
 | 
				
			||||||
 | 
						auto cmd = parseCmd(sub);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						long ctxlen = 3;
 | 
				
			||||||
 | 
						long bsize = 16;
 | 
				
			||||||
 | 
						bool helpWanted = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Опции и позиционные ТОЛЬКО после подкоманды
 | 
				
			||||||
 | 
						string[] optArgs = args.length > 2 ? args[2 .. $].dup : [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// getopt выкинет опции из optArgs и оставит только позиционные
 | 
				
			||||||
 | 
						auto r = getopt(optArgs,
 | 
				
			||||||
 | 
							"h|help", &helpWanted,
 | 
				
			||||||
 | 
							"C", &ctxlen, // актуально для `diff`
 | 
				
			||||||
 | 
							"B", &bsize // актуально для `bdiff`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						enforce(!helpWanted, "help");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Parsed p;
 | 
				
			||||||
 | 
						p.cmd = cmd;
 | 
				
			||||||
 | 
						p.ctxlen = ctxlen;
 | 
				
			||||||
 | 
						p.bsize = bsize;
 | 
				
			||||||
 | 
						p.positional = optArgs; // здесь уже только пути
 | 
				
			||||||
 | 
						return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(string[] args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// 1) Парсим
 | 
				
			||||||
 | 
						Parsed p;
 | 
				
			||||||
 | 
						try
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							p = parseArgs(args);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch (Exception)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printUsage(args[0]);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (p.positional.length != 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// каждая подкоманда требует ровно 2 пути
 | 
				
			||||||
 | 
							printUsage(args[0]);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						auto p1 = p.positional[0];
 | 
				
			||||||
 | 
						auto p2 = p.positional[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 2) Аллокатор libxdiff
 | 
				
			||||||
 | 
						installAllocator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 3) Готовим входы
 | 
				
			||||||
 | 
						auto mf1 = MmFile.create();
 | 
				
			||||||
 | 
						scope (exit)
 | 
				
			||||||
 | 
							mf1.deinit();
 | 
				
			||||||
 | 
						auto mf2 = MmFile.create();
 | 
				
			||||||
 | 
						scope (exit)
 | 
				
			||||||
 | 
							mf2.deinit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							loadMmFile(mf1, p1);
 | 
				
			||||||
 | 
							loadMmFile(mf2, p2);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch (Exception e)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stderr.writeln(e.msg);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 4) Запускаем действие
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						final switch (p.cmd)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case Cmd.diff:
 | 
				
			||||||
 | 
							rc = doDiff(mf1, mf2, p.ctxlen);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case Cmd.patch:
 | 
				
			||||||
 | 
							rc = doPatch(mf1, mf2, XDL_PATCH_NORMAL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case Cmd.bdiff:
 | 
				
			||||||
 | 
							rc = doBDiff(mf1, mf2, p.bsize);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case Cmd.rabdiff:
 | 
				
			||||||
 | 
							rc = doRaBDiff(mf1, mf2);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case Cmd.bpatch:
 | 
				
			||||||
 | 
							rc = doBPatch(mf1, mf2);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc < 0 ? 2 : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue