| [ Index ] |
PHP Cross Reference of Wordpress 2.9.1 |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Fri Jan 8 00:19:48 2010 | Cross-referenced by PHPXref 0.7 |