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.3 2005/06/23 19:40:18 selsky 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 
  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.  *
  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.  *
  179.  * @access private
  180.  */
  181. class Text_Diff3_Op_copy extends Text_Diff3_Op {
  182.  
  183.     function Text_Diff3_Op_Copy($lines = false)
  184.     {
  185.         $this->orig $lines $lines : array();
  186.         $this->final1 &$this->orig;
  187.         $this->final2 &$this->orig;
  188.     }
  189.  
  190.     function merged()
  191.     {
  192.         return $this->orig;
  193.     }
  194.  
  195.     function isConflict()
  196.     {
  197.         return false;
  198.     }
  199.  
  200. }
  201.  
  202. /**
  203.  * @package Text_Diff
  204.  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
  205.  *
  206.  * @access private
  207.  */
  208. class Text_Diff3_BlockBuilder {
  209.  
  210.     function Text_Diff3_BlockBuilder()
  211.     {
  212.         $this->_init();
  213.     }
  214.  
  215.     function input($lines)
  216.     {
  217.         if ($lines{
  218.             $this->_append($this->orig$lines);
  219.         }
  220.     }
  221.  
  222.     function out1($lines)
  223.     {
  224.         if ($lines{
  225.             $this->_append($this->final1$lines);
  226.         }
  227.     }
  228.  
  229.     function out2($lines)
  230.     {
  231.         if ($lines{
  232.             $this->_append($this->final2$lines);
  233.         }
  234.     }
  235.  
  236.     function isEmpty()
  237.     {
  238.         return !$this->orig && !$this->final1 && !$this->final2;
  239.     }
  240.  
  241.     function finish()
  242.     {
  243.         if ($this->isEmpty()) {
  244.             return false;
  245.         else {
  246.             $edit &new Text_Diff3_Op($this->orig$this->final1$this->final2);
  247.             $this->_init();
  248.             return $edit;
  249.         }
  250.     }
  251.  
  252.     function _init()
  253.     {
  254.         $this->orig $this->final1 $this->final2 = array();
  255.     }
  256.  
  257.     function _append(&$array$lines)
  258.     {
  259.         array_splice($arraysizeof($array)0$lines);
  260.     }
  261.  
  262. }

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