X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FStringUtils.php;h=c437b3c19e48a5d2b8341b303ee5802afdc22505;hb=a8118d9ddc70d11363e9dfee1937c146a38dc4cc;hp=4c4d219d8e7281afbf0ef21e7a38b288ea9af4e5;hpb=61af76f260c66bb354e3160c87b24d3f1e4ac37f;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/StringUtils.php b/includes/StringUtils.php index 4c4d219d8e..c437b3c19e 100644 --- a/includes/StringUtils.php +++ b/includes/StringUtils.php @@ -1,15 +1,17 @@ ', $replacer->cb(), $text ); @@ -148,7 +151,7 @@ class StringUtils { foreach( $items as $i => $str ) { $items[$i] = str_replace( $placeholder, $separator, $str ); } - + return $items; } @@ -164,10 +167,22 @@ class StringUtils { $string = str_replace( '$', '\\$', $string ); return $string; } + + /** + * Workalike for explode() with limited memory usage. + * Returns an Iterator + */ + static function explode( $separator, $subject ) { + if ( substr_count( $subject, $separator ) > 1000 ) { + return new ExplodeIterator( $separator, $subject ); + } else { + return new ArrayIterator( explode( $separator, $subject ) ); + } + } } /** - * Base class for "replacers", objects used in preg_replace_callback() and + * Base class for "replacers", objects used in preg_replace_callback() and * StringUtils::delimiterReplaceCallback() */ class Replacer { @@ -204,7 +219,7 @@ class DoubleReplacer extends Replacer { $this->to = $to; $this->index = $index; } - + function replace( $matches ) { return str_replace( $this->from, $this->to, $matches[$this->index] ); } @@ -280,6 +295,17 @@ class ReplacementArray { $this->fss = false; } + function removePair( $from ) { + unset($this->data[$from]); + $this->fss = false; + } + + function removeArray( $data ) { + foreach( $data as $from => $to ) + $this->removePair( $from ); + $this->fss = false; + } + function replace( $subject ) { if ( function_exists( 'fss_prep_replace' ) ) { wfProfileIn( __METHOD__.'-fss' ); @@ -297,4 +323,89 @@ class ReplacementArray { } } -?> +/** + * An iterator which works exactly like: + * + * foreach ( explode( $delim, $s ) as $element ) { + * ... + * } + * + * Except it doesn't use 193 byte per element + */ +class ExplodeIterator implements Iterator { + // The subject string + var $subject, $subjectLength; + + // The delimiter + var $delim, $delimLength; + + // The position of the start of the line + var $curPos; + + // The position after the end of the next delimiter + var $endPos; + + // The current token + var $current; + + /** + * Construct a DelimIterator + */ + function __construct( $delim, $s ) { + $this->subject = $s; + $this->delim = $delim; + + // Micro-optimisation (theoretical) + $this->subjectLength = strlen( $s ); + $this->delimLength = strlen( $delim ); + + $this->rewind(); + } + + function rewind() { + $this->curPos = 0; + $this->endPos = strpos( $this->subject, $this->delim ); + $this->refreshCurrent(); + } + + + function refreshCurrent() { + if ( $this->curPos === false ) { + $this->current = false; + } elseif ( $this->curPos >= $this->subjectLength ) { + $this->current = ''; + } elseif ( $this->endPos === false ) { + $this->current = substr( $this->subject, $this->curPos ); + } else { + $this->current = substr( $this->subject, $this->curPos, $this->endPos - $this->curPos ); + } + } + + function current() { + return $this->current; + } + + function key() { + return $this->curPos; + } + + function next() { + if ( $this->endPos === false ) { + $this->curPos = false; + } else { + $this->curPos = $this->endPos + $this->delimLength; + if ( $this->curPos >= $this->subjectLength ) { + $this->endPos = false; + } else { + $this->endPos = strpos( $this->subject, $this->delim, $this->curPos ); + } + } + $this->refreshCurrent(); + return $this->current; + } + + function valid() { + return $this->curPos !== false; + } +} +