Move normalizePath to regexes instead of looping
This is IMO a bit more readable and it seems to make the code faster. Tested it on the company instance where there are over 3k calls to this function. It shaves off around 10ms. The advantage here is that the pattern gets optimized by php itsel and cached. Also looking for all patterns at the same time and especially no longer looping for /./ patterns should save time. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
parent
1dbd7172c3
commit
d5bf2c4523
|
@ -812,7 +812,7 @@ class Filesystem {
|
||||||
return self::$normalizedPathCache[$cacheKey];
|
return self::$normalizedPathCache[$cacheKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($path == '') {
|
if ($path === '') {
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,38 +821,29 @@ class Filesystem {
|
||||||
$path = \OC_Util::normalizeUnicode($path);
|
$path = \OC_Util::normalizeUnicode($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//no windows style slashes
|
//add leading slash, if it is already there we strip it anyway
|
||||||
$path = str_replace('\\', '/', $path);
|
|
||||||
|
|
||||||
//add leading slash
|
|
||||||
if ($path[0] !== '/') {
|
|
||||||
$path = '/' . $path;
|
$path = '/' . $path;
|
||||||
}
|
|
||||||
|
|
||||||
// remove '/./'
|
$patterns = [
|
||||||
// ugly, but str_replace() can't replace them all in one go
|
'/\\\\/s', // no windows style slashes
|
||||||
// as the replacement itself is part of the search string
|
'/\/\.(\/\.)?\//s', // remove '/./'
|
||||||
// which will only be found during the next iteration
|
'/\/{2,}/s', // remove squence of slashes
|
||||||
while (strpos($path, '/./') !== false) {
|
'/\/\.$/s', // remove trailing /.
|
||||||
$path = str_replace('/./', '/', $path);
|
];
|
||||||
}
|
|
||||||
// remove sequences of slashes
|
do {
|
||||||
$path = preg_replace('#/{2,}#', '/', $path);
|
$count = 0;
|
||||||
|
$path = preg_replace($patterns, '/', $path, -1, $count);
|
||||||
|
} while ($count > 0);
|
||||||
|
|
||||||
//remove trailing slash
|
//remove trailing slash
|
||||||
if ($stripTrailingSlash and strlen($path) > 1) {
|
if ($stripTrailingSlash && strlen($path) > 1) {
|
||||||
$path = rtrim($path, '/');
|
$path = rtrim($path, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove trailing '/.'
|
self::$normalizedPathCache[$cacheKey] = $path;
|
||||||
if (substr($path, -2) == '/.') {
|
|
||||||
$path = substr($path, 0, -2);
|
|
||||||
}
|
|
||||||
|
|
||||||
$normalizedPath = $path;
|
return $path;
|
||||||
self::$normalizedPathCache[$cacheKey] = $normalizedPath;
|
|
||||||
|
|
||||||
return $normalizedPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -115,73 +115,80 @@ class FilesystemTest extends \Test\TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function normalizePathData() {
|
public function normalizePathData() {
|
||||||
return array(
|
return [
|
||||||
array('/', ''),
|
['/', ''],
|
||||||
array('/', '/'),
|
['/', '/'],
|
||||||
array('/', '//'),
|
['/', '//'],
|
||||||
array('/', '/', false),
|
['/', '/', false],
|
||||||
array('/', '//', false),
|
['/', '//', false],
|
||||||
|
|
||||||
array('/path', '/path/'),
|
['/path', '/path/'],
|
||||||
array('/path/', '/path/', false),
|
['/path/', '/path/', false],
|
||||||
array('/path', 'path'),
|
['/path', 'path'],
|
||||||
|
|
||||||
array('/foo/bar', '/foo//bar/'),
|
['/foo/bar', '/foo//bar/'],
|
||||||
array('/foo/bar/', '/foo//bar/', false),
|
['/foo/bar/', '/foo//bar/', false],
|
||||||
array('/foo/bar', '/foo////bar'),
|
['/foo/bar', '/foo////bar'],
|
||||||
array('/foo/bar', '/foo/////bar'),
|
['/foo/bar', '/foo/////bar'],
|
||||||
array('/foo/bar', '/foo/bar/.'),
|
['/foo/bar', '/foo/bar/.'],
|
||||||
array('/foo/bar', '/foo/bar/./'),
|
['/foo/bar', '/foo/bar/./'],
|
||||||
array('/foo/bar/', '/foo/bar/./', false),
|
['/foo/bar/', '/foo/bar/./', false],
|
||||||
array('/foo/bar', '/foo/bar/./.'),
|
['/foo/bar', '/foo/bar/./.'],
|
||||||
array('/foo/bar', '/foo/bar/././'),
|
['/foo/bar', '/foo/bar/././'],
|
||||||
array('/foo/bar/', '/foo/bar/././', false),
|
['/foo/bar/', '/foo/bar/././', false],
|
||||||
array('/foo/bar', '/foo/./bar/'),
|
['/foo/bar', '/foo/./bar/'],
|
||||||
array('/foo/bar/', '/foo/./bar/', false),
|
['/foo/bar/', '/foo/./bar/', false],
|
||||||
array('/foo/.bar', '/foo/.bar/'),
|
['/foo/.bar', '/foo/.bar/'],
|
||||||
array('/foo/.bar/', '/foo/.bar/', false),
|
['/foo/.bar/', '/foo/.bar/', false],
|
||||||
array('/foo/.bar/tee', '/foo/.bar/tee'),
|
['/foo/.bar/tee', '/foo/.bar/tee'],
|
||||||
|
|
||||||
|
['/foo/bar', '/.///././//./foo/.///././//./bar/./././.'],
|
||||||
|
['/foo/bar/', '/.///././//./foo/.///././//./bar/./././.', false],
|
||||||
|
['/foo/bar', '/.///././//./foo/.///././//./bar/././././'],
|
||||||
|
['/foo/bar/', '/.///././//./foo/.///././//./bar/././././', false],
|
||||||
|
|
||||||
// Windows paths
|
// Windows paths
|
||||||
array('/', ''),
|
['/', ''],
|
||||||
array('/', '\\'),
|
['/', '\\'],
|
||||||
array('/', '\\', false),
|
['/', '\\', false],
|
||||||
array('/', '\\\\'),
|
['/', '\\\\'],
|
||||||
array('/', '\\\\', false),
|
['/', '\\\\', false],
|
||||||
|
|
||||||
array('/path', '\\path'),
|
['/path', '\\path'],
|
||||||
array('/path', '\\path', false),
|
['/path', '\\path', false],
|
||||||
array('/path', '\\path\\'),
|
['/path', '\\path\\'],
|
||||||
array('/path/', '\\path\\', false),
|
['/path/', '\\path\\', false],
|
||||||
|
|
||||||
array('/foo/bar', '\\foo\\\\bar\\'),
|
['/foo/bar', '\\foo\\\\bar\\'],
|
||||||
array('/foo/bar/', '\\foo\\\\bar\\', false),
|
['/foo/bar/', '\\foo\\\\bar\\', false],
|
||||||
array('/foo/bar', '\\foo\\\\\\\\bar'),
|
['/foo/bar', '\\foo\\\\\\\\bar'],
|
||||||
array('/foo/bar', '\\foo\\\\\\\\\\bar'),
|
['/foo/bar', '\\foo\\\\\\\\\\bar'],
|
||||||
array('/foo/bar', '\\foo\\bar\\.'),
|
['/foo/bar', '\\foo\\bar\\.'],
|
||||||
array('/foo/bar', '\\foo\\bar\\.\\'),
|
['/foo/bar', '\\foo\\bar\\.\\'],
|
||||||
array('/foo/bar/', '\\foo\\bar\\.\\', false),
|
['/foo/bar/', '\\foo\\bar\\.\\', false],
|
||||||
array('/foo/bar', '\\foo\\bar\\.\\.'),
|
['/foo/bar', '\\foo\\bar\\.\\.'],
|
||||||
array('/foo/bar', '\\foo\\bar\\.\\.\\'),
|
['/foo/bar', '\\foo\\bar\\.\\.\\'],
|
||||||
array('/foo/bar/', '\\foo\\bar\\.\\.\\', false),
|
['/foo/bar/', '\\foo\\bar\\.\\.\\', false],
|
||||||
array('/foo/bar', '\\foo\\.\\bar\\'),
|
['/foo/bar', '\\foo\\.\\bar\\'],
|
||||||
array('/foo/bar/', '\\foo\\.\\bar\\', false),
|
['/foo/bar/', '\\foo\\.\\bar\\', false],
|
||||||
array('/foo/.bar', '\\foo\\.bar\\'),
|
['/foo/.bar', '\\foo\\.bar\\'],
|
||||||
array('/foo/.bar/', '\\foo\\.bar\\', false),
|
['/foo/.bar/', '\\foo\\.bar\\', false],
|
||||||
array('/foo/.bar/tee', '\\foo\\.bar\\tee'),
|
['/foo/.bar/tee', '\\foo\\.bar\\tee'],
|
||||||
|
|
||||||
// Absolute windows paths NOT marked as absolute
|
// Absolute windows paths NOT marked as absolute
|
||||||
array('/C:', 'C:\\'),
|
['/C:', 'C:\\'],
|
||||||
array('/C:/', 'C:\\', false),
|
['/C:/', 'C:\\', false],
|
||||||
array('/C:/tests', 'C:\\tests'),
|
['/C:/tests', 'C:\\tests'],
|
||||||
array('/C:/tests', 'C:\\tests', false),
|
['/C:/tests', 'C:\\tests', false],
|
||||||
array('/C:/tests', 'C:\\tests\\'),
|
['/C:/tests', 'C:\\tests\\'],
|
||||||
array('/C:/tests/', 'C:\\tests\\', false),
|
['/C:/tests/', 'C:\\tests\\', false],
|
||||||
|
['/C:/tests/bar', 'C:\\tests\\.\\.\\bar'],
|
||||||
|
['/C:/tests/bar/', 'C:\\tests\\.\\.\\bar\\.\\', false],
|
||||||
|
|
||||||
// normalize does not resolve '..' (by design)
|
// normalize does not resolve '..' (by design)
|
||||||
array('/foo/..', '/foo/../'),
|
['/foo/..', '/foo/../'],
|
||||||
array('/foo/..', '\\foo\\..\\'),
|
['/foo/..', '\\foo\\..\\'],
|
||||||
);
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue