Skip to content

Instantly share code, notes, and snippets.

@csthomas
Last active October 25, 2018 13:13
Show Gist options
  • Save csthomas/227bb6bc9b37e4c05514230f70b802d4 to your computer and use it in GitHub Desktop.
Save csthomas/227bb6bc9b37e4c05514230f70b802d4 to your computer and use it in GitHub Desktop.
A few versions of AbstractUri::cleanPath()
<?php
$max = 0;
// class Profiler
// {
// private $_data_array = array();
// private $max = 0;
//
// function __construct()
// {
// register_tick_function( array( $this, "tick" ) );
// declare(ticks = 1);
// }
//
// function __destruct()
// {
// unregister_tick_function( array( $this, "tick" ) );
// }
//
// function tick()
// {
// //$this->_data_array[] = array(
// //"memory" => memory_get_usage(),
// //"time" => microtime( TRUE ),
// //if you need a backtrace you can uncomment this next line
// //"backtrace" => debug_backtrace( FALSE ),
// //);
// $this->max = max($this->max, memory_get_usage());
// }
//
// function getDataArray()
// {
// return $this->max;//_data_array;
// }
// }
function set_memory_usage($memory) {
global $max;
if ($memory > $max) $max = $memory;
}
function cleanPath1($path)
{
$path = explode('/', preg_replace('#(/+)#', '/', $path));
for ($i = 0, $n = \count($path); $i < $n; $i++)
{
if ($path[$i] == '.' || $path[$i] == '..')
{
if (($path[$i] == '.') || ($path[$i] == '..' && $i == 1 && $path[0] == ''))
{
unset($path[$i]);
$path = array_values($path);
$i--;
$n--;
}
elseif ($path[$i] == '..' && ($i > 1 || ($i == 1 && $path[0] != '')))
{
unset($path[$i]);
unset($path[$i - 1]);
$path = array_values($path);
$i -= 2;
$n -= 2;
}
}
}
set_memory_usage(memory_get_usage());
return implode('/', $path);
}
function cleanPath2($path)
{
$length = strlen($path);
if ($length && $path[0] === '/')
{
// Keep the first slash
$blocks = array('');
$total = 1;
$offset = 1;
}
else
{
$blocks = array();
$total = 0;
$offset = 0;
}
while ($offset < $length)
{
$end = strpos($path, '/', $offset);
if ($end === $offset)
{
$offset++;
continue;
}
if ($end === false)
{
// Keep the last segment
$end = $length;
}
$block = substr($path, $offset, $end - $offset);
$offset = $end + 1;
if ($block === '.')
{
// Remove './'
continue;
}
if ($block === '..')
{
if ($total === 1 && $blocks[0] === '')
{
// Replace /../foo.php with /foo.php
continue;
}
if ($total >= 1)
{
// Replace foo/../boo.php with boo.php
unset($blocks[$total - 1]);
$total--;
continue;
}
}
$blocks[] = $block;
$total++;
}
if ($path[$length - 1] === '/')
{
// Keep the last slash
$blocks[] = '';
}
set_memory_usage(memory_get_usage());
return implode('/', $blocks);
}
function cleanPath3($path)
{
$segments = explode('/', $path);
$total = 0;
$blocks = array();
foreach ($segments as $i => $segment)
{
if ($segment === '')
{
if ($i === 0)
{
// Keep the first slash
$blocks[] = '';
$total++;
}
continue;
}
if ($segment === '.')
{
// Remove './'
continue;
}
if ($segment === '..')
{
if ($total === 1 && $blocks[0] === '')
{
// Replace /../foo.php with /foo.php
continue;
}
if ($total >= 1)
{
// Replace foo/../boo.php with boo.php
unset($blocks[$total - 1]);
$total--;
continue;
}
}
$blocks[] = $segment;
$total++;
}
if ($path[strlen($path) - 1] === '/')
{
// Keep the last slash
$blocks[] = '';
}
set_memory_usage(memory_get_usage());
return implode('/', $blocks);
}
function cleanPath4($path)
{
if ($path !== '' && $path[0] === '/')
{
// Keep the first slash
$blocks = array('');
$total = 1;
}
else
{
$blocks = array();
$total = 0;
}
$block = strtok($path, '/');
while ($block !== false)
{
if ($block === '.')
{
// Remove './'
$block = strtok('/');
continue;
}
if ($block === '..')
{
if ($total === 1 && $blocks[0] === '')
{
// Replace /../foo.php with /foo.php
$block = strtok('/');
continue;
}
if ($total >= 1)
{
// Replace foo/../boo.php with boo.php
unset($blocks[$total - 1]);
$total--;
$block = strtok('/');
continue;
}
}
$blocks[] = $block;
$total++;
$block = strtok('/');
}
if ($path[strlen($path) - 1] === '/')
{
// Keep the last slash
$blocks[] = '';
}
set_memory_usage(memory_get_usage());
return implode('/', $blocks);
}
$paths = [
'/foo/bar/boo.php',
'/fo1/bar/boo.php',
'/fo2/bar/boo.php',
'/fo3/bar/boo.php',
'/fo4/bar/boo.php',
'/fo5/bar/boo.php',
'/fo6/bar/boo.php',
'/fo7/bar/boo.php',
'/fo9/bar/boo.php',
'/fo8/bar/boo.php',
'/fo0/bar/boo.php',
'/foe/bar//boo.php',
'/foo/bar/../boo.php',
'/foo/bar/../../boo.php',
'/foo/bar/.././/boo.php',
'//.//foo//bar//..//.//.//boo.php',
'/..//foo//bar//..//.//.//boo.php',
'foo/../boo.php',
'.//boo.php',
'../boo.php',
'boo.php',
'/',
'//',
'/./',
'./',
'/folder/',
'/.',
'/..',
'/foo/..',
];
if (!isset($argv[1]) || $argv[1] == '1')
{
function cleanPath($path) { return cleanPath1($path); }
}
elseif ($argv[1] == '2')
{
function cleanPath($path) { return cleanPath2($path); }
}
elseif ($argv[1] == '3')
{
function cleanPath($path) { return cleanPath3($path); }
}
elseif ($argv[1] == '4')
{
function cleanPath($path) { return cleanPath4($path); }
}
$start = microtime(true);
printf("CleanPath" . (isset($argv[1]) ? $argv[1] : '1') . ":\n");
//$profiler = new Profiler(); //starts logging when created
$m = memory_get_usage();
for ($i=0; $i < 50000; $i++) {
if ($i === 0) {
foreach ($paths as $path) {
printf("\t%s => %s\n", $path, cleanPath($path));
}
echo "Total: ";
}
else {
foreach ($paths as $path) cleanPath($path);
}
}
//$data_array = $profiler->getDataArray();
//unset( $profiler ); //stops logging when __destruct is called
printf("%.4f\tMemory peak: %d\t Function memory peak: %d\n", (microtime(true) - $start), memory_get_peak_usage(), $max - $m);
/*
$start = microtime(true);
printf("CleanPath2:\n");
$profiler = new Profiler(); //starts logging when created
for ($i=0; $i < 50000; $i++) {
if ($i === 0) {
foreach ($paths as $path) {
printf("\t%s => %s\n", $path, cleanPath2($path));
}
}
else {
foreach ($paths as $path) cleanPath2($path);
}
}
$data_array = $profiler->getDataArray();
unset( $profiler ); //stops logging when __destruct is called
printf("Total: %.4f\n\n", (microtime(true) - $start));
print_r($data_array);echo "\n\n";
$start = microtime(true);
printf("CleanPath3:\n");
$profiler = new Profiler(); //starts logging when created
for ($i=0; $i < 50000; $i++) {
if ($i === 0) {
foreach ($paths as $path) {
printf("\t%s => %s\n", $path, cleanPath3($path));
}
}
else {
foreach ($paths as $path) cleanPath3($path);
}
}
$data_array = $profiler->getDataArray();
unset( $profiler ); //stops logging when __destruct is called
printf("Total: %.4f\n\n", (microtime(true) - $start));
print_r($data_array);echo "\n\n";
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment