home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Blogs / wordpress2.6.exe / wordpress2.6 / wp-includes / Text / Diff / Engine / string.php < prev    next >
Encoding:
PHP Script  |  2008-04-19  |  7.7 KB  |  235 lines

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