Projekt

Obecné

Profil

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