Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\Yaml;
|
Chris@0
|
13
|
Chris@0
|
14 use Symfony\Component\Yaml\Exception\ParseException;
|
Chris@0
|
15
|
Chris@0
|
16 /**
|
Chris@0
|
17 * Unescaper encapsulates unescaping rules for single and double-quoted
|
Chris@0
|
18 * YAML strings.
|
Chris@0
|
19 *
|
Chris@0
|
20 * @author Matthew Lewinski <matthew@lewinski.org>
|
Chris@0
|
21 *
|
Chris@0
|
22 * @internal
|
Chris@0
|
23 */
|
Chris@0
|
24 class Unescaper
|
Chris@0
|
25 {
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Regex fragment that matches an escaped character in a double quoted string.
|
Chris@0
|
28 */
|
Chris@0
|
29 const REGEX_ESCAPED_CHARACTER = '\\\\(x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8}|.)';
|
Chris@0
|
30
|
Chris@0
|
31 /**
|
Chris@0
|
32 * Unescapes a single quoted string.
|
Chris@0
|
33 *
|
Chris@0
|
34 * @param string $value A single quoted string
|
Chris@0
|
35 *
|
Chris@0
|
36 * @return string The unescaped string
|
Chris@0
|
37 */
|
Chris@0
|
38 public function unescapeSingleQuotedString($value)
|
Chris@0
|
39 {
|
Chris@0
|
40 return str_replace('\'\'', '\'', $value);
|
Chris@0
|
41 }
|
Chris@0
|
42
|
Chris@0
|
43 /**
|
Chris@0
|
44 * Unescapes a double quoted string.
|
Chris@0
|
45 *
|
Chris@0
|
46 * @param string $value A double quoted string
|
Chris@0
|
47 *
|
Chris@0
|
48 * @return string The unescaped string
|
Chris@0
|
49 */
|
Chris@0
|
50 public function unescapeDoubleQuotedString($value)
|
Chris@0
|
51 {
|
Chris@0
|
52 $callback = function ($match) {
|
Chris@0
|
53 return $this->unescapeCharacter($match[0]);
|
Chris@0
|
54 };
|
Chris@0
|
55
|
Chris@0
|
56 // evaluate the string
|
Chris@0
|
57 return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value);
|
Chris@0
|
58 }
|
Chris@0
|
59
|
Chris@0
|
60 /**
|
Chris@0
|
61 * Unescapes a character that was found in a double-quoted string.
|
Chris@0
|
62 *
|
Chris@0
|
63 * @param string $value An escaped character
|
Chris@0
|
64 *
|
Chris@0
|
65 * @return string The unescaped character
|
Chris@0
|
66 */
|
Chris@0
|
67 private function unescapeCharacter($value)
|
Chris@0
|
68 {
|
Chris@0
|
69 switch ($value[1]) {
|
Chris@0
|
70 case '0':
|
Chris@0
|
71 return "\x0";
|
Chris@0
|
72 case 'a':
|
Chris@0
|
73 return "\x7";
|
Chris@0
|
74 case 'b':
|
Chris@0
|
75 return "\x8";
|
Chris@0
|
76 case 't':
|
Chris@0
|
77 return "\t";
|
Chris@0
|
78 case "\t":
|
Chris@0
|
79 return "\t";
|
Chris@0
|
80 case 'n':
|
Chris@0
|
81 return "\n";
|
Chris@0
|
82 case 'v':
|
Chris@0
|
83 return "\xB";
|
Chris@0
|
84 case 'f':
|
Chris@0
|
85 return "\xC";
|
Chris@0
|
86 case 'r':
|
Chris@0
|
87 return "\r";
|
Chris@0
|
88 case 'e':
|
Chris@0
|
89 return "\x1B";
|
Chris@0
|
90 case ' ':
|
Chris@0
|
91 return ' ';
|
Chris@0
|
92 case '"':
|
Chris@0
|
93 return '"';
|
Chris@0
|
94 case '/':
|
Chris@0
|
95 return '/';
|
Chris@0
|
96 case '\\':
|
Chris@0
|
97 return '\\';
|
Chris@0
|
98 case 'N':
|
Chris@0
|
99 // U+0085 NEXT LINE
|
Chris@0
|
100 return "\xC2\x85";
|
Chris@0
|
101 case '_':
|
Chris@0
|
102 // U+00A0 NO-BREAK SPACE
|
Chris@0
|
103 return "\xC2\xA0";
|
Chris@0
|
104 case 'L':
|
Chris@0
|
105 // U+2028 LINE SEPARATOR
|
Chris@0
|
106 return "\xE2\x80\xA8";
|
Chris@0
|
107 case 'P':
|
Chris@0
|
108 // U+2029 PARAGRAPH SEPARATOR
|
Chris@0
|
109 return "\xE2\x80\xA9";
|
Chris@0
|
110 case 'x':
|
Chris@0
|
111 return self::utf8chr(hexdec(substr($value, 2, 2)));
|
Chris@0
|
112 case 'u':
|
Chris@0
|
113 return self::utf8chr(hexdec(substr($value, 2, 4)));
|
Chris@0
|
114 case 'U':
|
Chris@0
|
115 return self::utf8chr(hexdec(substr($value, 2, 8)));
|
Chris@0
|
116 default:
|
Chris@0
|
117 throw new ParseException(sprintf('Found unknown escape character "%s".', $value));
|
Chris@0
|
118 }
|
Chris@0
|
119 }
|
Chris@0
|
120
|
Chris@0
|
121 /**
|
Chris@0
|
122 * Get the UTF-8 character for the given code point.
|
Chris@0
|
123 *
|
Chris@0
|
124 * @param int $c The unicode code point
|
Chris@0
|
125 *
|
Chris@0
|
126 * @return string The corresponding UTF-8 character
|
Chris@0
|
127 */
|
Chris@0
|
128 private static function utf8chr($c)
|
Chris@0
|
129 {
|
Chris@0
|
130 if (0x80 > $c %= 0x200000) {
|
Chris@17
|
131 return \chr($c);
|
Chris@0
|
132 }
|
Chris@0
|
133 if (0x800 > $c) {
|
Chris@17
|
134 return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F);
|
Chris@0
|
135 }
|
Chris@0
|
136 if (0x10000 > $c) {
|
Chris@17
|
137 return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F);
|
Chris@0
|
138 }
|
Chris@0
|
139
|
Chris@17
|
140 return \chr(0xF0 | $c >> 18).\chr(0x80 | $c >> 12 & 0x3F).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F);
|
Chris@0
|
141 }
|
Chris@0
|
142 }
|