From https://github.com/apache/couchdb/blob/master/src/couchdb/couch_httpd_rewrite.erl#L367-385
Output for both programs:
=> /
/ => /
/foo/bar/baz => /foo/bar/baz
foo/one//two///three//// => /foo/one/two/three
foo/bar/..//baz => /foo/baz
% normalize_path experiments | |
-define(SEPARATOR, $\/). | |
main(_) -> ok | |
, Paths = [ "" | |
, "/" | |
, "/foo/bar/baz" | |
, "foo/one//two///three////" | |
, "foo/bar/..//baz" | |
] | |
, lists:foreach(fun(Path) -> ok | |
, io:format("~s => ~s\n", [Path, normalize_path(Path)]) | |
end, Paths) | |
. | |
normalize_path(Path) -> | |
"/" ++ string:join(normalize_path1(string:tokens(Path, | |
"/"), []), [?SEPARATOR]). | |
normalize_path1([], Acc) -> | |
lists:reverse(Acc); | |
normalize_path1([".."|Rest], Acc) -> | |
Acc1 = case Acc of | |
[] -> [".."|Acc]; | |
[T|_] when T =:= ".." -> [".."|Acc]; | |
[_|R] -> R | |
end, | |
normalize_path1(Rest, Acc1); | |
normalize_path1(["."|Rest], Acc) -> | |
normalize_path1(Rest, Acc); | |
normalize_path1([Path|Rest], Acc) -> | |
normalize_path1(Rest, [Path|Acc]). |
var SEPARATOR = '/' | |
main() | |
function main() { | |
var paths = [ "" | |
, "/" | |
, "/foo/bar/baz" | |
, "foo/one//two///three////" | |
, "foo/bar/..//baz" | |
] | |
paths.forEach(function(path, i) { | |
console.log(path + ' => ' + normalize_path(path)) | |
}) | |
} | |
function string_tokens(str, separator) { | |
return str.split(separator).filter(function(part) { return part != '' }) | |
} | |
// normalize_path(Path) -> | |
function normalize_path(path) { | |
return '/' + normalize_path1(string_tokens(path, '/'), []).join(SEPARATOR) | |
} | |
function normalize_path1(parts, acc) { | |
// normalize_path1([], Acc) -> | |
if(parts.length == 0) | |
return acc.reverse() | |
// normalize_path1([".."|Rest], Acc) -> | |
else if(parts[0] == '..') { | |
var rest = parts.slice(1) | |
var acc1 | |
if(acc.length == 0) | |
acc1 = ['..'].concat(acc) | |
else if(acc[0] == '..') | |
acc1 = ['..'].concat(acc) | |
else | |
acc1 = acc.slice(1) | |
return normalize_path1(rest, acc1) | |
} | |
// normalize_path1(["."|Rest], Acc) -> | |
else if(parts[0] == '.') { | |
var rest = parts.slice[1] | |
return normalize_path1(rest, acc) | |
} | |
// normalize_path1([Path|Rest], Acc) -> | |
else { | |
var path = parts[0] | |
, rest = parts.slice(1) | |
return normalize_path1(rest, [path].concat(acc)) | |
} | |
} |
From https://github.com/apache/couchdb/blob/master/src/couchdb/couch_httpd_rewrite.erl#L367-385
Output for both programs:
=> /
/ => /
/foo/bar/baz => /foo/bar/baz
foo/one//two///three//// => /foo/one/two/three
foo/bar/..//baz => /foo/baz