PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / prefixed / symfony / string / ByteString.php
matomo / app / vendor / prefixed / symfony / string Last commit date
Exception 2 years ago Inflector 1 year ago Resources 1 year ago Slugger 1 year ago AbstractString.php 1 year ago AbstractUnicodeString.php 1 year ago ByteString.php 1 year ago CodePointString.php 1 year ago LICENSE 2 years ago LazyString.php 2 years ago README.md 2 years ago UnicodeString.php 1 year ago
ByteString.php
405 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace Matomo\Dependencies\Symfony\Component\String;
12
13 use Matomo\Dependencies\Symfony\Component\String\Exception\ExceptionInterface;
14 use Matomo\Dependencies\Symfony\Component\String\Exception\InvalidArgumentException;
15 use Matomo\Dependencies\Symfony\Component\String\Exception\RuntimeException;
16 /**
17 * Represents a binary-safe string of bytes.
18 *
19 * @author Nicolas Grekas <p@tchwork.com>
20 * @author Hugo Hamon <hugohamon@neuf.fr>
21 *
22 * @throws ExceptionInterface
23 */
24 class ByteString extends AbstractString
25 {
26 private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
27 public function __construct(string $string = '')
28 {
29 $this->string = $string;
30 }
31 /*
32 * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
33 *
34 * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
35 *
36 * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
37 *
38 * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
39 */
40 public static function fromRandom(int $length = 16, ?string $alphabet = null) : self
41 {
42 if ($length <= 0) {
43 throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length));
44 }
45 $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC;
46 $alphabetSize = \strlen($alphabet);
47 $bits = (int) ceil(log($alphabetSize, 2.0));
48 if ($bits <= 0 || $bits > 56) {
49 throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
50 }
51 $ret = '';
52 while ($length > 0) {
53 $urandomLength = (int) ceil(2 * $length * $bits / 8.0);
54 $data = random_bytes($urandomLength);
55 $unpackedData = 0;
56 $unpackedBits = 0;
57 for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
58 // Unpack 8 bits
59 $unpackedData = $unpackedData << 8 | \ord($data[$i]);
60 $unpackedBits += 8;
61 // While we have enough bits to select a character from the alphabet, keep
62 // consuming the random data
63 for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
64 $index = $unpackedData & (1 << $bits) - 1;
65 $unpackedData >>= $bits;
66 // Unfortunately, the alphabet size is not necessarily a power of two.
67 // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
68 // have around a 50% chance of missing as k gets larger
69 if ($index < $alphabetSize) {
70 $ret .= $alphabet[$index];
71 --$length;
72 }
73 }
74 }
75 }
76 return new static($ret);
77 }
78 public function bytesAt(int $offset) : array
79 {
80 $str = $this->string[$offset] ?? '';
81 return '' === $str ? [] : [\ord($str)];
82 }
83 public function append(string ...$suffix) : parent
84 {
85 $str = clone $this;
86 $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : implode('', $suffix);
87 return $str;
88 }
89 public function camel() : parent
90 {
91 $str = clone $this;
92 $parts = explode(' ', trim(ucwords(preg_replace('/[^a-zA-Z0-9\\x7f-\\xff]++/', ' ', $this->string))));
93 $parts[0] = 1 !== \strlen($parts[0]) && ctype_upper($parts[0]) ? $parts[0] : lcfirst($parts[0]);
94 $str->string = implode('', $parts);
95 return $str;
96 }
97 public function chunk(int $length = 1) : array
98 {
99 if (1 > $length) {
100 throw new InvalidArgumentException('The chunk length must be greater than zero.');
101 }
102 if ('' === $this->string) {
103 return [];
104 }
105 $str = clone $this;
106 $chunks = [];
107 foreach (str_split($this->string, $length) as $chunk) {
108 $str->string = $chunk;
109 $chunks[] = clone $str;
110 }
111 return $chunks;
112 }
113 public function endsWith($suffix) : bool
114 {
115 if ($suffix instanceof parent) {
116 $suffix = $suffix->string;
117 } elseif (\is_array($suffix) || $suffix instanceof \Traversable) {
118 return parent::endsWith($suffix);
119 } else {
120 $suffix = (string) $suffix;
121 }
122 return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
123 }
124 public function equalsTo($string) : bool
125 {
126 if ($string instanceof parent) {
127 $string = $string->string;
128 } elseif (\is_array($string) || $string instanceof \Traversable) {
129 return parent::equalsTo($string);
130 } else {
131 $string = (string) $string;
132 }
133 if ('' !== $string && $this->ignoreCase) {
134 return 0 === strcasecmp($string, $this->string);
135 }
136 return $string === $this->string;
137 }
138 public function folded() : parent
139 {
140 $str = clone $this;
141 $str->string = strtolower($str->string);
142 return $str;
143 }
144 public function indexOf($needle, int $offset = 0) : ?int
145 {
146 if ($needle instanceof parent) {
147 $needle = $needle->string;
148 } elseif (\is_array($needle) || $needle instanceof \Traversable) {
149 return parent::indexOf($needle, $offset);
150 } else {
151 $needle = (string) $needle;
152 }
153 if ('' === $needle) {
154 return null;
155 }
156 $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset);
157 return \false === $i ? null : $i;
158 }
159 public function indexOfLast($needle, int $offset = 0) : ?int
160 {
161 if ($needle instanceof parent) {
162 $needle = $needle->string;
163 } elseif (\is_array($needle) || $needle instanceof \Traversable) {
164 return parent::indexOfLast($needle, $offset);
165 } else {
166 $needle = (string) $needle;
167 }
168 if ('' === $needle) {
169 return null;
170 }
171 $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset);
172 return \false === $i ? null : $i;
173 }
174 public function isUtf8() : bool
175 {
176 return '' === $this->string || preg_match('//u', $this->string);
177 }
178 public function join(array $strings, ?string $lastGlue = null) : parent
179 {
180 $str = clone $this;
181 $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . array_pop($strings) : '';
182 $str->string = implode($this->string, $strings) . $tail;
183 return $str;
184 }
185 public function length() : int
186 {
187 return \strlen($this->string);
188 }
189 public function lower() : parent
190 {
191 $str = clone $this;
192 $str->string = strtolower($str->string);
193 return $str;
194 }
195 public function match(string $regexp, int $flags = 0, int $offset = 0) : array
196 {
197 $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
198 if ($this->ignoreCase) {
199 $regexp .= 'i';
200 }
201 set_error_handler(static function ($t, $m) {
202 throw new InvalidArgumentException($m);
203 });
204 try {
205 if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
206 $lastError = preg_last_error();
207 foreach (get_defined_constants(\true)['pcre'] as $k => $v) {
208 if ($lastError === $v && '_ERROR' === substr($k, -6)) {
209 throw new RuntimeException('Matching failed with ' . $k . '.');
210 }
211 }
212 throw new RuntimeException('Matching failed with unknown error code.');
213 }
214 } finally {
215 restore_error_handler();
216 }
217 return $matches;
218 }
219 public function padBoth(int $length, string $padStr = ' ') : parent
220 {
221 $str = clone $this;
222 $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH);
223 return $str;
224 }
225 public function padEnd(int $length, string $padStr = ' ') : parent
226 {
227 $str = clone $this;
228 $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT);
229 return $str;
230 }
231 public function padStart(int $length, string $padStr = ' ') : parent
232 {
233 $str = clone $this;
234 $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT);
235 return $str;
236 }
237 public function prepend(string ...$prefix) : parent
238 {
239 $str = clone $this;
240 $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : implode('', $prefix)) . $str->string;
241 return $str;
242 }
243 public function replace(string $from, string $to) : parent
244 {
245 $str = clone $this;
246 if ('' !== $from) {
247 $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string);
248 }
249 return $str;
250 }
251 public function replaceMatches(string $fromRegexp, $to) : parent
252 {
253 if ($this->ignoreCase) {
254 $fromRegexp .= 'i';
255 }
256 if (\is_array($to)) {
257 if (!\is_callable($to)) {
258 throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class));
259 }
260 $replace = 'preg_replace_callback';
261 } else {
262 $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';
263 }
264 set_error_handler(static function ($t, $m) {
265 throw new InvalidArgumentException($m);
266 });
267 try {
268 if (null === ($string = $replace($fromRegexp, $to, $this->string))) {
269 $lastError = preg_last_error();
270 foreach (get_defined_constants(\true)['pcre'] as $k => $v) {
271 if ($lastError === $v && '_ERROR' === substr($k, -6)) {
272 throw new RuntimeException('Matching failed with ' . $k . '.');
273 }
274 }
275 throw new RuntimeException('Matching failed with unknown error code.');
276 }
277 } finally {
278 restore_error_handler();
279 }
280 $str = clone $this;
281 $str->string = $string;
282 return $str;
283 }
284 public function reverse() : parent
285 {
286 $str = clone $this;
287 $str->string = strrev($str->string);
288 return $str;
289 }
290 public function slice(int $start = 0, ?int $length = null) : parent
291 {
292 $str = clone $this;
293 $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX);
294 return $str;
295 }
296 public function snake() : parent
297 {
298 $str = $this->camel();
299 $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], '\\1_\\2', $str->string));
300 return $str;
301 }
302 public function splice(string $replacement, int $start = 0, ?int $length = null) : parent
303 {
304 $str = clone $this;
305 $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
306 return $str;
307 }
308 public function split(string $delimiter, ?int $limit = null, ?int $flags = null) : array
309 {
310 if (1 > ($limit = $limit ?? \PHP_INT_MAX)) {
311 throw new InvalidArgumentException('Split limit must be a positive integer.');
312 }
313 if ('' === $delimiter) {
314 throw new InvalidArgumentException('Split delimiter is empty.');
315 }
316 if (null !== $flags) {
317 return parent::split($delimiter, $limit, $flags);
318 }
319 $str = clone $this;
320 $chunks = $this->ignoreCase ? preg_split('{' . preg_quote($delimiter) . '}iD', $this->string, $limit) : explode($delimiter, $this->string, $limit);
321 foreach ($chunks as &$chunk) {
322 $str->string = $chunk;
323 $chunk = clone $str;
324 }
325 return $chunks;
326 }
327 public function startsWith($prefix) : bool
328 {
329 if ($prefix instanceof parent) {
330 $prefix = $prefix->string;
331 } elseif (!\is_string($prefix)) {
332 return parent::startsWith($prefix);
333 }
334 return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix)));
335 }
336 public function title(bool $allWords = \false) : parent
337 {
338 $str = clone $this;
339 $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string);
340 return $str;
341 }
342 public function toUnicodeString(?string $fromEncoding = null) : UnicodeString
343 {
344 return new UnicodeString($this->toCodePointString($fromEncoding)->string);
345 }
346 public function toCodePointString(?string $fromEncoding = null) : CodePointString
347 {
348 $u = new CodePointString();
349 if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && preg_match('//u', $this->string)) {
350 $u->string = $this->string;
351 return $u;
352 }
353 set_error_handler(static function ($t, $m) {
354 throw new InvalidArgumentException($m);
355 });
356 try {
357 try {
358 $validEncoding = \false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true);
359 } catch (InvalidArgumentException $e) {
360 if (!\function_exists('iconv')) {
361 throw $e;
362 }
363 $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);
364 return $u;
365 }
366 } finally {
367 restore_error_handler();
368 }
369 if (!$validEncoding) {
370 throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
371 }
372 $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
373 return $u;
374 }
375 public function trim(string $chars = " \t\n\r\x00\v\f") : parent
376 {
377 $str = clone $this;
378 $str->string = trim($str->string, $chars);
379 return $str;
380 }
381 public function trimEnd(string $chars = " \t\n\r\x00\v\f") : parent
382 {
383 $str = clone $this;
384 $str->string = rtrim($str->string, $chars);
385 return $str;
386 }
387 public function trimStart(string $chars = " \t\n\r\x00\v\f") : parent
388 {
389 $str = clone $this;
390 $str->string = ltrim($str->string, $chars);
391 return $str;
392 }
393 public function upper() : parent
394 {
395 $str = clone $this;
396 $str->string = strtoupper($str->string);
397 return $str;
398 }
399 public function width(bool $ignoreAnsiDecoration = \true) : int
400 {
401 $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\\x80-\\xFF]/', '?', $this->string);
402 return (new CodePointString($string))->width($ignoreAnsiDecoration);
403 }
404 }
405