Revert r39618 "Per discussion for bug 6455, merged functionality of StringFunctions into the ParserFunctions extension."

o_O These look like the least CPU- and memory-efficient implementations of strlen(), strpos() etc that could possibly be created...
This commit is contained in:
Brion Vibber 2008-08-19 18:53:09 +00:00
parent c17e837fa1
commit e42686cd0a
2 changed files with 3 additions and 314 deletions

View file

@ -25,16 +25,6 @@ function efParserFunctionsWords( $lang ) {
'timel' => array( 0, 'timel' ),
'rel2abs' => array( 0, 'rel2abs' ),
'titleparts' => array( 0, 'titleparts' ),
'len' => array( 0, 'len' ),
'pos' => array( 0, 'pos' ),
'rpos' => array( 0, 'rpos' ),
'sub' => array( 0, 'sub' ),
'pad' => array( 0, 'pad' ),
'replace' => array( 0, 'replace' ),
'explode' => array( 0, 'explode' ),
'urlencode' => array( 0, 'urlencode' ),
'urldecode' => array( 0, 'urldecode' ),
);
/**

View file

@ -7,9 +7,9 @@ if ( !defined( 'MEDIAWIKI' ) ) {
$wgExtensionFunctions[] = 'wfSetupParserFunctions';
$wgExtensionCredits['parserhook'][] = array(
'name' => 'ParserFunctions',
'version' => '2.0',
'version' => '1.1.1',
'url' => 'http://meta.wikimedia.org/wiki/ParserFunctions',
'author' => array('Tim Starling', 'Ross McClure', 'Juraj Simlovic', 'Fran Rogers'),
'author' => 'Tim Starling',
'description' => 'Enhance parser with logical functions',
'descriptionmsg' => 'pfunc_desc',
);
@ -17,10 +17,6 @@ $wgExtensionCredits['parserhook'][] = array(
$wgExtensionMessagesFiles['ParserFunctions'] = dirname(__FILE__) . '/ParserFunctions.i18n.php';
$wgHooks['LanguageGetMagic'][] = 'wfParserFunctionsLanguageGetMagic';
$wgStringFunctionsLimitSearch = 30;
$wgStringFunctionsLimitReplace = 30;
$wgStringFunctionsLimitPad = 100;
class ExtParserFunctions {
var $mExprParser;
var $mTimeCache = array();
@ -51,16 +47,6 @@ class ExtParserFunctions {
$parser->setFunctionHook( 'rel2abs', array( &$this, 'rel2abs' ) );
$parser->setFunctionHook( 'titleparts', array( &$this, 'titleparts' ) );
$parser->setFunctionHook( 'len', array( &$this, 'len' ) );
$parser->setFunctionHook( 'pos', array( &$this, 'pos' ) );
$parser->setFunctionHook( 'rpos', array( &$this, 'rpos' ) );
$parser->setFunctionHook( 'sub', array( &$this, 'sub' ) );
$parser->setFunctionHook( 'pad', array( &$this, 'pad' ) );
$parser->setFunctionHook( 'replace', array( &$this, 'replace' ) );
$parser->setFunctionHook( 'explode', array( &$this, 'explode' ) );
$parser->setFunctionHook( 'urlencode', array( &$this, 'urlencode' ) );
$parser->setFunctionHook( 'urldecode', array( &$this, 'urldecode' ) );
return true;
}
@ -490,294 +476,6 @@ class ExtParserFunctions {
return $title;
}
}
/**
* Splits the string into its component parts using preg_match_all().
* $chars is set to the resulting array of multibyte characters.
* Returns count($chars).
*/
function mwSplit ( &$parser, $str, &$chars ) {
# Get marker prefix & suffix
$prefix = preg_quote( $parser->mUniqPrefix );
if( isset($parser->mMarkerSuffix) )
$suffix = preg_quote( $parser->mMarkerSuffix );
else if ( strcmp( MW_PARSER_VERSION, '1.6.1' ) > 0 )
$suffix = 'QINU\x07';
else $suffix = 'QINU';
# Treat strip markers as single multibyte characters
$count = preg_match_all('/' . $prefix . '.*?' . $suffix . '|./su', $str, $arr);
$chars = $arr[0];
return $count;
}
/**
* {{#len:value}}
*/
function len( &$parser, $inStr = '' ) {
return $this->mwSplit ( $parser, $inStr, $chars );
}
/**
* {{#pos:value|key|offset}}
* Note: If the needle is an empty string, single space is used instead.
* Note: If the needle is not found, empty string is returned.
* Note: The needle is limited to specific length.
*/
function pos( &$parser, $inStr = '', $inNeedle = '', $inOffset = 0 ) {
global $wgStringFunctionsLimitSearch;
if ( $inNeedle === '' ) {
# empty needle
$needle = array(' ');
$nSize = 1;
} else {
# convert needle
$nSize = $this->mwSplit ( $parser, $inNeedle, $needle );
if ( $nSize > $wgStringFunctionsLimitSearch ) {
$nSize = $wgStringFunctionsLimitSearch;
$needle = array_slice ( $needle, 0, $nSize );
}
}
# convert string
$size = $this->mwSplit( $parser, $inStr, $chars ) - $nSize;
$inOffset = max ( intval($inOffset), 0 );
# find needle
for ( $i = $inOffset; $i <= $size; $i++ ) {
if ( $chars[$i] !== $needle[0] ) continue;
for ( $j = 1; ; $j++ ) {
if ( $j >= $nSize ) return $i;
if ( $chars[$i + $j] !== $needle[$j] ) break;
}
}
# return empty string upon not found
return '';
}
/**
* {{#rpos:value|key}}
* Note: If the needle is an empty string, single space is used instead.
* Note: If the needle is not found, -1 is returned.
* Note: The needle is limited to specific length.
*/
function rPos( &$parser, $inStr = '', $inNeedle = '' ) {
global $wgStringFunctionsLimitSearch;
if ( $inNeedle === '' ) {
# empty needle
$needle = array(' ');
$nSize = 1;
} else {
# convert needle
$nSize = $this->mwSplit ( $parser, $inNeedle, $needle );
if ( $nSize > $wgStringFunctionsLimitSearch ) {
$nSize = $wgStringFunctionsLimitSearch;
$needle = array_slice ( $needle, 0, $nSize );
}
}
# convert string
$size = $this->mwSplit( $parser, $inStr, $chars ) - $nSize;
# find needle
for ( $i = $size; $i >= 0; $i-- ) {
if ( $chars[$i] !== $needle[0] ) continue;
for ( $j = 1; ; $j++ ) {
if ( $j >= $nSize ) return $i;
if ( $chars[$i + $j] !== $needle[$j] ) break;
}
}
# return -1 upon not found
return "-1";
}
/**
* {{#sub:value|start|length}}
* Note: If length is zero, the rest of the input is returned.
*/
function sub( &$parser, $inStr = '', $inStart = 0, $inLength = 0 ) {
# convert string
$this->mwSplit( $parser, $inStr, $chars );
# zero length
if ( intval($inLength) == 0 )
return join('', array_slice( $chars, intval($inStart) ));
# non-zero length
return join('', array_slice( $chars, intval($inStart), intval($inLength) ));
}
/**
* {{#pad:value|length|with|direction}}
* Note: Length of the resulting string is limited.
*/
function pad( &$parser, $inStr = '', $inLen = 0, $inWith = '', $inDirection = '' ) {
global $wgStringFunctionsLimitPad;
# direction
switch ( strtolower ( $inDirection ) ) {
case 'center':
$direction = STR_PAD_BOTH;
break;
case 'right':
$direction = STR_PAD_RIGHT;
break;
case 'left':
default:
$direction = STR_PAD_LEFT;
break;
}
# prevent markers in padding
$a = explode ( $parser->mUniqPrefix, $inWith, 2 );
if ( $a[0] === '' )
$inWith = ' ';
else $inWith = $a[0];
# limit pad length
$inLen = intval ( $inLen );
if ($wgStringFunctionsLimitPad > 0)
$inLen = min ( $inLen, $wgStringFunctionsLimitPad );
# adjust for multibyte strings
$inLen += strlen( $inStr ) - $this->mwSplit( $parser, $inStr, $a );
# pad
return str_pad ( $inStr, $inLen, $inWith, $direction );
}
/**
* {{#replace:value|from|to}}
* Note: If the needle is an empty string, single space is used instead.
* Note: The needle is limited to specific length.
* Note: The product is limited to specific length.
*/
function replace( &$parser, $inStr = '', $inReplaceFrom = '', $inReplaceTo = '' ) {
global $wgStringFunctionsLimitSearch, $wgStringFunctionsLimitReplace;
if ( $inReplaceFrom === '' ) {
# empty needle
$needle = array(' ');
$nSize = 1;
} else {
# convert needle
$nSize = $this->mwSplit ( $parser, $inReplaceFrom, $needle );
if ( $nSize > $wgStringFunctionsLimitSearch ) {
$nSize = $wgStringFunctionsLimitSearch;
$needle = array_slice ( $needle, 0, $nSize );
}
}
# convert product
$pSize = $this->mwSplit ( $parser, $inReplaceTo, $product );
if ( $pSize > $wgStringFunctionsLimitReplace ) {
$pSize = $wgStringFunctionsLimitReplace;
$product = array_slice ( $product, 0, $pSize );
}
# remove markers in product
for( $i = 0; $i < $pSize; $i++ ) {
if( strlen( $product[$i] ) > 6 ) $product[$i] = ' ';
}
# convert string
$size = $this->mwSplit ( $parser, $inStr, $chars ) - $nSize;
# replace
for ( $i = 0; $i <= $size; $i++ ) {
if ( $chars[$i] !== $needle[0] ) continue;
for ( $j = 1; ; $j++ ) {
if ( $j >= $nSize ) {
array_splice ( $chars, $i, $j, $product );
$size += ( $pSize - $nSize );
$i += ( $pSize - 1 );
break;
}
if ( $chars[$i + $j] !== $needle[$j] ) break;
}
}
return join('', $chars);
}
/**
* {{#explode:value|delimiter|position}}
* Note: Negative position can be used to specify tokens from the end.
* Note: If the divider is an empty string, single space is used instead.
* Note: The divider is limited to specific length.
* Note: Empty string is returned, if there is not enough exploded chunks.
*/
function explode( &$parser, $inStr = '', $inDiv = '', $inPos = 0 ) {
global $wgStringFunctionsLimitSearch;
if ( $inDiv === '' ) {
# empty divider
$div = array(' ');
$dSize = 1;
} else {
# convert divider
$dSize = $this->mwSplit ( $parser, $inDiv, $div );
if ( $dSize > $wgStringFunctionsLimitSearch ) {
$dSize = $wgStringFunctionsLimitSearch;
$div = array_slice ( $div, 0, $dSize );
}
}
# convert string
$size = $this->mwSplit ( $parser, $inStr, $chars ) - $dSize;
# explode
$inPos = intval ( $inPos );
$tokens = array();
$start = 0;
for ( $i = 0; $i <= $size; $i++ ) {
if ( $chars[$i] !== $div[0] ) continue;
for ( $j = 1; ; $j++ ) {
if ( $j >= $dSize ) {
if ( $inPos > 0 ) $inPos--;
else {
$tokens[] = join('', array_slice($chars, $start, ($i - $start)));
if ( $inPos == 0 ) return $tokens[0];
}
$start = $i + $j;
$i = $start - 1;
break;
}
if ( $chars[$i + $j] !== $div[$j] ) break;
}
}
$tokens[] = join('', array_slice( $chars, $start ));
# negative $inPos
if ( $inPos < 0 ) $inPos += count ( $tokens );
# out of range
if ( !isset ( $tokens[$inPos] ) ) return "";
# in range
return $tokens[$inPos];
}
/**
* {{#urlencode:value}}
*/
function urlEncode ( &$parser, $inStr = '' ) {
# encode
return urlencode ( $inStr );
}
/**
* {{#urldecode:value}}
*/
function urlDecode ( &$parser, $inStr = '' ) {
# decode
return urldecode ( $inStr );
}
}
function wfSetupParserFunctions() {
@ -804,3 +502,4 @@ function wfParserFunctionsLanguageGetMagic( &$magicWords, $langCode ) {
$magicWords[$word] = $trans;
return true;
}