<?php
function doCharDiff($from_text, $to_text)
{
$result = [];
$jobs = [[0, strlen($from_text), 0, strlen($to_text)]];
while ($job = array_pop($jobs))
{
// get the segments which must be diff'ed
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
$from_segment_len = $from_segment_end - $from_segment_start;
$to_segment_len = $to_segment_end - $to_segment_start;
// catch easy cases first
if (!$from_segment_len || !$to_segment_len)
{
if ($from_segment_len)
$result[$from_segment_start * 4 + 0] = new FineDiffDeleteOp($from_segment_len);
else if ($to_segment_len)
$result[$from_segment_start * 4 + 1] = new FineDiffInsertOp(substr($to_text, $to_segment_start, $to_segment_len));
continue;
}
if ($from_segment_len >= $to_segment_len)
{
$copy_len = $to_segment_len;
while ($copy_len)
{
$to_copy_start = $to_segment_start;
$to_copy_start_max = $to_segment_end - $copy_len;
while ($to_copy_start <= $to_copy_start_max)
{
$from_copy_start = strpos(substr($from_text, $from_segment_start, $from_segment_len), substr($to_text, $to_copy_start, $copy_len));
if ($from_copy_start !== false)
{
$from_copy_start += $from_segment_start;
break 2;
}
$to_copy_start++;
}
$copy_len--;
}
}
else
{
$copy_len = $from_segment_len;
while ($copy_len)
{
$from_copy_start = $from_segment_start;
$from_copy_start_max = $from_segment_end - $copy_len;
while ($from_copy_start <= $from_copy_start_max)
{
$to_copy_start = strpos(substr($to_text, $to_segment_start, $to_segment_len), substr($from_text, $from_copy_start, $copy_len));
if ($to_copy_start !== false)
{
$to_copy_start += $to_segment_start;
break 2;
}
$from_copy_start++;
}
$copy_len--;
}
}
// match found
if ($copy_len)
{
$jobs[] = [$from_segment_start, $from_copy_start, $to_segment_start, $to_copy_start];
$result[$from_copy_start * 4 + 2] = new FineDiffCopyOp($copy_len);
$jobs[] = [$from_copy_start + $copy_len, $from_segment_end, $to_copy_start + $copy_len, $to_segment_end];
}
// no match, so delete all, insert all
else
{
$result[$from_segment_start * 4] = new FineDiffReplaceOp($from_segment_len, substr($to_text, $to_segment_start, $to_segment_len));
}
}
ksort($result, SORT_NUMERIC);
return array_values($result);
}
preferences:
37.98 ms | 402 KiB | 5 Q