Skip to content

Commit 90fbfa5

Browse files
committed
is_exe: native only: fast enough
1 parent 3e4265a commit 90fbfa5

File tree

7 files changed

+33
-42
lines changed

7 files changed

+33
-42
lines changed

+stdlib/+java/is_exe.m

Lines changed: 0 additions & 11 deletions
This file was deleted.

+stdlib/+legacy/is_exe.m

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
function y = is_exe(file)
2+
arguments
3+
file (1,1) string
4+
end
25

3-
y = isfile(file);
6+
y = false;
47

5-
if ispc()
6-
y = y && stdlib.native.has_windows_executable_suffix(file);
8+
if ispc() && ~stdlib.native.has_windows_executable_suffix(file)
9+
return
710
end
811

9-
if ~y, return, end
12+
if ~isfile(file), return, end
1013

1114
a = file_attributes(file);
1215
y = a.UserExecute || a.GroupExecute || a.OtherExecute;

+stdlib/is_exe.m

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,16 @@
55
% file: path to check
66
%% Outputs
77
% ok: true if path is a file and has executable permissions
8-
% b: backend used
98

10-
function [ok, b] = is_exe(file, backend)
9+
function ok = is_exe(file)
1110
arguments
1211
file string
13-
backend (1,:) string = ["java", "python", "native", "legacy"]
1412
end
1513

16-
% Java or Python ~ 100x faster than Matlab native
17-
[fun, b] = hbackend(backend, "is_exe");
18-
19-
if isscalar(file) || b == "native"
20-
ok = fun(file);
14+
if isscalar(file)
15+
ok = stdlib.legacy.is_exe(file);
2116
else
22-
ok = arrayfun(fun, file);
17+
ok = stdlib.native.is_exe(file);
2318
end
2419

2520
end

example/+javafun/is_exe.m

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
%% IS_EXE is file executable
1+
function y = is_exe(p)
22

3-
function ok = is_exe(p)
3+
y = isfile(p);
44

5-
% about the same time as fileattrib
6-
% https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/io/File.html#canExecute()
7-
% more complicated
8-
% ok = java.nio.file.Files.isExecutable(javaPathObject(stdlib.canonical(p)));
5+
if ispc()
6+
y = y && stdlib.native.has_windows_executable_suffix(p);
7+
end
98

10-
ok = javaFileObject(p).canExecute();
9+
y = y && java.io.File(p).canExecute();
1110

12-
end
11+
end
File renamed without changes.

example/bench_is_exe.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ function bench_is_exe()
88
ff = @() stdlib.is_exe(in);
99
fn = @() stdlib.native.is_exe(in);
1010
fl = @() stdlib.legacy.is_exe(in);
11-
fj = @() stdlib.java.is_exe(in);
12-
fp = @() stdlib.python.is_exe(in);
11+
fj = @() javafun.is_exe(in);
12+
fp = @() python.is_exe(in);
1313

1414
tj = timeit(fj) * 1e3;
15-
tp = timeit(fp) * 1e3;
15+
tl = timeit(fl) * 1e3;
1616
tf = timeit(ff) * 1e3;
1717
tn = timeit(fn) * 1e3;
18-
tl = timeit(fl) * 1e3;
18+
tp = timeit(fp) * 1e3;
1919

20-
fprintf('Full: %f\nNative: %f\nLegacy: %f\nJava: %f\nPython: %f\n', tf, tl, tn, tj, tp);
20+
fprintf('Full %f\nNative: %f\nLegacy: %f\nJava: %f\nPython: %f\n', tf, tn, tl, tj, tp);
2121

2222
end

test/TestIsExe.m

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
{matlab_path(), true}
1313
}
1414
peb = init_exe_bin()
15-
backend = init_backend({'java', 'python', 'native', 'legacy'}, 'native', ~isMATLABReleaseOlderThan('R2025a'))
1615
end
1716

1817
methods(TestClassSetup)
@@ -25,18 +24,24 @@ function test_dirs(tc)
2524

2625
methods(Test)
2726

28-
function test_is_exe(tc, p, backend)
29-
r = stdlib.is_exe(p{1}, backend);
27+
function test_is_exe(tc, p)
28+
r = stdlib.is_exe(p{1});
29+
tc.verifyEqual(r, p{2})
30+
end
31+
32+
function test_is_exe_legacy(tc, p)
33+
r = stdlib.legacy.is_exe(p{1});
3034
tc.verifyEqual(r, p{2})
3135
end
3236

3337

34-
function test_is_exe_array(tc, backend)
38+
function test_is_exe_array(tc)
39+
tc.assumeFalse(isMATLABReleaseOlderThan('R2025a'))
3540
n = fullfile(matlabroot, "bin/matlab");
3641
if ispc()
3742
n = n + ".exe";
3843
end
39-
r = stdlib.is_exe(["Readme.md", tempname(), n], backend);
44+
r = stdlib.is_exe(["Readme.md", tempname(), n]);
4045
tc.verifyEqual(r, [false, false, true])
4146
end
4247

0 commit comments

Comments
 (0)