Text_Diff_Engine_string

Parses unified or context diffs output from eg.

Defined (1)

The class is defined in the following location(s).

/wp-includes/Text/Diff/Engine/string.php  
  1. class Text_Diff_Engine_string { 
  2.  
  3. /** 
  4. * Parses a unified or context diff. 
  5. * First param contains the whole diff and the second can be used to force 
  6. * a specific diff type. If the second parameter is 'autodetect', the 
  7. * diff will be examined to find out which type of diff this is. 
  8. * @param string $diff The diff content. 
  9. * @param string $mode The diff mode of the content in $diff. One of 
  10. * 'context', 'unified', or 'autodetect'. 
  11. * @return array List of all diff operations. 
  12. */ 
  13. function diff($diff, $mode = 'autodetect') 
  14. // Detect line breaks. 
  15. $lnbr = "\n"; 
  16. if (strpos($diff, "\r\n") !== false) { 
  17. $lnbr = "\r\n"; 
  18. } elseif (strpos($diff, "\r") !== false) { 
  19. $lnbr = "\r"; 
  20.  
  21. // Make sure we have a line break at the EOF. 
  22. if (substr($diff, -strlen($lnbr)) != $lnbr) { 
  23. $diff .= $lnbr; 
  24.  
  25. if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { 
  26. return PEAR::raiseError('Type of diff is unsupported'); 
  27.  
  28. if ($mode == 'autodetect') { 
  29. $context = strpos($diff, '***'); 
  30. $unified = strpos($diff, '---'); 
  31. if ($context === $unified) { 
  32. return PEAR::raiseError('Type of diff could not be detected'); 
  33. } elseif ($context === false || $unified === false) { 
  34. $mode = $context !== false ? 'context' : 'unified'; 
  35. } else { 
  36. $mode = $context < $unified ? 'context' : 'unified'; 
  37.  
  38. // Split by new line and remove the diff header, if there is one. 
  39. $diff = explode($lnbr, $diff); 
  40. if (($mode == 'context' && strpos($diff[0], '***') === 0) || 
  41. ($mode == 'unified' && strpos($diff[0], '---') === 0)) { 
  42. array_shift($diff); 
  43. array_shift($diff); 
  44.  
  45. if ($mode == 'context') { 
  46. return $this->parseContextDiff($diff); 
  47. } else { 
  48. return $this->parseUnifiedDiff($diff); 
  49.  
  50. /** 
  51. * Parses an array containing the unified diff. 
  52. * @param array $diff Array of lines. 
  53. * @return array List of all diff operations. 
  54. */ 
  55. function parseUnifiedDiff($diff) 
  56. $edits = array(); 
  57. $end = count($diff) - 1; 
  58. for ($i = 0; $i < $end;) { 
  59. $diff1 = array(); 
  60. switch (substr($diff[$i], 0, 1)) { 
  61. case ' ': 
  62. do { 
  63. $diff1[] = substr($diff[$i], 1); 
  64. } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); 
  65. $edits[] = new Text_Diff_Op_copy($diff1); 
  66. break; 
  67.  
  68. case '+': 
  69. // get all new lines 
  70. do { 
  71. $diff1[] = substr($diff[$i], 1); 
  72. } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); 
  73. $edits[] = new Text_Diff_Op_add($diff1); 
  74. break; 
  75.  
  76. case '-': 
  77. // get changed or removed lines 
  78. $diff2 = array(); 
  79. do { 
  80. $diff1[] = substr($diff[$i], 1); 
  81. } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); 
  82.  
  83. while ($i < $end && substr($diff[$i], 0, 1) == '+') { 
  84. $diff2[] = substr($diff[$i++], 1); 
  85. if (count($diff2) == 0) { 
  86. $edits[] = new Text_Diff_Op_delete($diff1); 
  87. } else { 
  88. $edits[] = new Text_Diff_Op_change($diff1, $diff2); 
  89. break; 
  90.  
  91. default: 
  92. $i++; 
  93. break; 
  94.  
  95. return $edits; 
  96.  
  97. /** 
  98. * Parses an array containing the context diff. 
  99. * @param array $diff Array of lines. 
  100. * @return array List of all diff operations. 
  101. */ 
  102. function parseContextDiff(&$diff) 
  103. $edits = array(); 
  104. $i = $max_i = $j = $max_j = 0; 
  105. $end = count($diff) - 1; 
  106. while ($i < $end && $j < $end) { 
  107. while ($i >= $max_i && $j >= $max_j) { 
  108. // Find the boundaries of the diff output of the two files 
  109. for ($i = $j; 
  110. $i < $end && substr($diff[$i], 0, 3) == '***'; 
  111. $i++); 
  112. for ($max_i = $i; 
  113. $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; 
  114. $max_i++); 
  115. for ($j = $max_i; 
  116. $j < $end && substr($diff[$j], 0, 3) == '---'; 
  117. $j++); 
  118. for ($max_j = $j; 
  119. $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; 
  120. $max_j++); 
  121.  
  122. // find what hasn't been changed 
  123. $array = array(); 
  124. while ($i < $max_i && 
  125. $j < $max_j && 
  126. strcmp($diff[$i], $diff[$j]) == 0) { 
  127. $array[] = substr($diff[$i], 2); 
  128. $i++; 
  129. $j++; 
  130.  
  131. while ($i < $max_i && ($max_j-$j) <= 1) { 
  132. if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { 
  133. break; 
  134. $array[] = substr($diff[$i++], 2); 
  135.  
  136. while ($j < $max_j && ($max_i-$i) <= 1) { 
  137. if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { 
  138. break; 
  139. $array[] = substr($diff[$j++], 2); 
  140. if (count($array) > 0) { 
  141. $edits[] = new Text_Diff_Op_copy($array); 
  142.  
  143. if ($i < $max_i) { 
  144. $diff1 = array(); 
  145. switch (substr($diff[$i], 0, 1)) { 
  146. case '!': 
  147. $diff2 = array(); 
  148. do { 
  149. $diff1[] = substr($diff[$i], 2); 
  150. if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { 
  151. $diff2[] = substr($diff[$j++], 2); 
  152. } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); 
  153. $edits[] = new Text_Diff_Op_change($diff1, $diff2); 
  154. break; 
  155.  
  156. case '+': 
  157. do { 
  158. $diff1[] = substr($diff[$i], 2); 
  159. } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); 
  160. $edits[] = new Text_Diff_Op_add($diff1); 
  161. break; 
  162.  
  163. case '-': 
  164. do { 
  165. $diff1[] = substr($diff[$i], 2); 
  166. } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); 
  167. $edits[] = new Text_Diff_Op_delete($diff1); 
  168. break; 
  169.  
  170. if ($j < $max_j) { 
  171. $diff2 = array(); 
  172. switch (substr($diff[$j], 0, 1)) { 
  173. case '+': 
  174. do { 
  175. $diff2[] = substr($diff[$j++], 2); 
  176. } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); 
  177. $edits[] = new Text_Diff_Op_add($diff2); 
  178. break; 
  179.  
  180. case '-': 
  181. do { 
  182. $diff2[] = substr($diff[$j++], 2); 
  183. } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); 
  184. $edits[] = new Text_Diff_Op_delete($diff2); 
  185. break; 
  186.  
  187. return $edits; 
  188.