public function splitMax(&$patches)
{
$patchSize = $this->getMatch()->getMaxBits();
if ($patchSize == 0) {
// TODO PHP has fixed size int, so this case isn't relevant.
return;
}
for ($i = 0; $i < count($patches); $i++) {
if ($patches[$i]->getLength1() <= $patchSize) {
continue;
}
$bigPatch = $patches[$i];
// Remove the big old patch.
array_splice($patches, $i, 1);
$i--;
$start1 = $bigPatch->getStart1();
$start2 = $bigPatch->getStart2();
$preContext = '';
$bigPatchDiffs = $bigPatch->getChanges();
while (count($bigPatchDiffs)) {
// Create one of several smaller patches.
$empty = true;
$patch = new PatchObject();
$preContextLen = mb_strlen($preContext);
$patch->setStart1($start1 - $preContextLen);
$patch->setStart2($start2 - $preContextLen);
if ($preContext != '') {
$patch->setLength1($preContextLen);
$patch->setLength2($preContextLen);
$patch->appendChanges(array(Diff::EQUAL, $preContext));
}
while (count($bigPatchDiffs) && $patch->getLength1() < $patchSize - $this->getMargin()) {
list($diffType, $diffText) = $bigPatchDiffs[0];
$diffTextLen = mb_strlen($diffText);
if ($diffType == Diff::INSERT) {
// Insertions are harmless.
$patch->setLength2($patch->getLength2() + $diffTextLen);
$start2 += $diffTextLen;
$patch->appendChanges(array_shift($bigPatchDiffs));
$empty = false;
} elseif ($diffType == Diff::DELETE && ($patchDiffs = $patch->getChanges()) && count($patchDiffs) == 1 && $patchDiffs[0][0] == Diff::EQUAL && 2 * $patchSize < $diffTextLen) {
// This is a large deletion. Let it pass in one chunk.
$patch->setLength1($patch->getLength1() + $diffTextLen);
$start1 += $diffTextLen;
array_shift($bigPatchDiffs);
$patch->appendChanges(array($diffType, $diffText));
$empty = false;
} else {
// Deletion or equality. Only take as much as we can stomach.
$diffText = mb_substr($diffText, 0, $patchSize - $patch->getLength1() - $this->getMargin());
$diffTextLen = mb_strlen($diffText);
$patch->setLength1($patch->getLength1() + $diffTextLen);
$start1 += $diffTextLen;
if ($diffType == Diff::EQUAL) {
$patch->setLength2($patch->getLength2() + $diffTextLen);
$start2 += $diffTextLen;
} else {
$empty = false;
}
if ($diffText == $bigPatchDiffs[0][1]) {
array_shift($bigPatchDiffs);
} else {
$bigPatchDiffs[0][1] = mb_substr($bigPatchDiffs[0][1], $diffTextLen);
}
$patch->appendChanges(array($diffType, $diffText));
}
}
// Compute the head context for the next patch.
$diff = $this->getDiff();
$diff->setChanges($patch->getChanges());
$preContext = $diff->text2();
$preContext = mb_substr($preContext, -$this->getMargin());
// Append the end context for this patch.
$diff->setChanges($bigPatchDiffs);
$postContext = $diff->text1();
$postContext = mb_substr($postContext, 0, $this->getMargin());
if ($postContext != '') {
$patch->setLength1($patch->getLength1() + mb_strlen($postContext));
$patch->setLength2($patch->getLength2() + mb_strlen($postContext));
if (($patchDiffs = $patch->getChanges()) && count($patchDiffs) && $patchDiffs[count($patchDiffs) - 1][0] == Diff::EQUAL) {
$patchDiffs[count($patchDiffs) - 1][1] .= $postContext;
$patch->setChanges($patchDiffs);
} else {
$patch->appendChanges(array(Diff::EQUAL, $postContext));
}
}
if (!$empty) {
$i++;
array_splice($patches, $i, 0, array($patch));
}
}
}
}