RequestFactory: optimized UTF-8 validation performance

Benchmark:

~~~php
$s = str_repeat('a', 1e6) . 'b';
$datasets = [
	'empty' => ['', TRUE],
	'valid' => [$s, TRUE],
	'control character' => [str_replace('b', "\x00", $s), FALSE],
	'invalid UTF-8' => [str_replace('b', "\xC0", $s), FALSE],
];

$tests = [
	'NONCHARS' => function ($testCount, $s, $expected) {
		for ($i = 0; $i < $testCount; $i++) {
			$actual = !preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $s) && !preg_last_error();
		}
		assert($actual === $expected);
	},
	'CHARS*' => function ($testCount, $s, $expected) {
		for ($i = 0; $i < $testCount; $i++) {
			$actual = preg_match('#^[\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]*\z#u', $s) && !preg_last_error();
		}
		assert($actual === $expected);
	},
	'CHARS*+' => function ($testCount, $s, $expected) {
		for ($i = 0; $i < $testCount; $i++) {
			$actual = preg_match('#^[\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]*+\z#u', $s) && !preg_last_error();
		}
		assert($actual === $expected);
	}
];

$testCount = 10;
$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 NONCHARS:
  empty                   0 ms
  valid                 251 ms
  control character     250 ms
  invalid UTF-8           7 ms

Test CHARS*:
  empty                   0 ms
  valid                  51 ms
  control character     149 ms
  invalid UTF-8           7 ms

Test CHARS*+:
  empty                   0 ms
  valid                  52 ms
  control character      54 ms
  invalid UTF-8           6 ms
~~~