Arquivos
hhvm/hphp/system/php/spl/iterators/LimitIterator.php
T
Eric Caruso 533ed5d493 Implement LimitIterator
Implements LimitIterator from SPL.

Closes #788
2013-06-25 13:19:03 -07:00

165 linhas
5.1 KiB
PHP

<?php
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/class.limititerator.php )
*
* The LimitIterator class allows iteration over a limited subset of items
* in an Iterator.
*
*/
class LimitIterator extends IteratorIterator implements OuterIterator {
private $offset;
private $count;
private $valid;
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.construct.php )
*
* Constructs a new LimitIterator from an iterator with a given starting
* offset and maximum count.
*
* @iterator mixed The Iterator to limit.
* @offset mixed Optional offset of the limit.
* @count mixed Optional count of the limit.
*
* @return mixed The new LimitIterator.
*/
public function __construct($iterator, $offset = 0, $count = -1) {
if ($offset < 0) {
throw new OutOfRangeException(
"Parameter offset must be >= 0");
} else if ($count < -1) {
throw new OutOfRangeException(
"Parameter count must either be -1 or ".
"a value greater than or equal 0");
}
parent::__construct($iterator);
$this->offset = $offset;
$this->count = $count;
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.getposition.php )
*
* Gets the current zero-based position of the inner Iterator.
*
* @return mixed The current position.
*/
public function getPosition() {
return $this->_getPosition();
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.rewind.php )
*
* Rewinds the iterator to the starting offset specified in
* LimitIterator::__construct().
*
* @return mixed No value is returned.
*/
public function rewind() {
$this->getInnerIterator()->rewind();
$this->_setPosition(0);
$this->seek($this->offset);
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.next.php )
*
* Moves the iterator forward.
*
* @return mixed No value is returned.
*/
public function next() {
$this->getInnerIterator()->next();
$this->_setPosition($this->_getPosition() + 1);
if ($this->count == -1 ||
$this->_getPosition() < $this->offset + $this->count) {
$this->valid = $this->_fetch(true);
}
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.seek.php )
*
* Moves the iterator to the offset specified by position.
*
* @position mixed The position to seek to.
*
* @return mixed Returns the offset position after seeking.
*/
public function seek($position) {
// Bounds checking
if ($position < $this->offset) {
throw new OutOfBoundsException(
"Cannot seek to ".$position.
" which is below the offset ".$this->offset);
} else if ($this->count != -1 &&
$position >= $this->offset + $this->count) {
throw new OutOfBoundsException(
"Cannot seek to ".$position.
" which is behind offset ".$this->offset.
" plus count ".$this->count);
}
$iter = $this->getInnerIterator();
if ($this->_getPosition() != $position &&
$iter instanceof SeekableIterator) {
// We can use the underlying seek implementation.
$iter->seek($position);
$this->_setPosition($position);
if (($this->count == -1 ||
$this->_getPosition() < $this->offset + $this->count) &&
$iter->valid()) {
$this->valid = $this->_fetch(false);
}
} else {
// We need to simulate the seek using rewind() and next().
// Backwards seeking is done using rewind() first.
if ($this->_getPosition() > $position) {
$iter->rewind();
$this->_setPosition(0);
}
// We can seek forwards using next().
while ($this->_getPosition() < $position && $iter->valid()) {
/*
* Note that we're basically reimplementing next() here.
* This is because the SPL implementation does not fetch
* when it's walking the iterator - it only fetches when
* it reaches the right position. This also accounts for
* why we update _position manually (and similarly, why
* we set it manually to 0 in the block above).
*/
$iter->next();
$this->_setPosition($this->_getPosition() + 1);
}
// Fetch.
if ($iter->valid()) {
$this->valid = $this->_fetch(true);
}
}
return $this->_getPosition();
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/limititerator.valid.php )
*
* Checks whether the current element is valid.
*
* @return mixed Returns TRUE on success or FALSE on failure.
*/
public function valid() {
return ($this->count == -1 ||
$this->_getPosition() < $this->offset + $this->count) &&
$this->valid;
}
}