RequestFactory: optimized script path detection performance

Micro-optimization. 

Benchmark:
~~~php
$datasets = [
	'a' => [new UrlScript('/projects/blog/www/'), '/projects/blog/www/index.php', '/projects/blog/www/'],
	'b' => [new UrlScript('/projects/blog/www/contact'), '/projects/blog/www/index.php', '/projects/blog/www/'],
	'c' => [new UrlScript('/projects/blog/www/index.php'), '/projects/blog/www/index.php', '/projects/blog/www/index.php'],
	'd' => [new UrlScript('/test/in'), '/test/index.php', '/test/'],
	'e' => [new UrlScript('/test//'), '/test/index.php', '/test/'],
];

$tests = [
	'old' => function ($testCount, UrlScript $url, $script, $expected) {
		for ($x = 0; $x < $testCount; $x++) {
			$path = strtolower($url->getPath()) . '/';
			$script = strtolower($script) . '/';
			$max = min(strlen($path), strlen($script));
			for ($i = 0; $i < $max; $i++) {
				if ($path[$i] !== $script[$i]) {
					break;
				} elseif ($path[$i] === '/') {
					$url->setScriptPath(substr($url->getPath(), 0, $i + 1));
				}
			}
		}
		Assert::same($expected, $url->scriptPath);
	},
	'new1' => function ($testCount, UrlScript $url, $script, $expected) {
		for ($x = 0; $x < $testCount; $x++) {
			$path = $url->getPath();
			$min = min(strlen($path), strlen($script));
			for ($i = 0, $j = 0; $i < $min; $i++) {
				if ($path[$i] !== $script[$i] && strcasecmp($path[$i], $script[$i])) {
					break;
				} elseif ($path[$i] === '/') {
					$j = $i;
				}
			}
			$url->setScriptPath($i === $min && strlen($path) === strlen($script) ? $path : substr($path, 0, $j + 1));
		}
		Assert::same($expected, $url->scriptPath);
	},
	'new2' => function ($testCount, UrlScript $url, $script, $expected) {
		for ($x = 0; $x < $testCount; $x++) {
			$path = $url->getPath();
			$max = min(strlen($path), strlen($script));
			for ($i = 0; $i < $max; $i++) {
				if ($path[$i] !== $script[$i] && strcasecmp($path[$i], $script[$i])) {
					break;
				}
			}
			$url->setScriptPath($i === $max && strlen($path) === strlen($script)
				? $path
				: substr($path, 0, strrpos($path, '/', $i - $max - 1) + 1)
			);
		}
		Assert::same($expected, $url->scriptPath);
	},
	'new3' => function ($testCount, UrlScript $url, $script, $expected) {
		for ($x = 0; $x < $testCount; $x++) {
			$path = $url->getPath();
			$max = min(strlen($path), strlen($script));
			for ($i = 0; $i < $max && ($path[$i] === $script[$i] || !strcasecmp($path[$i], $script[$i])); $i++);
			$url->setScriptPath($i === $max && strlen($path) === strlen($script)
				? $path
				: substr($path, 0, strrpos($path, '/', $i - $max - 1) + 1)
			);
		}
		Assert::same($expected, $url->scriptPath);
	},

];

$testCount = 10000;
$padLength = max(array_map('strlen', array_keys($datasets))) + 3;
foreach ($tests as $testName => $testCallback) {
	printf("Test %s:\n", $testName);
	foreach ($datasets as $datasetName => $dataset) {
		$time = -microtime(TRUE);
		$testCallback($testCount, ...$dataset);
		$time += microtime(TRUE);
		printf("  %s%5.0f ms\n", str_pad($datasetName, $padLength), $time * 1e3);
	}
	printf("\n");
}
~~~

Results:
~~~
Test old:
  a    1045 ms
  b    1049 ms
  c    1075 ms
  d    1002 ms
  e    1007 ms

Test new1:
  a      56 ms
  b      58 ms
  c      75 ms
  d      31 ms
  e      28 ms

Test new2:
  a      44 ms
  b      46 ms
  c      54 ms
  d      27 ms
  e      25 ms

Test new3:
  a      46 ms
  b      46 ms
  c      54 ms
  d      27 ms
  e      26 ms
~~~