Skip to content

Commit b4e18c4

Browse files
committed
relative,proximate: can use .net
1 parent fc9662d commit b4e18c4

File tree

5 files changed

+64
-27
lines changed

5 files changed

+64
-27
lines changed

+stdlib/proximate_to.m

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@
66
% * other {mustBeTextScalar}
77
%%% Outputs
88
% * rel {mustBeTextScalar}
9-
%
10-
% This function is written in C++ using STL <filesystem>
119

12-
function proximate_to(~,~)
13-
error("buildtool mex")
10+
function rel = proximate_to(base, other)
11+
arguments
12+
base {mustBeTextScalar}
13+
other {mustBeTextScalar}
14+
end
15+
16+
rel = stdlib.relative_to(base, other);
17+
if strempty(rel)
18+
rel = fullfile(other);
19+
end
20+
21+
1422
end
1523

1624
%!testif 0

+stdlib/relative_to.m

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,43 @@
11
%% RELATIVE_TO relative path to base
2-
% requires: mex
2+
% optional: mex
33
%
44
%%% Inputs
55
% * base {mustBeTextScalar}
66
% * other {mustBeTextScalar}
77
%%% Outputs
88
% * rel {mustBeTextScalar}
99
%
10-
% This function is written in C++ using STL <filesystem>
11-
%
1210
% Note: Java Path.relativize has an algorithm so different that we choose not to use it.
1311
% https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html#relativize-java.nio.file.Path-
1412

15-
function relative_to(~,~)
16-
error("buildtool mex")
13+
function rel = relative_to(base, other)
14+
arguments
15+
base {mustBeTextScalar}
16+
other {mustBeTextScalar}
17+
end
18+
19+
20+
if stdlib.has_dotnet()
21+
22+
if strempty(base) || strempty(other), rel = "."; return, end
23+
24+
bis = stdlib.is_absolute(base);
25+
ois = stdlib.is_absolute(other);
26+
27+
if bis ~= ois, rel = ""; return, end
28+
29+
base = fullfile(base);
30+
other = fullfile(other);
31+
32+
if bis && ~(startsWith(base, other) || startsWith(other, base))
33+
rel = "";
34+
else
35+
rel = string(System.IO.Path.GetRelativePath(base, other));
36+
end
37+
else
38+
error('no supported relative path method found, please install .NET or "buildtool mex"')
39+
end
40+
1741
end
1842

1943
%!testif 0

buildfile.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,15 @@ function build_exe(context)
265265
["src/is_admin.cpp", "src/admin_fs.cpp"] ...
266266
"src/is_char_device.cpp", ...
267267
["src/normalize.cpp", normal], ...
268-
"src/relative_to.cpp", ...
269-
"src/proximate_to.cpp", ...
270268
"src/disk_available.cpp", ...
271269
"src/disk_capacity.cpp", ...
272270
"src/set_permissions.cpp", ...
273271
};
274272

273+
if ~stdlib.has_dotnet() || build_all
274+
srcs{end+1} = ["src/relative_to.cpp", "src/proximate_to.cpp"];
275+
end
276+
275277
if (isMATLABReleaseOlderThan("R2024b") && ~stdlib.has_dotnet()) || build_all
276278
srcs{end+1} = ["src/is_symlink.cpp", win, sym];
277279
end

src/relative_to.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class MexFunction : public matlab::mex::Function {
2828
matlab_2string(inputs, &base, &other);
2929

3030
std::error_code ec;
31-
std::string out = std::filesystem::relative(other, base, ec).generic_string();
31+
std::string out = std::filesystem::relative(other, base, ec).string();
3232

3333
if(ec)
3434
matlabEng->feval(u"error", 0,

test/TestRelative.m

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@
55
pp = init_prox()
66
end
77

8-
methods (Test, TestTags = "mex")
8+
methods (Test)
99

1010
function test_relative_to(tc, pr)
11-
tc.assertTrue(stdlib.is_mex_fun("stdlib.relative_to"))
11+
tc.assumeTrue(stdlib.has_dotnet() || stdlib.is_mex_fun("stdlib.relative_to"))
1212

1313
tc.verifyEqual(stdlib.relative_to(pr{1}, pr{2}), pr{3}, ...
1414
"relative_to(" + pr{1} + "," + pr{2}+")")
1515
end
1616

1717
function test_proximate_to(tc, pp)
18-
tc.assertTrue(stdlib.is_mex_fun("stdlib.proximate_to"))
18+
tc.assumeTrue(stdlib.has_dotnet() || stdlib.is_mex_fun("stdlib.proximate_to"))
1919

2020
tc.verifyEqual(stdlib.proximate_to(pp{1}, pp{2}), pp{3}, ...
21-
"proximate_to(" + pp{1} + "," + pp{2}+")")
21+
"proximate_to(" + pp{1} + ", " + pp{2}+")")
2222
end
2323

2424
end
@@ -32,30 +32,32 @@ function test_proximate_to(tc, pp)
3232
{"Hello", "Hello/", "."}, ...
3333
{"a/./b", "a/b", "."}, ...
3434
{"a/b", "a/./b", "."}, ...
35-
{"./a/b", "./a/c", "../c"}, ...
35+
{"./a/b", "./a/c", fullfile("..", "c")}, ...
3636
{"/", "/", "."}, ...
37-
{"a/b/c/d", "a/b", "../.."}, ...
38-
{"a/b", "a/c", "../c"}, ...
39-
{"a/b", "c", "../../c"}, ...
40-
{"c", "a/b", "../a/b"}, ...
37+
{"a/b/c/d", "a/b", fullfile("..", "..")}, ...
38+
{"a/b", "a/c", fullfile("..", "c")}, ...
39+
{"a/b", "c", fullfile("..", "..", "c")}, ...
40+
{"c", "a/b", fullfile("..", "a", "b")}, ...
4141
{"a/b", "a/b", "."}, ...
4242
{"a/b", "a", ".."}
4343
};
4444
% NOTE: ".." in relative_to(base) is ambiguous including for python.pathlib, C++ <filesystem>, etc.
4545

4646
if ispc
4747
p = [p, ...
48-
{{"C:/a/b", "C:/", "../.."}, ...
49-
{"C:/", "C:/a/b", "a/b"}, ...
48+
{{"C:/a/b", "C:/", fullfile("..", "..")}, ...
49+
{"C:/", "C:/a/b", fullfile("a", "b")}, ...
5050
{"c:/a/b", "c:/a/b", "."}, ...
5151
{"c:/a/b", "c:/a", ".."}, ...
52-
{"c:\a/b\c/d", "c:/a\b", "../.."}, ...
53-
{"C:/path", "D:/path", ""}}];
52+
{"c:\a/b\c/d", "c:/a\b", fullfile("..", "..")}, ...
53+
{"C:/path", "D:/path", ""}, ...
54+
{"D:/a/b", "c", ""}}];
5455
% note: on Windows the drive letter should be uppercase!
5556
else
5657
p = [p, ...
5758
{{"", "a", "a"}, ...
58-
{"/dev/null", "/dev/null", "."}}];
59+
{"/dev/null", "/dev/null", "."}, ...
60+
{"/a/b", "c", ""}}];
5961
end
6062

6163
end
@@ -67,7 +69,8 @@ function test_proximate_to(tc, pp)
6769

6870

6971
if ispc
70-
p{end}{3} = "D:/path";
72+
p{end-1}{3} = fullfile("D:", "path");
73+
p{end}{3} = "c";
7174
end
7275

7376
end

0 commit comments

Comments
 (0)