[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 require_once 'Text/Diff.php'; 4 5 /** 6 * A class for computing three way diffs. 7 * 8 * $Horde: framework/Text_Diff/Diff3.php,v 1.2.10.3 2005/10/18 11:01:31 jan Exp $ 9 * 10 * @package Text_Diff 11 * @author Geoffrey T. Dairiki <dairiki@dairiki.org> 12 */ 13 class Text_Diff3 extends Text_Diff { 14 15 /** 16 * Conflict counter. 17 * 18 * @var integer 19 */ 20 var $_conflictingBlocks = 0; 21 22 /** 23 * Computes diff between 3 sequences of strings. 24 * 25 * @param array $orig The original lines to use. 26 * @param array $final1 The first version to compare to. 27 * @param array $final2 The second version to compare to. 28 */ 29 function Text_Diff3($orig, $final1, $final2) 30 { 31 if (extension_loaded('xdiff')) { 32 $engine = &new Text_Diff_Engine_xdiff(); 33 } else { 34 $engine = &new Text_Diff_Engine_native(); 35 } 36 37 $this->_edits = $this->_diff3($engine->diff($orig, $final1), 38 $engine->diff($orig, $final2)); 39 } 40 41 function mergedOutput($label1 = false, $label2 = false) 42 { 43 $lines = array(); 44 foreach ($this->_edits as $edit) { 45 if ($edit->isConflict()) { 46 /* FIXME: this should probably be moved somewhere else. */ 47 $lines = array_merge($lines, 48 array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), 49 $edit->final1, 50 array("======="), 51 $edit->final2, 52 array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); 53 $this->_conflictingBlocks++; 54 } else { 55 $lines = array_merge($lines, $edit->merged()); 56 } 57 } 58 59 return $lines; 60 } 61 62 /** 63 * @access private 64 */ 65 function _diff3($edits1, $edits2) 66 { 67 $edits = array(); 68 $bb = &new Text_Diff3_BlockBuilder(); 69 70 $e1 = current($edits1); 71 $e2 = current($edits2); 72 while ($e1 || $e2) { 73 if ($e1 && $e2 && is_a($e1, 'Text_Diff_Op_copy') && is_a($e2, 'Text_Diff_Op_copy')) { 74 /* We have copy blocks from both diffs. This is the (only) 75 * time we want to emit a diff3 copy block. Flush current 76 * diff3 diff block, if any. */ 77 if ($edit = $bb->finish()) { 78 $edits[] = $edit; 79 } 80 81 $ncopy = min($e1->norig(), $e2->norig()); 82 assert($ncopy > 0); 83 $edits[] = &new Text_Diff3_Op_copy(array_slice($e1->orig, 0, $ncopy)); 84 85 if ($e1->norig() > $ncopy) { 86 array_splice($e1->orig, 0, $ncopy); 87 array_splice($e1->final, 0, $ncopy); 88 } else { 89 $e1 = next($edits1); 90 } 91 92 if ($e2->norig() > $ncopy) { 93 array_splice($e2->orig, 0, $ncopy); 94 array_splice($e2->final, 0, $ncopy); 95 } else { 96 $e2 = next($edits2); 97 } 98 } else { 99 if ($e1 && $e2) { 100 if ($e1->orig && $e2->orig) { 101 $norig = min($e1->norig(), $e2->norig()); 102 $orig = array_splice($e1->orig, 0, $norig); 103 array_splice($e2->orig, 0, $norig); 104 $bb->input($orig); 105 } 106 107 if (is_a($e1, 'Text_Diff_Op_copy')) { 108 $bb->out1(array_splice($e1->final, 0, $norig)); 109 } 110 111 if (is_a($e2, 'Text_Diff_Op_copy')) { 112 $bb->out2(array_splice($e2->final, 0, $norig)); 113 } 114 } 115 116 if ($e1 && ! $e1->orig) { 117 $bb->out1($e1->final); 118 $e1 = next($edits1); 119 } 120 if ($e2 && ! $e2->orig) { 121 $bb->out2($e2->final); 122 $e2 = next($edits2); 123 } 124 } 125 } 126 127 if ($edit = $bb->finish()) { 128 $edits[] = $edit; 129 } 130 131 return $edits; 132 } 133 134 } 135 136 /** 137 * @package Text_Diff 138 * @author Geoffrey T. Dairiki <dairiki@dairiki.org> 139 * 140 * @access private 141 */ 142 class Text_Diff3_Op { 143 144 function Text_Diff3_Op($orig = false, $final1 = false, $final2 = false) 145 { 146 $this->orig = $orig ? $orig : array(); 147 $this->final1 = $final1 ? $final1 : array(); 148 $this->final2 = $final2 ? $final2 : array(); 149 } 150 151 function merged() 152 { 153 if (!isset($this->_merged)) { 154 if ($this->final1 === $this->final2) { 155 $this->_merged = &$this->final1; 156 } elseif ($this->final1 === $this->orig) { 157 $this->_merged = &$this->final2; 158 } elseif ($this->final2 === $this->orig) { 159 $this->_merged = &$this->final1; 160 } else { 161 $this->_merged = false; 162 } 163 } 164 165 return $this->_merged; 166 } 167 168 function isConflict() 169 { 170 return $this->merged() === false; 171 } 172 173 } 174 175 /** 176 * @package Text_Diff 177 * @author Geoffrey T. Dairiki <dairiki@dairiki.org> 178 * 179 * @access private 180 */ 181 class Text_Diff3_Op_copy extends Text_Diff3_Op { 182 183 function Text_Diff3_Op_Copy($lines = false) 184 { 185 $this->orig = $lines ? $lines : array(); 186 $this->final1 = &$this->orig; 187 $this->final2 = &$this->orig; 188 } 189 190 function merged() 191 { 192 return $this->orig; 193 } 194 195 function isConflict() 196 { 197 return false; 198 } 199 200 } 201 202 /** 203 * @package Text_Diff 204 * @author Geoffrey T. Dairiki <dairiki@dairiki.org> 205 * 206 * @access private 207 */ 208 class Text_Diff3_BlockBuilder { 209 210 function Text_Diff3_BlockBuilder() 211 { 212 $this->_init(); 213 } 214 215 function input($lines) 216 { 217 if ($lines) { 218 $this->_append($this->orig, $lines); 219 } 220 } 221 222 function out1($lines) 223 { 224 if ($lines) { 225 $this->_append($this->final1, $lines); 226 } 227 } 228 229 function out2($lines) 230 { 231 if ($lines) { 232 $this->_append($this->final2, $lines); 233 } 234 } 235 236 function isEmpty() 237 { 238 return !$this->orig && !$this->final1 && !$this->final2; 239 } 240 241 function finish() 242 { 243 if ($this->isEmpty()) { 244 return false; 245 } else { 246 $edit = &new Text_Diff3_Op($this->orig, $this->final1, $this->final2); 247 $this->_init(); 248 return $edit; 249 } 250 } 251 252 function _init() 253 { 254 $this->orig = $this->final1 = $this->final2 = array(); 255 } 256 257 function _append(&$array, $lines) 258 { 259 array_splice($array, sizeof($array), 0, $lines); 260 } 261 262 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |