Text_Diff
[ class tree: Text_Diff ] [ index: Text_Diff ] [ all elements ]

Source for file string.php

Documentation is available at string.php

  1. <?php
  2. /**
  3.  * Parses unified or context diffs output from eg. the diff utility.
  4.  *
  5.  * Example:
  6.  * <code>
  7.  * $patch = file_get_contents('example.patch');
  8.  * $diff = new Text_Diff('string', array($patch));
  9.  * $renderer = new Text_Diff_Renderer_inline();
  10.  * echo $renderer->render($diff);
  11.  * </code>
  12.  *
  13.  * $Horde: framework/Text_Diff/Diff/Engine/string.php,v 1.5.2.7 2009/07/24 13:04:43 jan Exp $
  14.  *
  15.  * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
  16.  *
  17.  * See the enclosed file COPYING for license information (LGPL). If you did
  18.  * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
  19.  *
  20.  * @author
  21.  * @package Text_Diff
  22.  * @since   0.2.0
  23.  */
  24.  
  25.     /**
  26.      * Parses a unified or context diff.
  27.      *
  28.      * First param contains the whole diff and the second can be used to force
  29.      * a specific diff type. If the second parameter is 'autodetect', the
  30.      * diff will be examined to find out which type of diff this is.
  31.      *
  32.      * @param string $diff  The diff content.
  33.      * @param string $mode  The diff mode of the content in $diff. One of
  34.      *                       'context', 'unified', or 'autodetect'.
  35.      *
  36.      * @return array  List of all diff operations.
  37.      */
  38.     function diff($diff$mode 'autodetect')
  39.     {
  40.         // Detect line breaks.
  41.         $lnbr "\n";
  42.         if (strpos($diff"\r\n"!== false{
  43.             $lnbr "\r\n";
  44.         elseif (strpos($diff"\r"!== false{
  45.             $lnbr "\r";
  46.         }
  47.  
  48.         // Make sure we have a line break at the EOF.
  49.         if (substr($diff-strlen($lnbr)) != $lnbr{
  50.             $diff .= $lnbr;
  51.         }
  52.  
  53.         if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified'{
  54.             return PEAR::raiseError('Type of diff is unsupported');
  55.         }
  56.  
  57.         if ($mode == 'autodetect'{
  58.             $context strpos($diff'***');
  59.             $unified strpos($diff'---');
  60.             if ($context === $unified{
  61.                 return PEAR::raiseError('Type of diff could not be detected');
  62.             elseif ($context === false || $unified === false{
  63.                 $mode $context !== false ? 'context' 'unified';
  64.             else {
  65.                 $mode $context $unified 'context' 'unified';
  66.             }
  67.         }
  68.  
  69.         // Split by new line and remove the diff header, if there is one.
  70.         $diff explode($lnbr$diff);
  71.         if (($mode == 'context' && strpos($diff[0]'***'=== 0||
  72.             ($mode == 'unified' && strpos($diff[0]'---'=== 0)) {
  73.             array_shift($diff);
  74.             array_shift($diff);
  75.         }
  76.  
  77.         if ($mode == 'context'{
  78.             return $this->parseContextDiff($diff);
  79.         else {
  80.             return $this->parseUnifiedDiff($diff);
  81.         }
  82.     }
  83.  
  84.     /**
  85.      * Parses an array containing the unified diff.
  86.      *
  87.      * @param array $diff  Array of lines.
  88.      *
  89.      * @return array  List of all diff operations.
  90.      */
  91.     function parseUnifiedDiff($diff)
  92.     {
  93.         $edits = array();
  94.         $end count($diff- 1;
  95.         for ($i = 0; $i $end;{
  96.             $diff1 = array();
  97.             switch (substr($diff[$i]01)) {
  98.             case ' ':
  99.                 do {
  100.                     $diff1[substr($diff[$i]1);
  101.                 while (++$i $end && substr($diff[$i]01== ' ');
  102.                 $edits[= new Text_Diff_Op_copy($diff1);
  103.                 break;
  104.  
  105.             case '+':
  106.                 // get all new lines
  107.                 do {
  108.                     $diff1[substr($diff[$i]1);
  109.                 while (++$i $end && substr($diff[$i]01== '+');
  110.                 $edits[= new Text_Diff_Op_add($diff1);
  111.                 break;
  112.  
  113.             case '-':
  114.                 // get changed or removed lines
  115.                 $diff2 = array();
  116.                 do {
  117.                     $diff1[substr($diff[$i]1);
  118.                 while (++$i $end && substr($diff[$i]01== '-');
  119.  
  120.                 while ($i $end && substr($diff[$i]01== '+'{
  121.                     $diff2[substr($diff[$i++]1);
  122.                 }
  123.                 if (count($diff2== 0{
  124.                     $edits[= new Text_Diff_Op_delete($diff1);
  125.                 else {
  126.                     $edits[= new Text_Diff_Op_change($diff1$diff2);
  127.                 }
  128.                 break;
  129.  
  130.             default:
  131.                 $i++;
  132.                 break;
  133.             }
  134.         }
  135.  
  136.         return $edits;
  137.     }
  138.  
  139.     /**
  140.      * Parses an array containing the context diff.
  141.      *
  142.      * @param array $diff  Array of lines.
  143.      *
  144.      * @return array  List of all diff operations.
  145.      */
  146.     function parseContextDiff(&$diff)
  147.     {
  148.         $edits = array();
  149.         $i $max_i $j $max_j = 0;
  150.         $end count($diff- 1;
  151.         while ($i $end && $j $end{
  152.             while ($i >= $max_i && $j >= $max_j{
  153.                 // Find the boundaries of the diff output of the two files
  154.                 for ($i $j;
  155.                      $i $end && substr($diff[$i]03== '***';
  156.                      $i++);
  157.                 for ($max_i $i;
  158.                      $max_i $end && substr($diff[$max_i]03!= '---';
  159.                      $max_i++);
  160.                 for ($j $max_i;
  161.                      $j $end && substr($diff[$j]03== '---';
  162.                      $j++);
  163.                 for ($max_j $j;
  164.                      $max_j $end && substr($diff[$max_j]03!= '***';
  165.                      $max_j++);
  166.             }
  167.  
  168.             // find what hasn't been changed
  169.             $array = array();
  170.             while ($i $max_i &&
  171.                    $j $max_j &&
  172.                    strcmp($diff[$i]$diff[$j]== 0{
  173.                 $array[substr($diff[$i]2);
  174.                 $i++;
  175.                 $j++;
  176.             }
  177.  
  178.             while ($i $max_i && ($max_j-$j<= 1{
  179.                 if ($diff[$i!= '' && substr($diff[$i]01!= ' '{
  180.                     break;
  181.                 }
  182.                 $array[substr($diff[$i++]2);
  183.             }
  184.  
  185.             while ($j $max_j && ($max_i-$i<= 1{
  186.                 if ($diff[$j!= '' && substr($diff[$j]01!= ' '{
  187.                     break;
  188.                 }
  189.                 $array[substr($diff[$j++]2);
  190.             }
  191.             if (count($array> 0{
  192.                 $edits[= new Text_Diff_Op_copy($array);
  193.             }
  194.  
  195.             if ($i $max_i{
  196.                 $diff1 = array();
  197.                 switch (substr($diff[$i]01)) {
  198.                 case '!':
  199.                     $diff2 = array();
  200.                     do {
  201.                         $diff1[substr($diff[$i]2);
  202.                         if ($j $max_j && substr($diff[$j]01== '!'{
  203.                             $diff2[substr($diff[$j++]2);
  204.                         }
  205.                     while (++$i $max_i && substr($diff[$i]01== '!');
  206.                     $edits[= new Text_Diff_Op_change($diff1$diff2);
  207.                     break;
  208.  
  209.                 case '+':
  210.                     do {
  211.                         $diff1[substr($diff[$i]2);
  212.                     while (++$i $max_i && substr($diff[$i]01== '+');
  213.                     $edits[= new Text_Diff_Op_add($diff1);
  214.                     break;
  215.  
  216.                 case '-':
  217.                     do {
  218.                         $diff1[substr($diff[$i]2);
  219.                     while (++$i $max_i && substr($diff[$i]01== '-');
  220.                     $edits[= new Text_Diff_Op_delete($diff1);
  221.                     break;
  222.                 }
  223.             }
  224.  
  225.             if ($j $max_j{
  226.                 $diff2 = array();
  227.                 switch (substr($diff[$j]01)) {
  228.                 case '+':
  229.                     do {
  230.                         $diff2[substr($diff[$j++]2);
  231.                     while ($j $max_j && substr($diff[$j]01== '+');
  232.                     $edits[= new Text_Diff_Op_add($diff2);
  233.                     break;
  234.  
  235.                 case '-':
  236.                     do {
  237.                         $diff2[substr($diff[$j++]2);
  238.                     while ($j $max_j && substr($diff[$j]01== '-');
  239.                     $edits[= new Text_Diff_Op_delete($diff2);
  240.                     break;
  241.                 }
  242.             }
  243.         }
  244.  
  245.         return $edits;
  246.     }
  247.  
  248. }

Documentation generated on Wed, 08 Mar 2017 15:30:03 +0000 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.