comparison vendor/masterminds/html5/src/HTML5/Parser/StringInputStream.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 4c8ae668cc8c
children
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
1 <?php 1 <?php
2 /** 2 /**
3 * Loads a string to be parsed. 3 * Loads a string to be parsed.
4 */ 4 */
5
5 namespace Masterminds\HTML5\Parser; 6 namespace Masterminds\HTML5\Parser;
6 7
7 /* 8 /*
8 * 9 *
9 * Based on code from html5lib: 10 * Based on code from html5lib:
37 // HTML5-PHP, I have been using this version: 38 // HTML5-PHP, I have been using this version:
38 // http://www.w3.org/TR/2012/CR-html5-20121217/Overview.html#contents 39 // http://www.w3.org/TR/2012/CR-html5-20121217/Overview.html#contents
39 // 40 //
40 // - // indicates regular comments 41 // - // indicates regular comments
41 42
43 /**
44 * @deprecated since 2.4, to remove in 3.0. Use a string in the scanner instead.
45 */
42 class StringInputStream implements InputStream 46 class StringInputStream implements InputStream
43 { 47 {
44
45 /** 48 /**
46 * The string data we're parsing. 49 * The string data we're parsing.
47 */ 50 */
48 private $data; 51 private $data;
49 52
50 /** 53 /**
51 * The current integer byte position we are in $data 54 * The current integer byte position we are in $data.
52 */ 55 */
53 private $char; 56 private $char;
54 57
55 /** 58 /**
56 * Length of $data; when $char === $data, we are at the end-of-file. 59 * Length of $data; when $char === $data, we are at the end-of-file.
63 public $errors = array(); 66 public $errors = array();
64 67
65 /** 68 /**
66 * Create a new InputStream wrapper. 69 * Create a new InputStream wrapper.
67 * 70 *
68 * @param $data Data 71 * @param string $data Data to parse.
69 * to parse 72 * @param string $encoding The encoding to use for the data.
73 * @param string $debug A fprintf format to use to echo the data on stdout.
70 */ 74 */
71 public function __construct($data, $encoding = 'UTF-8', $debug = '') 75 public function __construct($data, $encoding = 'UTF-8', $debug = '')
72 { 76 {
73 $data = UTF8Utils::convertToUTF8($data, $encoding); 77 $data = UTF8Utils::convertToUTF8($data, $encoding);
74 if ($debug) 78 if ($debug) {
75 fprintf(STDOUT, $debug, $data, strlen($data)); 79 fprintf(STDOUT, $debug, $data, strlen($data));
76 80 }
77 // There is good reason to question whether it makes sense to 81
78 // do this here, since most of these checks are done during 82 // There is good reason to question whether it makes sense to
79 // parsing, and since this check doesn't actually *do* anything. 83 // do this here, since most of these checks are done during
84 // parsing, and since this check doesn't actually *do* anything.
80 $this->errors = UTF8Utils::checkForIllegalCodepoints($data); 85 $this->errors = UTF8Utils::checkForIllegalCodepoints($data);
81 // if (!empty($e)) {
82 // throw new ParseError("UTF-8 encoding issues: " . implode(', ', $e));
83 // }
84 86
85 $data = $this->replaceLinefeeds($data); 87 $data = $this->replaceLinefeeds($data);
86 88
87 $this->data = $data; 89 $this->data = $data;
88 $this->char = 0; 90 $this->char = 0;
89 $this->EOF = strlen($data); 91 $this->EOF = strlen($data);
90 } 92 }
91 93
94 public function __toString()
95 {
96 return $this->data;
97 }
98
92 /** 99 /**
93 * Replace linefeed characters according to the spec. 100 * Replace linefeed characters according to the spec.
94 */ 101 */
95 protected function replaceLinefeeds($data) 102 protected function replaceLinefeeds($data)
96 { 103 {
97 /* 104 /*
98 * U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. Any CR characters that are followed by LF characters must be removed, and any CR characters not followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are represented by LF characters, and there are never any CR characters in the input to the tokenization stage. 105 * U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially.
106 * Any CR characters that are followed by LF characters must be removed, and any CR characters not
107 * followed by LF characters must be converted to LF characters. Thus, newlines in HTML DOMs are
108 * represented by LF characters, and there are never any CR characters in the input to the tokenization
109 * stage.
99 */ 110 */
100 $crlfTable = array( 111 $crlfTable = array(
101 "\0" => "\xEF\xBF\xBD", 112 "\0" => "\xEF\xBF\xBD",
102 "\r\n" => "\n", 113 "\r\n" => "\n",
103 "\r" => "\n" 114 "\r" => "\n",
104 ); 115 );
105 116
106 return strtr($data, $crlfTable); 117 return strtr($data, $crlfTable);
107 } 118 }
108 119
109 /** 120 /**
110 * Returns the current line that the tokenizer is at. 121 * Returns the current line that the tokenizer is at.
111 */ 122 */
112 public function currentLine() 123 public function currentLine()
113 { 124 {
114 if (empty($this->EOF) || $this->char == 0) { 125 if (empty($this->EOF) || 0 === $this->char) {
115 return 1; 126 return 1;
116 } 127 }
117 // Add one to $this->char because we want the number for the next 128 // Add one to $this->char because we want the number for the next
118 // byte to be processed. 129 // byte to be processed.
119 return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1; 130 return substr_count($this->data, "\n", 0, min($this->char, $this->EOF)) + 1;
120 } 131 }
121 132
122 /** 133 /**
123 *
124 * @deprecated 134 * @deprecated
125 *
126 */ 135 */
127 public function getCurrentLine() 136 public function getCurrentLine()
128 { 137 {
129 return currentLine(); 138 return $this->currentLine();
130 } 139 }
131 140
132 /** 141 /**
133 * Returns the current column of the current line that the tokenizer is at. 142 * Returns the current column of the current line that the tokenizer is at.
134 *
135 * Newlines are column 0. The first char after a newline is column 1. 143 * Newlines are column 0. The first char after a newline is column 1.
136 * 144 *
137 * @return int The column number. 145 * @return int The column number.
138 */ 146 */
139 public function columnOffset() 147 public function columnOffset()
140 { 148 {
141 // Short circuit for the first char. 149 // Short circuit for the first char.
142 if ($this->char == 0) { 150 if (0 === $this->char) {
143 return 0; 151 return 0;
144 } 152 }
145 // strrpos is weird, and the offset needs to be negative for what we 153 // strrpos is weird, and the offset needs to be negative for what we
146 // want (i.e., the last \n before $this->char). This needs to not have 154 // want (i.e., the last \n before $this->char). This needs to not have
147 // one (to make it point to the next character, the one we want the 155 // one (to make it point to the next character, the one we want the
150 $backwardFrom = $this->char - 1 - strlen($this->data); 158 $backwardFrom = $this->char - 1 - strlen($this->data);
151 $lastLine = strrpos($this->data, "\n", $backwardFrom); 159 $lastLine = strrpos($this->data, "\n", $backwardFrom);
152 160
153 // However, for here we want the length up until the next byte to be 161 // However, for here we want the length up until the next byte to be
154 // processed, so add one to the current byte ($this->char). 162 // processed, so add one to the current byte ($this->char).
155 if ($lastLine !== false) { 163 if (false !== $lastLine) {
156 $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine); 164 $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine);
157 } else { 165 } else {
158 // After a newline. 166 // After a newline.
159 $findLengthOf = substr($this->data, 0, $this->char); 167 $findLengthOf = substr($this->data, 0, $this->char);
160 } 168 }
161 169
162 return UTF8Utils::countChars($findLengthOf); 170 return UTF8Utils::countChars($findLengthOf);
163 } 171 }
164 172
165 /** 173 /**
166 *
167 * @deprecated 174 * @deprecated
168 *
169 */ 175 */
170 public function getColumnOffset() 176 public function getColumnOffset()
171 { 177 {
172 return $this->columnOffset(); 178 return $this->columnOffset();
173 } 179 }
186 * Advance the pointer. 192 * Advance the pointer.
187 * This is part of the Iterator interface. 193 * This is part of the Iterator interface.
188 */ 194 */
189 public function next() 195 public function next()
190 { 196 {
191 $this->char ++; 197 ++$this->char;
192 } 198 }
193 199
194 /** 200 /**
195 * Rewind to the start of the string. 201 * Rewind to the start of the string.
196 */ 202 */
200 } 206 }
201 207
202 /** 208 /**
203 * Is the current pointer location valid. 209 * Is the current pointer location valid.
204 * 210 *
205 * @return bool Is the current pointer location valid. 211 * @return bool Whether the current pointer location is valid.
206 */ 212 */
207 public function valid() 213 public function valid()
208 { 214 {
209 if ($this->char < $this->EOF) { 215 return $this->char < $this->EOF;
210 return true;
211 }
212
213 return false;
214 } 216 }
215 217
216 /** 218 /**
217 * Get all characters until EOF. 219 * Get all characters until EOF.
218 * 220 *
219 * This reads to the end of the file, and sets the read marker at the 221 * This reads to the end of the file, and sets the read marker at the
220 * end of the file. 222 * end of the file.
221 * 223 *
222 * @note This performs bounds checking 224 * Note this performs bounds checking.
223 * 225 *
224 * @return string Returns the remaining text. If called when the InputStream is 226 * @return string Returns the remaining text. If called when the InputStream is
225 * already exhausted, it returns an empty string. 227 * already exhausted, it returns an empty string.
226 */ 228 */
227 public function remainingChars() 229 public function remainingChars()
228 { 230 {
229 if ($this->char < $this->EOF) { 231 if ($this->char < $this->EOF) {
230 $data = substr($this->data, $this->char); 232 $data = substr($this->data, $this->char);
242 * This operates on byte sequences, not characters. 244 * This operates on byte sequences, not characters.
243 * 245 *
244 * Matches as far as possible until we reach a certain set of bytes 246 * Matches as far as possible until we reach a certain set of bytes
245 * and returns the matched substring. 247 * and returns the matched substring.
246 * 248 *
247 * @param string $bytes 249 * @param string $bytes Bytes to match.
248 * Bytes to match. 250 * @param int $max Maximum number of bytes to scan.
249 * @param int $max 251 *
250 * Maximum number of bytes to scan.
251 * @return mixed Index or false if no match is found. You should use strong 252 * @return mixed Index or false if no match is found. You should use strong
252 * equality when checking the result, since index could be 0. 253 * equality when checking the result, since index could be 0.
253 */ 254 */
254 public function charsUntil($bytes, $max = null) 255 public function charsUntil($bytes, $max = null)
255 { 256 {
256 if ($this->char >= $this->EOF) { 257 if ($this->char >= $this->EOF) {
257 return false; 258 return false;
258 } 259 }
259 260
260 if ($max === 0 || $max) { 261 if (0 === $max || $max) {
261 $len = strcspn($this->data, $bytes, $this->char, $max); 262 $len = strcspn($this->data, $bytes, $this->char, $max);
262 } else { 263 } else {
263 $len = strcspn($this->data, $bytes, $this->char); 264 $len = strcspn($this->data, $bytes, $this->char);
264 } 265 }
265 266
273 * Returns the string so long as $bytes matches. 274 * Returns the string so long as $bytes matches.
274 * 275 *
275 * Matches as far as possible with a certain set of bytes 276 * Matches as far as possible with a certain set of bytes
276 * and returns the matched substring. 277 * and returns the matched substring.
277 * 278 *
278 * @param string $bytes 279 * @param string $bytes A mask of bytes to match. If ANY byte in this mask matches the
279 * A mask of bytes to match. If ANY byte in this mask matches the 280 * current char, the pointer advances and the char is part of the
280 * current char, the pointer advances and the char is part of the 281 * substring.
281 * substring. 282 * @param int $max The max number of chars to read.
282 * @param int $max 283 *
283 * The max number of chars to read. 284 * @return string
284 */ 285 */
285 public function charsWhile($bytes, $max = null) 286 public function charsWhile($bytes, $max = null)
286 { 287 {
287 if ($this->char >= $this->EOF) { 288 if ($this->char >= $this->EOF) {
288 return false; 289 return false;
289 } 290 }
290 291
291 if ($max === 0 || $max) { 292 if (0 === $max || $max) {
292 $len = strspn($this->data, $bytes, $this->char, $max); 293 $len = strspn($this->data, $bytes, $this->char, $max);
293 } else { 294 } else {
294 $len = strspn($this->data, $bytes, $this->char); 295 $len = strspn($this->data, $bytes, $this->char);
295 } 296 }
296 $string = (string) substr($this->data, $this->char, $len); 297 $string = (string) substr($this->data, $this->char, $len);
300 } 301 }
301 302
302 /** 303 /**
303 * Unconsume characters. 304 * Unconsume characters.
304 * 305 *
305 * @param int $howMany 306 * @param int $howMany The number of characters to unconsume.
306 * The number of characters to unconsume.
307 */ 307 */
308 public function unconsume($howMany = 1) 308 public function unconsume($howMany = 1)
309 { 309 {
310 if (($this->char - $howMany) >= 0) { 310 if (($this->char - $howMany) >= 0) {
311 $this->char = $this->char - $howMany; 311 $this->char -= $howMany;
312 } 312 }
313 } 313 }
314 314
315 /** 315 /**
316 * Look ahead without moving cursor. 316 * Look ahead without moving cursor.