Skip to content

Instantly share code, notes, and snippets.

@BinaryMoon
Created May 13, 2017 22:35
Show Gist options
  • Save BinaryMoon/d6416caad61bdb5e7ae07c729201dd0e to your computer and use it in GitHub Desktop.
Save BinaryMoon/d6416caad61bdb5e7ae07c729201dd0e to your computer and use it in GitHub Desktop.
do a diff between files
function PHPDiff ($old, $new) {
$t1 = $old;
$t2 = $new;
# build a reverse-index array using the line as key and line number as value
# don't store blank lines, so they won't be targets of the shortest distance
# search
foreach ($t1 as $i => $x) {
if ($x>'') {
$r1[$x][] = $i;
}
}
foreach ($t2 as $i => $x) {
if ($x>'') {
$r2[$x][] = $i;
}
}
$a1 = 0;
$a2 = 0; # start at beginning of each list
$actions = array();
# walk this loop until we reach the end of one of the lists
while ($a1 < count($t1) && $a2 < count($t2)) {
# if we have a common element, save it and go to the next
if ($t1[$a1] == $t2[$a2]) {
$actions[] = 4;
$a1++;
$a2++;
continue;
}
# otherwise, find the shortest move (Manhattan-distance) from the
# current location
$best1 = count($t1);
$best2 = count($t2);
$s1 = $a1;
$s2 = $a2;
while(($s1 + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2)) {
$d = -1;
foreach((array) @$r1[$t2[$s2]] as $n) {
if ($n >= $s1) {
$d = $n;
break;
}
}
if ($d >= $s1 && ($d + $s2 - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2)) {
$best1 = $d;
$best2 = $s2;
}
$d = -1;
foreach((array) @$r2[$t1[$s1]] as $n) {
if ($n >= $s2) {
$d = $n;
break;
}
}
if ($d >= $s2 && ($s1 + $d - $a1 - $a2) < ($best1 + $best2 - $a1 - $a2)) {
$best1 = $s1;
$best2 = $d;
}
$s1++;
$s2++;
}
// deleted elements
while ($a1 < $best1) {
$actions[] = 1;
$a1++;
}
// added elements
while ($a2 < $best2) {
$actions[] = 2;
$a2++;
}
}
# we've reached the end of one list, now walk to the end of the other
# deleted elements
while($a1 < count($t1)) {
$actions[] = 1;
$a1 ++;
}
# added elements
while($a2 < count($t2)) {
$actions[] = 2;
$a2 ++;
}
# and this marks our ending point
$actions[] = 8;
# now, let's follow the path we just took and report the added/deleted
# elements into $out.
$op = 0;
$x0 = $x1 = $y0 = $y1 = 0;
$changeCount = 0;
$out = array();
foreach($actions as $act) {
if ($act == 1) {
$op |= $act;
$x1 ++;
continue;
}
if ($act==2) {
$op |= $act;
$y1 ++;
continue;
}
if ($op>0) {
$xstr = ($x1 == ($x0 + 1)) ? $x1 : ($x0 + 1) . ', ' . $x1;
$ystr = ($y1 == ($y0 + 1)) ? $y1 : ($y0 + 1) . ', ' . $y1;
$out[] = '<li>';
if ($op == 1) {
$out[] = '<p><strong>Code deleted</strong> : lines ' . $xstr . '</p>';
}
if ($op == 3) {
$out[] = '<p><strong>Code changed</strong> : lines ' . $xstr . ' &#8594; ' . $ystr . '</p>';
}
// deleted elems
if ($x0 < $x1) {
$out[] = "<pre>";
while ($x0 < $x1) {
if($t1[$x0] != "") {
$out[] = str_replace("\n", "", str_replace("<", "&lt;", $t1[$x0]));
}
$x0++;
}
$out[] = "</pre>";
}
if ($op == 2) {
//$out[] = "<p><strong>Lines added</strong> : " . $x1 . " to " . $ystr . "</p>";
$out[] = "<p><strong>Lines added</strong> : " . $ystr . "</p>";
}
if ($op == 3) {
$out[] = '<p>changed to : </p>';
}
# added elems
if ($y0 < $y1) {
$out[] = "<pre>";
while ($y0 < $y1) {
if($t2[$y0] != "") {
$out[] = str_replace("\n", "", str_replace("<", "&lt;", $t2[$y0]));
}
$y0++;
}
$out[] = "</pre>";
}
$out[] = '</li>';
$changeCount ++;
}
$x1++;
$x0=$x1;
$y1++;
$y0=$y1;
$op=0;
}
$ret["changes"] = join("\n", $out);
$ret["changeCount"] = $changeCount;
return $ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment