PEAR is discontinued

This is a static archive preserving historical releases and metadata. No new packages or updates will be published. For updates to existing packages, or to publish new packages, please use Composer and Packagist.

Home » Text » Text_Diff » Bug #8096

diff generated is wrong.

Details

Request #8096diff generated is wrong.
Submitted2006-07-01 11:15 UTC
Fromviraj dot kanwade at yahoo dot com
StatusNo Feedback
PackageText_Diff
PHP Version5.1.0
OSNA
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.