[ Index ]

PHP Cross Reference of MyBB 1.6.7

title

Body

[close]

/inc/3rdparty/diff/Diff/Engine/ -> string.php (source)

   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.5 2008/09/10 08:31:58 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 || $unified === 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, if there is one.
  59          $diff = explode("\n", $diff);
  60          if (($mode == 'context' && strpos($diff[0], '***') === 0) ||
  61              ($mode == 'unified' && strpos($diff[0], '---') === 0)) {
  62              array_shift($diff);
  63              array_shift($diff);
  64          }
  65  
  66          if ($mode == 'context') {
  67              return $this->parseContextDiff($diff);
  68          } else {
  69              return $this->parseUnifiedDiff($diff);
  70          }
  71      }
  72  
  73      /**
  74       * Parses an array containing the unified diff.
  75       *
  76       * @param array $diff  Array of lines.
  77       *
  78       * @return array  List of all diff operations.
  79       */
  80      function parseUnifiedDiff($diff)
  81      {
  82          $edits = array();
  83          $end = count($diff) - 1;
  84          for ($i = 0; $i < $end;) {
  85              $diff1 = array();
  86              switch (substr($diff[$i], 0, 1)) {
  87              case ' ':
  88                  do {
  89                      $diff1[] = substr($diff[$i], 1);
  90                  } while (++$i < $end && substr($diff[$i], 0, 1) == ' ');
  91                  $edits[] = new Text_Diff_Op_copy($diff1);
  92                  break;
  93  
  94              case '+':
  95                  // get all new lines
  96                  do {
  97                      $diff1[] = substr($diff[$i], 1);
  98                  } while (++$i < $end && substr($diff[$i], 0, 1) == '+');
  99                  $edits[] = new Text_Diff_Op_add($diff1);
 100                  break;
 101  
 102              case '-':
 103                  // get changed or removed lines
 104                  $diff2 = array();
 105                  do {
 106                      $diff1[] = substr($diff[$i], 1);
 107                  } while (++$i < $end && substr($diff[$i], 0, 1) == '-');
 108  
 109                  while ($i < $end && substr($diff[$i], 0, 1) == '+') {
 110                      $diff2[] = substr($diff[$i++], 1);
 111                  }
 112                  if (count($diff2) == 0) {
 113                      $edits[] = new Text_Diff_Op_delete($diff1);
 114                  } else {
 115                      $edits[] = new Text_Diff_Op_change($diff1, $diff2);
 116                  }
 117                  break;
 118  
 119              default:
 120                  $i++;
 121                  break;
 122              }
 123          }
 124  
 125          return $edits;
 126      }
 127  
 128      /**
 129       * Parses an array containing the context diff.
 130       *
 131       * @param array $diff  Array of lines.
 132       *
 133       * @return array  List of all diff operations.
 134       */
 135      function parseContextDiff(&$diff)
 136      {
 137          $edits = array();
 138          $i = $max_i = $j = $max_j = 0;
 139          $end = count($diff) - 1;
 140          while ($i < $end && $j < $end) {
 141              while ($i >= $max_i && $j >= $max_j) {
 142                  // Find the boundaries of the diff output of the two files
 143                  for ($i = $j;
 144                       $i < $end && substr($diff[$i], 0, 3) == '***';
 145                       $i++);
 146                  for ($max_i = $i;
 147                       $max_i < $end && substr($diff[$max_i], 0, 3) != '---';
 148                       $max_i++);
 149                  for ($j = $max_i;
 150                       $j < $end && substr($diff[$j], 0, 3) == '---';
 151                       $j++);
 152                  for ($max_j = $j;
 153                       $max_j < $end && substr($diff[$max_j], 0, 3) != '***';
 154                       $max_j++);
 155              }
 156  
 157              // find what hasn't been changed
 158              $array = array();
 159              while ($i < $max_i &&
 160                     $j < $max_j &&
 161                     strcmp($diff[$i], $diff[$j]) == 0) {
 162                  $array[] = substr($diff[$i], 2);
 163                  $i++;
 164                  $j++;
 165              }
 166  
 167              while ($i < $max_i && ($max_j-$j) <= 1) {
 168                  if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') {
 169                      break;
 170                  }
 171                  $array[] = substr($diff[$i++], 2);
 172              }
 173  
 174              while ($j < $max_j && ($max_i-$i) <= 1) {
 175                  if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') {
 176                      break;
 177                  }
 178                  $array[] = substr($diff[$j++], 2);
 179              }
 180              if (count($array) > 0) {
 181                  $edits[] = new Text_Diff_Op_copy($array);
 182              }
 183  
 184              if ($i < $max_i) {
 185                  $diff1 = array();
 186                  switch (substr($diff[$i], 0, 1)) {
 187                  case '!':
 188                      $diff2 = array();
 189                      do {
 190                          $diff1[] = substr($diff[$i], 2);
 191                          if ($j < $max_j && substr($diff[$j], 0, 1) == '!') {
 192                              $diff2[] = substr($diff[$j++], 2);
 193                          }
 194                      } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!');
 195                      $edits[] = new Text_Diff_Op_change($diff1, $diff2);
 196                      break;
 197  
 198                  case '+':
 199                      do {
 200                          $diff1[] = substr($diff[$i], 2);
 201                      } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+');
 202                      $edits[] = new Text_Diff_Op_add($diff1);
 203                      break;
 204  
 205                  case '-':
 206                      do {
 207                          $diff1[] = substr($diff[$i], 2);
 208                      } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-');
 209                      $edits[] = new Text_Diff_Op_delete($diff1);
 210                      break;
 211                  }
 212              }
 213  
 214              if ($j < $max_j) {
 215                  $diff2 = array();
 216                  switch (substr($diff[$j], 0, 1)) {
 217                  case '+':
 218                      do {
 219                          $diff2[] = substr($diff[$j++], 2);
 220                      } while ($j < $max_j && substr($diff[$j], 0, 1) == '+');
 221                      $edits[] = new Text_Diff_Op_add($diff2);
 222                      break;
 223  
 224                  case '-':
 225                      do {
 226                          $diff2[] = substr($diff[$j++], 2);
 227                      } while ($j < $max_j && substr($diff[$j], 0, 1) == '-');
 228                      $edits[] = new Text_Diff_Op_delete($diff2);
 229                      break;
 230                  }
 231              }
 232          }
 233  
 234          return $edits;
 235      }
 236  
 237  }


Generated: Sat Mar 31 17:55:03 2012 Cross-referenced by PHPXref 0.7.1