| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | <?php  if (!defined('PmWiki')) exit();/*      Copyright 2003,2004 Nils Knappmeier (nk@knappi.org)    Copyright 2004-2005 Patrick R. Michaud (pmichaud@pobox.com)    This file is part of PmWiki; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published    by the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.  See pmwiki.php for full details.    This file implements a diff function in native PHP.  It is based    upon the PHPDiffEngine code written by Nils Knappmeier, who in turn    had used Daniel Unterberger's diff     (http://www.holomind.de/phpnet/diff.php) as the basis for his code.    Pm's revision of Nils' code simply attempts to streamline it     for speed (eliminate function calls and unnecessary string ops)    and place everything into a single file.*/## PHPDiff returns the differences between $old and $new, formatted## in the standard diff(1) output format.function PHPDiff($old,$new) {   # split the source text into arrays of lines   $t1 = explode("\n",$old);   $x=array_pop($t1);    if ($x>'') $t1[]="$x\n\\ No newline at end of file";   $t2 = explode("\n",$new);   $x=array_pop($t2);    if ($x>'') $t2[]="$x\n\\ No newline at end of file";   # 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++;     }     while ($a1<$best1) { $actions[]=1; $a1++; }  # deleted elements     while ($a2<$best2) { $actions[]=2; $a2++; }  # added elements  }  # we've reached the end of one list, now walk to the end of the other  while($a1<count($t1)) { $actions[]=1; $a1++; }  # deleted elements  while($a2<count($t2)) { $actions[]=2; $a2++; }  # added elements  # 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=0; $y0=$y1=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";      if ($op==1) $out[] = "{$xstr}d{$y1}";      elseif ($op==3) $out[] = "{$xstr}c{$ystr}";      while ($x0<$x1) { $out[] = '< '.$t1[$x0]; $x0++; }   # deleted elems      if ($op==2) $out[] = "{$x1}a{$ystr}";      elseif ($op==3) $out[] = '---';      while ($y0<$y1) { $out[] = '> '.$t2[$y0]; $y0++; }   # added elems    }    $x1++; $x0=$x1;    $y1++; $y0=$y1;    $op=0;  }  $out[] = '';  return join("\n",$out);}$DiffFunction = 'PHPDiff';
 |