[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php declare(strict_types=1); 2 3 /** 4 * @package s9e\RegexpBuilder 5 * @copyright Copyright (c) 2016-2022 The s9e authors 6 * @license http://www.opensource.org/licenses/mit-license.php The MIT License 7 */ 8 namespace s9e\RegexpBuilder; 9 10 use InvalidArgumentException; 11 use function count, preg_match; 12 use s9e\RegexpBuilder\Input\InputInterface; 13 14 class MetaCharacters 15 { 16 /** 17 * @const Bit value that indicates whether a meta-character represents a single character usable 18 * in a character class 19 */ 20 const IS_CHAR = 1; 21 22 /** 23 * @const Bit value that indicates whether a meta-character represents a quantifiable expression 24 */ 25 const IS_QUANTIFIABLE = 2; 26 27 /** 28 * @var array Map of meta values and the expression they represent 29 */ 30 protected $exprs = []; 31 32 /** 33 * @var InputInterface 34 */ 35 protected $input; 36 37 /** 38 * @var array Map of meta-characters' codepoints and their value 39 */ 40 protected $meta = []; 41 42 /** 43 * @param InputInterface $input 44 */ 45 public function __construct(InputInterface $input) 46 { 47 $this->input = $input; 48 } 49 50 /** 51 * Add a meta-character to the list 52 * 53 * @param string $char Meta-character 54 * @param string $expr Regular expression 55 * @return void 56 */ 57 public function add(string $char, string $expr): void 58 { 59 $split = $this->input->split($char); 60 if (count($split) !== 1) 61 { 62 throw new InvalidArgumentException('Meta-characters must be represented by exactly one character'); 63 } 64 if (@preg_match('(' . $expr . ')u', '') === false) 65 { 66 throw new InvalidArgumentException("Invalid expression '" . $expr . "'"); 67 } 68 69 $inputValue = $split[0]; 70 $metaValue = $this->computeValue($expr); 71 72 $this->exprs[$metaValue] = $expr; 73 $this->meta[$inputValue] = $metaValue; 74 } 75 76 /** 77 * Get the expression associated with a meta value 78 * 79 * @param integer $metaValue 80 * @return string 81 */ 82 public function getExpression(int $metaValue): string 83 { 84 if (!isset($this->exprs[$metaValue])) 85 { 86 throw new InvalidArgumentException('Invalid meta value ' . $metaValue); 87 } 88 89 return $this->exprs[$metaValue]; 90 } 91 92 /** 93 * Return whether a given value represents a single character usable in a character class 94 * 95 * @param integer $value 96 * @return bool 97 */ 98 public static function isChar(int $value): bool 99 { 100 return ($value >= 0 || ($value & self::IS_CHAR)); 101 } 102 103 /** 104 * Return whether a given value represents a quantifiable expression 105 * 106 * @param integer $value 107 * @return bool 108 */ 109 public static function isQuantifiable(int $value): bool 110 { 111 return ($value >= 0 || ($value & self::IS_QUANTIFIABLE)); 112 } 113 114 /** 115 * Replace values from meta-characters in a list of strings with their meta value 116 * 117 * @param array[] $strings 118 * @return array[] 119 */ 120 public function replaceMeta(array $strings): array 121 { 122 foreach ($strings as &$string) 123 { 124 foreach ($string as &$value) 125 { 126 if (isset($this->meta[$value])) 127 { 128 $value = $this->meta[$value]; 129 } 130 } 131 } 132 133 return $strings; 134 } 135 136 /** 137 * Compute and return a value for given expression 138 * 139 * Values are meant to be a unique negative integer. The least significant bits are used to 140 * store the expression's properties 141 * 142 * @param string $expr Regular expression 143 * @return integer 144 */ 145 protected function computeValue(string $expr): int 146 { 147 $properties = [ 148 self::IS_CHAR => 'exprIsChar', 149 self::IS_QUANTIFIABLE => 'exprIsQuantifiable' 150 ]; 151 $value = (1 + count($this->meta)) * -(2 ** count($properties)); 152 foreach ($properties as $bitValue => $methodName) 153 { 154 if ($this->$methodName($expr)) 155 { 156 $value |= $bitValue; 157 } 158 } 159 160 return $value; 161 } 162 163 /** 164 * Test whether given expression represents a single character usable in a character class 165 * 166 * @param string $expr 167 * @return bool 168 */ 169 protected function exprIsChar(string $expr): bool 170 { 171 $regexps = [ 172 // Escaped literal or escape sequence such as \w but not \R 173 '(^\\\\[adefhnrstvwDHNSVW\\W]$)D', 174 175 // Unicode properties such as \pL or \p{Lu} 176 '(^\\\\p(?:.|\\{[^}]+\\})$)Di', 177 178 // An escape sequence such as \x1F or \x{2600} 179 '(^\\\\x(?:[0-9a-f]{2}|\\{[^}]+\\})$)Di' 180 ]; 181 182 return $this->matchesAny($expr, $regexps); 183 } 184 185 /** 186 * Test whether given expression is quantifiable 187 * 188 * @param string $expr 189 * @return bool 190 */ 191 protected function exprIsQuantifiable(string $expr): bool 192 { 193 $regexps = [ 194 // A dot or \R 195 '(^(?:\\.|\\\\R)$)D', 196 197 // A character class 198 '(^\\[\\^?(?:([^\\\\\\]]|\\\\.)(?:-(?-1))?)++\\]$)D' 199 ]; 200 201 return $this->matchesAny($expr, $regexps) || $this->exprIsChar($expr); 202 } 203 204 /** 205 * Test whether given expression matches any of the given regexps 206 * 207 * @param string $expr 208 * @param string[] $regexps 209 * @return bool 210 */ 211 protected function matchesAny(string $expr, array $regexps): bool 212 { 213 foreach ($regexps as $regexp) 214 { 215 if (preg_match($regexp, $expr)) 216 { 217 return true; 218 } 219 } 220 221 return false; 222 } 223 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |