Edit File by line
/home/barbar84/public_h.../wp-inclu.../Text/Diff/Engine
File: native.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* Class used internally by Text_Diff to actually compute the diffs.
[2] Fix | Delete
*
[3] Fix | Delete
* This class is implemented using native PHP code.
[4] Fix | Delete
*
[5] Fix | Delete
* The algorithm used here is mostly lifted from the perl module
[6] Fix | Delete
* Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
[7] Fix | Delete
* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
[8] Fix | Delete
*
[9] Fix | Delete
* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html
[10] Fix | Delete
*
[11] Fix | Delete
* Some ideas (and a bit of code) are taken from analyze.c, of GNU
[12] Fix | Delete
* diffutils-2.7, which can be found at:
[13] Fix | Delete
* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
[14] Fix | Delete
*
[15] Fix | Delete
* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from
[16] Fix | Delete
* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this
[17] Fix | Delete
* code was written by him, and is used/adapted with his permission.
[18] Fix | Delete
*
[19] Fix | Delete
* Copyright 2004-2010 The Horde Project (http://www.horde.org/)
[20] Fix | Delete
*
[21] Fix | Delete
* See the enclosed file COPYING for license information (LGPL). If you did
[22] Fix | Delete
* not receive this file, see http://opensource.org/licenses/lgpl-license.php.
[23] Fix | Delete
*
[24] Fix | Delete
* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
[25] Fix | Delete
* @package Text_Diff
[26] Fix | Delete
*/
[27] Fix | Delete
class Text_Diff_Engine_native {
[28] Fix | Delete
[29] Fix | Delete
function diff($from_lines, $to_lines)
[30] Fix | Delete
{
[31] Fix | Delete
array_walk($from_lines, array('Text_Diff', 'trimNewlines'));
[32] Fix | Delete
array_walk($to_lines, array('Text_Diff', 'trimNewlines'));
[33] Fix | Delete
[34] Fix | Delete
$n_from = count($from_lines);
[35] Fix | Delete
$n_to = count($to_lines);
[36] Fix | Delete
[37] Fix | Delete
$this->xchanged = $this->ychanged = array();
[38] Fix | Delete
$this->xv = $this->yv = array();
[39] Fix | Delete
$this->xind = $this->yind = array();
[40] Fix | Delete
unset($this->seq);
[41] Fix | Delete
unset($this->in_seq);
[42] Fix | Delete
unset($this->lcs);
[43] Fix | Delete
[44] Fix | Delete
// Skip leading common lines.
[45] Fix | Delete
for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
[46] Fix | Delete
if ($from_lines[$skip] !== $to_lines[$skip]) {
[47] Fix | Delete
break;
[48] Fix | Delete
}
[49] Fix | Delete
$this->xchanged[$skip] = $this->ychanged[$skip] = false;
[50] Fix | Delete
}
[51] Fix | Delete
[52] Fix | Delete
// Skip trailing common lines.
[53] Fix | Delete
$xi = $n_from; $yi = $n_to;
[54] Fix | Delete
for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) {
[55] Fix | Delete
if ($from_lines[$xi] !== $to_lines[$yi]) {
[56] Fix | Delete
break;
[57] Fix | Delete
}
[58] Fix | Delete
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
[59] Fix | Delete
}
[60] Fix | Delete
[61] Fix | Delete
// Ignore lines which do not exist in both files.
[62] Fix | Delete
for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
[63] Fix | Delete
$xhash[$from_lines[$xi]] = 1;
[64] Fix | Delete
}
[65] Fix | Delete
for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
[66] Fix | Delete
$line = $to_lines[$yi];
[67] Fix | Delete
if (($this->ychanged[$yi] = empty($xhash[$line]))) {
[68] Fix | Delete
continue;
[69] Fix | Delete
}
[70] Fix | Delete
$yhash[$line] = 1;
[71] Fix | Delete
$this->yv[] = $line;
[72] Fix | Delete
$this->yind[] = $yi;
[73] Fix | Delete
}
[74] Fix | Delete
for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
[75] Fix | Delete
$line = $from_lines[$xi];
[76] Fix | Delete
if (($this->xchanged[$xi] = empty($yhash[$line]))) {
[77] Fix | Delete
continue;
[78] Fix | Delete
}
[79] Fix | Delete
$this->xv[] = $line;
[80] Fix | Delete
$this->xind[] = $xi;
[81] Fix | Delete
}
[82] Fix | Delete
[83] Fix | Delete
// Find the LCS.
[84] Fix | Delete
$this->_compareseq(0, count($this->xv), 0, count($this->yv));
[85] Fix | Delete
[86] Fix | Delete
// Merge edits when possible.
[87] Fix | Delete
$this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged);
[88] Fix | Delete
$this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged);
[89] Fix | Delete
[90] Fix | Delete
// Compute the edit operations.
[91] Fix | Delete
$edits = array();
[92] Fix | Delete
$xi = $yi = 0;
[93] Fix | Delete
while ($xi < $n_from || $yi < $n_to) {
[94] Fix | Delete
assert($yi < $n_to || $this->xchanged[$xi]);
[95] Fix | Delete
assert($xi < $n_from || $this->ychanged[$yi]);
[96] Fix | Delete
[97] Fix | Delete
// Skip matching "snake".
[98] Fix | Delete
$copy = array();
[99] Fix | Delete
while ($xi < $n_from && $yi < $n_to
[100] Fix | Delete
&& !$this->xchanged[$xi] && !$this->ychanged[$yi]) {
[101] Fix | Delete
$copy[] = $from_lines[$xi++];
[102] Fix | Delete
++$yi;
[103] Fix | Delete
}
[104] Fix | Delete
if ($copy) {
[105] Fix | Delete
$edits[] = new Text_Diff_Op_copy($copy);
[106] Fix | Delete
}
[107] Fix | Delete
[108] Fix | Delete
// Find deletes & adds.
[109] Fix | Delete
$delete = array();
[110] Fix | Delete
while ($xi < $n_from && $this->xchanged[$xi]) {
[111] Fix | Delete
$delete[] = $from_lines[$xi++];
[112] Fix | Delete
}
[113] Fix | Delete
[114] Fix | Delete
$add = array();
[115] Fix | Delete
while ($yi < $n_to && $this->ychanged[$yi]) {
[116] Fix | Delete
$add[] = $to_lines[$yi++];
[117] Fix | Delete
}
[118] Fix | Delete
[119] Fix | Delete
if ($delete && $add) {
[120] Fix | Delete
$edits[] = new Text_Diff_Op_change($delete, $add);
[121] Fix | Delete
} elseif ($delete) {
[122] Fix | Delete
$edits[] = new Text_Diff_Op_delete($delete);
[123] Fix | Delete
} elseif ($add) {
[124] Fix | Delete
$edits[] = new Text_Diff_Op_add($add);
[125] Fix | Delete
}
[126] Fix | Delete
}
[127] Fix | Delete
[128] Fix | Delete
return $edits;
[129] Fix | Delete
}
[130] Fix | Delete
[131] Fix | Delete
/**
[132] Fix | Delete
* Divides the Largest Common Subsequence (LCS) of the sequences (XOFF,
[133] Fix | Delete
* XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized
[134] Fix | Delete
* segments.
[135] Fix | Delete
*
[136] Fix | Delete
* Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of
[137] Fix | Delete
* NCHUNKS+1 (X, Y) indexes giving the diving points between sub
[138] Fix | Delete
* sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1),
[139] Fix | Delete
* the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) ==
[140] Fix | Delete
* (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
[141] Fix | Delete
*
[142] Fix | Delete
* This function assumes that the first lines of the specified portions of
[143] Fix | Delete
* the two files do not match, and likewise that the last lines do not
[144] Fix | Delete
* match. The caller must trim matching lines from the beginning and end
[145] Fix | Delete
* of the portions it is going to specify.
[146] Fix | Delete
*/
[147] Fix | Delete
function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks)
[148] Fix | Delete
{
[149] Fix | Delete
$flip = false;
[150] Fix | Delete
[151] Fix | Delete
if ($xlim - $xoff > $ylim - $yoff) {
[152] Fix | Delete
/* Things seems faster (I'm not sure I understand why) when the
[153] Fix | Delete
* shortest sequence is in X. */
[154] Fix | Delete
$flip = true;
[155] Fix | Delete
list ($xoff, $xlim, $yoff, $ylim)
[156] Fix | Delete
= array($yoff, $ylim, $xoff, $xlim);
[157] Fix | Delete
}
[158] Fix | Delete
[159] Fix | Delete
if ($flip) {
[160] Fix | Delete
for ($i = $ylim - 1; $i >= $yoff; $i--) {
[161] Fix | Delete
$ymatches[$this->xv[$i]][] = $i;
[162] Fix | Delete
}
[163] Fix | Delete
} else {
[164] Fix | Delete
for ($i = $ylim - 1; $i >= $yoff; $i--) {
[165] Fix | Delete
$ymatches[$this->yv[$i]][] = $i;
[166] Fix | Delete
}
[167] Fix | Delete
}
[168] Fix | Delete
[169] Fix | Delete
$this->lcs = 0;
[170] Fix | Delete
$this->seq[0]= $yoff - 1;
[171] Fix | Delete
$this->in_seq = array();
[172] Fix | Delete
$ymids[0] = array();
[173] Fix | Delete
[174] Fix | Delete
$numer = $xlim - $xoff + $nchunks - 1;
[175] Fix | Delete
$x = $xoff;
[176] Fix | Delete
for ($chunk = 0; $chunk < $nchunks; $chunk++) {
[177] Fix | Delete
if ($chunk > 0) {
[178] Fix | Delete
for ($i = 0; $i <= $this->lcs; $i++) {
[179] Fix | Delete
$ymids[$i][$chunk - 1] = $this->seq[$i];
[180] Fix | Delete
}
[181] Fix | Delete
}
[182] Fix | Delete
[183] Fix | Delete
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks);
[184] Fix | Delete
for (; $x < $x1; $x++) {
[185] Fix | Delete
$line = $flip ? $this->yv[$x] : $this->xv[$x];
[186] Fix | Delete
if (empty($ymatches[$line])) {
[187] Fix | Delete
continue;
[188] Fix | Delete
}
[189] Fix | Delete
$matches = $ymatches[$line];
[190] Fix | Delete
reset($matches);
[191] Fix | Delete
while ($y = current($matches)) {
[192] Fix | Delete
if (empty($this->in_seq[$y])) {
[193] Fix | Delete
$k = $this->_lcsPos($y);
[194] Fix | Delete
assert($k > 0);
[195] Fix | Delete
$ymids[$k] = $ymids[$k - 1];
[196] Fix | Delete
break;
[197] Fix | Delete
}
[198] Fix | Delete
next($matches);
[199] Fix | Delete
}
[200] Fix | Delete
while ($y = current($matches)) {
[201] Fix | Delete
if ($y > $this->seq[$k - 1]) {
[202] Fix | Delete
assert($y <= $this->seq[$k]);
[203] Fix | Delete
/* Optimization: this is a common case: next match is
[204] Fix | Delete
* just replacing previous match. */
[205] Fix | Delete
$this->in_seq[$this->seq[$k]] = false;
[206] Fix | Delete
$this->seq[$k] = $y;
[207] Fix | Delete
$this->in_seq[$y] = 1;
[208] Fix | Delete
} elseif (empty($this->in_seq[$y])) {
[209] Fix | Delete
$k = $this->_lcsPos($y);
[210] Fix | Delete
assert($k > 0);
[211] Fix | Delete
$ymids[$k] = $ymids[$k - 1];
[212] Fix | Delete
}
[213] Fix | Delete
next($matches);
[214] Fix | Delete
}
[215] Fix | Delete
}
[216] Fix | Delete
}
[217] Fix | Delete
[218] Fix | Delete
$seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
[219] Fix | Delete
$ymid = $ymids[$this->lcs];
[220] Fix | Delete
for ($n = 0; $n < $nchunks - 1; $n++) {
[221] Fix | Delete
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
[222] Fix | Delete
$y1 = $ymid[$n] + 1;
[223] Fix | Delete
$seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
[224] Fix | Delete
}
[225] Fix | Delete
$seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
[226] Fix | Delete
[227] Fix | Delete
return array($this->lcs, $seps);
[228] Fix | Delete
}
[229] Fix | Delete
[230] Fix | Delete
function _lcsPos($ypos)
[231] Fix | Delete
{
[232] Fix | Delete
$end = $this->lcs;
[233] Fix | Delete
if ($end == 0 || $ypos > $this->seq[$end]) {
[234] Fix | Delete
$this->seq[++$this->lcs] = $ypos;
[235] Fix | Delete
$this->in_seq[$ypos] = 1;
[236] Fix | Delete
return $this->lcs;
[237] Fix | Delete
}
[238] Fix | Delete
[239] Fix | Delete
$beg = 1;
[240] Fix | Delete
while ($beg < $end) {
[241] Fix | Delete
$mid = (int)(($beg + $end) / 2);
[242] Fix | Delete
if ($ypos > $this->seq[$mid]) {
[243] Fix | Delete
$beg = $mid + 1;
[244] Fix | Delete
} else {
[245] Fix | Delete
$end = $mid;
[246] Fix | Delete
}
[247] Fix | Delete
}
[248] Fix | Delete
[249] Fix | Delete
assert($ypos != $this->seq[$end]);
[250] Fix | Delete
[251] Fix | Delete
$this->in_seq[$this->seq[$end]] = false;
[252] Fix | Delete
$this->seq[$end] = $ypos;
[253] Fix | Delete
$this->in_seq[$ypos] = 1;
[254] Fix | Delete
return $end;
[255] Fix | Delete
}
[256] Fix | Delete
[257] Fix | Delete
/**
[258] Fix | Delete
* Finds LCS of two sequences.
[259] Fix | Delete
*
[260] Fix | Delete
* The results are recorded in the vectors $this->{x,y}changed[], by
[261] Fix | Delete
* storing a 1 in the element for each line that is an insertion or
[262] Fix | Delete
* deletion (ie. is not in the LCS).
[263] Fix | Delete
*
[264] Fix | Delete
* The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1.
[265] Fix | Delete
*
[266] Fix | Delete
* Note that XLIM, YLIM are exclusive bounds. All line numbers are
[267] Fix | Delete
* origin-0 and discarded lines are not counted.
[268] Fix | Delete
*/
[269] Fix | Delete
function _compareseq ($xoff, $xlim, $yoff, $ylim)
[270] Fix | Delete
{
[271] Fix | Delete
/* Slide down the bottom initial diagonal. */
[272] Fix | Delete
while ($xoff < $xlim && $yoff < $ylim
[273] Fix | Delete
&& $this->xv[$xoff] == $this->yv[$yoff]) {
[274] Fix | Delete
++$xoff;
[275] Fix | Delete
++$yoff;
[276] Fix | Delete
}
[277] Fix | Delete
[278] Fix | Delete
/* Slide up the top initial diagonal. */
[279] Fix | Delete
while ($xlim > $xoff && $ylim > $yoff
[280] Fix | Delete
&& $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) {
[281] Fix | Delete
--$xlim;
[282] Fix | Delete
--$ylim;
[283] Fix | Delete
}
[284] Fix | Delete
[285] Fix | Delete
if ($xoff == $xlim || $yoff == $ylim) {
[286] Fix | Delete
$lcs = 0;
[287] Fix | Delete
} else {
[288] Fix | Delete
/* This is ad hoc but seems to work well. $nchunks =
[289] Fix | Delete
* sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks =
[290] Fix | Delete
* max(2,min(8,(int)$nchunks)); */
[291] Fix | Delete
$nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
[292] Fix | Delete
list($lcs, $seps)
[293] Fix | Delete
= $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
[294] Fix | Delete
}
[295] Fix | Delete
[296] Fix | Delete
if ($lcs == 0) {
[297] Fix | Delete
/* X and Y sequences have no common subsequence: mark all
[298] Fix | Delete
* changed. */
[299] Fix | Delete
while ($yoff < $ylim) {
[300] Fix | Delete
$this->ychanged[$this->yind[$yoff++]] = 1;
[301] Fix | Delete
}
[302] Fix | Delete
while ($xoff < $xlim) {
[303] Fix | Delete
$this->xchanged[$this->xind[$xoff++]] = 1;
[304] Fix | Delete
}
[305] Fix | Delete
} else {
[306] Fix | Delete
/* Use the partitions to split this problem into subproblems. */
[307] Fix | Delete
reset($seps);
[308] Fix | Delete
$pt1 = $seps[0];
[309] Fix | Delete
while ($pt2 = next($seps)) {
[310] Fix | Delete
$this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
[311] Fix | Delete
$pt1 = $pt2;
[312] Fix | Delete
}
[313] Fix | Delete
}
[314] Fix | Delete
}
[315] Fix | Delete
[316] Fix | Delete
/**
[317] Fix | Delete
* Adjusts inserts/deletes of identical lines to join changes as much as
[318] Fix | Delete
* possible.
[319] Fix | Delete
*
[320] Fix | Delete
* We do something when a run of changed lines include a line at one end
[321] Fix | Delete
* and has an excluded, identical line at the other. We are free to
[322] Fix | Delete
* choose which identical line is included. `compareseq' usually chooses
[323] Fix | Delete
* the one at the beginning, but usually it is cleaner to consider the
[324] Fix | Delete
* following identical line to be the "change".
[325] Fix | Delete
*
[326] Fix | Delete
* This is extracted verbatim from analyze.c (GNU diffutils-2.7).
[327] Fix | Delete
*/
[328] Fix | Delete
function _shiftBoundaries($lines, &$changed, $other_changed)
[329] Fix | Delete
{
[330] Fix | Delete
$i = 0;
[331] Fix | Delete
$j = 0;
[332] Fix | Delete
[333] Fix | Delete
assert(count($lines) == count($changed));
[334] Fix | Delete
$len = count($lines);
[335] Fix | Delete
$other_len = count($other_changed);
[336] Fix | Delete
[337] Fix | Delete
while (1) {
[338] Fix | Delete
/* Scan forward to find the beginning of another run of
[339] Fix | Delete
* changes. Also keep track of the corresponding point in the
[340] Fix | Delete
* other file.
[341] Fix | Delete
*
[342] Fix | Delete
* Throughout this code, $i and $j are adjusted together so that
[343] Fix | Delete
* the first $i elements of $changed and the first $j elements of
[344] Fix | Delete
* $other_changed both contain the same number of zeros (unchanged
[345] Fix | Delete
* lines).
[346] Fix | Delete
*
[347] Fix | Delete
* Furthermore, $j is always kept so that $j == $other_len or
[348] Fix | Delete
* $other_changed[$j] == false. */
[349] Fix | Delete
while ($j < $other_len && $other_changed[$j]) {
[350] Fix | Delete
$j++;
[351] Fix | Delete
}
[352] Fix | Delete
[353] Fix | Delete
while ($i < $len && ! $changed[$i]) {
[354] Fix | Delete
assert($j < $other_len && ! $other_changed[$j]);
[355] Fix | Delete
$i++; $j++;
[356] Fix | Delete
while ($j < $other_len && $other_changed[$j]) {
[357] Fix | Delete
$j++;
[358] Fix | Delete
}
[359] Fix | Delete
}
[360] Fix | Delete
[361] Fix | Delete
if ($i == $len) {
[362] Fix | Delete
break;
[363] Fix | Delete
}
[364] Fix | Delete
[365] Fix | Delete
$start = $i;
[366] Fix | Delete
[367] Fix | Delete
/* Find the end of this run of changes. */
[368] Fix | Delete
while (++$i < $len && $changed[$i]) {
[369] Fix | Delete
continue;
[370] Fix | Delete
}
[371] Fix | Delete
[372] Fix | Delete
do {
[373] Fix | Delete
/* Record the length of this run of changes, so that we can
[374] Fix | Delete
* later determine whether the run has grown. */
[375] Fix | Delete
$runlength = $i - $start;
[376] Fix | Delete
[377] Fix | Delete
/* Move the changed region back, so long as the previous
[378] Fix | Delete
* unchanged line matches the last changed one. This merges
[379] Fix | Delete
* with previous changed regions. */
[380] Fix | Delete
while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) {
[381] Fix | Delete
$changed[--$start] = 1;
[382] Fix | Delete
$changed[--$i] = false;
[383] Fix | Delete
while ($start > 0 && $changed[$start - 1]) {
[384] Fix | Delete
$start--;
[385] Fix | Delete
}
[386] Fix | Delete
assert($j > 0);
[387] Fix | Delete
while ($other_changed[--$j]) {
[388] Fix | Delete
continue;
[389] Fix | Delete
}
[390] Fix | Delete
assert($j >= 0 && !$other_changed[$j]);
[391] Fix | Delete
}
[392] Fix | Delete
[393] Fix | Delete
/* Set CORRESPONDING to the end of the changed run, at the
[394] Fix | Delete
* last point where it corresponds to a changed run in the
[395] Fix | Delete
* other file. CORRESPONDING == LEN means no such point has
[396] Fix | Delete
* been found. */
[397] Fix | Delete
$corresponding = $j < $other_len ? $i : $len;
[398] Fix | Delete
[399] Fix | Delete
/* Move the changed region forward, so long as the first
[400] Fix | Delete
* changed line matches the following unchanged one. This
[401] Fix | Delete
* merges with following changed regions. Do this second, so
[402] Fix | Delete
* that if there are no merges, the changed region is moved
[403] Fix | Delete
* forward as far as possible. */
[404] Fix | Delete
while ($i < $len && $lines[$start] == $lines[$i]) {
[405] Fix | Delete
$changed[$start++] = false;
[406] Fix | Delete
$changed[$i++] = 1;
[407] Fix | Delete
while ($i < $len && $changed[$i]) {
[408] Fix | Delete
$i++;
[409] Fix | Delete
}
[410] Fix | Delete
[411] Fix | Delete
assert($j < $other_len && ! $other_changed[$j]);
[412] Fix | Delete
$j++;
[413] Fix | Delete
if ($j < $other_len && $other_changed[$j]) {
[414] Fix | Delete
$corresponding = $i;
[415] Fix | Delete
while ($j < $other_len && $other_changed[$j]) {
[416] Fix | Delete
$j++;
[417] Fix | Delete
}
[418] Fix | Delete
}
[419] Fix | Delete
}
[420] Fix | Delete
} while ($runlength != $i - $start);
[421] Fix | Delete
[422] Fix | Delete
/* If possible, move the fully-merged run of changes back to a
[423] Fix | Delete
* corresponding run in the other file. */
[424] Fix | Delete
while ($corresponding < $i) {
[425] Fix | Delete
$changed[--$start] = 1;
[426] Fix | Delete
$changed[--$i] = 0;
[427] Fix | Delete
assert($j > 0);
[428] Fix | Delete
while ($other_changed[--$j]) {
[429] Fix | Delete
continue;
[430] Fix | Delete
}
[431] Fix | Delete
assert($j >= 0 && !$other_changed[$j]);
[432] Fix | Delete
}
[433] Fix | Delete
}
[434] Fix | Delete
}
[435] Fix | Delete
[436] Fix | Delete
}
[437] Fix | Delete
[438] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function