Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Created May 31, 2016 09:13
Show Gist options
  • Select an option

  • Save rikkimax/6ebef99d1d4ef56193a873096688b0ea to your computer and use it in GitHub Desktop.

Select an option

Save rikkimax/6ebef99d1d4ef56193a873096688b0ea to your computer and use it in GitHub Desktop.
module diff;
struct Diff {
import std.utf : validate;
import std.experimental.allocator : IAllocator, dispose, makeArray, expandArray;
bool treatingAsBinary;
ubyte[] diff;
private {
IAllocator alloc;
}
@disable this(this);
~this() {
alloc.dispose(diffText);
}
this(IAllocator allocator, string filenameA, string filenameB, void[] fileA, void[] fileB) {
alloc = allocator;
try {
validate(cast(char[])fileA);
validate(cast(char[])fileB);
} catch (Exception e) {
// not valid
treatingAsBinary = true;
}
if (treatingAsBinary) {
foreach(DiffOperation op, const(void[]) value, size_t fileOffset; mba_impl(fileA, fileB)) {
}
} else {
foreach(DiffOperation op, const(void[]) value, size_t fileOffset; mba_impl(fileA, fileB)) {
}
}
}
enum DiffOperation {
Match,
Removed,
Inserted
}
private {
auto mba_impl(void[] fileA, void[] fileB) {
import mba.diff;
import mba.varray;
import mba.allocator;
struct Result {
int opApply(int delegate(DiffOperation op, const(void[]) value, size_t fileOffset) dg) {
int result = 0;
varray* ses = varray_new(diff_edit.sizeof, null);
int d, sn;
if ((d == diff(fileA.ptr, 0, cast(int)fileA.length,
fileB.ptr, 0, cast(int)fileB.length,
null, null, null, 0, ses, &sn, null)) == -1) {
return -1;
}
F1: foreach(i; 0 .. sn) {
diff_edit* e = cast(diff_edit*)varray_get(ses, i);
final switch(e.op) {
case diff_op.DIFF_MATCH:
result = dg(DiffOperation.Match, cast(const(void[]))fileA[e.off .. e.off + e.len], e.off);
if (result)
break F1;
break;
case diff_op.DIFF_INSERT:
result = dg(DiffOperation.Inserted, cast(const(void[]))fileB[e.off .. e.off + e.len], e.off);
if (result)
break F1;
break;
case diff_op.DIFF_DELETE:
result = dg(DiffOperation.Removed, cast(const(void[]))fileA[e.off .. e.off + e.len], e.off);
if (result)
break F1;
break;
}
}
varray_deinit(ses);
return result;
}
}
return Result;
}
}
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <mba/diff.h>
#include <mba/msgno.h>
int
main(int argc, char *argv[])
{
const char *a = argv[1];
const char *b = argv[2];
int n, m, d;
int sn, i;
struct varray *ses = varray_new(sizeof(struct diff_edit), NULL);
if (argc < 3) {
fprintf(stderr, "usage: %s <str1> <str2>\n", argv[0]);
return EXIT_FAILURE;
}
n = strlen(a);
m = strlen(b);
if ((d = diff(a, 0, n, b, 0, m, NULL, NULL, NULL, 0, ses, &sn, NULL)) == -1) {
MMNO(errno);
return EXIT_FAILURE;
}
printf("d=%d sn=%d\n", d, sn);
for (i = 0; i < sn; i++) {
struct diff_edit *e = varray_get(ses, i);
switch (e->op) {
case DIFF_MATCH:
printf("MAT: ");
fwrite(a + e->off, 1, e->len, stdout);
break;
case DIFF_INSERT:
printf("INS: ");
fwrite(b + e->off, 1, e->len, stdout);
break;
case DIFF_DELETE:
printf("DEL: ");
fwrite(a + e->off, 1, e->len, stdout);
break;
}
printf("\n");
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment