r62727 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r62726‎ | r62727 | r62728 >
Date:02:42, 20 February 2010
Author:aaron
Status:ok
Tags:
Comment:
truncateHtml() performance tweaks
Modified paths:
  • /trunk/extensions/CodeReview/backend/CodeCommentLinker.php (modified) (history)

Diff [purge]

Index: trunk/extensions/CodeReview/backend/CodeCommentLinker.php
@@ -41,13 +41,15 @@
4242 $displayLen = 0; // innerHTML legth so far
4343 $doTruncate = true; // truncated string plus '...' shorter than original?
4444 $tagType = 0; // 0-open, 1-close
45 - $bracketState = 0; // 1-tag start, 2-tag name, 3-tag params, 0-neither
 45+ $bracketState = 0; // 1-tag start, 2-tag name, 0-neither
4646 $entityState = 0; // 0-not entity, 1-entity
47 - $tag = $ret = $ch = $lastCh = '';
 47+ $tag = $ret = $ch = '';
4848 $openTags = array();
49 - for( $pos = 0; $pos < strlen($text); $pos++ ) {
50 - $lastCh = $ch;
 49+ $textLen = strlen($text);
 50+ for( $pos = 0; $pos < $textLen; ++$pos ) {
5151 $ch = $text[$pos];
 52+ $lastCh = $pos ? $text[$pos-1] : '';
 53+ $ret .= $ch; // add to result string
5254 if ( $ch == '<' ) {
5355 self::onEndBracket( $tag, $tagType, $lastCh, $openTags ); // for bad HTML
5456 $entityState = 0; // for bad HTML
@@ -58,9 +60,9 @@
5961 $bracketState = 0; // out of brackets
6062 } elseif ( $bracketState == 1 ) {
6163 if ( $ch == '/' ) {
62 - $tagType = 1; // close tag
 64+ $tagType = 1; // close tag (e.g. "</span>")
6365 } else {
64 - $tagType = 0; // open tag
 66+ $tagType = 0; // open tag (e.g. "<span>")
6567 $tag .= $ch;
6668 }
6769 $bracketState = 2; // building tag name
@@ -68,28 +70,35 @@
6971 if ( $ch != ' ' ) {
7072 $tag .= $ch;
7173 } else {
72 - $bracketState = 3; // name found (e.g. "<a href=...")
 74+ // Name found (e.g. "<a href=..."), add on tag attributes...
 75+ $pos += self::skipAndAppend( $ret, $text, "<>", $pos + 1 );
7376 }
7477 } elseif ( $bracketState == 0 ) {
7578 if ( $entityState ) {
7679 if ( $ch == ';' ) {
7780 $entityState = 0;
78 - $displayLen++; // entity is one char
 81+ $displayLen++; // entity is one displayed char
7982 }
80 - } elseif ( $ch == '&' ) {
81 - $entityState = 1; // entity found, (e.g. "&nbsp;")
8283 } else {
83 - $displayLen++; // not in brackets
 84+ if ( $ch == '&' ) {
 85+ $entityState = 1; // entity found, (e.g. "&nbsp;")
 86+ } else {
 87+ $displayLen++; // this char is displayed
 88+ // Add on the other display text after this...
 89+ $skipped = self::skipAndAppend(
 90+ $ret, $text, "<>&", $pos + 1, $maxLen - $displayLen );
 91+ $displayLen += $skipped;
 92+ $pos += $skipped;
 93+ }
8494 }
8595 }
86 - $ret .= $ch;
8796 if( !$doTruncate ) continue;
8897 # Truncate if not in the middle of a bracket/entity...
8998 if ( $bracketState == 0 && $entityState == 0 && $displayLen >= $maxLen ) {
90 - $left = substr( $text, $pos + 1 ); // remaining string
91 - $left = StringUtils::delimiterReplace( '<', '>', '', $left ); // rm tags
92 - $left = StringUtils::delimiterReplace( '&', ';', '', $left ); // rm entities
93 - $doTruncate = ( strlen($left) > strlen($ellipsis) );
 99+ $remaining = substr( $text, $pos + 1 ); // remaining string
 100+ $remaining = StringUtils::delimiterReplace( '<', '>', '', $remaining ); // rm tags
 101+ $remaining = StringUtils::delimiterReplace( '&', ';', '', $remaining ); // rm entities
 102+ $doTruncate = ( strlen($remaining) > strlen($ellipsis) );
94103 if ( $doTruncate ) {
95104 # Hack: go one char over so truncate() will handle multi-byte chars
96105 $ret = $wgLang->truncate( $ret . 'x', strlen($ret), '' ) . $ellipsis;
@@ -100,14 +109,26 @@
101110 if( $displayLen == 0 ) {
102111 return ''; // no text shown, nothing to format
103112 }
104 - self::onEndBracket( $tag, $lastCh, $tagType, $openTags ); // for bad HTML
 113+ self::onEndBracket( $tag, $text[$textLen-1], $tagType, $openTags ); // for bad HTML
105114 while ( count( $openTags ) > 0 ) {
106 - $ret .= '</' . array_pop($openTags) . '>'; // close open tags
 115+ $ret .= '</' . array_pop( $openTags ) . '>'; // close open tags
107116 }
108117 return $ret;
109118 }
110119
111 - protected function onEndBracket( &$tag, $tagType, $lastCh, &$openTags ) {
 120+ // like strcspn() but adds the skipped chars to $ret
 121+ private function skipAndAppend( &$ret, $text, $search, $start, $len = NULL ) {
 122+ $skipCount = 0;
 123+ if( $start < strlen($text) ) {
 124+ $skipCount = strcspn( $text, $search, $start, $len );
 125+ $ret .= substr( $text, $start, $skipCount );
 126+ }
 127+ return $skipCount;
 128+ }
 129+
 130+ // (a) push or pop $tag from $openTags as needed
 131+ // (b) clear $tag value
 132+ private function onEndBracket( &$tag, $tagType, $lastCh, &$openTags ) {
112133 $tag = ltrim( $tag );
113134 if( $tag != '' ) {
114135 if( $tagType == 0 && $lastCh != '/' ) {

Status & tagging log