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.2 2004/10/13 09:30:20 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 $_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 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->orig0$ncopy));
  84.  
  85.                 if ($e1->norig($ncopy{
  86.                     array_splice($e1->orig0$ncopy);
  87.                     array_splice($e1->final0$ncopy);
  88.                 else {
  89.                     $e1 next($edits1);
  90.                 }
  91.  
  92.                 if ($e2->norig($ncopy{
  93.                     array_splice($e2->orig0$ncopy);
  94.                     array_splice($e2->final0$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->orig0$norig);
  103.                         array_splice($e2->orig0$norig);
  104.                         $bb->input($orig);
  105.                     }
  106.  
  107.                     if (is_a($e1'Text_Diff_Op_copy')) {
  108.                         $bb->out1(array_splice($e1->final0$norig));
  109.                     }
  110.  
  111.                     if (is_a($e2'Text_Diff_Op_copy')) {
  112.                         $bb->out2(array_splice($e2->final0$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.  * @access  private
  140.  */
  141. class Text_Diff3_Op {
  142.  
  143.     function Text_Diff3_Op($orig = false$final1 = false$final2 = false)
  144.     {
  145.         $this->orig $orig $orig : array();
  146.         $this->final1 $final1 $final1 : array();
  147.         $this->final2 $final2 $final2 : array();
  148.     }
  149.  
  150.     function merged()
  151.     {
  152.         if (!isset($this->_merged)) {
  153.             if ($this->final1 === $this->final2{
  154.                 $this->_merged &$this->final1;
  155.             elseif ($this->final1 === $this->orig{
  156.                 $this->_merged &$this->final2;
  157.             elseif ($this->final2 === $this->orig{
  158.                 $this->_merged &$this->final1;
  159.             else {
  160.                 $this->_merged = false;
  161.             }
  162.         }
  163.  
  164.         return $this->_merged;
  165.     }
  166.  
  167.     function isConflict()
  168.     {
  169.         return $this->merged(=== false;
  170.     }
  171.  
  172. }
  173.  
  174. /**
  175.  * @package Text_Diff
  176.  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
  177.  * @access  private
  178.  */
  179. class Text_Diff3_Op_copy extends Text_Diff3_Op {
  180.  
  181.     function Text_Diff3_Op_Copy($lines = false)
  182.     {
  183.         $this->orig $lines $lines : array();
  184.         $this->final1 &$this->orig;
  185.         $this->final2 &$this->orig;
  186.     }
  187.  
  188.     function merged()
  189.     {
  190.         return $this->orig;
  191.     }
  192.  
  193.     function isConflict()
  194.     {
  195.         return false;
  196.     }
  197.  
  198. }
  199.  
  200. /**
  201.  * @package Text_Diff
  202.  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
  203.  * @access  private
  204.  */
  205. class Text_Diff3_BlockBuilder {
  206.  
  207.     function Text_Diff3_BlockBuilder()
  208.     {
  209.         $this->_init();
  210.     }
  211.  
  212.     function input($lines)
  213.     {
  214.         if ($lines{
  215.             $this->_append($this->orig$lines);
  216.         }
  217.     }
  218.  
  219.     function out1($lines)
  220.     {
  221.         if ($lines{
  222.             $this->_append($this->final1$lines);
  223.         }
  224.     }
  225.  
  226.     function out2($lines)
  227.     {
  228.         if ($lines{
  229.             $this->_append($this->final2$lines);
  230.         }
  231.     }
  232.  
  233.     function isEmpty()
  234.     {
  235.         return !$this->orig && !$this->final1 && !$this->final2;
  236.     }
  237.  
  238.     function finish()
  239.     {
  240.         if ($this->isEmpty()) {
  241.             return false;
  242.         else {
  243.             $edit &new Text_Diff3_Op($this->orig$this->final1$this->final2);
  244.             $this->_init();
  245.             return $edit;
  246.         }
  247.     }
  248.  
  249.     function _init()
  250.     {
  251.         $this->orig $this->final1 $this->final2 = array();
  252.     }
  253.  
  254.     function _append(&$array$lines)
  255.     {
  256.         array_splice($arraysizeof($array)0$lines);
  257.     }
  258.  
  259. }

Documentation generated on Mon, 11 Mar 2019 14:20:29 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.