2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
5 // $Id: diff.php,v 1.7 2003/06/11 00:00:51 arino Exp $
8 define('DIFF_SHOW_TABLE',TRUE);
11 function do_diff($strlines1,$strlines2)
13 $obj = new line_diff();
14 $str = $obj->str_compare($strlines1,$strlines2);
18 // º¹Ê¬¤ÎºîÀ®(¹¹¿·¤Î¾×ÆÍ)
19 function do_update_diff($pagestr,$poststr,$original)
21 $obj = new line_diff();
23 $obj->set_str('left',$original,$pagestr);
25 $diff1 = $obj->toArray();
27 $obj->set_str('right',$original,$poststr);
29 $diff2 = $obj->toArray();
31 $arr = $obj->arr_compare('all',$diff1,$diff2);
35 global $do_update_diff_table;
37 $do_update_diff_table = <<<EOD
38 <p>l : between backup data and stored page data.<br />
39 r : between backup data and your post data.</p>
40 <table class="style_table">
47 $tags = array('th','th','td');
48 foreach ($arr as $_obj)
50 $do_update_diff_table .= '<tr>';
51 $params = array($_obj->get('left'),$_obj->get('right'),$_obj->text());
52 foreach ($params as $key=>$text)
54 $text = htmlspecialchars($text);
55 if (trim($text) == '')
59 $do_update_diff_table .= "<{$tags[$key]} class=\"style_{$tags[$key]}\">$text</{$tags[$key]}>";
61 $do_update_diff_table .= '</tr>'."\n";
63 $do_update_diff_table .= '</table>'."\n";
67 foreach ($arr as $_obj)
69 if ($_obj->get('left') != '-' and $_obj->get('right') != '-')
71 $body .= $_obj->text();
77 return array(rtrim($body)."\n",$auto);
83 °Ê²¼¤Î¾ðÊó¤ò»²¹Í¤Ë¤·¤ÆºîÀ®¤·¤Þ¤·¤¿¡£
85 S. Wu, <A HREF="http://www.cs.arizona.edu/people/gene/vita.html">
86 E. Myers,</A> U. Manber, and W. Miller,
87 <A HREF="http://www.cs.arizona.edu/people/gene/PAPERS/np_diff.ps">
88 "An O(NP) Sequence Comparison Algorithm,"</A>
89 Information Processing Letters 35, 6 (1990), 317-323.
95 var $arr1,$arr2,$m,$n,$pos,$key,$plus,$minus,$equal,$reverse;
97 function line_diff($plus='+',$minus='-',$equal=' ')
100 $this->minus = $minus;
101 $this->equal = $equal;
103 function arr_compare($key,$arr1,$arr2)
109 $arr = $this->toArray();
112 function set_str($key,$str1,$str2)
115 $this->arr1 = array();
116 $this->arr2 = array();
117 $str1 = preg_replace("/\r/",'',$str1);
118 $str2 = preg_replace("/\r/",'',$str2);
119 foreach (explode("\n",$str1) as $line)
121 $this->arr1[] = new DiffLine($line);
123 foreach (explode("\n",$str2) as $line)
125 $this->arr2[] = new DiffLine($line);
128 function str_compare($str1,$str2)
130 $this->set_str('diff',$str1,$str2);
134 foreach ($this->toArray() as $obj)
136 $str .= $obj->get('diff').$obj->text();
142 $this->m = count($this->arr1);
143 $this->n = count($this->arr2);
145 if ($this->m == 0 or $this->n == 0) // no need compare.
147 $this->result = array(array('x'=>0,'y'=>0));
152 array_unshift($this->arr1,new DiffLine(''));
154 array_unshift($this->arr2,new DiffLine(''));
157 $this->reverse = ($this->n < $this->m);
158 if ($this->reverse) // swap
160 $tmp = $this->m; $this->m = $this->n; $this->n = $tmp;
161 $tmp = $this->arr1; $this->arr1 = $this->arr2; $this->arr2 = $tmp;
165 $delta = $this->n - $this->m; // must be >=0;
168 $this->path = array();
170 for ($p = -($this->m + 1); $p <= ($this->n + 1); $p++)
173 $this->path[$p] = array();
178 for ($k = -$p; $k <= $delta - 1; $k++)
180 $fp[$k] = $this->snake($k, $fp[$k - 1], $fp[$k + 1]);
182 for ($k = $delta + $p; $k >= $delta + 1; $k--)
184 $fp[$k] = $this->snake($k, $fp[$k - 1], $fp[$k + 1]);
186 $fp[$delta] = $this->snake($delta, $fp[$delta - 1], $fp[$delta + 1]);
187 if ($fp[$delta] >= $this->n)
189 $this->pos = $this->path[$delta]; // ·ÐÏ©¤ò·èÄê
194 function snake($k, $y1, $y2)
206 $this->path[$k] = $this->path[$_k];// ¤³¤³¤Þ¤Ç¤Î·ÐÏ©¤ò¥³¥Ô¡¼
208 while ((($x + 1) < $this->m) and (($y + 1) < $this->n)
209 and $this->arr1[$x + 1]->compare($this->arr2[$y + 1]))
212 $this->path[$k][] = array('x'=>$x,'y'=>$y); // ·ÐÏ©¤òÄɲÃ
219 if ($this->reverse) //¸È©¤Ê¡Ä
221 $_x = 'y'; $_y = 'x'; $_m = $this->n; $arr1 =& $this->arr2; $arr2 =& $this->arr1;
225 $_x = 'x'; $_y = 'y'; $_m = $this->m; $arr1 =& $this->arr1; $arr2 =& $this->arr2;
229 $this->add_count = $this->delete_count = 0;
230 $this->pos[] = array('x'=>$this->m,'y'=>$this->n); // sentinel
231 foreach ($this->pos as $pos)
233 $this->delete_count += ($pos[$_x] - $x);
234 $this->add_count += ($pos[$_y] - $y);
236 while ($pos[$_x] > $x)
238 $arr1[$x]->set($this->key,$this->minus);
239 $arr[] = $arr1[$x++];
242 while ($pos[$_y] > $y)
244 $arr2[$y]->set($this->key,$this->plus);
245 $arr[] = $arr2[$y++];
250 $arr1[$x]->merge($arr2[$y]);
251 $arr1[$x]->set($this->key,$this->equal);
265 function DiffLine($text)
267 $this->text = "$text\n";
268 $this->status = array();
270 function compare($obj)
272 return $this->text == $obj->text;
274 function set($key,$status)
276 $this->status[$key] = $status;
280 return array_key_exists($key,$this->status) ? $this->status[$key] : '';
284 $this->status += $obj->status;