533ed5d493
Implements LimitIterator from SPL. Closes #788
165 linhas
5.1 KiB
PHP
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;
|
|
}
|
|
}
|