Skip to content

Commit

Permalink
Reduce overhead of flushIterator() call when input stream is large
Browse files Browse the repository at this point in the history
  • Loading branch information
slusarz committed Feb 18, 2014
1 parent 8cbbf33 commit ae199c3
Showing 1 changed file with 99 additions and 80 deletions.
179 changes: 99 additions & 80 deletions framework/Imap_Client/lib/Horde/Imap/Client/Tokenize.php
Expand Up @@ -50,6 +50,13 @@ class Horde_Imap_Client_Tokenize implements Iterator
*/
protected $_level = false;

/**
* next() modifiers.
*
* @var array
*/
protected $_nextModify = array();

/**
* Data stream.
*
Expand Down Expand Up @@ -124,22 +131,19 @@ public function flushIterator($return = true, $sublevel = true)
$out = array();

if ($return) {
$level = $sublevel ? $this->_level : 0;
do {
$curr = $this->next();
if ($this->_level < $level) {
break;
}

if (!is_bool($curr) && ($level === $this->_level)) {
$out[] = $curr;
}
} while (($curr !== false) || $this->_level || !$this->eos);
$this->_nextModify = array(
'level' => $sublevel ? $this->_level : 0,
'out' => array()
);
$this->next();
$out = $this->_nextModify['out'];
$this->_nextModify = array();
} elseif ($sublevel && $this->_level) {
$level = $this->_level;
while ($level <= $this->_level) {
$this->next();
}
$this->_nextModify = array(
'level' => $this->_level
);
$this->next();
$this->_nextModify = array();
} else {
$this->_stream->end();
$this->_stream->getChar();
Expand Down Expand Up @@ -197,96 +201,111 @@ public function key()
*/
public function next()
{
$check_len = true;
$in_quote = $text = false;
$level = isset($this->_nextModify['level'])
? $this->_nextModify['level']
: null;
/* Directly access stream here to drastically reduce the number of
* getChar() calls we would have to make. */
$stream = $this->_stream->stream;

while (($c = fgetc($stream)) !== false) {
switch ($c) {
case '\\':
$text .= $in_quote
? fgetc($stream)
: $c;
break;
do {
$check_len = true;
$in_quote = $text = false;

case '"':
if ($in_quote) {
$check_len = false;
break 2;
}
$in_quote = true;
break;
while (($c = fgetc($stream)) !== false) {
switch ($c) {
case '\\':
$text .= $in_quote
? fgetc($stream)
: $c;
break;

default:
if ($in_quote) {
$text .= $c;
case '"':
if ($in_quote) {
$check_len = false;
break 2;
}
$in_quote = true;
break;
}

switch ($c) {
case '(':
++$this->_level;
$check_len = false;
$text = true;
break 3;

case ')':
if ($text === false) {
--$this->_level;
$check_len = $text = false;
} else {
$this->_stream->seek(-1);
default:
if ($in_quote) {
$text .= $c;
break;
}
break 3;

case '~':
// Ignore binary string identifier. PHP strings are
// binary-safe.
break;
switch ($c) {
case '(':
++$this->_level;
$check_len = false;
$text = true;
break 3;

case '{':
$text = $this->_stream->substring(
0,
intval($this->_stream->getToChar('}'))
);
$check_len = false;
break 3;
case ')':
if ($text === false) {
--$this->_level;
$check_len = $text = false;
} else {
$this->_stream->seek(-1);
}
break 3;

case ' ':
if ($text !== false) {
case '~':
// Ignore binary string identifier. PHP strings are
// binary-safe.
break;

case '{':
$text = $this->_stream->substring(
0,
intval($this->_stream->getToChar('}'))
);
$check_len = false;
break 3;

case ' ':
if ($text !== false) {
break 3;
}
break;

default:
$text .= $c;
break;
}
break;
}
}

if ($check_len) {
switch (strlen($text)) {
case 0:
$text = false;
break;

default:
$text .= $c;
case 3:
if (($text === 'NIL') || (strcasecmp($text, 'NIL') === 0)) {
$text = null;
}
break;
}
break;
}
}

if ($check_len) {
switch (strlen($text)) {
case 0:
$text = false;
if (($text === false) && feof($stream)) {
$this->_key = $this->_level = false;
break;
}

case 3:
if (($text === 'NIL') || (strcasecmp($text, 'NIL') === 0)) {
$text = null;
}
++$this->_key;

if (is_null($level) || ($level > $this->_level)) {
break;
}
}

if (($text === false) && feof($stream)) {
$this->_key = $this->_level = false;
} else {
++$this->_key;
}
if (($level === $this->_level) && !is_bool($text)) {
$this->_nextModify['out'][] = $text;
}
} while (true);

$this->_current = $text;

Expand Down

0 comments on commit ae199c3

Please sign in to comment.