From 40de03b42d18579e810d78520690a328420c92f1 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 4 Apr 2015 15:46:24 +0000 Subject: [PATCH] enhanced diff finding given two strings in the code diff view. codepot_find_matching_sequences() and codepot_find_longest_matching_sequence() have been added for this --- .../src/codepot/helpers/codepot_helper.php | 114 ++++++++++++++++++ codepot/src/codepot/views/code_diff.php | 72 ++++++++++- 2 files changed, 184 insertions(+), 2 deletions(-) diff --git a/codepot/src/codepot/helpers/codepot_helper.php b/codepot/src/codepot/helpers/codepot_helper.php index 0d1341c3..f1feca3c 100644 --- a/codepot/src/codepot/helpers/codepot_helper.php +++ b/codepot/src/codepot/helpers/codepot_helper.php @@ -142,3 +142,117 @@ if ( !function_exists ('codepot_delete_files')) } } } + +if ( !function_exists ('codepot_find_longest_matching_sequence')) +{ + function codepot_find_longest_matching_sequence ($old, $old_start, $old_len, $new, $new_start, $new_len) + { + $old_end = $old_start + $old_len; + $new_end = $new_start + $new_len; + + $match_start_in_old = $old_start; + $match_start_in_new = $new_start; + $match_len = 0; + + $runs = array (); + for ($i = $old_start; $i < $old_end; $i++) + { + $new_runs = array(); + for ($j = $new_start; $j < $new_end; $j++) + { + if ($old[$i] == $new[$j]) + { + if (isset($runs[$j - 1])) + $new_runs[$j] = $runs[$j - 1] + 1; + else + $new_runs[$j] = 1; + if ($new_runs[$j] > $match_len) + { + $match_len = $new_runs[$j]; + $match_start_in_old = ($i + 1) - $match_len; + $match_start_in_new = ($j + 1) - $match_len; + } + } + } + $runs = $new_runs; + } + + + //print "$match_start_in_old\n"; + //print "$match_start_in_new\n"; + //print "$match_len\n"; + //print "----------------\n"; + + return array ($match_len, $match_start_in_old, $match_start_in_new); + } +} + + +if ( !function_exists ('codepot_find_matching_sequences')) +{ + function codepot_find_matching_sequences ($old, $new) + { + $stack = array (); + $result = array (); + + if (is_array($old) && is_array($new)) + { + $old_size = count($old); + $new_size = count($new); + } + else if (is_string($old) && is_string($new)) + { + $old_size = strlen($old); + $new_size = strlen($new); + } + else + { + return FALSE; + } + + // push the whole range for the initial search. + array_push ($stack, array (0, 0, $old_size, 0, $new_size)); + + while (count($stack) > 0) + { + $item = array_pop($stack); + + if ($item[0] == 0) + { + $old_seg_pos = $item[1]; + $old_seg_len = $item[2]; + $new_seg_pos = $item[3]; + $new_seg_len = $item[4]; + + list ($match_len, $match_start_in_old, $match_start_in_new) = + codepot_find_longest_matching_sequence ($old, $old_seg_pos, $old_seg_len, $new, $new_seg_pos, $new_seg_len); + if ($match_len > 0) + { + // push the back part + $a = $match_start_in_old + $match_len; // beginning of the back part of $old + $b = $old_seg_len - ($a - $old_seg_pos); // length of the back part of $old + $c = $match_start_in_new + $match_len; // beginning of the back part in $new + $d = $new_seg_len - ($c - $new_seg_pos); // length of the back part of $new + if ($b > 0 && $d > 0) array_push ($stack, array (0, $a, $b, $c, $d)); + + // push the longest sequence found to hold it until the front part + // has been processed. + array_push ($stack, array (1, $match_start_in_old, $match_start_in_new, $match_len)); + + // push the front part + $b = $match_start_in_old - $old_seg_pos; // length of the front part of $old + $d = $match_start_in_new - $new_seg_pos; // length of the front part of $new + if ($b > 0 && $d > 0) array_push ($stack, array (0, $old_seg_pos, $b, $new_seg_pos, $d)); + } + } + else + { + // move the result item to the result array + array_push ($result, array_slice ($item, 1, 3)); + } + } + + + return $result; + } +} diff --git a/codepot/src/codepot/views/code_diff.php b/codepot/src/codepot/views/code_diff.php index 2cc4f97d..f7ca7290 100644 --- a/codepot/src/codepot/views/code_diff.php +++ b/codepot/src/codepot/views/code_diff.php @@ -136,6 +136,63 @@ $this->load->view (
$k) + { + $cc .= sprintf ('', $css_class); + $cc .= htmlspecialchars(substr($a, $k, $mp1 - $k)); + $cc .= ''; + } + $cc .= htmlspecialchars(substr($a, $mp1, $ml)); + $k = $mp1 + $ml; + } + if ($k < strlen($a)) + { + $cc .= sprintf ('', $css_class); + $cc .= htmlspecialchars(substr($a, $k)); + $cc .= ''; + } + } + else + { + for ($i = 0; $i < $ms_count; $i++) + { + list($mp1, $mp2, $ml) = $ms[$i]; + if ($mp2 > $k) + { + $cc .= sprintf ('', $css_class); + $cc .= htmlspecialchars(substr($b, $k, $mp2 - $k)); + $cc .= ''; + } + $cc .= htmlspecialchars(substr($b, $mp2, $ml)); + $k = $mp2 + $ml; + } + if ($k < strlen($b)) + { + $cc .= sprintf ('', $css_class); + $cc .= htmlspecialchars(substr($b, $k)); + $cc .= ''; + } + } + + + return $cc; +} + +/* function format_diff ($a, $b, $css_class) { if ($b == '') return htmlspecialchars($a); @@ -183,6 +240,7 @@ function format_diff ($a, $b, $css_class) return $cc; } +*/ //if (!$fullview) if (FALSE) // don't want to delete code for the original diff view. @@ -358,9 +416,14 @@ else print ""; if ($diffclass == 'diffchanged') - $xline = format_diff ($x['rev1line'], $x['rev2line'], 'diffchangedold'); + { + //$xline = format_diff ($x['rev1line'], $x['rev2line'], 'diffchangedold'); + $xline = format_diff2 ($x['rev1line'], $x['rev2line'], 'diffchangedold'); + } else + { $xline = htmlspecialchars($x['rev1line']); + } if ($is_msie && $xline == '') $xline = ' '; print $xline; @@ -407,9 +470,14 @@ else print ""; if ($diffclass == 'diffchanged') - $xline = format_diff ($x['rev2line'], $x['rev1line'], 'diffchangednew'); + { + //$xline = format_diff ($x['rev2line'], $x['rev1line'], 'diffchangednew'); + $xline = format_diff2 ($x['rev1line'], $x['rev2line'], 'diffchangednew'); + } else + { $xline = htmlspecialchars($x['rev2line']); + } if ($is_msie && $xline == '') $xline = ' '; print $xline;