diff --git a/lib/ActiveFormattingElementsList.php b/lib/ActiveFormattingElementsList.php index f666dda..bd9c6b0 100644 --- a/lib/ActiveFormattingElementsList.php +++ b/lib/ActiveFormattingElementsList.php @@ -25,11 +25,11 @@ class ActiveFormattingElementsList extends Stack { } public function offsetSet($offset, $value) { - $count = count($this->_storage); + $count = $this->count; assert($offset >= 0 && $offset <= $count, new Exception(Exception::STACK_INVALID_INDEX, $offset)); assert($value instanceof ActiveFormattingElementsMarker || ( is_array($value) - && sizeof($value) === 2 + && count($value) === 2 && isset($value['token']) && isset($value['element']) && $value['token'] instanceof StartTagToken @@ -69,6 +69,7 @@ class ActiveFormattingElementsList extends Stack { } else { $this->_storage[$offset ?? $count] = $value; } + $this->count = count($this->_storage); } protected function matchElement(Element $a, Element $b): bool { @@ -99,7 +100,7 @@ class ActiveFormattingElementsList extends Stack { } public function insert(StartTagToken $token, Element $element, ?int $at = null): void { - assert($at === null || ($at >= 0 && $at <= count($this->_storage)), new \Exception("Invalid list index $at (max ".count($this->_storage).")")); + assert($at === null || ($at >= 0 && $at <= $this->count), new \Exception("Invalid list index $at (max ".$this->count.")")); if ($at === null) { $this[] = [ 'token' => $token, @@ -110,6 +111,7 @@ class ActiveFormattingElementsList extends Stack { 'token' => $token, 'element' => $element, ]]); + $this->count = count($this->_storage); } } @@ -125,7 +127,7 @@ class ActiveFormattingElementsList extends Stack { if (!$this->_storage) { return; } - $last = count($this->_storage) - 1; + $last = $this->count - 1; # 2. If the last (most recently added) entry in the list of active formatting # elements is a marker, or if it is an element that is in the stack of open # elements, then there is nothing to reconstruct; stop this algorithm. @@ -187,6 +189,7 @@ class ActiveFormattingElementsList extends Stack { break; } } + $this->count = count($this->_storage); } public function findSame(Element $target): int { diff --git a/lib/OpenElementsStack.php b/lib/OpenElementsStack.php index 6cf5003..8b6235b 100644 --- a/lib/OpenElementsStack.php +++ b/lib/OpenElementsStack.php @@ -138,8 +138,8 @@ class OpenElementsStack extends Stack { $this[] = $element; } else { array_splice($this->_storage, $at, 0, [$element]); - $this->computeProperties(); } + $this->computeProperties(); } public function popUntil(string ...$target): void { @@ -205,6 +205,7 @@ class OpenElementsStack extends Stack { } while (!$this->isEmpty() && $this->top()->namespaceURI === null && ($map[$this->top()->nodeName] ?? false)) { array_pop($this->_storage); + $this->count--; } $this->computeProperties(); } @@ -215,6 +216,7 @@ class OpenElementsStack extends Stack { # the UA must pop the current node off the stack of open elements. while (!$this->isEmpty() && $this->top()->namespaceURI === null && (self::IMPLIED_END_TAGS_THOROUGH[$this->top()->nodeName] ?? false)) { array_pop($this->_storage); + $this->count--; } $this->computeProperties(); } @@ -224,11 +226,11 @@ class OpenElementsStack extends Stack { # table context, it means that the UA must, while the current node # is not a table, template, or html element, pop elements from the # stack of open elements. - assert(sizeof($this->_storage) > 0, new \Exception("Stack is empty")); + assert(count($this->_storage) > 0, new \Exception("Stack is empty")); $pos = $this->find("table", "template", "html"); assert($pos > -1, new \Exception("No table context exists")); $stop = $pos + 1; - while (sizeof($this->_storage) > $stop) { + while (count($this->_storage) > $stop) { array_pop($this->_storage); } $this->computeProperties(); @@ -239,11 +241,11 @@ class OpenElementsStack extends Stack { # table body context, it means that the UA must, while the current # node is not a tbody, tfoot, thead, template, or html element, # pop elements from the stack of open elements. - assert(sizeof($this->_storage) > 0, new \Exception("Stack is empty")); + assert(count($this->_storage) > 0, new \Exception("Stack is empty")); $pos = $this->find("tbody", "tfoot", "thead", "template", "html"); assert($pos > -1, new \Exception("No table body context exists")); $stop = $pos + 1; - while (sizeof($this->_storage) > $stop) { + while (count($this->_storage) > $stop) { array_pop($this->_storage); } $this->computeProperties(); @@ -254,11 +256,11 @@ class OpenElementsStack extends Stack { # table row context, it means that the UA must, while the current # node is not a tr, template, or html element, pop elements from # the stack of open elements. - assert(sizeof($this->_storage) > 0, new \Exception("Stack is empty")); + assert(count($this->_storage) > 0, new \Exception("Stack is empty")); $pos = $this->find("tr", "template", "html"); assert($pos > -1, new \Exception("No table row context exists")); $stop = $pos + 1; - while (sizeof($this->_storage) > $stop) { + while (count($this->_storage) > $stop) { array_pop($this->_storage); } $this->computeProperties(); @@ -331,12 +333,13 @@ class OpenElementsStack extends Stack { } protected function computeProperties(): void { + $this->count = count($this->_storage); $this->currentNode = $this->top(); # The adjusted current node is the context element if the parser was created by # the HTML fragment parsing algorithm and the stack of open elements has only one # element in it (fragment case); otherwise, the adjusted current node is the # current node. - if ($this->fragmentContext && sizeof($this->_storage) === 1) { + if ($this->fragmentContext && $this->count === 1) { $this->adjustedCurrentNode = $this->fragmentContext; } else { $this->adjustedCurrentNode = $this->currentNode; diff --git a/lib/Parser.php b/lib/Parser.php index 13f918d..5f8428e 100644 --- a/lib/Parser.php +++ b/lib/Parser.php @@ -74,7 +74,7 @@ class Parser { // Try to find a Content-Type header-field foreach ($meta['wrapper_data'] as $h) { $h = explode(":", $h, 2); - if (sizeof($h) === 2) { + if (count($h) === 2) { if (preg_match("/^\s*Content-Type\s*$/i", $h[0])) { // Try to get an encoding from it $encoding = Charset::fromTransport($h[1]); diff --git a/lib/Stack.php b/lib/Stack.php index f4b6e7b..6bdcfc6 100644 --- a/lib/Stack.php +++ b/lib/Stack.php @@ -4,6 +4,7 @@ namespace dW\HTML5; abstract class Stack implements \ArrayAccess, \Countable, \IteratorAggregate { protected $_storage = []; + protected $count = 0; public function offsetSet($offset, $value) { assert($offset >= 0, new Exception(Exception::STACK_INVALID_INDEX, $offset)); @@ -13,6 +14,7 @@ abstract class Stack implements \ArrayAccess, \Countable, \IteratorAggregate { } else { $this->_storage[$offset] = $value; } + $this->count = count($this->_storage); } public function offsetExists($offset) { @@ -22,6 +24,7 @@ abstract class Stack implements \ArrayAccess, \Countable, \IteratorAggregate { public function offsetUnset($offset) { assert($offset >= 0 && $offset < count($this->_storage), new Exception(Exception::STACK_INVALID_INDEX, $offset)); array_splice($this->_storage, $offset, 1, []); + $this->count = count($this->_storage); } public function offsetGet($offset) { @@ -30,16 +33,17 @@ abstract class Stack implements \ArrayAccess, \Countable, \IteratorAggregate { } public function count(): int { - return count($this->_storage); + return $this->count; } public function getIterator(): \Traversable { - for ($a = count($this->_storage) - 1; $a > -1; $a--) { + for ($a = $this->count - 1; $a > -1; $a--) { yield $a => $this->_storage[$a]; } } public function pop() { + $this->count = max($this->count - 1, 0); return array_pop($this->_storage); } @@ -49,6 +53,6 @@ abstract class Stack implements \ArrayAccess, \Countable, \IteratorAggregate { public function top(int $offset = 0) { assert($offset >= 0, new \Exception("Offset must be at least 0")); - return ($c = count($this->_storage)) > $offset ? $this->_storage[$c - ($offset + 1)] : null; + return ($c = $this->count) > $offset ? $this->_storage[$c - ($offset + 1)] : null; } }