b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_ext/phpsvnclient/ext/Diff/Diff/Engine/string.php - 253 lines - 8539 bytes - Summary - Text - Print

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

title

Description

title

Description

title

Description

title

title

Body