src/Diff.php
protected function compute($text1, $text2, $checklines, $deadline)
    {
        if ($text1 == '') {
            // Just add some text (speedup).
            return array(
                array(self::INSERT, $text2),
            );
        }

        if ($text2 == '') {
            // Just delete some text (speedup).
            return array(
                array(self::DELETE, $text1),
            );
        }

        if (mb_strlen($text1) < mb_strlen($text2)) {
            $shortText = $text1;
            $longText = $text2;
        } else {
            $shortText = $text2;
            $longText = $text1;
        }

        $i = mb_strpos($longText, $shortText);
        if ($i !== false) {
            // Shorter text is inside the longer text (speedup).
            $diffs = array(
                array(self::INSERT, mb_substr($longText, 0, $i)),
                array(self::EQUAL, $shortText),
                array(self::INSERT, mb_substr($longText, $i + mb_strlen($shortText))),
            );
            // Swap insertions for deletions if diff is reversed.
            if (mb_strlen($text2) < mb_strlen($text1)) {
                $diffs[0][0] = self::DELETE;
                $diffs[2][0] = self::DELETE;
            }
            return $diffs;
        }

        if (mb_strlen($shortText) == 1) {
            // Single character string.
            // After the previous speedup, the character can't be an equality.
            $diffs = array(
                array(self::DELETE, $text1),
                array(self::INSERT, $text2),
            );
            return $diffs;
        }

        // Don't risk returning a non-optimal diff if we have unlimited time.
        if ($this->getTimeout() > 0) {
            // Check to see if the problem can be split in two.
            $hm = $this->getToolkit()->halfMatch($text1, $text2);
            if ($hm) {
                // A half-match was found, sort out the return data.
                list($text1_a, $text1_b, $text2_a, $text2_b, $mid_common) = $hm;
                // Send both pairs off for separate processing.
                $diffA = new Diff();
                $diffA->main($text1_a, $text2_a, $checklines, $deadline);
                $diffB = new Diff();
                $diffB->main($text1_b, $text2_b, $checklines, $deadline);
                // Merge the results.
                $diffs = array_merge(
                    $diffA->getChanges(),
                    array(
                        array(self::EQUAL, $mid_common),
                    ),
                    $diffB->getChanges()
                );
                return $diffs;
            }
        }

        if ($checklines
          && mb_strlen($text1) > Diff::LINEMODE_THRESOLD
          && mb_strlen($text2) > Diff::LINEMODE_THRESOLD) {
            return $this->lineMode($text1, $text2, $deadline);
        }

        return $this->bisect($text1, $text2, $deadline);
    }
protected function compute($text1, $text2, $checklines, $deadline)
    {
        if ($text1 == '') {
            // Just add some text (speedup).
            return array(
                array(self::INSERT, $text2),
            );
        }

        if ($text2 == '') {
            // Just delete some text (speedup).
            return array(
                array(self::DELETE, $text1),
            );
        }

        if (mb_strlen($text1) < mb_strlen($text2)) {
            $shortText = $text1;
            $longText = $text2;
        } else {
            $shortText = $text2;
            $longText = $text1;
        }

        $i = mb_strpos($longText, $shortText);
        if ($i !== false) {
            // Shorter text is inside the longer text (speedup).
            $diffs = array(
                array(self::INSERT, mb_substr($longText, 0, $i)),
                array(self::EQUAL, $shortText),
                array(self::INSERT, mb_substr($longText, $i + mb_strlen($shortText))),
            );
            // Swap insertions for deletions if diff is reversed.
            if (mb_strlen($text2) < mb_strlen($text1)) {
                $diffs[0][0] = self::DELETE;
                $diffs[2][0] = self::DELETE;
            }
            return $diffs;
        }

        if (mb_strlen($shortText) == 1) {
            // Single character string.
            // After the previous speedup, the character can't be an equality.
            $diffs = array(
                array(self::DELETE, $text1),
                array(self::INSERT, $text2),
            );
            return $diffs;
        }

        // Don't risk returning a non-optimal diff if we have unlimited time.
        if ($this->getTimeout() > 0) {
            // Check to see if the problem can be split in two.
            $hm = $this->getToolkit()->halfMatch($text1, $text2);
            if ($hm) {
                // A half-match was found, sort out the return data.
                list($text1_a, $text1_b, $text2_a, $text2_b, $mid_common) = $hm;
                // Send both pairs off for separate processing.
                $diffA = new Diff();
                $diffA->main($text1_a, $text2_a, $checklines, $deadline);
                $diffB = new Diff();
                $diffB->main($text1_b, $text2_b, $checklines, $deadline);
                // Merge the results.
                $diffs = array_merge(
                    $diffA->getChanges(),
                    array(
                        array(self::EQUAL, $mid_common),
                    ),
                    $diffB->getChanges()
                );
                return $diffs;
            }
        }

        if ($checklines
          && mb_strlen($text1) > Diff::LINEMODE_THRESOLD
          && mb_strlen($text2) > Diff::LINEMODE_THRESOLD) {
            return $this->lineMode($text1, $text2, $deadline);
        }

        return $this->bisect($text1, $text2, $deadline);
    }
Find the differences between two texts.  Assumes that the texts do not
have any common prefix or suffix.

@param string $text1         Old string to be diffed.
@param string $text2         New string to be diffed.
@param bool   $checklines    Speedup flag.  If false, then don't run a line-level diff
first to identify the changed areas.
If true, then run a faster, slightly less optimal diff.
@param int    $deadline      Time when the diff should be complete by.

@return array Array of changes.