Skip to content

Commit 9182764

Browse files
committed
add normalize, canonical-distinct from absolute_path
1 parent 263cabc commit 9182764

File tree

12 files changed

+114
-32
lines changed

12 files changed

+114
-32
lines changed

+stdlib/+fileio/absolute_path.m

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,16 @@
1111
return
1212
end
1313

14-
if ~stdlib.fileio.is_absolute_path(abspath)
15-
% otherwise the default is Documents/Matlab, which is probably not wanted.
16-
abspath = fullfile(pwd, abspath);
17-
end
18-
1914
if ispc && startsWith(abspath, "\\")
2015
% UNC path is not canonicalized
2116
return
2217
end
2318

24-
% similar benchmark time as java method
25-
% REQUIRES path to exist, while java method does not.
26-
% abspath = builtin('_canonicalizepath', abspath);
19+
if ~stdlib.fileio.is_absolute_path(abspath)
20+
% .toAbsolutePath() default is Documents/Matlab, which is probably not wanted.
21+
abspath = fullfile(pwd, abspath);
22+
end
2723

28-
abspath = string(java.io.File(abspath).getCanonicalPath());
24+
abspath = string(java.io.File(abspath).getAbsolutePath());
2925

3026
end % function

+stdlib/+fileio/canonical.m

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function c = canonical(p)
2+
3+
arguments
4+
p string {mustBeScalarOrEmpty}
5+
end
6+
7+
% have to expand ~ first (like C++ filesystem::path::absolute)
8+
c = stdlib.fileio.expanduser(p);
9+
10+
if isempty(c)
11+
return
12+
end
13+
14+
if ispc && startsWith(c, "\\")
15+
% UNC path is not canonicalized
16+
return
17+
end
18+
19+
if ~stdlib.fileio.is_absolute_path(c)
20+
% .toAbsolutePath() default is Documents/Matlab, which is probably not wanted.
21+
c = fullfile(pwd, c);
22+
end
23+
24+
% similar benchmark time as java method
25+
% REQUIRES path to exist, while java method does not.
26+
% abspath = builtin('_canonicalizepath', abspath);
27+
28+
c = string(java.io.File(c).getCanonicalPath());
29+
30+
end % function

+stdlib/+fileio/extract_zstd.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ function extract_zstd(archive, out_dir)
55
out_dir (1,1) string {mustBeFolder}
66
end
77

8-
archive = stdlib.fileio.absolute_path(archive);
9-
out_dir = stdlib.fileio.absolute_path(out_dir);
8+
archive = stdlib.fileio.canonical(archive);
9+
out_dir = stdlib.fileio.canonical(out_dir);
1010

1111
exe = stdlib.fileio.which("cmake");
1212
if isempty(exe)

+stdlib/+fileio/normalize.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function n = normalize(p)
2+
% normalize(p) remove redundant elements of path p
3+
arguments
4+
p string {mustBeScalarOrEmpty}
5+
end
6+
7+
n = p;
8+
if isempty(p)
9+
return
10+
end
11+
12+
n = string(java.io.File(stdlib.fileio.expanduser(n)).toPath().normalize());
13+
14+
end

+stdlib/+fileio/path_tail.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
return
1010
end
1111

12-
[~, name, ext] = fileparts(stdlib.fileio.absolute_path(apath));
12+
[~, name, ext] = fileparts(stdlib.fileio.canonical(apath));
1313

1414
last = append(name, ext);
1515

+stdlib/+fileio/samepath.m

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
return
1111
end
1212

13-
% absolute_path because unlike c++ filesystem, isSameFile does not
14-
% canonicalize first
15-
p1 = java.io.File(stdlib.fileio.absolute_path(path1)).toPath();
16-
p2 = java.io.File(stdlib.fileio.absolute_path(path2)).toPath();
13+
% unlike c++ filesystem, isSameFile does not canonicalize first
14+
p1 = java.io.File(stdlib.fileio.canonical(path1)).toPath();
15+
p2 = java.io.File(stdlib.fileio.canonical(path2)).toPath();
1716

1817
try
1918
issame = java.nio.file.Files.isSameFile(p1, p2);

+stdlib/+test/TestFilePure.m

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,12 @@ function test_absolute_path(tc)
6565

6666
par1 = absolute_path("../2foo");
6767
tc.verifyNotEmpty(par1)
68-
tc.verifyFalse(contains(par1, ".."))
6968

7069
par2 = absolute_path("../4foo");
7170
tc.verifyTrue(strncmp(par2, pabs2, 2))
7271

7372
pt1 = absolute_path("bar/../2foo");
7473
tc.verifyNotEmpty(pt1)
75-
tc.verifyFalse(contains(pt1, ".."))
7674

7775
va = absolute_path("2foo");
7876
vb = absolute_path("4foo");
@@ -81,6 +79,40 @@ function test_absolute_path(tc)
8179

8280
end
8381

82+
83+
function test_canonical(tc)
84+
85+
import stdlib.canonical
86+
87+
tc.assumeTrue(usejava("jvm"), "Java required for absolute_path")
88+
89+
tc.verifyEmpty(canonical(string.empty))
90+
tc.verifyEqual(canonical(""), string(pwd))
91+
92+
pabs = canonical('2foo');
93+
pabs2 = canonical('4foo');
94+
tc.verifyFalse(startsWith(pabs, "2"))
95+
tc.verifyTrue(strncmp(pabs, pabs2, 2))
96+
97+
par1 = canonical("../2foo");
98+
tc.verifyNotEmpty(par1)
99+
tc.verifyFalse(contains(par1, ".."))
100+
101+
par2 = canonical("../4foo");
102+
tc.verifyTrue(strncmp(par2, pabs2, 2))
103+
104+
pt1 = canonical("bar/../2foo");
105+
tc.verifyNotEmpty(pt1)
106+
tc.verifyFalse(contains(pt1, ".."))
107+
108+
va = canonical("2foo");
109+
vb = canonical("4foo");
110+
tc.verifyFalse(startsWith(va, "2"))
111+
tc.verifyTrue(strncmp(va, vb, 2))
112+
113+
end
114+
115+
84116
function test_with_suffix(tc)
85117
import stdlib.with_suffix
86118

+stdlib/+test/TestWindowsCOM.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function test_shortname(tc)
1414
tc.verifyTrue(endsWith(short, 'notepad.exe'), "Short name should end with 'notepad.exe'")
1515
tc.verifyTrue(contains(short, "MICROS~1"))
1616

17-
tc.verifyEqual(stdlib.absolute_path(short), test_file)
17+
tc.verifyEqual(stdlib.canonical(short), test_file)
1818

1919
end
2020

+stdlib/absolute_path.m

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1-
function abspath = absolute_path(p)
1+
function a = absolute_path(p)
22
%% absolute_path(p)
33
% path need not exist, but absolute path is returned
44
%
55
% NOTE: some network file systems are not resolvable by Matlab Java
66
% subsystem, but are sometimes still valid--so return
77
% unmodified path if this occurs.
88
%
9-
% This also resolves Windows short paths to full long paths.
10-
%
119
%%% Inputs
1210
% * p: path to make absolute
1311
%%% Outputs
14-
% * abspath: absolute path, if determined
12+
% * a: absolute path, if determined
1513

1614
arguments
1715
p string {mustBeScalarOrEmpty}
1816
end
1917

20-
abspath = stdlib.fileio.absolute_path(p);
18+
a = stdlib.fileio.absolute_path(p);
2119

2220
end

+stdlib/canonical.m

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
function abspath = canonical(p)
1+
function c = canonical(p)
22
%% canonical(p)
3-
% yes this is the same as absolute_path
4-
% path need not exist, but absolute path is returned
3+
% path need not exist, but canonical path is returned
54
%
65
% NOTE: some network file systems are not resolvable by Matlab Java
76
% subsystem, but are sometimes still valid--so return
@@ -10,14 +9,14 @@
109
% This also resolves Windows short paths to full long paths.
1110
%
1211
%%% Inputs
13-
% * p: path to make absolute
12+
% * p: path to make canonical
1413
%%% Outputs
15-
% * abspath: absolute path, if determined
14+
% * c: canonical path, if determined
1615

1716
arguments
1817
p string {mustBeScalarOrEmpty}
1918
end
2019

21-
abspath = stdlib.fileio.absolute_path(p);
20+
c = stdlib.fileio.canonical(p);
2221

2322
end

0 commit comments

Comments
 (0)