@@ -65,5 +65,6 @@ hphp/system/php/spl/datastructures/SplObjectStorage.php
|
||||
hphp/system/php/spl/datastructures/SplPriorityQueue.php
|
||||
hphp/system/php/spl/iterators/AppendIterator.php
|
||||
hphp/system/php/spl/iterators/ArrayIterator.php
|
||||
hphp/system/php/spl/iterators/LimitIterator.php
|
||||
hphp/system/php/spl/iterators/RecursiveIteratorIterator.php
|
||||
hphp/system/php/spl/miscellaneous/ArrayObject.php
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
*/
|
||||
class IteratorIterator implements OuterIterator {
|
||||
private $iterator;
|
||||
private $current;
|
||||
private $key;
|
||||
private $valid;
|
||||
private $position;
|
||||
|
||||
// This doc comment block generated by idl/sysdoc.php
|
||||
/**
|
||||
@@ -72,7 +76,7 @@ class IteratorIterator implements OuterIterator {
|
||||
* @return mixed The key of the current element.
|
||||
*/
|
||||
public function key() {
|
||||
return $this->iterator->key();
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
// This doc comment block generated by idl/sysdoc.php
|
||||
@@ -84,7 +88,7 @@ class IteratorIterator implements OuterIterator {
|
||||
* @return mixed The value of the current element.
|
||||
*/
|
||||
public function current() {
|
||||
return $this->iterator->current();
|
||||
return $this->current;
|
||||
}
|
||||
|
||||
// This doc comment block generated by idl/sysdoc.php
|
||||
@@ -96,7 +100,10 @@ class IteratorIterator implements OuterIterator {
|
||||
* @return mixed No value is returned.
|
||||
*/
|
||||
public function next() {
|
||||
return $this->iterator->next();
|
||||
$this->iterator->next();
|
||||
$this->_position++;
|
||||
$this->_fetch(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// This doc comment block generated by idl/sysdoc.php
|
||||
@@ -108,10 +115,42 @@ class IteratorIterator implements OuterIterator {
|
||||
* @return mixed No value is returned.
|
||||
*/
|
||||
public function rewind() {
|
||||
return $this->iterator->rewind();
|
||||
$this->iterator->rewind();
|
||||
$this->_position = 0;
|
||||
$this->_fetch(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public function __call($func, $params) {
|
||||
return call_user_func_array(array($this->iterator, $func), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function appears in the php source in spl_iterators.c as
|
||||
* spl_dual_it_fetch. Apparently, all iterators that store other
|
||||
* iterators are forced to do this layer of caching. If you call
|
||||
* next(), these "dual" iterators will need to get the key and
|
||||
* current value out of the underlying iterator and store it.
|
||||
*
|
||||
* Basically, if you see a call to spl_dual_it_fetch in the
|
||||
* PHP source, it's very likely that you should call this.
|
||||
*/
|
||||
protected function _fetch($check) {
|
||||
if (!$check || $this->iterator->valid()) {
|
||||
$this->current = $this->iterator->current();
|
||||
$key = $this->iterator->key();
|
||||
$this->key = is_null($key) ? $this->_position : $key;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function _getPosition() {
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
protected function _setPosition($position) {
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
// Create an iterator to be limited
|
||||
$fruits = new ArrayIterator(array(
|
||||
'apple',
|
||||
'banana',
|
||||
'cherry',
|
||||
'damson',
|
||||
'elderberry'
|
||||
));
|
||||
|
||||
// Loop over first three fruits only
|
||||
foreach (new LimitIterator($fruits, 0, 3) as $fruit) {
|
||||
var_dump($fruit);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Loop from third fruit until the end
|
||||
// Note: offset starts from zero for apple
|
||||
foreach (new LimitIterator($fruits, 2) as $fruit) {
|
||||
var_dump($fruit);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
string(5) "apple"
|
||||
string(6) "banana"
|
||||
string(6) "cherry"
|
||||
|
||||
string(6) "cherry"
|
||||
string(6) "damson"
|
||||
string(10) "elderberry"
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
$arr = new ArrayIterator(array('a','b','c'));
|
||||
|
||||
function check_seek($lim, $seek) {
|
||||
try {
|
||||
$lim->seek($seek);
|
||||
} catch (OutOfBoundsException $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$lim1 = new LimitIterator($arr, 0, 2);
|
||||
check_seek($lim1, 0);
|
||||
check_seek($lim1, 1);
|
||||
check_seek($lim1, 2);
|
||||
|
||||
$lim2 = new LimitIterator($arr, 1);
|
||||
check_seek($lim2, 0);
|
||||
check_seek($lim2, 1);
|
||||
check_seek($lim2, 2);
|
||||
@@ -0,0 +1,2 @@
|
||||
string(54) "Cannot seek to 2 which is behind offset 0 plus count 2"
|
||||
string(44) "Cannot seek to 0 which is below the offset 1"
|
||||
Referência em uma Nova Issue
Bloquear um usuário