Text_Diff
[ class tree: Text_Diff ] [ index: Text_Diff ] [ all elements ]

Source for file Diff3.php

Documentation is available at Diff3.php

  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.1 2004/03/19 18:53:11 chuck 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 $_conflictCounter 
  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
  47.                 // else.
  48.                 $lines array_merge($lines,
  49.                                      array('<<<<<<<' ($label1 ' ' $label1 '')),
  50.                                      $edit->final1,
  51.                                      array("======="),
  52.                                      $edit->final2,
  53.                                      array('>>>>>>>' ($label2 ' ' $label2 '')));
  54.                 $this->_conflictingBlocks++;
  55.             else {
  56.                 $lines array_merge($lines$edit->merged());
  57.             }
  58.         }
  59.  
  60.         return $lines;
  61.     }
  62.  
  63.     /**
  64.      * @access private
  65.      */
  66.     function _diff3($edits1$edits2)
  67.     {
  68.         $edits = array();
  69.         $bb &new Text_Diff3_BlockBuilder();
  70.  
  71.         $e1 current($edits1);
  72.         $e2 current($edits2);
  73.         while ($e1 || $e2{
  74.             if ($e1 && $e2 && is_a($e1'Text_Diff_Op_copy'&& is_a($e2'Text_Diff_Op_copy')) {
  75.                 // We have copy blocks from both diffs. This is the
  76.                 // (only) time we want to emit a diff3 copy block.
  77.                 // Flush current diff3 diff block, if any.
  78.                 if ($edit $bb->finish()) {
  79.                     $edits[$edit;
  80.                 }
  81.  
  82.                 $ncopy min($e1->norig()$e2->norig());
  83.                 assert($ncopy > 0);
  84.                 $edits[&new Text_Diff3_Op_copy(array_slice($e1->orig0$ncopy));
  85.  
  86.                 if ($e1->norig($ncopy{
  87.                     array_splice($e1->orig0$ncopy);
  88.                     array_splice($e1->final0$ncopy);
  89.                 else {
  90.                     $e1 next($edits1);
  91.                 }
  92.  
  93.                 if ($e2->norig($ncopy{
  94.                     array_splice($e2->orig0$ncopy);
  95.                     array_splice($e2->final0$ncopy);
  96.                 else {
  97.                     $e2 next($edits2);
  98.                 }
  99.             else {
  100.                 if ($e1 && $e2{
  101.                     if ($e1->orig && $e2->orig{
  102.                         $norig min($e1->norig()$e2->norig());
  103.                         $orig array_splice($e1->orig0$norig);
  104.                         array_splice($e2->orig0$norig);
  105.                         $bb->input($orig);
  106.                     }
  107.  
  108.                     if (is_a($e1'Text_Diff_Op_copy')) {
  109.                         $bb->out1(array_splice($e1->final0$norig));
  110.                     }
  111.  
  112.                     if (is_a($e2'Text_Diff_Op_copy')) {
  113.                         $bb->out2(array_splice($e2->final0$norig));
  114.                     }
  115.                 }
  116.  
  117.                 if ($e1 && $e1->orig{
  118.                     $bb->out1($e1->final);
  119.                     $e1 next($edits1);
  120.                 }
  121.                 if ($e2 && $e2->orig{
  122.                     $bb->out2($e2->final);
  123.                     $e2 next($edits2);
  124.                 }
  125.             }
  126.         }
  127.  
  128.         if ($edit $bb->finish()) {
  129.             $edits[$edit;
  130.         }
  131.  
  132.         return $edits;
  133.     }
  134.  
  135. }
  136.  
  137. /**
  138.  * @package Text_Diff
  139.  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
  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.  * @access  private
  179.  */
  180. class Text_Diff3_Op_copy extends Text_Diff3_Op {
  181.  
  182.     function Text_Diff3_Op_Copy($lines = false)
  183.     {
  184.         $this->orig $lines $lines : array();
  185.         $this->final1 &$this->orig;
  186.         $this->final2 &$this->orig;
  187.     }
  188.  
  189.     function merged()
  190.     {
  191.         return $this->orig;
  192.     }
  193.  
  194.     function isConflict()
  195.     {
  196.         return false;
  197.     }
  198.  
  199. }
  200.  
  201. /**
  202.  * @package Text_Diff
  203.  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
  204.  * @access  private
  205.  */
  206. class Text_Diff3_BlockBuilder {
  207.  
  208.     function Text_Diff3_BlockBuilder()
  209.     {
  210.         $this->_init();
  211.     }
  212.  
  213.     function input($lines)
  214.     {
  215.         if ($lines{
  216.             $this->_append($this->orig$lines);
  217.         }
  218.     }
  219.  
  220.     function out1($lines)
  221.     {
  222.         if ($lines{
  223.             $this->_append($this->final1$lines);
  224.         }
  225.     }
  226.  
  227.     function out2($lines)
  228.     {
  229.         if ($lines{
  230.             $this->_append($this->final2$lines);
  231.         }
  232.     }
  233.  
  234.     function isEmpty()
  235.     {
  236.         return !$this->orig && !$this->final1 && !$this->final2;
  237.     }
  238.  
  239.     function finish()
  240.     {
  241.         if ($this->isEmpty()) {
  242.             return false;
  243.         else {
  244.             $edit &new Text_Diff3_Op($this->orig$this->final1$this->final2);
  245.             $this->_init();
  246.             return $edit;
  247.         }
  248.     }
  249.  
  250.     function _init()
  251.     {
  252.         $this->orig $this->final1 $this->final2 = array();
  253.     }
  254.  
  255.     function _append(&$array$lines)
  256.     {
  257.         array_splice($arraysizeof($array)0$lines);
  258.     }
  259.  
  260. }

Documentation generated on Mon, 11 Mar 2019 10:15:12 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.