Skip to content

Commit

Permalink
Optimize stripcslashes
Browse files Browse the repository at this point in the history
See twigphp#4176 (comment)

Co-Authored-By: Simon André <[email protected]>

```
# Old
Benchmark 1: php bench.php
  Time (mean ± σ):      1.192 s ±  0.004 s    [User: 1.163 s, System: 0.009 s]
  Range (min … max):    1.186 s …  1.198 s    10 runs

# New
Benchmark 1: php bench.php
  Time (mean ± σ):     356.5 ms ±   1.1 ms    [User: 342.0 ms, System: 7.6 ms]
  Range (min … max):   354.6 ms … 358.2 ms    10 runs
```

Using bench.php:
```
<?php

require_once __DIR__.'/vendor/autoload.php';

$string = str_repeat("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a tincidunt turpis. \\App\\Entity\\Product \World \065 App\#{var} \'quoted\' Donec pharetra enim quis erat pharetra, dignissim molestie erat laoreet. Vivamus auctor purus sed lorem vestibulum rhoncus.", 10);
$loader = new Twig\Loader\ArrayLoader([
    'index.twig' => <<<EOF
{{ "$string" }}
EOF
    ,
]);

$twig = new Twig\Environment($loader);

for ($i = 0; $i < 10000; $i++) {
    $twig->tokenize(new Twig\Source($twig->getLoader()->getSourceContext('index.twig')->getCode(), 'index.twig'));
}

```
  • Loading branch information
ruudk committed Aug 12, 2024
1 parent 5541e6a commit 49bf596
Showing 1 changed file with 28 additions and 35 deletions.
63 changes: 28 additions & 35 deletions src/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -398,62 +398,55 @@ private function stripcslashes(string $str, string $quoteType): string
'v' => "\v",
];

for ($i = 0; $i < $length; $i++) {
if ($str[$i] !== '\\' || $i + 1 >= $length) {
$result .= $str[$i];
$i = 0;
while ($i < $length) {
if (false === $pos = strpos($str, '\\', $i)) {
$result .= substr($str, $i);
break;
}

continue;
$result .= substr($str, $i, $pos - $i);
$i = $pos + 1;

if ($i >= $length) {
$result .= '\\';
break;
}

$nextChar = $str[$i + 1];
$nextChar = $str[$i];

if (isset($specialChars[$nextChar])) {
$result .= $specialChars[$nextChar];
$i++;
} elseif ($nextChar === '\\') {
$result .= '\\';
$i++;
$result .= $nextChar;
} elseif ($nextChar === "'" || $nextChar === '"') {
if ($nextChar !== $quoteType) {
trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d does not need to be escaped anymore.', $nextChar, $i + 2);
trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d does not need to be escaped anymore.', $nextChar, $i + 1);
}
$result .= $nextChar;
$i++;
} elseif ($nextChar === '#' && $i + 2 < $length && $str[$i + 2] === '{') {
} elseif ($nextChar === '#' && $i + 1 < $length && $str[$i + 1] === '{') {
$result .= '#{';
$i += 2;
} elseif ($nextChar === 'x' && $i + 2 < $length && ctype_xdigit($str[$i + 2])) {
$hex = $str[$i + 2];
if ($i + 3 < $length && ctype_xdigit($str[$i + 3])) {
$hex .= $str[$i + 3];
$i++;
$i++;
} elseif ($nextChar === 'x' && $i + 1 < $length && ctype_xdigit($str[$i + 1])) {
$hex = $str[++$i];
if ($i + 1 < $length && ctype_xdigit($str[$i + 1])) {
$hex .= $str[++$i];
}
$result .= chr(hexdec($hex));
$i += 2;
} elseif (ctype_digit($nextChar) && $nextChar < '8') {
$octal = $nextChar;
for ($j = $i + 1; $j <= 3; $j++) {
$o = $j + 1;
if ($o >= $length) {
break;
}
if (!ctype_digit($str[$o])) {
break;
}
if ($str[$o] >= '8') {
break;
}
$octal .= $str[$o];
$i++;
while ($i + 1 < $length && ctype_digit($str[$i + 1]) && $str[$i + 1] < '8' && strlen($octal) < 3) {
$octal .= $str[++$i];
}
$result .= chr(octdec($octal));
$i++;
} else {
trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d does not need to be escaped anymore.', $nextChar, $i + 2);
trigger_deprecation('twig/twig', '3.12', sprintf('Character "%s" at position %d does not need to be escaped anymore.', $nextChar, $i + 1));
$result .= $nextChar;
$i++;
}

$i++;
}

return $result;
}

Expand Down

0 comments on commit 49bf596

Please sign in to comment.