Avoid counting input lines twice in BlockLevelPass::execute()
authorC. Scott Ananian <cscott@cscott.net>
Wed, 20 Mar 2019 20:37:49 +0000 (16:37 -0400)
committerC. Scott Ananian <cscott@cscott.net>
Wed, 20 Mar 2019 21:35:14 +0000 (17:35 -0400)
In T208070 / I120ca25a77b7b933de4afddd1d458e36a95e26da we added a
check whether we were processing the last line of input, in order
to avoid emitting extra trailing newlines.  But if the number of
input lines is large, StringUtils::explode() will return an
iterator which doesn't implement Countable for efficiency.
I22eebb70af1b19d7c25241fc78bfcced4470e78a fixed this, but at the
cost of scanning the string twice: once just to count the number
of newlines before we begin to iterate over the lines.

This patch uses Iterator::valid() to determine if we're on the
last iteration without having to scan the string twice.

Bug: T208070
Bug: T218817
Change-Id: I41a45266d266195aa6002d3854e018cacf052ca6

includes/parser/BlockLevelPass.php

index 6d6af77..f925038 100644 (file)
@@ -192,8 +192,6 @@ class BlockLevelPass {
                # happening here is handling of block-level elements p, pre,
                # and making lists from lines starting with * # : etc.
                $textLines = StringUtils::explode( "\n", $text );
-               # Count this way because $textLines could be an ExplodeIterator
-               $lineCount = substr_count( $text, "\n" ) + 1;
 
                $lastPrefix = $output = '';
                $this->DTopen = $inBlockElem = false;
@@ -201,9 +199,11 @@ class BlockLevelPass {
                $pendingPTag = false;
                $inBlockquote = false;
 
-               $nextLineNum = 0;
-               foreach ( $textLines as $inputLine ) {
-                       $nextLineNum += 1;
+               for ( $textLines->rewind(); $textLines->valid(); ) {
+                       $inputLine = $textLines->current();
+                       $textLines->next();
+                       $notLastLine = $textLines->valid();
+
                        # Fix up $lineStart
                        if ( !$this->lineStart ) {
                                $output .= $inputLine;
@@ -410,7 +410,7 @@ class BlockLevelPass {
                                        $output .= $t;
                                        // Add a newline if there's an open paragraph
                                        // or we've yet to reach the last line.
-                                       if ( $nextLineNum < $lineCount || $this->hasOpenParagraph() ) {
+                                       if ( $notLastLine || $this->hasOpenParagraph() ) {
                                                $output .= "\n";
                                        }
                                } else {