xref: /PHP-7.2/ext/spl/internal/limititerator.inc (revision 60a69dae)
1<?php
2
3/** @file limititerator.inc
4 * @ingroup SPL
5 * @brief class LimitIterator
6 * @author  Marcus Boerger
7 * @date    2003 - 2009
8 *
9 * SPL - Standard PHP Library
10 */
11
12/**
13 * @brief   Limited Iteration over another Iterator
14 * @author  Marcus Boerger
15 * @version 1.1
16 * @since PHP 5.0
17 *
18 * A class that starts iteration at a certain offset and only iterates over
19 * a specified amount of elements.
20 *
21 * This class uses SeekableIterator::seek() if available and rewind() plus
22 * a skip loop otehrwise.
23 */
24class LimitIterator implements OuterIterator
25{
26	private $it;
27	private $offset;
28	private $count;
29	private $pos;
30
31	/** Construct
32	 *
33	 * @param it     Iterator to limit
34	 * @param offset Offset to first element
35	 * @param count  Maximum number of elements to show or -1 for all
36	 */
37	function __construct(Iterator $it, $offset = 0, $count = -1)
38	{
39		if ($offset < 0) {
40			throw new exception('Parameter offset must be > 0');
41		}
42		if ($count < 0 && $count != -1) {
43			throw new exception('Parameter count must either be -1 or a value greater than or equal to 0');
44		}
45		$this->it     = $it;
46		$this->offset = $offset;
47		$this->count  = $count;
48		$this->pos    = 0;
49	}
50
51	/** Seek to specified position
52	 * @param position offset to seek to (relative to beginning not offset
53	 *                 specified in constructor).
54	 * @throw exception when position is invalid
55	 */
56	function seek($position) {
57		if ($position < $this->offset) {
58			throw new exception('Cannot seek to '.$position.' which is below offset '.$this->offset);
59		}
60		if ($position > $this->offset + $this->count && $this->count != -1) {
61			throw new exception('Cannot seek to '.$position.' which is behind offset '.$this->offset.' plus count '.$this->count);
62		}
63		if ($this->it instanceof SeekableIterator) {
64			$this->it->seek($position);
65			$this->pos = $position;
66		} else {
67			while($this->pos < $position && $this->it->valid()) {
68				$this->next();
69			}
70		}
71	}
72
73    /** Rewind to offset specified in constructor
74     */
75	function rewind()
76	{
77		$this->it->rewind();
78		$this->pos = 0;
79		$this->seek($this->offset);
80	}
81
82	/** @return whether iterator is valid
83	 */
84	function valid() {
85		return ($this->count == -1 || $this->pos < $this->offset + $this->count)
86			 && $this->it->valid();
87	}
88
89	/** @return current key
90	 */
91	function key() {
92		return $this->it->key();
93	}
94
95	/** @return current element
96	 */
97	function current() {
98		return $this->it->current();
99	}
100
101	/** Forward to nect element
102	 */
103	function next() {
104		$this->it->next();
105		$this->pos++;
106	}
107
108	/** @return current position relative to zero (not to offset specified in
109	 *          constructor).
110	 */
111	function getPosition() {
112		return $this->pos;
113	}
114
115	/**
116	 * @return The inner iterator
117	 */
118	function getInnerIterator()
119	{
120		return $this->it;
121	}
122
123	/** Aggregate the inner iterator
124	 *
125	 * @param func    Name of method to invoke
126	 * @param params  Array of parameters to pass to method
127	 */
128	function __call($func, $params)
129	{
130		return call_user_func_array(array($this->it, $func), $params);
131	}
132}
133
134?>
135