Merge "rest: Return a 400 for invalid render IDs"
[mediawiki.git] / includes / libs / ExplodeIterator.php
blob461ae9b52ce9bcef1e7d5c938e6f7bc3347fa159
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @file
21 /**
22 * An iterator which works exactly like:
24 * foreach ( explode( $delim, $s ) as $element ) {
25 * ...
26 * }
28 * Except it doesn't use 193 byte per element
30 class ExplodeIterator implements Iterator {
31 /** @var string */
32 private $subject;
34 /** @var int */
35 private $subjectLength;
37 /** @var string */
38 private $delim;
40 /** @var int */
41 private $delimLength;
43 /** @var int|false The position of the start of the line */
44 private $curPos;
46 /** @var int|false The position after the end of the next delimiter */
47 private $endPos;
49 /** @var string|false The current token */
50 private $current;
52 /**
53 * Construct a DelimIterator
54 * @param string $delim
55 * @param string $subject
57 public function __construct( $delim, $subject ) {
58 $this->subject = $subject;
59 $this->delim = $delim;
61 // Micro-optimisation (theoretical)
62 $this->subjectLength = strlen( $subject );
63 $this->delimLength = strlen( $delim );
65 $this->rewind();
68 public function rewind(): void {
69 $this->curPos = 0;
70 $this->endPos = strpos( $this->subject, $this->delim );
71 $this->refreshCurrent();
74 public function refreshCurrent() {
75 if ( $this->curPos === false ) {
76 $this->current = false;
77 } elseif ( $this->curPos >= $this->subjectLength ) {
78 $this->current = '';
79 } elseif ( $this->endPos === false ) {
80 $this->current = substr( $this->subject, $this->curPos );
81 } else {
82 $this->current = substr( $this->subject, $this->curPos, $this->endPos - $this->curPos );
86 /**
87 * @return string|false
89 #[\ReturnTypeWillChange]
90 public function current() {
91 return $this->current;
94 /**
95 * @return int|false Current position or boolean false if invalid
97 #[\ReturnTypeWillChange]
98 public function key() {
99 return $this->curPos;
102 public function next(): void {
103 if ( $this->endPos === false ) {
104 $this->curPos = false;
105 } else {
106 $this->curPos = $this->endPos + $this->delimLength;
107 if ( $this->curPos >= $this->subjectLength ) {
108 $this->endPos = false;
109 } else {
110 $this->endPos = strpos( $this->subject, $this->delim, $this->curPos );
113 $this->refreshCurrent();
116 public function valid(): bool {
117 return $this->curPos !== false;