-
+ 1DA38D50411AB980390921575EA0794FF271C00A319602DE84BB08EB7F8D02E2FF08DC0154F4E1351E9895D713FBD3C24EB21B97AA29A15D035D8D958964C9D3
mp-wp/wp-includes/Text/Diff/Engine/string.php
(0 . 0)(1 . 232)
69698 <?php
69699 /**
69700 * Parses unified or context diffs output from eg. the diff utility.
69701 *
69702 * Example:
69703 * <code>
69704 * $patch = file_get_contents('example.patch');
69705 * $diff = new Text_Diff('string', array($patch));
69706 * $renderer = new Text_Diff_Renderer_inline();
69707 * echo $renderer->render($diff);
69708 * </code>
69709 *
69710 * $Horde: framework/Text_Diff/Diff/Engine/string.php,v 1.7 2008/01/04 10:07:50 jan Exp $
69711 *
69712 *
69713 * See the enclosed file COPYING for license information (LGPL). If you did
69714 * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
69715 *
69716 * @author Orjan Persson <o@42mm.org>
69717 * @package Text_Diff
69718 * @since 0.2.0
69719 */
69720 class Text_Diff_Engine_string {
69721
69722 /**
69723 * Parses a unified or context diff.
69724 *
69725 * First param contains the whole diff and the second can be used to force
69726 * a specific diff type. If the second parameter is 'autodetect', the
69727 * diff will be examined to find out which type of diff this is.
69728 *
69729 * @param string $diff The diff content.
69730 * @param string $mode The diff mode of the content in $diff. One of
69731 * 'context', 'unified', or 'autodetect'.
69732 *
69733 * @return array List of all diff operations.
69734 */
69735 function diff($diff, $mode = 'autodetect')
69736 {
69737 if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') {
69738 return PEAR::raiseError('Type of diff is unsupported');
69739 }
69740
69741 if ($mode == 'autodetect') {
69742 $context = strpos($diff, '***');
69743 $unified = strpos($diff, '---');
69744 if ($context === $unified) {
69745 return PEAR::raiseError('Type of diff could not be detected');
69746 } elseif ($context === false || $context === false) {
69747 $mode = $context !== false ? 'context' : 'unified';
69748 } else {
69749 $mode = $context < $unified ? 'context' : 'unified';
69750 }
69751 }
69752
69753 // split by new line and remove the diff header
69754 $diff = explode("\n", $diff);
69755 array_shift($diff);
69756 array_shift($diff);
69757
69758 if ($mode == 'context') {
69759 return $this->parseContextDiff($diff);
69760 } else {
69761 return $this->parseUnifiedDiff($diff);
69762 }
69763 }
69764
69765 /**
69766 * Parses an array containing the unified diff.
69767 *
69768 * @param array $diff Array of lines.
69769 *
69770 * @return array List of all diff operations.
69771 */
69772 function parseUnifiedDiff($diff)
69773 {
69774 $edits = array();
69775 $end = count($diff) - 1;
69776 for ($i = 0; $i < $end;) {
69777 $diff1 = array();
69778 switch (substr($diff[$i], 0, 1)) {
69779 case ' ':
69780 do {
69781 $diff1[] = substr($diff[$i], 1);
69782 } while (++$i < $end && substr($diff[$i], 0, 1) == ' ');
69783 $edits[] = &new Text_Diff_Op_copy($diff1);
69784 break;
69785
69786 case '+':
69787 // get all new lines
69788 do {
69789 $diff1[] = substr($diff[$i], 1);
69790 } while (++$i < $end && substr($diff[$i], 0, 1) == '+');
69791 $edits[] = &new Text_Diff_Op_add($diff1);
69792 break;
69793
69794 case '-':
69795 // get changed or removed lines
69796 $diff2 = array();
69797 do {
69798 $diff1[] = substr($diff[$i], 1);
69799 } while (++$i < $end && substr($diff[$i], 0, 1) == '-');
69800
69801 while ($i < $end && substr($diff[$i], 0, 1) == '+') {
69802 $diff2[] = substr($diff[$i++], 1);
69803 }
69804 if (count($diff2) == 0) {
69805 $edits[] = &new Text_Diff_Op_delete($diff1);
69806 } else {
69807 $edits[] = &new Text_Diff_Op_change($diff1, $diff2);
69808 }
69809 break;
69810
69811 default:
69812 $i++;
69813 break;
69814 }
69815 }
69816
69817 return $edits;
69818 }
69819
69820 /**
69821 * Parses an array containing the context diff.
69822 *
69823 * @param array $diff Array of lines.
69824 *
69825 * @return array List of all diff operations.
69826 */
69827 function parseContextDiff(&$diff)
69828 {
69829 $edits = array();
69830 $i = $max_i = $j = $max_j = 0;
69831 $end = count($diff) - 1;
69832 while ($i < $end && $j < $end) {
69833 while ($i >= $max_i && $j >= $max_j) {
69834 // Find the boundaries of the diff output of the two files
69835 for ($i = $j;
69836 $i < $end && substr($diff[$i], 0, 3) == '***';
69837 $i++);
69838 for ($max_i = $i;
69839 $max_i < $end && substr($diff[$max_i], 0, 3) != '---';
69840 $max_i++);
69841 for ($j = $max_i;
69842 $j < $end && substr($diff[$j], 0, 3) == '---';
69843 $j++);
69844 for ($max_j = $j;
69845 $max_j < $end && substr($diff[$max_j], 0, 3) != '***';
69846 $max_j++);
69847 }
69848
69849 // find what hasn't been changed
69850 $array = array();
69851 while ($i < $max_i &&
69852 $j < $max_j &&
69853 strcmp($diff[$i], $diff[$j]) == 0) {
69854 $array[] = substr($diff[$i], 2);
69855 $i++;
69856 $j++;
69857 }
69858
69859 while ($i < $max_i && ($max_j-$j) <= 1) {
69860 if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') {
69861 break;
69862 }
69863 $array[] = substr($diff[$i++], 2);
69864 }
69865
69866 while ($j < $max_j && ($max_i-$i) <= 1) {
69867 if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') {
69868 break;
69869 }
69870 $array[] = substr($diff[$j++], 2);
69871 }
69872 if (count($array) > 0) {
69873 $edits[] = &new Text_Diff_Op_copy($array);
69874 }
69875
69876 if ($i < $max_i) {
69877 $diff1 = array();
69878 switch (substr($diff[$i], 0, 1)) {
69879 case '!':
69880 $diff2 = array();
69881 do {
69882 $diff1[] = substr($diff[$i], 2);
69883 if ($j < $max_j && substr($diff[$j], 0, 1) == '!') {
69884 $diff2[] = substr($diff[$j++], 2);
69885 }
69886 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!');
69887 $edits[] = &new Text_Diff_Op_change($diff1, $diff2);
69888 break;
69889
69890 case '+':
69891 do {
69892 $diff1[] = substr($diff[$i], 2);
69893 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+');
69894 $edits[] = &new Text_Diff_Op_add($diff1);
69895 break;
69896
69897 case '-':
69898 do {
69899 $diff1[] = substr($diff[$i], 2);
69900 } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-');
69901 $edits[] = &new Text_Diff_Op_delete($diff1);
69902 break;
69903 }
69904 }
69905
69906 if ($j < $max_j) {
69907 $diff2 = array();
69908 switch (substr($diff[$j], 0, 1)) {
69909 case '+':
69910 do {
69911 $diff2[] = substr($diff[$j++], 2);
69912 } while ($j < $max_j && substr($diff[$j], 0, 1) == '+');
69913 $edits[] = &new Text_Diff_Op_add($diff2);
69914 break;
69915
69916 case '-':
69917 do {
69918 $diff2[] = substr($diff[$j++], 2);
69919 } while ($j < $max_j && substr($diff[$j], 0, 1) == '-');
69920 $edits[] = &new Text_Diff_Op_delete($diff2);
69921 break;
69922 }
69923 }
69924 }
69925
69926 return $edits;
69927 }
69928
69929 }