Skip to content

Commit b534d61

Browse files
committed
[Yaml] Remove escaping regex
1 parent e4b48bb commit b534d61

File tree

4 files changed

+62
-35
lines changed

4 files changed

+62
-35
lines changed

benchmark.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
use Symfony\Component\Yaml\Parser;
6+
7+
$parser = new Parser();
8+
9+
$start = microtime(true);
10+
11+
for ($i = 0; $i < 10000; ++$i) {
12+
$parser->parse('[foo, bar, quz: foo, {bar: foo, quz: mou,}]');
13+
}
14+
15+
echo 'Time: '.(microtime(true) - $start).PHP_EOL;

src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/legacy-services9.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ parameters:
44

55
services:
66
foo:
7-
class: Bar\FooClass
7+
class: "Bar\\FooClass"
88
tags:
99
- { name: foo, foo: foo }
1010
- { name: foo, bar: bar }
11-
factory_class: Bar\FooClass
11+
factory_class: "Bar\\FooClass"
1212
factory_method: getInstance
1313
arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container']
1414
properties: { foo: bar, moo: '@foo.baz', qux: { '%foo%': 'foo is %foo%', foobar: '%foo%' } }

src/Symfony/Component/Yaml/Escaper.php

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,22 @@ class Escaper
2626
// first to ensure proper escaping because str_replace operates iteratively
2727
// on the input arrays. This ordering of the characters avoids the use of strtr,
2828
// which performs more slowly.
29-
private static $escapees = array('\\', '\\\\', '\\"', '"',
30-
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
31-
"\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
32-
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
33-
"\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
34-
"\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9");
35-
private static $escaped = array('\\\\', '\\"', '\\\\', '\\"',
36-
'\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a',
37-
'\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f',
38-
'\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',
39-
'\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f',
40-
'\\N', '\\_', '\\L', '\\P');
29+
private static $escapees = array(
30+
'\\', '\\\\', '\\"', '"', '/',
31+
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
32+
"\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
33+
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
34+
"\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
35+
"\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9",
36+
);
37+
private static $escaped = array(
38+
'\\\\', '\\"', '\\\\', '\\"', '\\/',
39+
'\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a',
40+
'\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f',
41+
'\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',
42+
'\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f',
43+
'\\N', '\\_', '\\L', '\\P',
44+
);
4145

4246
/**
4347
* Determines if a PHP value would require double quoting in YAML.
@@ -48,7 +52,10 @@ class Escaper
4852
*/
4953
public static function requiresDoubleQuoting($value)
5054
{
51-
return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value);
55+
// Removes quotes and slashes
56+
$mask = implode('', array_slice(self::$escapees, 5));
57+
58+
return strlen($value) !== strcspn($value, $mask);
5259
}
5360

5461
/**
@@ -78,9 +85,13 @@ public static function requiresSingleQuoting($value)
7885
return true;
7986
}
8087

81-
// Determines if the PHP value contains any single characters that would
82-
// cause it to require single quoting in YAML.
83-
return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value);
88+
// First character is reserved
89+
if ($value && in_array($value[0], array('-', '|', '<', '>', '=', '!', '%', '@', '`'))) {
90+
return true;
91+
}
92+
93+
// Contains spaces or ambigous characters
94+
return strlen($value) !== strcspn($value, "\011\n\013\014\r '\":{}[],&*#?");
8495
}
8596

8697
/**

src/Symfony/Component/Yaml/Tests/DumperTest.php

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -209,23 +209,24 @@ public function testEscapedEscapeSequencesInQuotedScalar($input, $expected)
209209
public function getEscapeSequences()
210210
{
211211
return array(
212-
'null' => array("\t\\0", '"\t\\\\0"'),
213-
'bell' => array("\t\\a", '"\t\\\\a"'),
214-
'backspace' => array("\t\\b", '"\t\\\\b"'),
215-
'horizontal-tab' => array("\t\\t", '"\t\\\\t"'),
216-
'line-feed' => array("\t\\n", '"\t\\\\n"'),
217-
'vertical-tab' => array("\t\\v", '"\t\\\\v"'),
218-
'form-feed' => array("\t\\f", '"\t\\\\f"'),
219-
'carriage-return' => array("\t\\r", '"\t\\\\r"'),
220-
'escape' => array("\t\\e", '"\t\\\\e"'),
221-
'space' => array("\t\\ ", '"\t\\\\ "'),
222-
'double-quote' => array("\t\\\"", '"\t\\\\\\""'),
223-
'slash' => array("\t\\/", '"\t\\\\/"'),
224-
'backslash' => array("\t\\\\", '"\t\\\\\\\\"'),
225-
'next-line' => array("\t\\N", '"\t\\\\N"'),
226-
'non-breaking-space' => array("\t\\", '"\t\\\\�"'),
227-
'line-separator' => array("\t\\L", '"\t\\\\L"'),
228-
'paragraph-separator' => array("\t\\P", '"\t\\\\P"'),
212+
'null' => array("\x0", '"\\0"'),
213+
'bell' => array("\x7", '"\\a"'),
214+
'backspace' => array("\x8", '"\\b"'),
215+
'horizontal-tab' => array("\t", '"\\t"'),
216+
'line-feed' => array("\n", '"\\n"'),
217+
'vertical-tab' => array("\v", '"\\v"'),
218+
'form-feed' => array("\xC", '"\\f"'),
219+
'carriage-return' => array("\r", '"\\r"'),
220+
'escape' => array("\x1B", '"\\e"'),
221+
'space' => array(' ', "' '"),
222+
'double-quote' => array('"', "'\"'"),
223+
'slash' => array('/', '/'),
224+
'backslash' => array('\\', "\\"),
225+
'next-line' => array("\xC2\x85", '"\\N"'),
226+
'non-breaking-space' => array('', ''),
227+
'line-separator' => array("\xE2\x80\xA8", '"\\L"'),
228+
'paragraph-separator' => array("\xE2\x80\xA9", '"\\P"'),
229+
'colon' => array(':', "':'"),
229230
);
230231
}
231232

0 commit comments

Comments
 (0)