Home » Text » Text_Diff » Bug #8096
diff generated is wrong.
Details
| Request #8096 | diff generated is wrong. |
|---|---|
| Submitted | 2006-07-01 11:15 UTC |
| From | viraj dot kanwade at yahoo dot com |
| Status | No Feedback |
| Package | Text_Diff |
| PHP Version | 5.1.0 |
| OS | NA |
| Roadmaps | (Not assigned) |
Comments
[2006-07-01 11:15 UTC] viraj dot kanwade at yahoo dot com
Description:
------------
Wrong diff is generated by your diff generating code.
Also
I have written a class to display diff in side by side comparision format, something like kompare or winmerge.
How do i send it to you?
Test script:
---------------
print_r($diff) in your test script confirmed my findings.
this (91,108c124) is the a part of the result i get when it should be (91,96c118,122 and 98,108c124)
Expected result:
----------------
$ diff r.php r1.php
8c8
< * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 ja
n Exp $
---
> * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 ja
n Exp $
67,68c67,75
< function render($diff)
< {
---
> function render($diff)
> {
> $xi = $yi = 1;
> $block = false;
> $context = array();
>
> $nlead = $this->_leading_context_lines;
> $ntrail = $this->_trailing_context_lines;
>
71a79,108
> foreach ($diffs as $i => $edit) {
> if (is_a($edit, 'Text_Diff_Op_copy')) {
> if (is_array($block)) {
> $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntra
il;
> if (count($edit->orig) <= $keep) {
> $block[] = $edit;
> } else {
> if ($ntrail) {
> $context = array_slice($edit->orig, 0, $ntrail);
> $block[] = &new Text_Diff_Op_copy($context);
> }
> $output .= $this->_block($x0, $ntrail + $xi - $x0,
> $y0, $ntrail + $yi - $y0,
> $block);
> $block = false;
> }
> }
> $context = $edit->orig;
> } else {
> if (!is_array($block)) {
> $context = array_slice($context, count($context) - $nlead)
;
> $x0 = $xi - count($context);
> $y0 = $yi - count($context);
> $block = array();
> if ($context) {
> $block[] = &new Text_Diff_Op_copy($context);
> }
> }
> $block[] = $edit;
> }
73,89c110,116
< $x0 = 0;
< $y0 = 0;
< $x1 = 0;
< $y1 = 0;
< foreach ($diffs as $i => $edit) {
< switch (strtolower(get_class($edit))) {
< case 'text_diff_op_copy':
< $x0 += count($edit->orig);
< $x1 += count($edit->orig);
< break;
<
< case 'text_diff_op_add':
< $y1 = count($edit->final);
< $output .= $this->_startBlock($this->_blockHeader($x0,0,$x1+1,$y
1));
< $output .= $this->_added($edit->final);
< $x1 += $y1;
< break;
---
> if ($edit->orig) {
> $xi += count($edit->orig);
> }
> if ($edit->final) {
> $yi += count($edit->final);
> }
> }
91,96c118,122
< case 'text_diff_op_delete':
< $y0 = count($edit->orig);
< $output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1,
0));
< $output .= $this->_deleted($edit->orig);
< $x0 += $y0;
< break;
---
> if (is_array($block)) {
> $output .= $this->_block($x0, $xi - $x0,
> $y0, $yi - $y0,
> $block);
> }
98,108c124
< case 'text_diff_op_change':
< $y0 = count($edit->orig);
< $y1 = count($edit->final);
< $output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1+
1,$y1));
< $output .= $this->_changed($edit->orig, $edit->final);
< $x0 += $y0;
< $x1 += $y1;
< break;
< }
< }
< return $output . $this->_endDiff();
---
> return $output . $this->_endDiff();
182c198
< return $this->_lines($lines, '> ');
---
> return $this->_lines($lines, '>');
187c203
< return $this->_lines($lines, '< ');
---
> return $this->_lines($lines, '<');
Actual result:
--------------
8c8
< * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 jan Exp $
---
> * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 jan Exp $
67,68c67,75
< function render($diff)
< {
---
> function render($diff)
> {
> $xi = $yi = 1;
> $block = false;
> $context = array();
>
> $nlead = $this->_leading_context_lines;
> $ntrail = $this->_trailing_context_lines;
>
71a79,108
> foreach ($diffs as $i => $edit) {
> if (is_a($edit, 'Text_Diff_Op_copy')) {
> if (is_array($block)) {
> $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
> if (count($edit->orig) <= $keep) {
> $block[] = $edit;
> } else {
> if ($ntrail) {
> $context = array_slice($edit->orig, 0, $ntrail);
> $block[] = &new Text_Diff_Op_copy($context);
> }
> $output .= $this->_block($x0, $ntrail + $xi - $x0,
> $y0, $ntrail + $yi - $y0,
> $block);
> $block = false;
> }
> }
> $context = $edit->orig;
> } else {
> if (!is_array($block)) {
> $context = array_slice($context, count($context) - $nlead);
> $x0 = $xi - count($context);
> $y0 = $yi - count($context);
> $block = array();
> if ($context) {
> $block[] = &new Text_Diff_Op_copy($context);
> }
> }
> $block[] = $edit;
> }
73,82c110,116
< $x0 = 0;
< $y0 = 0;
< $x1 = 0;
< $y1 = 0;
< foreach ($diffs as $i => $edit) {
< switch (strtolower(get_class($edit))) {
< case 'text_diff_op_copy':
< $x0 += count($edit->orig);
< $x1 += count($edit->orig);
< break;
---
> if ($edit->orig) {
> $xi += count($edit->orig);
> }
> if ($edit->final) {
> $yi += count($edit->final);
> }
> }
84,89c118,122
< case 'text_diff_op_add':
< $y1 = count($edit->final);
< $output .= $this->_startBlock($this->_blockHeader($x0,0,$x1+1,$y1));
< $output .= $this->_added($edit->final);
< $x1 += $y1;
< break;
---
> if (is_array($block)) {
> $output .= $this->_block($x0, $xi - $x0,
> $y0, $yi - $y0,
> $block);
> }
91,108c124
< case 'text_diff_op_delete':
< $y0 = count($edit->orig);
< $output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1,0));
< $output .= $this->_deleted($edit->orig);
< $x0 += $y0;
< break;
<
< case 'text_diff_op_change':
< $y0 = count($edit->orig);
< $y1 = count($edit->final);
< $output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1+1,$y1));
< $output .= $this->_changed($edit->orig, $edit->final);
< $x0 += $y0;
< $x1 += $y1;
< break;
< }
< }
< return $output . $this->_endDiff();
---
> return $output . $this->_endDiff();
182c198
< return $this->_lines($lines, '> ');
---
> return $this->_lines($lines, '>');
187c203
< return $this->_lines($lines, '< ');
---
> return $this->_lines($lines, '<');
[2006-07-03 15:25 UTC] viraj dot kanwade at yahoo dot com
file 1:
<?php
/**
* A class to render Diffs in different formats.
*
* This class renders the diff in classic diff format. It is intended that
* this class be customized via inheritance, to obtain fancier outputs.
*
* $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 jan Exp $
*
* @package Text_Diff
*/
class Text_Diff_Renderer {
/**
* Number of leading context "lines" to preserve.
*
* This should be left at zero for this class, but subclasses may want to
* set this to other values.
*/
var $_leading_context_lines = 0;
/**
* Number of trailing context "lines" to preserve.
*
* This should be left at zero for this class, but subclasses may want to
* set this to other values.
*/
var $_trailing_context_lines = 0;
/**
* Constructor.
*/
function Text_Diff_Renderer($params = array())
{
foreach ($params as $param => $value) {
$v = '_' . $param;
if (isset($this->$v)) {
$this->$v = $value;
}
}
}
/**
* Get any renderer parameters.
*
* @return array All parameters of this renderer object.
*/
function getParams()
{
$params = array();
foreach (get_object_vars($this) as $k => $v) {
if ($k[0] == '_') {
$params[substr($k, 1)] = $v;
}
}
return $params;
}
/**
* Renders a diff.
*
* @param Text_Diff $diff A Text_Diff object.
*
* @return string The formatted output.
*/
function render($diff)
{
$xi = $yi = 1;
$block = false;
$context = array();
$nlead = $this->_leading_context_lines;
$ntrail = $this->_trailing_context_lines;
$output = $this->_startDiff();
$diffs = $diff->getDiff();
foreach ($diffs as $i => $edit) {
if (is_a($edit, 'Text_Diff_Op_copy')) {
if (is_array($block)) {
$keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
if (count($edit->orig) <= $keep) {
$block[] = $edit;
} else {
if ($ntrail) {
$context = array_slice($edit->orig, 0, $ntrail);
$block[] = &new Text_Diff_Op_copy($context);
}
$output .= $this->_block($x0, $ntrail + $xi - $x0,
$y0, $ntrail + $yi - $y0,
$block);
$block = false;
}
}
$context = $edit->orig;
} else {
if (!is_array($block)) {
$context = array_slice($context, count($context) - $nlead);
$x0 = $xi - count($context);
$y0 = $yi - count($context);
$block = array();
if ($context) {
$block[] = &new Text_Diff_Op_copy($context);
}
}
$block[] = $edit;
}
if ($edit->orig) {
$xi += count($edit->orig);
}
if ($edit->final) {
$yi += count($edit->final);
}
}
if (is_array($block)) {
$output .= $this->_block($x0, $xi - $x0,
$y0, $yi - $y0,
$block);
}
return $output . $this->_endDiff();
}
function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
{
$output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
foreach ($edits as $edit) {
switch (strtolower(get_class($edit))) {
case 'text_diff_op_copy':
$output .= $this->_context($edit->orig);
break;
case 'text_diff_op_add':
$output .= $this->_added($edit->final);
break;
case 'text_diff_op_delete':
$output .= $this->_deleted($edit->orig);
break;
case 'text_diff_op_change':
$output .= $this->_changed($edit->orig, $edit->final);
break;
}
}
return $output . $this->_endBlock();
}
function _startDiff()
{
return '';
}
function _endDiff()
{
return '';
}
function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
{
if ($xlen > 1) {
$xbeg .= ',' . ($xbeg + $xlen - 1);
}
if ($ylen > 1) {
$ybeg .= ',' . ($ybeg + $ylen - 1);
}
return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
}
function _startBlock($header)
{
return $header . "\n";
}
function _endBlock()
{
return '';
}
function _lines($lines, $prefix = ' ')
{
return $prefix . implode("\n$prefix", $lines) . "\n";
}
function _context($lines)
{
return $this->_lines($lines);
}
function _added($lines)
{
return $this->_lines($lines, '>');
}
function _deleted($lines)
{
return $this->_lines($lines, '<');
}
function _changed($orig, $final)
{
return $this->_deleted($orig) . "---\n" . $this->_added($final);
}
}
file 2:
<?php
/**
* A class to render Diffs in different formats.
*
* This class renders the diff in classic diff format. It is intended that
* this class be customized via inheritance, to obtain fancier outputs.
*
* $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.12 2005/12/16 11:07:33 jan Exp $
*
* @package Text_Diff
*/
class Text_Diff_Renderer {
/**
* Number of leading context "lines" to preserve.
*
* This should be left at zero for this class, but subclasses may want to
* set this to other values.
*/
var $_leading_context_lines = 0;
/**
* Number of trailing context "lines" to preserve.
*
* This should be left at zero for this class, but subclasses may want to
* set this to other values.
*/
var $_trailing_context_lines = 0;
/**
* Constructor.
*/
function Text_Diff_Renderer($params = array())
{
foreach ($params as $param => $value) {
$v = '_' . $param;
if (isset($this->$v)) {
$this->$v = $value;
}
}
}
/**
* Get any renderer parameters.
*
* @return array All parameters of this renderer object.
*/
function getParams()
{
$params = array();
foreach (get_object_vars($this) as $k => $v) {
if ($k[0] == '_') {
$params[substr($k, 1)] = $v;
}
}
return $params;
}
/**
* Renders a diff.
*
* @param Text_Diff $diff A Text_Diff object.
*
* @return string The formatted output.
*/
function render($diff)
{
$output = $this->_startDiff();
$diffs = $diff->getDiff();
$x0 = 0;
$y0 = 0;
$x1 = 0;
$y1 = 0;
foreach ($diffs as $i => $edit) {
switch (strtolower(get_class($edit))) {
case 'text_diff_op_copy':
$x0 += count($edit->orig);
$x1 += count($edit->orig);
break;
case 'text_diff_op_add':
$y1 = count($edit->final);
$output .= $this->_startBlock($this->_blockHeader($x0,0,$x1+1,$y1));
$output .= $this->_added($edit->final);
$x1 += $y1;
break;
case 'text_diff_op_delete':
$y0 = count($edit->orig);
$output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1,0));
$output .= $this->_deleted($edit->orig);
$x0 += $y0;
break;
case 'text_diff_op_change':
$y0 = count($edit->orig);
$y1 = count($edit->final);
$output .= $this->_startBlock($this->_blockHeader($x0+1,$y0,$x1+1,$y1));
$output .= $this->_changed($edit->orig, $edit->final);
$x0 += $y0;
$x1 += $y1;
break;
}
}
return $output . $this->_endDiff();
}
function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
{
$output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
foreach ($edits as $edit) {
switch (strtolower(get_class($edit))) {
case 'text_diff_op_copy':
$output .= $this->_context($edit->orig);
break;
case 'text_diff_op_add':
$output .= $this->_added($edit->final);
break;
case 'text_diff_op_delete':
$output .= $this->_deleted($edit->orig);
break;
case 'text_diff_op_change':
$output .= $this->_changed($edit->orig, $edit->final);
break;
}
}
return $output . $this->_endBlock();
}
function _startDiff()
{
return '';
}
function _endDiff()
{
return '';
}
function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
{
if ($xlen > 1) {
$xbeg .= ',' . ($xbeg + $xlen - 1);
}
if ($ylen > 1) {
$ybeg .= ',' . ($ybeg + $ylen - 1);
}
return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
}
function _startBlock($header)
{
return $header . "\n";
}
function _endBlock()
{
return '';
}
function _lines($lines, $prefix = ' ')
{
return $prefix . implode("\n$prefix", $lines) . "\n";
}
function _context($lines)
{
return $this->_lines($lines);
}
function _added($lines)
{
return $this->_lines($lines, '> ');
}
function _deleted($lines)
{
return $this->_lines($lines, '< ');
}
function _changed($orig, $final)
{
return $this->_deleted($orig) . "---\n" . $this->_added($final);
}
}
Also for the new renderer i have written, wht project should i select. theres no diff project.