4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Yaml;
14 use Symfony\Component\Yaml\Exception\ParseException;
17 * Unescaper encapsulates unescaping rules for single and double-quoted
20 * @author Matthew Lewinski <matthew@lewinski.org>
27 * Regex fragment that matches an escaped character in a double quoted string.
29 const REGEX_ESCAPED_CHARACTER = '\\\\(x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8}|.)';
32 * Unescapes a single quoted string.
34 * @param string $value A single quoted string
36 * @return string The unescaped string
38 public function unescapeSingleQuotedString($value)
40 return str_replace('\'\'', '\'', $value);
44 * Unescapes a double quoted string.
46 * @param string $value A double quoted string
48 * @return string The unescaped string
50 public function unescapeDoubleQuotedString($value)
52 $callback = function ($match) {
53 return $this->unescapeCharacter($match[0]);
56 // evaluate the string
57 return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value);
61 * Unescapes a character that was found in a double-quoted string.
63 * @param string $value An escaped character
65 * @return string The unescaped character
67 private function unescapeCharacter($value)
102 // U+00A0 NO-BREAK SPACE
105 // U+2028 LINE SEPARATOR
106 return "\xE2\x80\xA8";
108 // U+2029 PARAGRAPH SEPARATOR
109 return "\xE2\x80\xA9";
111 return self::utf8chr(hexdec(substr($value, 2, 2)));
113 return self::utf8chr(hexdec(substr($value, 2, 4)));
115 return self::utf8chr(hexdec(substr($value, 2, 8)));
117 throw new ParseException(sprintf('Found unknown escape character "%s".', $value));
122 * Get the UTF-8 character for the given code point.
124 * @param int $c The unicode code point
126 * @return string The corresponding UTF-8 character
128 private static function utf8chr($c)
130 if (0x80 > $c %= 0x200000) {
134 return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F);
137 return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F);
140 return \chr(0xF0 | $c >> 18).\chr(0x80 | $c >> 12 & 0x3F).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F);