Added new (clean) yii boilerplate
This commit is contained in:
		
							
								
								
									
										438
									
								
								framework/gii/components/Pear/Text/Diff/Engine/native.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										438
									
								
								framework/gii/components/Pear/Text/Diff/Engine/native.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,438 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Class used internally by Text_Diff to actually compute the diffs. | ||||
|  * | ||||
|  * This class is implemented using native PHP code. | ||||
|  * | ||||
|  * The algorithm used here is mostly lifted from the perl module | ||||
|  * Algorithm::Diff (version 1.06) by Ned Konz, which is available at: | ||||
|  * http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip | ||||
|  * | ||||
|  * More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html | ||||
|  * | ||||
|  * Some ideas (and a bit of code) are taken from analyze.c, of GNU | ||||
|  * diffutils-2.7, which can be found at: | ||||
|  * ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz | ||||
|  * | ||||
|  * Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from | ||||
|  * Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this | ||||
|  * code was written by him, and is used/adapted with his permission. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Engine/native.php,v 1.7.2.4 2008/01/04 10:38:10 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Engine_native { | ||||
|  | ||||
|     function diff($from_lines, $to_lines) | ||||
|     { | ||||
|         array_walk($from_lines, array('Text_Diff', 'trimNewlines')); | ||||
|         array_walk($to_lines, array('Text_Diff', 'trimNewlines')); | ||||
|  | ||||
|         $n_from = count($from_lines); | ||||
|         $n_to = count($to_lines); | ||||
|  | ||||
|         $this->xchanged = $this->ychanged = array(); | ||||
|         $this->xv = $this->yv = array(); | ||||
|         $this->xind = $this->yind = array(); | ||||
|         unset($this->seq); | ||||
|         unset($this->in_seq); | ||||
|         unset($this->lcs); | ||||
|  | ||||
|         // Skip leading common lines. | ||||
|         for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { | ||||
|             if ($from_lines[$skip] !== $to_lines[$skip]) { | ||||
|                 break; | ||||
|             } | ||||
|             $this->xchanged[$skip] = $this->ychanged[$skip] = false; | ||||
|         } | ||||
|  | ||||
|         // Skip trailing common lines. | ||||
|         $xi = $n_from; $yi = $n_to; | ||||
|         for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { | ||||
|             if ($from_lines[$xi] !== $to_lines[$yi]) { | ||||
|                 break; | ||||
|             } | ||||
|             $this->xchanged[$xi] = $this->ychanged[$yi] = false; | ||||
|         } | ||||
|  | ||||
|         // Ignore lines which do not exist in both files. | ||||
|         for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { | ||||
|             $xhash[$from_lines[$xi]] = 1; | ||||
|         } | ||||
|         for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { | ||||
|             $line = $to_lines[$yi]; | ||||
|             if (($this->ychanged[$yi] = empty($xhash[$line]))) { | ||||
|                 continue; | ||||
|             } | ||||
|             $yhash[$line] = 1; | ||||
|             $this->yv[] = $line; | ||||
|             $this->yind[] = $yi; | ||||
|         } | ||||
|         for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { | ||||
|             $line = $from_lines[$xi]; | ||||
|             if (($this->xchanged[$xi] = empty($yhash[$line]))) { | ||||
|                 continue; | ||||
|             } | ||||
|             $this->xv[] = $line; | ||||
|             $this->xind[] = $xi; | ||||
|         } | ||||
|  | ||||
|         // Find the LCS. | ||||
|         $this->_compareseq(0, count($this->xv), 0, count($this->yv)); | ||||
|  | ||||
|         // Merge edits when possible. | ||||
|         $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); | ||||
|         $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); | ||||
|  | ||||
|         // Compute the edit operations. | ||||
|         $edits = array(); | ||||
|         $xi = $yi = 0; | ||||
|         while ($xi < $n_from || $yi < $n_to) { | ||||
|             assert($yi < $n_to || $this->xchanged[$xi]); | ||||
|             assert($xi < $n_from || $this->ychanged[$yi]); | ||||
|  | ||||
|             // Skip matching "snake". | ||||
|             $copy = array(); | ||||
|             while ($xi < $n_from && $yi < $n_to | ||||
|                    && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { | ||||
|                 $copy[] = $from_lines[$xi++]; | ||||
|                 ++$yi; | ||||
|             } | ||||
|             if ($copy) { | ||||
|                 $edits[] = new Text_Diff_Op_copy($copy); | ||||
|             } | ||||
|  | ||||
|             // Find deletes & adds. | ||||
|             $delete = array(); | ||||
|             while ($xi < $n_from && $this->xchanged[$xi]) { | ||||
|                 $delete[] = $from_lines[$xi++]; | ||||
|             } | ||||
|  | ||||
|             $add = array(); | ||||
|             while ($yi < $n_to && $this->ychanged[$yi]) { | ||||
|                 $add[] = $to_lines[$yi++]; | ||||
|             } | ||||
|  | ||||
|             if ($delete && $add) { | ||||
|                 $edits[] = new Text_Diff_Op_change($delete, $add); | ||||
|             } elseif ($delete) { | ||||
|                 $edits[] = new Text_Diff_Op_delete($delete); | ||||
|             } elseif ($add) { | ||||
|                 $edits[] = new Text_Diff_Op_add($add); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, | ||||
|      * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized | ||||
|      * segments. | ||||
|      * | ||||
|      * Returns (LCS, PTS).  LCS is the length of the LCS. PTS is an array of | ||||
|      * NCHUNKS+1 (X, Y) indexes giving the diving points between sub | ||||
|      * sequences.  The first sub-sequence is contained in (X0, X1), (Y0, Y1), | ||||
|      * the second in (X1, X2), (Y1, Y2) and so on.  Note that (X0, Y0) == | ||||
|      * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). | ||||
|      * | ||||
|      * This function assumes that the first lines of the specified portions of | ||||
|      * the two files do not match, and likewise that the last lines do not | ||||
|      * match.  The caller must trim matching lines from the beginning and end | ||||
|      * of the portions it is going to specify. | ||||
|      */ | ||||
|     function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) | ||||
|     { | ||||
|         $flip = false; | ||||
|  | ||||
|         if ($xlim - $xoff > $ylim - $yoff) { | ||||
|             /* Things seems faster (I'm not sure I understand why) when the | ||||
|              * shortest sequence is in X. */ | ||||
|             $flip = true; | ||||
|             list ($xoff, $xlim, $yoff, $ylim) | ||||
|                 = array($yoff, $ylim, $xoff, $xlim); | ||||
|         } | ||||
|  | ||||
|         if ($flip) { | ||||
|             for ($i = $ylim - 1; $i >= $yoff; $i--) { | ||||
|                 $ymatches[$this->xv[$i]][] = $i; | ||||
|             } | ||||
|         } else { | ||||
|             for ($i = $ylim - 1; $i >= $yoff; $i--) { | ||||
|                 $ymatches[$this->yv[$i]][] = $i; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $this->lcs = 0; | ||||
|         $this->seq[0]= $yoff - 1; | ||||
|         $this->in_seq = array(); | ||||
|         $ymids[0] = array(); | ||||
|  | ||||
|         $numer = $xlim - $xoff + $nchunks - 1; | ||||
|         $x = $xoff; | ||||
|         for ($chunk = 0; $chunk < $nchunks; $chunk++) { | ||||
|             if ($chunk > 0) { | ||||
|                 for ($i = 0; $i <= $this->lcs; $i++) { | ||||
|                     $ymids[$i][$chunk - 1] = $this->seq[$i]; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); | ||||
|             for (; $x < $x1; $x++) { | ||||
|                 $line = $flip ? $this->yv[$x] : $this->xv[$x]; | ||||
|                 if (empty($ymatches[$line])) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 $matches = $ymatches[$line]; | ||||
|                 reset($matches); | ||||
|                 while (list(, $y) = each($matches)) { | ||||
|                     if (empty($this->in_seq[$y])) { | ||||
|                         $k = $this->_lcsPos($y); | ||||
|                         assert($k > 0); | ||||
|                         $ymids[$k] = $ymids[$k - 1]; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|                 while (list(, $y) = each($matches)) { | ||||
|                     if ($y > $this->seq[$k - 1]) { | ||||
|                         assert($y <= $this->seq[$k]); | ||||
|                         /* Optimization: this is a common case: next match is | ||||
|                          * just replacing previous match. */ | ||||
|                         $this->in_seq[$this->seq[$k]] = false; | ||||
|                         $this->seq[$k] = $y; | ||||
|                         $this->in_seq[$y] = 1; | ||||
|                     } elseif (empty($this->in_seq[$y])) { | ||||
|                         $k = $this->_lcsPos($y); | ||||
|                         assert($k > 0); | ||||
|                         $ymids[$k] = $ymids[$k - 1]; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); | ||||
|         $ymid = $ymids[$this->lcs]; | ||||
|         for ($n = 0; $n < $nchunks - 1; $n++) { | ||||
|             $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); | ||||
|             $y1 = $ymid[$n] + 1; | ||||
|             $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); | ||||
|         } | ||||
|         $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); | ||||
|  | ||||
|         return array($this->lcs, $seps); | ||||
|     } | ||||
|  | ||||
|     function _lcsPos($ypos) | ||||
|     { | ||||
|         $end = $this->lcs; | ||||
|         if ($end == 0 || $ypos > $this->seq[$end]) { | ||||
|             $this->seq[++$this->lcs] = $ypos; | ||||
|             $this->in_seq[$ypos] = 1; | ||||
|             return $this->lcs; | ||||
|         } | ||||
|  | ||||
|         $beg = 1; | ||||
|         while ($beg < $end) { | ||||
|             $mid = (int)(($beg + $end) / 2); | ||||
|             if ($ypos > $this->seq[$mid]) { | ||||
|                 $beg = $mid + 1; | ||||
|             } else { | ||||
|                 $end = $mid; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         assert($ypos != $this->seq[$end]); | ||||
|  | ||||
|         $this->in_seq[$this->seq[$end]] = false; | ||||
|         $this->seq[$end] = $ypos; | ||||
|         $this->in_seq[$ypos] = 1; | ||||
|         return $end; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Finds LCS of two sequences. | ||||
|      * | ||||
|      * The results are recorded in the vectors $this->{x,y}changed[], by | ||||
|      * storing a 1 in the element for each line that is an insertion or | ||||
|      * deletion (ie. is not in the LCS). | ||||
|      * | ||||
|      * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. | ||||
|      * | ||||
|      * Note that XLIM, YLIM are exclusive bounds.  All line numbers are | ||||
|      * origin-0 and discarded lines are not counted. | ||||
|      */ | ||||
|     function _compareseq ($xoff, $xlim, $yoff, $ylim) | ||||
|     { | ||||
|         /* Slide down the bottom initial diagonal. */ | ||||
|         while ($xoff < $xlim && $yoff < $ylim | ||||
|                && $this->xv[$xoff] == $this->yv[$yoff]) { | ||||
|             ++$xoff; | ||||
|             ++$yoff; | ||||
|         } | ||||
|  | ||||
|         /* Slide up the top initial diagonal. */ | ||||
|         while ($xlim > $xoff && $ylim > $yoff | ||||
|                && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) { | ||||
|             --$xlim; | ||||
|             --$ylim; | ||||
|         } | ||||
|  | ||||
|         if ($xoff == $xlim || $yoff == $ylim) { | ||||
|             $lcs = 0; | ||||
|         } else { | ||||
|             /* This is ad hoc but seems to work well.  $nchunks = | ||||
|              * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks = | ||||
|              * max(2,min(8,(int)$nchunks)); */ | ||||
|             $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; | ||||
|             list($lcs, $seps) | ||||
|                 = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); | ||||
|         } | ||||
|  | ||||
|         if ($lcs == 0) { | ||||
|             /* X and Y sequences have no common subsequence: mark all | ||||
|              * changed. */ | ||||
|             while ($yoff < $ylim) { | ||||
|                 $this->ychanged[$this->yind[$yoff++]] = 1; | ||||
|             } | ||||
|             while ($xoff < $xlim) { | ||||
|                 $this->xchanged[$this->xind[$xoff++]] = 1; | ||||
|             } | ||||
|         } else { | ||||
|             /* Use the partitions to split this problem into subproblems. */ | ||||
|             reset($seps); | ||||
|             $pt1 = $seps[0]; | ||||
|             while ($pt2 = next($seps)) { | ||||
|                 $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); | ||||
|                 $pt1 = $pt2; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adjusts inserts/deletes of identical lines to join changes as much as | ||||
|      * possible. | ||||
|      * | ||||
|      * We do something when a run of changed lines include a line at one end | ||||
|      * and has an excluded, identical line at the other.  We are free to | ||||
|      * choose which identical line is included.  `compareseq' usually chooses | ||||
|      * the one at the beginning, but usually it is cleaner to consider the | ||||
|      * following identical line to be the "change". | ||||
|      * | ||||
|      * This is extracted verbatim from analyze.c (GNU diffutils-2.7). | ||||
|      */ | ||||
|     function _shiftBoundaries($lines, &$changed, $other_changed) | ||||
|     { | ||||
|         $i = 0; | ||||
|         $j = 0; | ||||
|  | ||||
|         assert('count($lines) == count($changed)'); | ||||
|         $len = count($lines); | ||||
|         $other_len = count($other_changed); | ||||
|  | ||||
|         while (1) { | ||||
|             /* Scan forward to find the beginning of another run of | ||||
|              * changes. Also keep track of the corresponding point in the | ||||
|              * other file. | ||||
|              * | ||||
|              * Throughout this code, $i and $j are adjusted together so that | ||||
|              * the first $i elements of $changed and the first $j elements of | ||||
|              * $other_changed both contain the same number of zeros (unchanged | ||||
|              * lines). | ||||
|              * | ||||
|              * Furthermore, $j is always kept so that $j == $other_len or | ||||
|              * $other_changed[$j] == false. */ | ||||
|             while ($j < $other_len && $other_changed[$j]) { | ||||
|                 $j++; | ||||
|             } | ||||
|  | ||||
|             while ($i < $len && ! $changed[$i]) { | ||||
|                 assert('$j < $other_len && ! $other_changed[$j]'); | ||||
|                 $i++; $j++; | ||||
|                 while ($j < $other_len && $other_changed[$j]) { | ||||
|                     $j++; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if ($i == $len) { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             $start = $i; | ||||
|  | ||||
|             /* Find the end of this run of changes. */ | ||||
|             while (++$i < $len && $changed[$i]) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             do { | ||||
|                 /* Record the length of this run of changes, so that we can | ||||
|                  * later determine whether the run has grown. */ | ||||
|                 $runlength = $i - $start; | ||||
|  | ||||
|                 /* Move the changed region back, so long as the previous | ||||
|                  * unchanged line matches the last changed one.  This merges | ||||
|                  * with previous changed regions. */ | ||||
|                 while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { | ||||
|                     $changed[--$start] = 1; | ||||
|                     $changed[--$i] = false; | ||||
|                     while ($start > 0 && $changed[$start - 1]) { | ||||
|                         $start--; | ||||
|                     } | ||||
|                     assert('$j > 0'); | ||||
|                     while ($other_changed[--$j]) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     assert('$j >= 0 && !$other_changed[$j]'); | ||||
|                 } | ||||
|  | ||||
|                 /* Set CORRESPONDING to the end of the changed run, at the | ||||
|                  * last point where it corresponds to a changed run in the | ||||
|                  * other file. CORRESPONDING == LEN means no such point has | ||||
|                  * been found. */ | ||||
|                 $corresponding = $j < $other_len ? $i : $len; | ||||
|  | ||||
|                 /* Move the changed region forward, so long as the first | ||||
|                  * changed line matches the following unchanged one.  This | ||||
|                  * merges with following changed regions.  Do this second, so | ||||
|                  * that if there are no merges, the changed region is moved | ||||
|                  * forward as far as possible. */ | ||||
|                 while ($i < $len && $lines[$start] == $lines[$i]) { | ||||
|                     $changed[$start++] = false; | ||||
|                     $changed[$i++] = 1; | ||||
|                     while ($i < $len && $changed[$i]) { | ||||
|                         $i++; | ||||
|                     } | ||||
|  | ||||
|                     assert('$j < $other_len && ! $other_changed[$j]'); | ||||
|                     $j++; | ||||
|                     if ($j < $other_len && $other_changed[$j]) { | ||||
|                         $corresponding = $i; | ||||
|                         while ($j < $other_len && $other_changed[$j]) { | ||||
|                             $j++; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } while ($runlength != $i - $start); | ||||
|  | ||||
|             /* If possible, move the fully-merged run of changes back to a | ||||
|              * corresponding run in the other file. */ | ||||
|             while ($corresponding < $i) { | ||||
|                 $changed[--$start] = 1; | ||||
|                 $changed[--$i] = 0; | ||||
|                 assert('$j > 0'); | ||||
|                 while ($other_changed[--$j]) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 assert('$j >= 0 && !$other_changed[$j]'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										162
									
								
								framework/gii/components/Pear/Text/Diff/Engine/shell.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								framework/gii/components/Pear/Text/Diff/Engine/shell.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Class used internally by Diff to actually compute the diffs. | ||||
|  * | ||||
|  * This class uses the Unix `diff` program via shell_exec to compute the | ||||
|  * differences between the two input arrays. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Engine/shell.php,v 1.6.2.3 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2007-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  Milian Wolff <mail@milianw.de> | ||||
|  * @package Text_Diff | ||||
|  * @since   0.3.0 | ||||
|  */ | ||||
| class Text_Diff_Engine_shell { | ||||
|  | ||||
|     /** | ||||
|      * Path to the diff executable | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     var $_diffCommand = 'diff'; | ||||
|  | ||||
|     /** | ||||
|      * Returns the array of differences. | ||||
|      * | ||||
|      * @param array $from_lines lines of text from old file | ||||
|      * @param array $to_lines   lines of text from new file | ||||
|      * | ||||
|      * @return array all changes made (array with Text_Diff_Op_* objects) | ||||
|      */ | ||||
|     function diff($from_lines, $to_lines) | ||||
|     { | ||||
|         array_walk($from_lines, array('Text_Diff', 'trimNewlines')); | ||||
|         array_walk($to_lines, array('Text_Diff', 'trimNewlines')); | ||||
|  | ||||
|         $temp_dir = Text_Diff::_getTempDir(); | ||||
|  | ||||
|         // Execute gnu diff or similar to get a standard diff file. | ||||
|         $from_file = tempnam($temp_dir, 'Text_Diff'); | ||||
|         $to_file = tempnam($temp_dir, 'Text_Diff'); | ||||
|         $fp = fopen($from_file, 'w'); | ||||
|         fwrite($fp, implode("\n", $from_lines)); | ||||
|         fclose($fp); | ||||
|         $fp = fopen($to_file, 'w'); | ||||
|         fwrite($fp, implode("\n", $to_lines)); | ||||
|         fclose($fp); | ||||
|         $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); | ||||
|         unlink($from_file); | ||||
|         unlink($to_file); | ||||
|  | ||||
|         if (is_null($diff)) { | ||||
|             // No changes were made | ||||
|             return array(new Text_Diff_Op_copy($from_lines)); | ||||
|         } | ||||
|  | ||||
|         $from_line_no = 1; | ||||
|         $to_line_no = 1; | ||||
|         $edits = array(); | ||||
|  | ||||
|         // Get changed lines by parsing something like: | ||||
|         // 0a1,2 | ||||
|         // 1,2c4,6 | ||||
|         // 1,5d6 | ||||
|         preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff, | ||||
|             $matches, PREG_SET_ORDER); | ||||
|  | ||||
|         foreach ($matches as $match) { | ||||
|             if (!isset($match[5])) { | ||||
|                 // This paren is not set every time (see regex). | ||||
|                 $match[5] = false; | ||||
|             } | ||||
|  | ||||
|             if ($match[3] == 'a') { | ||||
|                 $from_line_no--; | ||||
|             } | ||||
|  | ||||
|             if ($match[3] == 'd') { | ||||
|                 $to_line_no--; | ||||
|             } | ||||
|  | ||||
|             if ($from_line_no < $match[1] || $to_line_no < $match[4]) { | ||||
|                 // copied lines | ||||
|                 assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); | ||||
|                 array_push($edits, | ||||
|                     new Text_Diff_Op_copy( | ||||
|                         $this->_getLines($from_lines, $from_line_no, $match[1] - 1), | ||||
|                         $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); | ||||
|             } | ||||
|  | ||||
|             switch ($match[3]) { | ||||
|             case 'd': | ||||
|                 // deleted lines | ||||
|                 array_push($edits, | ||||
|                     new Text_Diff_Op_delete( | ||||
|                         $this->_getLines($from_lines, $from_line_no, $match[2]))); | ||||
|                 $to_line_no++; | ||||
|                 break; | ||||
|  | ||||
|             case 'c': | ||||
|                 // changed lines | ||||
|                 array_push($edits, | ||||
|                     new Text_Diff_Op_change( | ||||
|                         $this->_getLines($from_lines, $from_line_no, $match[2]), | ||||
|                         $this->_getLines($to_lines, $to_line_no, $match[5]))); | ||||
|                 break; | ||||
|  | ||||
|             case 'a': | ||||
|                 // added lines | ||||
|                 array_push($edits, | ||||
|                     new Text_Diff_Op_add( | ||||
|                         $this->_getLines($to_lines, $to_line_no, $match[5]))); | ||||
|                 $from_line_no++; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!empty($from_lines)) { | ||||
|             // Some lines might still be pending. Add them as copied | ||||
|             array_push($edits, | ||||
|                 new Text_Diff_Op_copy( | ||||
|                     $this->_getLines($from_lines, $from_line_no, | ||||
|                                      $from_line_no + count($from_lines) - 1), | ||||
|                     $this->_getLines($to_lines, $to_line_no, | ||||
|                                      $to_line_no + count($to_lines) - 1))); | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get lines from either the old or new text | ||||
|      * | ||||
|      * @access private | ||||
|      * | ||||
|      * @param array &$text_lines Either $from_lines or $to_lines | ||||
|      * @param integer &$line_no Current line number | ||||
|      * @param integer $end Optional end line, when we want to chop more than one line. | ||||
|      * @return array The chopped lines | ||||
|      */ | ||||
|     function _getLines(&$text_lines, &$line_no, $end = false) | ||||
|     { | ||||
|         if (!empty($end)) { | ||||
|             $lines = array(); | ||||
|             // We can shift even more | ||||
|             while ($line_no <= $end) { | ||||
|                 array_push($lines, array_shift($text_lines)); | ||||
|                 $line_no++; | ||||
|             } | ||||
|         } else { | ||||
|             $lines = array(array_shift($text_lines)); | ||||
|             $line_no++; | ||||
|         } | ||||
|  | ||||
|         return $lines; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										237
									
								
								framework/gii/components/Pear/Text/Diff/Engine/string.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								framework/gii/components/Pear/Text/Diff/Engine/string.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Parses unified or context diffs output from eg. the diff utility. | ||||
|  * | ||||
|  * Example: | ||||
|  * <code> | ||||
|  * $patch = file_get_contents('example.patch'); | ||||
|  * $diff = new Text_Diff('string', array($patch)); | ||||
|  * $renderer = new Text_Diff_Renderer_inline(); | ||||
|  * echo $renderer->render($diff); | ||||
|  * </code> | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Engine/string.php,v 1.5.2.5 2008/09/10 08:31:58 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2005 <20>rjan Persson <o@42mm.org> | ||||
|  * Copyright 2005-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  <20>rjan Persson <o@42mm.org> | ||||
|  * @package Text_Diff | ||||
|  * @since   0.2.0 | ||||
|  */ | ||||
| class Text_Diff_Engine_string { | ||||
|  | ||||
|     /** | ||||
|      * Parses a unified or context diff. | ||||
|      * | ||||
|      * First param contains the whole diff and the second can be used to force | ||||
|      * a specific diff type. If the second parameter is 'autodetect', the | ||||
|      * diff will be examined to find out which type of diff this is. | ||||
|      * | ||||
|      * @param string $diff  The diff content. | ||||
|      * @param string $mode  The diff mode of the content in $diff. One of | ||||
|      *                      'context', 'unified', or 'autodetect'. | ||||
|      * | ||||
|      * @return array  List of all diff operations. | ||||
|      */ | ||||
|     function diff($diff, $mode = 'autodetect') | ||||
|     { | ||||
|         if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { | ||||
|             return PEAR::raiseError('Type of diff is unsupported'); | ||||
|         } | ||||
|  | ||||
|         if ($mode == 'autodetect') { | ||||
|             $context = strpos($diff, '***'); | ||||
|             $unified = strpos($diff, '---'); | ||||
|             if ($context === $unified) { | ||||
|                 return PEAR::raiseError('Type of diff could not be detected'); | ||||
|             } elseif ($context === false || $unified === false) { | ||||
|                 $mode = $context !== false ? 'context' : 'unified'; | ||||
|             } else { | ||||
|                 $mode = $context < $unified ? 'context' : 'unified'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Split by new line and remove the diff header, if there is one. | ||||
|         $diff = explode("\n", $diff); | ||||
|         if (($mode == 'context' && strpos($diff[0], '***') === 0) || | ||||
|             ($mode == 'unified' && strpos($diff[0], '---') === 0)) { | ||||
|             array_shift($diff); | ||||
|             array_shift($diff); | ||||
|         } | ||||
|  | ||||
|         if ($mode == 'context') { | ||||
|             return $this->parseContextDiff($diff); | ||||
|         } else { | ||||
|             return $this->parseUnifiedDiff($diff); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses an array containing the unified diff. | ||||
|      * | ||||
|      * @param array $diff  Array of lines. | ||||
|      * | ||||
|      * @return array  List of all diff operations. | ||||
|      */ | ||||
|     function parseUnifiedDiff($diff) | ||||
|     { | ||||
|         $edits = array(); | ||||
|         $end = count($diff) - 1; | ||||
|         for ($i = 0; $i < $end;) { | ||||
|             $diff1 = array(); | ||||
|             switch (substr($diff[$i], 0, 1)) { | ||||
|             case ' ': | ||||
|                 do { | ||||
|                     $diff1[] = substr($diff[$i], 1); | ||||
|                 } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); | ||||
|                 $edits[] = new Text_Diff_Op_copy($diff1); | ||||
|                 break; | ||||
|  | ||||
|             case '+': | ||||
|                 // get all new lines | ||||
|                 do { | ||||
|                     $diff1[] = substr($diff[$i], 1); | ||||
|                 } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); | ||||
|                 $edits[] = new Text_Diff_Op_add($diff1); | ||||
|                 break; | ||||
|  | ||||
|             case '-': | ||||
|                 // get changed or removed lines | ||||
|                 $diff2 = array(); | ||||
|                 do { | ||||
|                     $diff1[] = substr($diff[$i], 1); | ||||
|                 } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); | ||||
|  | ||||
|                 while ($i < $end && substr($diff[$i], 0, 1) == '+') { | ||||
|                     $diff2[] = substr($diff[$i++], 1); | ||||
|                 } | ||||
|                 if (count($diff2) == 0) { | ||||
|                     $edits[] = new Text_Diff_Op_delete($diff1); | ||||
|                 } else { | ||||
|                     $edits[] = new Text_Diff_Op_change($diff1, $diff2); | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|             default: | ||||
|                 $i++; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses an array containing the context diff. | ||||
|      * | ||||
|      * @param array $diff  Array of lines. | ||||
|      * | ||||
|      * @return array  List of all diff operations. | ||||
|      */ | ||||
|     function parseContextDiff(&$diff) | ||||
|     { | ||||
|         $edits = array(); | ||||
|         $i = $max_i = $j = $max_j = 0; | ||||
|         $end = count($diff) - 1; | ||||
|         while ($i < $end && $j < $end) { | ||||
|             while ($i >= $max_i && $j >= $max_j) { | ||||
|                 // Find the boundaries of the diff output of the two files | ||||
|                 for ($i = $j; | ||||
|                      $i < $end && substr($diff[$i], 0, 3) == '***'; | ||||
|                      $i++); | ||||
|                 for ($max_i = $i; | ||||
|                      $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; | ||||
|                      $max_i++); | ||||
|                 for ($j = $max_i; | ||||
|                      $j < $end && substr($diff[$j], 0, 3) == '---'; | ||||
|                      $j++); | ||||
|                 for ($max_j = $j; | ||||
|                      $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; | ||||
|                      $max_j++); | ||||
|             } | ||||
|  | ||||
|             // find what hasn't been changed | ||||
|             $array = array(); | ||||
|             while ($i < $max_i && | ||||
|                    $j < $max_j && | ||||
|                    strcmp($diff[$i], $diff[$j]) == 0) { | ||||
|                 $array[] = substr($diff[$i], 2); | ||||
|                 $i++; | ||||
|                 $j++; | ||||
|             } | ||||
|  | ||||
|             while ($i < $max_i && ($max_j-$j) <= 1) { | ||||
|                 if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { | ||||
|                     break; | ||||
|                 } | ||||
|                 $array[] = substr($diff[$i++], 2); | ||||
|             } | ||||
|  | ||||
|             while ($j < $max_j && ($max_i-$i) <= 1) { | ||||
|                 if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { | ||||
|                     break; | ||||
|                 } | ||||
|                 $array[] = substr($diff[$j++], 2); | ||||
|             } | ||||
|             if (count($array) > 0) { | ||||
|                 $edits[] = new Text_Diff_Op_copy($array); | ||||
|             } | ||||
|  | ||||
|             if ($i < $max_i) { | ||||
|                 $diff1 = array(); | ||||
|                 switch (substr($diff[$i], 0, 1)) { | ||||
|                 case '!': | ||||
|                     $diff2 = array(); | ||||
|                     do { | ||||
|                         $diff1[] = substr($diff[$i], 2); | ||||
|                         if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { | ||||
|                             $diff2[] = substr($diff[$j++], 2); | ||||
|                         } | ||||
|                     } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); | ||||
|                     $edits[] = new Text_Diff_Op_change($diff1, $diff2); | ||||
|                     break; | ||||
|  | ||||
|                 case '+': | ||||
|                     do { | ||||
|                         $diff1[] = substr($diff[$i], 2); | ||||
|                     } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); | ||||
|                     $edits[] = new Text_Diff_Op_add($diff1); | ||||
|                     break; | ||||
|  | ||||
|                 case '-': | ||||
|                     do { | ||||
|                         $diff1[] = substr($diff[$i], 2); | ||||
|                     } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); | ||||
|                     $edits[] = new Text_Diff_Op_delete($diff1); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if ($j < $max_j) { | ||||
|                 $diff2 = array(); | ||||
|                 switch (substr($diff[$j], 0, 1)) { | ||||
|                 case '+': | ||||
|                     do { | ||||
|                         $diff2[] = substr($diff[$j++], 2); | ||||
|                     } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); | ||||
|                     $edits[] = new Text_Diff_Op_add($diff2); | ||||
|                     break; | ||||
|  | ||||
|                 case '-': | ||||
|                     do { | ||||
|                         $diff2[] = substr($diff[$j++], 2); | ||||
|                     } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); | ||||
|                     $edits[] = new Text_Diff_Op_delete($diff2); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										63
									
								
								framework/gii/components/Pear/Text/Diff/Engine/xdiff.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								framework/gii/components/Pear/Text/Diff/Engine/xdiff.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Class used internally by Diff to actually compute the diffs. | ||||
|  * | ||||
|  * This class uses the xdiff PECL package (http://pecl.php.net/package/xdiff) | ||||
|  * to compute the differences between the two input arrays. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Engine/xdiff.php,v 1.4.2.3 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  Jon Parise <jon@horde.org> | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Engine_xdiff { | ||||
|  | ||||
|     /** | ||||
|      */ | ||||
|     function diff($from_lines, $to_lines) | ||||
|     { | ||||
|         array_walk($from_lines, array('Text_Diff', 'trimNewlines')); | ||||
|         array_walk($to_lines, array('Text_Diff', 'trimNewlines')); | ||||
|  | ||||
|         /* Convert the two input arrays into strings for xdiff processing. */ | ||||
|         $from_string = implode("\n", $from_lines); | ||||
|         $to_string = implode("\n", $to_lines); | ||||
|  | ||||
|         /* Diff the two strings and convert the result to an array. */ | ||||
|         $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); | ||||
|         $diff = explode("\n", $diff); | ||||
|  | ||||
|         /* Walk through the diff one line at a time.  We build the $edits | ||||
|          * array of diff operations by reading the first character of the | ||||
|          * xdiff output (which is in the "unified diff" format). | ||||
|          * | ||||
|          * Note that we don't have enough information to detect "changed" | ||||
|          * lines using this approach, so we can't add Text_Diff_Op_changed | ||||
|          * instances to the $edits array.  The result is still perfectly | ||||
|          * valid, albeit a little less descriptive and efficient. */ | ||||
|         $edits = array(); | ||||
|         foreach ($diff as $line) { | ||||
|             switch ($line[0]) { | ||||
|             case ' ': | ||||
|                 $edits[] = new Text_Diff_Op_copy(array(substr($line, 1))); | ||||
|                 break; | ||||
|  | ||||
|             case '+': | ||||
|                 $edits[] = new Text_Diff_Op_add(array(substr($line, 1))); | ||||
|                 break; | ||||
|  | ||||
|             case '-': | ||||
|                 $edits[] = new Text_Diff_Op_delete(array(substr($line, 1))); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										55
									
								
								framework/gii/components/Pear/Text/Diff/Mapped.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								framework/gii/components/Pear/Text/Diff/Mapped.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| <?php | ||||
| /** | ||||
|  * $Horde: framework/Text_Diff/Diff/Mapped.php,v 1.3.2.3 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2007-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @package Text_Diff | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  */ | ||||
| class Text_Diff_Mapped extends Text_Diff { | ||||
|  | ||||
|     /** | ||||
|      * Computes a diff between sequences of strings. | ||||
|      * | ||||
|      * This can be used to compute things like case-insensitve diffs, or diffs | ||||
|      * which ignore changes in white-space. | ||||
|      * | ||||
|      * @param array $from_lines         An array of strings. | ||||
|      * @param array $to_lines           An array of strings. | ||||
|      * @param array $mapped_from_lines  This array should have the same size | ||||
|      *                                  number of elements as $from_lines.  The | ||||
|      *                                  elements in $mapped_from_lines and | ||||
|      *                                  $mapped_to_lines are what is actually | ||||
|      *                                  compared when computing the diff. | ||||
|      * @param array $mapped_to_lines    This array should have the same number | ||||
|      *                                  of elements as $to_lines. | ||||
|      */ | ||||
|     function Text_Diff_Mapped($from_lines, $to_lines, | ||||
|                               $mapped_from_lines, $mapped_to_lines) | ||||
|     { | ||||
|         assert(count($from_lines) == count($mapped_from_lines)); | ||||
|         assert(count($to_lines) == count($mapped_to_lines)); | ||||
|  | ||||
|         parent::Text_Diff($mapped_from_lines, $mapped_to_lines); | ||||
|  | ||||
|         $xi = $yi = 0; | ||||
|         for ($i = 0; $i < count($this->_edits); $i++) { | ||||
|             $orig = &$this->_edits[$i]->orig; | ||||
|             if (is_array($orig)) { | ||||
|                 $orig = array_slice($from_lines, $xi, count($orig)); | ||||
|                 $xi += count($orig); | ||||
|             } | ||||
|  | ||||
|             $final = &$this->_edits[$i]->final; | ||||
|             if (is_array($final)) { | ||||
|                 $final = array_slice($to_lines, $yi, count($final)); | ||||
|                 $yi += count($final); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										237
									
								
								framework/gii/components/Pear/Text/Diff/Renderer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								framework/gii/components/Pear/Text/Diff/Renderer.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
| <?php | ||||
| /** | ||||
|  * A class to render Diffs in different formats. | ||||
|  * | ||||
|  * This class renders the diff in classic diff format. It is intended that | ||||
|  * this class be customized via inheritance, to obtain fancier outputs. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.5.10.10 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Renderer { | ||||
|  | ||||
|     /** | ||||
|      * Number of leading context "lines" to preserve. | ||||
|      * | ||||
|      * This should be left at zero for this class, but subclasses may want to | ||||
|      * set this to other values. | ||||
|      */ | ||||
|     var $_leading_context_lines = 0; | ||||
|  | ||||
|     /** | ||||
|      * Number of trailing context "lines" to preserve. | ||||
|      * | ||||
|      * This should be left at zero for this class, but subclasses may want to | ||||
|      * set this to other values. | ||||
|      */ | ||||
|     var $_trailing_context_lines = 0; | ||||
|  | ||||
|     /** | ||||
|      * Constructor. | ||||
|      */ | ||||
|     function Text_Diff_Renderer($params = array()) | ||||
|     { | ||||
|         foreach ($params as $param => $value) { | ||||
|             $v = '_' . $param; | ||||
|             if (isset($this->$v)) { | ||||
|                 $this->$v = $value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get any renderer parameters. | ||||
|      * | ||||
|      * @return array  All parameters of this renderer object. | ||||
|      */ | ||||
|     function getParams() | ||||
|     { | ||||
|         $params = array(); | ||||
|         foreach (get_object_vars($this) as $k => $v) { | ||||
|             if ($k[0] == '_') { | ||||
|                 $params[substr($k, 1)] = $v; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $params; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Renders a diff. | ||||
|      * | ||||
|      * @param Text_Diff $diff  A Text_Diff object. | ||||
|      * | ||||
|      * @return string  The formatted output. | ||||
|      */ | ||||
|     function render($diff) | ||||
|     { | ||||
|         $xi = $yi = 1; | ||||
|         $block = false; | ||||
|         $context = array(); | ||||
|  | ||||
|         $nlead = $this->_leading_context_lines; | ||||
|         $ntrail = $this->_trailing_context_lines; | ||||
|  | ||||
|         $output = $this->_startDiff(); | ||||
|  | ||||
|         $diffs = $diff->getDiff(); | ||||
|         foreach ($diffs as $i => $edit) { | ||||
|             /* If these are unchanged (copied) lines, and we want to keep | ||||
|              * leading or trailing context lines, extract them from the copy | ||||
|              * block. */ | ||||
|             if (is_a($edit, 'Text_Diff_Op_copy')) { | ||||
|                 /* Do we have any diff blocks yet? */ | ||||
|                 if (is_array($block)) { | ||||
|                     /* How many lines to keep as context from the copy | ||||
|                      * block. */ | ||||
|                     $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; | ||||
|                     if (count($edit->orig) <= $keep) { | ||||
|                         /* We have less lines in the block than we want for | ||||
|                          * context => keep the whole block. */ | ||||
|                         $block[] = $edit; | ||||
|                     } else { | ||||
|                         if ($ntrail) { | ||||
|                             /* Create a new block with as many lines as we need | ||||
|                              * for the trailing context. */ | ||||
|                             $context = array_slice($edit->orig, 0, $ntrail); | ||||
|                             $block[] = new Text_Diff_Op_copy($context); | ||||
|                         } | ||||
|                         /* @todo */ | ||||
|                         $output .= $this->_block($x0, $ntrail + $xi - $x0, | ||||
|                                                  $y0, $ntrail + $yi - $y0, | ||||
|                                                  $block); | ||||
|                         $block = false; | ||||
|                     } | ||||
|                 } | ||||
|                 /* Keep the copy block as the context for the next block. */ | ||||
|                 $context = $edit->orig; | ||||
|             } else { | ||||
|                 /* Don't we have any diff blocks yet? */ | ||||
|                 if (!is_array($block)) { | ||||
|                     /* Extract context lines from the preceding copy block. */ | ||||
|                     $context = array_slice($context, count($context) - $nlead); | ||||
|                     $x0 = $xi - count($context); | ||||
|                     $y0 = $yi - count($context); | ||||
|                     $block = array(); | ||||
|                     if ($context) { | ||||
|                         $block[] = new Text_Diff_Op_copy($context); | ||||
|                     } | ||||
|                 } | ||||
|                 $block[] = $edit; | ||||
|             } | ||||
|  | ||||
|             if ($edit->orig) { | ||||
|                 $xi += count($edit->orig); | ||||
|             } | ||||
|             if ($edit->final) { | ||||
|                 $yi += count($edit->final); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (is_array($block)) { | ||||
|             $output .= $this->_block($x0, $xi - $x0, | ||||
|                                      $y0, $yi - $y0, | ||||
|                                      $block); | ||||
|         } | ||||
|  | ||||
|         return $output . $this->_endDiff(); | ||||
|     } | ||||
|  | ||||
|     function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) | ||||
|     { | ||||
|         $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); | ||||
|  | ||||
|         foreach ($edits as $edit) { | ||||
|             switch (strtolower(get_class($edit))) { | ||||
|             case 'text_diff_op_copy': | ||||
|                 $output .= $this->_context($edit->orig); | ||||
|                 break; | ||||
|  | ||||
|             case 'text_diff_op_add': | ||||
|                 $output .= $this->_added($edit->final); | ||||
|                 break; | ||||
|  | ||||
|             case 'text_diff_op_delete': | ||||
|                 $output .= $this->_deleted($edit->orig); | ||||
|                 break; | ||||
|  | ||||
|             case 'text_diff_op_change': | ||||
|                 $output .= $this->_changed($edit->orig, $edit->final); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $output . $this->_endBlock(); | ||||
|     } | ||||
|  | ||||
|     function _startDiff() | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     function _endDiff() | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     function _blockHeader($xbeg, $xlen, $ybeg, $ylen) | ||||
|     { | ||||
|         if ($xlen > 1) { | ||||
|             $xbeg .= ',' . ($xbeg + $xlen - 1); | ||||
|         } | ||||
|         if ($ylen > 1) { | ||||
|             $ybeg .= ',' . ($ybeg + $ylen - 1); | ||||
|         } | ||||
|  | ||||
|         // this matches the GNU Diff behaviour | ||||
|         if ($xlen && !$ylen) { | ||||
|             $ybeg--; | ||||
|         } elseif (!$xlen) { | ||||
|             $xbeg--; | ||||
|         } | ||||
|  | ||||
|         return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; | ||||
|     } | ||||
|  | ||||
|     function _startBlock($header) | ||||
|     { | ||||
|         return $header . "\n"; | ||||
|     } | ||||
|  | ||||
|     function _endBlock() | ||||
|     { | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     function _lines($lines, $prefix = ' ') | ||||
|     { | ||||
|         return $prefix . implode("\n$prefix", $lines) . "\n"; | ||||
|     } | ||||
|  | ||||
|     function _context($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '  '); | ||||
|     } | ||||
|  | ||||
|     function _added($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '> '); | ||||
|     } | ||||
|  | ||||
|     function _deleted($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '< '); | ||||
|     } | ||||
|  | ||||
|     function _changed($orig, $final) | ||||
|     { | ||||
|         return $this->_deleted($orig) . "---\n" . $this->_added($final); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										77
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/context.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/context.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| <?php | ||||
| /** | ||||
|  * "Context" diff renderer. | ||||
|  * | ||||
|  * This class renders the diff in classic "context diff" format. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Renderer/context.php,v 1.3.2.3 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
|  | ||||
| /** Text_Diff_Renderer */ | ||||
| require_once 'Text/Diff/Renderer.php'; | ||||
|  | ||||
| /** | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Renderer_context extends Text_Diff_Renderer { | ||||
|  | ||||
|     /** | ||||
|      * Number of leading context "lines" to preserve. | ||||
|      */ | ||||
|     var $_leading_context_lines = 4; | ||||
|  | ||||
|     /** | ||||
|      * Number of trailing context "lines" to preserve. | ||||
|      */ | ||||
|     var $_trailing_context_lines = 4; | ||||
|  | ||||
|     var $_second_block = ''; | ||||
|  | ||||
|     function _blockHeader($xbeg, $xlen, $ybeg, $ylen) | ||||
|     { | ||||
|         if ($xlen != 1) { | ||||
|             $xbeg .= ',' . $xlen; | ||||
|         } | ||||
|         if ($ylen != 1) { | ||||
|             $ybeg .= ',' . $ylen; | ||||
|         } | ||||
|         $this->_second_block = "--- $ybeg ----\n"; | ||||
|         return "***************\n*** $xbeg ****"; | ||||
|     } | ||||
|  | ||||
|     function _endBlock() | ||||
|     { | ||||
|         return $this->_second_block; | ||||
|     } | ||||
|  | ||||
|     function _context($lines) | ||||
|     { | ||||
|         $this->_second_block .= $this->_lines($lines, '  '); | ||||
|         return $this->_lines($lines, '  '); | ||||
|     } | ||||
|  | ||||
|     function _added($lines) | ||||
|     { | ||||
|         $this->_second_block .= $this->_lines($lines, '+ '); | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     function _deleted($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '- '); | ||||
|     } | ||||
|  | ||||
|     function _changed($orig, $final) | ||||
|     { | ||||
|         $this->_second_block .= $this->_lines($final, '! '); | ||||
|         return $this->_lines($orig, '! '); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										170
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/inline.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/inline.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| <?php | ||||
| /** | ||||
|  * "Inline" diff renderer. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Renderer/inline.php,v 1.4.10.14 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  Ciprian Popovici | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
|  | ||||
| /** Text_Diff_Renderer */ | ||||
| require_once 'Text/Diff/Renderer.php'; | ||||
|  | ||||
| /** | ||||
|  * "Inline" diff renderer. | ||||
|  * | ||||
|  * This class renders diffs in the Wiki-style "inline" format. | ||||
|  * | ||||
|  * @author  Ciprian Popovici | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Renderer_inline extends Text_Diff_Renderer { | ||||
|  | ||||
|     /** | ||||
|      * Number of leading context "lines" to preserve. | ||||
|      */ | ||||
|     var $_leading_context_lines = 10000; | ||||
|  | ||||
|     /** | ||||
|      * Number of trailing context "lines" to preserve. | ||||
|      */ | ||||
|     var $_trailing_context_lines = 10000; | ||||
|  | ||||
|     /** | ||||
|      * Prefix for inserted text. | ||||
|      */ | ||||
|     var $_ins_prefix = '<ins>'; | ||||
|  | ||||
|     /** | ||||
|      * Suffix for inserted text. | ||||
|      */ | ||||
|     var $_ins_suffix = '</ins>'; | ||||
|  | ||||
|     /** | ||||
|      * Prefix for deleted text. | ||||
|      */ | ||||
|     var $_del_prefix = '<del>'; | ||||
|  | ||||
|     /** | ||||
|      * Suffix for deleted text. | ||||
|      */ | ||||
|     var $_del_suffix = '</del>'; | ||||
|  | ||||
|     /** | ||||
|      * Header for each change block. | ||||
|      */ | ||||
|     var $_block_header = ''; | ||||
|  | ||||
|     /** | ||||
|      * What are we currently splitting on? Used to recurse to show word-level | ||||
|      * changes. | ||||
|      */ | ||||
|     var $_split_level = 'lines'; | ||||
|  | ||||
|     function _blockHeader($xbeg, $xlen, $ybeg, $ylen) | ||||
|     { | ||||
|         return $this->_block_header; | ||||
|     } | ||||
|  | ||||
|     function _startBlock($header) | ||||
|     { | ||||
|         return $header; | ||||
|     } | ||||
|  | ||||
|     function _lines($lines, $prefix = ' ', $encode = true) | ||||
|     { | ||||
|         if ($encode) { | ||||
|             array_walk($lines, array(&$this, '_encode')); | ||||
|         } | ||||
|  | ||||
|         if ($this->_split_level == 'words') { | ||||
|             return implode('', $lines); | ||||
|         } else { | ||||
|             return implode("\n", $lines) . "\n"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function _added($lines) | ||||
|     { | ||||
|         array_walk($lines, array(&$this, '_encode')); | ||||
|         $lines[0] = $this->_ins_prefix . $lines[0]; | ||||
|         $lines[count($lines) - 1] .= $this->_ins_suffix; | ||||
|         return $this->_lines($lines, ' ', false); | ||||
|     } | ||||
|  | ||||
|     function _deleted($lines, $words = false) | ||||
|     { | ||||
|         array_walk($lines, array(&$this, '_encode')); | ||||
|         $lines[0] = $this->_del_prefix . $lines[0]; | ||||
|         $lines[count($lines) - 1] .= $this->_del_suffix; | ||||
|         return $this->_lines($lines, ' ', false); | ||||
|     } | ||||
|  | ||||
|     function _changed($orig, $final) | ||||
|     { | ||||
|         /* If we've already split on words, don't try to do so again - just | ||||
|          * display. */ | ||||
|         if ($this->_split_level == 'words') { | ||||
|             $prefix = ''; | ||||
|             while ($orig[0] !== false && $final[0] !== false && | ||||
|                    substr($orig[0], 0, 1) == ' ' && | ||||
|                    substr($final[0], 0, 1) == ' ') { | ||||
|                 $prefix .= substr($orig[0], 0, 1); | ||||
|                 $orig[0] = substr($orig[0], 1); | ||||
|                 $final[0] = substr($final[0], 1); | ||||
|             } | ||||
|             return $prefix . $this->_deleted($orig) . $this->_added($final); | ||||
|         } | ||||
|  | ||||
|         $text1 = implode("\n", $orig); | ||||
|         $text2 = implode("\n", $final); | ||||
|  | ||||
|         /* Non-printing newline marker. */ | ||||
|         $nl = "\0"; | ||||
|  | ||||
|         /* We want to split on word boundaries, but we need to | ||||
|          * preserve whitespace as well. Therefore we split on words, | ||||
|          * but include all blocks of whitespace in the wordlist. */ | ||||
|         $diff = new Text_Diff($this->_splitOnWords($text1, $nl), | ||||
|                               $this->_splitOnWords($text2, $nl)); | ||||
|  | ||||
|         /* Get the diff in inline format. */ | ||||
|         $renderer = new Text_Diff_Renderer_inline(array_merge($this->getParams(), | ||||
|                                                               array('split_level' => 'words'))); | ||||
|  | ||||
|         /* Run the diff and get the output. */ | ||||
|         return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; | ||||
|     } | ||||
|  | ||||
|     function _splitOnWords($string, $newlineEscape = "\n") | ||||
|     { | ||||
|         // Ignore \0; otherwise the while loop will never finish. | ||||
|         $string = str_replace("\0", '', $string); | ||||
|  | ||||
|         $words = array(); | ||||
|         $length = strlen($string); | ||||
|         $pos = 0; | ||||
|  | ||||
|         while ($pos < $length) { | ||||
|             // Eat a word with any preceding whitespace. | ||||
|             $spaces = strspn(substr($string, $pos), " \n"); | ||||
|             $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); | ||||
|             $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos)); | ||||
|             $pos += $spaces + $nextpos; | ||||
|         } | ||||
|  | ||||
|         return $words; | ||||
|     } | ||||
|  | ||||
|     function _encode(&$string) | ||||
|     { | ||||
|         $string = htmlspecialchars($string); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										67
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/unified.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								framework/gii/components/Pear/Text/Diff/Renderer/unified.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| <?php | ||||
| /** | ||||
|  * "Unified" diff renderer. | ||||
|  * | ||||
|  * This class renders the diff in classic "unified diff" format. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/Renderer/unified.php,v 1.3.10.6 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2004-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @author  Ciprian Popovici | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
|  | ||||
| /** Text_Diff_Renderer */ | ||||
| require_once 'Text/Diff/Renderer.php'; | ||||
|  | ||||
| /** | ||||
|  * @package Text_Diff | ||||
|  */ | ||||
| class Text_Diff_Renderer_unified extends Text_Diff_Renderer { | ||||
|  | ||||
|     /** | ||||
|      * Number of leading context "lines" to preserve. | ||||
|      */ | ||||
|     var $_leading_context_lines = 4; | ||||
|  | ||||
|     /** | ||||
|      * Number of trailing context "lines" to preserve. | ||||
|      */ | ||||
|     var $_trailing_context_lines = 4; | ||||
|  | ||||
|     function _blockHeader($xbeg, $xlen, $ybeg, $ylen) | ||||
|     { | ||||
|         if ($xlen != 1) { | ||||
|             $xbeg .= ',' . $xlen; | ||||
|         } | ||||
|         if ($ylen != 1) { | ||||
|             $ybeg .= ',' . $ylen; | ||||
|         } | ||||
|         return "@@ -$xbeg +$ybeg @@"; | ||||
|     } | ||||
|  | ||||
|     function _context($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, ' '); | ||||
|     } | ||||
|  | ||||
|     function _added($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '+'); | ||||
|     } | ||||
|  | ||||
|     function _deleted($lines) | ||||
|     { | ||||
|         return $this->_lines($lines, '-'); | ||||
|     } | ||||
|  | ||||
|     function _changed($orig, $final) | ||||
|     { | ||||
|         return $this->_deleted($orig) . $this->_added($final); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										276
									
								
								framework/gii/components/Pear/Text/Diff/ThreeWay.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								framework/gii/components/Pear/Text/Diff/ThreeWay.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,276 @@ | ||||
| <?php | ||||
| /** | ||||
|  * A class for computing three way diffs. | ||||
|  * | ||||
|  * $Horde: framework/Text_Diff/Diff/ThreeWay.php,v 1.3.2.3 2008/01/04 10:37:27 jan Exp $ | ||||
|  * | ||||
|  * Copyright 2007-2008 The Horde Project (http://www.horde.org/) | ||||
|  * | ||||
|  * See the enclosed file COPYING for license information (LGPL). If you did | ||||
|  * not receive this file, see http://opensource.org/licenses/lgpl-license.php. | ||||
|  * | ||||
|  * @package Text_Diff | ||||
|  * @since   0.3.0 | ||||
|  */ | ||||
|  | ||||
| /** Text_Diff */ | ||||
| require_once 'Text/Diff.php'; | ||||
|  | ||||
| /** | ||||
|  * A class for computing three way diffs. | ||||
|  * | ||||
|  * @package Text_Diff | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  */ | ||||
| class Text_Diff_ThreeWay extends Text_Diff { | ||||
|  | ||||
|     /** | ||||
|      * Conflict counter. | ||||
|      * | ||||
|      * @var integer | ||||
|      */ | ||||
|     var $_conflictingBlocks = 0; | ||||
|  | ||||
|     /** | ||||
|      * Computes diff between 3 sequences of strings. | ||||
|      * | ||||
|      * @param array $orig    The original lines to use. | ||||
|      * @param array $final1  The first version to compare to. | ||||
|      * @param array $final2  The second version to compare to. | ||||
|      */ | ||||
|     function Text_Diff_ThreeWay($orig, $final1, $final2) | ||||
|     { | ||||
|         if (extension_loaded('xdiff')) { | ||||
|             $engine = new Text_Diff_Engine_xdiff(); | ||||
|         } else { | ||||
|             $engine = new Text_Diff_Engine_native(); | ||||
|         } | ||||
|  | ||||
|         $this->_edits = $this->_diff3($engine->diff($orig, $final1), | ||||
|                                       $engine->diff($orig, $final2)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      */ | ||||
|     function mergedOutput($label1 = false, $label2 = false) | ||||
|     { | ||||
|         $lines = array(); | ||||
|         foreach ($this->_edits as $edit) { | ||||
|             if ($edit->isConflict()) { | ||||
|                 /* FIXME: this should probably be moved somewhere else. */ | ||||
|                 $lines = array_merge($lines, | ||||
|                                      array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), | ||||
|                                      $edit->final1, | ||||
|                                      array("======="), | ||||
|                                      $edit->final2, | ||||
|                                      array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); | ||||
|                 $this->_conflictingBlocks++; | ||||
|             } else { | ||||
|                 $lines = array_merge($lines, $edit->merged()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $lines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @access private | ||||
|      */ | ||||
|     function _diff3($edits1, $edits2) | ||||
|     { | ||||
|         $edits = array(); | ||||
|         $bb = new Text_Diff_ThreeWay_BlockBuilder(); | ||||
|  | ||||
|         $e1 = current($edits1); | ||||
|         $e2 = current($edits2); | ||||
|         while ($e1 || $e2) { | ||||
|             if ($e1 && $e2 && is_a($e1, 'Text_Diff_Op_copy') && is_a($e2, 'Text_Diff_Op_copy')) { | ||||
|                 /* We have copy blocks from both diffs. This is the (only) | ||||
|                  * time we want to emit a diff3 copy block.  Flush current | ||||
|                  * diff3 diff block, if any. */ | ||||
|                 if ($edit = $bb->finish()) { | ||||
|                     $edits[] = $edit; | ||||
|                 } | ||||
|  | ||||
|                 $ncopy = min($e1->norig(), $e2->norig()); | ||||
|                 assert($ncopy > 0); | ||||
|                 $edits[] = new Text_Diff_ThreeWay_Op_copy(array_slice($e1->orig, 0, $ncopy)); | ||||
|  | ||||
|                 if ($e1->norig() > $ncopy) { | ||||
|                     array_splice($e1->orig, 0, $ncopy); | ||||
|                     array_splice($e1->final, 0, $ncopy); | ||||
|                 } else { | ||||
|                     $e1 = next($edits1); | ||||
|                 } | ||||
|  | ||||
|                 if ($e2->norig() > $ncopy) { | ||||
|                     array_splice($e2->orig, 0, $ncopy); | ||||
|                     array_splice($e2->final, 0, $ncopy); | ||||
|                 } else { | ||||
|                     $e2 = next($edits2); | ||||
|                 } | ||||
|             } else { | ||||
|                 if ($e1 && $e2) { | ||||
|                     if ($e1->orig && $e2->orig) { | ||||
|                         $norig = min($e1->norig(), $e2->norig()); | ||||
|                         $orig = array_splice($e1->orig, 0, $norig); | ||||
|                         array_splice($e2->orig, 0, $norig); | ||||
|                         $bb->input($orig); | ||||
|                     } | ||||
|  | ||||
|                     if (is_a($e1, 'Text_Diff_Op_copy')) { | ||||
|                         $bb->out1(array_splice($e1->final, 0, $norig)); | ||||
|                     } | ||||
|  | ||||
|                     if (is_a($e2, 'Text_Diff_Op_copy')) { | ||||
|                         $bb->out2(array_splice($e2->final, 0, $norig)); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if ($e1 && ! $e1->orig) { | ||||
|                     $bb->out1($e1->final); | ||||
|                     $e1 = next($edits1); | ||||
|                 } | ||||
|                 if ($e2 && ! $e2->orig) { | ||||
|                     $bb->out2($e2->final); | ||||
|                     $e2 = next($edits2); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($edit = $bb->finish()) { | ||||
|             $edits[] = $edit; | ||||
|         } | ||||
|  | ||||
|         return $edits; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @package Text_Diff | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  * | ||||
|  * @access private | ||||
|  */ | ||||
| class Text_Diff_ThreeWay_Op { | ||||
|  | ||||
|     function Text_Diff_ThreeWay_Op($orig = false, $final1 = false, $final2 = false) | ||||
|     { | ||||
|         $this->orig = $orig ? $orig : array(); | ||||
|         $this->final1 = $final1 ? $final1 : array(); | ||||
|         $this->final2 = $final2 ? $final2 : array(); | ||||
|     } | ||||
|  | ||||
|     function merged() | ||||
|     { | ||||
|         if (!isset($this->_merged)) { | ||||
|             if ($this->final1 === $this->final2) { | ||||
|                 $this->_merged = &$this->final1; | ||||
|             } elseif ($this->final1 === $this->orig) { | ||||
|                 $this->_merged = &$this->final2; | ||||
|             } elseif ($this->final2 === $this->orig) { | ||||
|                 $this->_merged = &$this->final1; | ||||
|             } else { | ||||
|                 $this->_merged = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $this->_merged; | ||||
|     } | ||||
|  | ||||
|     function isConflict() | ||||
|     { | ||||
|         return $this->merged() === false; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @package Text_Diff | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  * | ||||
|  * @access private | ||||
|  */ | ||||
| class Text_Diff_ThreeWay_Op_copy extends Text_Diff_ThreeWay_Op { | ||||
|  | ||||
|     function Text_Diff_ThreeWay_Op_Copy($lines = false) | ||||
|     { | ||||
|         $this->orig = $lines ? $lines : array(); | ||||
|         $this->final1 = &$this->orig; | ||||
|         $this->final2 = &$this->orig; | ||||
|     } | ||||
|  | ||||
|     function merged() | ||||
|     { | ||||
|         return $this->orig; | ||||
|     } | ||||
|  | ||||
|     function isConflict() | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @package Text_Diff | ||||
|  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org> | ||||
|  * | ||||
|  * @access private | ||||
|  */ | ||||
| class Text_Diff_ThreeWay_BlockBuilder { | ||||
|  | ||||
|     function Text_Diff_ThreeWay_BlockBuilder() | ||||
|     { | ||||
|         $this->_init(); | ||||
|     } | ||||
|  | ||||
|     function input($lines) | ||||
|     { | ||||
|         if ($lines) { | ||||
|             $this->_append($this->orig, $lines); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function out1($lines) | ||||
|     { | ||||
|         if ($lines) { | ||||
|             $this->_append($this->final1, $lines); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function out2($lines) | ||||
|     { | ||||
|         if ($lines) { | ||||
|             $this->_append($this->final2, $lines); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function isEmpty() | ||||
|     { | ||||
|         return !$this->orig && !$this->final1 && !$this->final2; | ||||
|     } | ||||
|  | ||||
|     function finish() | ||||
|     { | ||||
|         if ($this->isEmpty()) { | ||||
|             return false; | ||||
|         } else { | ||||
|             $edit = new Text_Diff_ThreeWay_Op($this->orig, $this->final1, $this->final2); | ||||
|             $this->_init(); | ||||
|             return $edit; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function _init() | ||||
|     { | ||||
|         $this->orig = $this->final1 = $this->final2 = array(); | ||||
|     } | ||||
|  | ||||
|     function _append(&$array, $lines) | ||||
|     { | ||||
|         array_splice($array, sizeof($array), 0, $lines); | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user