| ... | @@ -749,8 +749,12 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void { | ... | @@ -749,8 +749,12 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void { |
| 749 | return testing.expect(mem.eql(u8, actual, expected)); | 749 | return testing.expect(mem.eql(u8, actual, expected)); |
| 750 | } | 750 | } |
| 751 | | 751 | |
| | 752 | /// Strip the last component from a file path. |
| | 753 | /// |
| 752 | /// If the path is a file in the current directory (no directory component) | 754 | /// If the path is a file in the current directory (no directory component) |
| 753 | /// then returns null | 755 | /// then returns null. |
| | 756 | /// |
| | 757 | /// If the path is the root directory, returns null. |
| 754 | pub fn dirname(path: []const u8) ?[]const u8 { | 758 | pub fn dirname(path: []const u8) ?[]const u8 { |
| 755 | if (builtin.os.tag == .windows) { | 759 | if (builtin.os.tag == .windows) { |
| 756 | return dirnameWindows(path); | 760 | return dirnameWindows(path); |
| ... | @@ -765,19 +769,19 @@ pub fn dirnameWindows(path: []const u8) ?[]const u8 { | ... | @@ -765,19 +769,19 @@ pub fn dirnameWindows(path: []const u8) ?[]const u8 { |
| 765 | | 769 | |
| 766 | const root_slice = diskDesignatorWindows(path); | 770 | const root_slice = diskDesignatorWindows(path); |
| 767 | if (path.len == root_slice.len) | 771 | if (path.len == root_slice.len) |
| 768 | return path; | 772 | return null; |
| 769 | | 773 | |
| 770 | const have_root_slash = path.len > root_slice.len and (path[root_slice.len] == '/' or path[root_slice.len] == '\\'); | 774 | const have_root_slash = path.len > root_slice.len and (path[root_slice.len] == '/' or path[root_slice.len] == '\\'); |
| 771 | | 775 | |
| 772 | var end_index: usize = path.len - 1; | 776 | var end_index: usize = path.len - 1; |
| 773 | | 777 | |
| 774 | while ((path[end_index] == '/' or path[end_index] == '\\') and end_index > root_slice.len) { | 778 | while (path[end_index] == '/' or path[end_index] == '\\') { |
| 775 | if (end_index == 0) | 779 | if (end_index == 0) |
| 776 | return null; | 780 | return null; |
| 777 | end_index -= 1; | 781 | end_index -= 1; |
| 778 | } | 782 | } |
| 779 | | 783 | |
| 780 | while (path[end_index] != '/' and path[end_index] != '\\' and end_index > root_slice.len) { | 784 | while (path[end_index] != '/' and path[end_index] != '\\') { |
| 781 | if (end_index == 0) | 785 | if (end_index == 0) |
| 782 | return null; | 786 | return null; |
| 783 | end_index -= 1; | 787 | end_index -= 1; |
| ... | @@ -800,7 +804,7 @@ pub fn dirnamePosix(path: []const u8) ?[]const u8 { | ... | @@ -800,7 +804,7 @@ pub fn dirnamePosix(path: []const u8) ?[]const u8 { |
| 800 | var end_index: usize = path.len - 1; | 804 | var end_index: usize = path.len - 1; |
| 801 | while (path[end_index] == '/') { | 805 | while (path[end_index] == '/') { |
| 802 | if (end_index == 0) | 806 | if (end_index == 0) |
| 803 | return path[0..1]; | 807 | return null; |
| 804 | end_index -= 1; | 808 | end_index -= 1; |
| 805 | } | 809 | } |
| 806 | | 810 | |
| ... | @@ -810,7 +814,7 @@ pub fn dirnamePosix(path: []const u8) ?[]const u8 { | ... | @@ -810,7 +814,7 @@ pub fn dirnamePosix(path: []const u8) ?[]const u8 { |
| 810 | end_index -= 1; | 814 | end_index -= 1; |
| 811 | } | 815 | } |
| 812 | | 816 | |
| 813 | if (end_index == 0 and path[end_index] == '/') | 817 | if (end_index == 0 and path[0] == '/') |
| 814 | return path[0..1]; | 818 | return path[0..1]; |
| 815 | | 819 | |
| 816 | if (end_index == 0) | 820 | if (end_index == 0) |
| ... | @@ -823,8 +827,10 @@ test "dirnamePosix" { | ... | @@ -823,8 +827,10 @@ test "dirnamePosix" { |
| 823 | testDirnamePosix("/a/b/c", "/a/b"); | 827 | testDirnamePosix("/a/b/c", "/a/b"); |
| 824 | testDirnamePosix("/a/b/c///", "/a/b"); | 828 | testDirnamePosix("/a/b/c///", "/a/b"); |
| 825 | testDirnamePosix("/a", "/"); | 829 | testDirnamePosix("/a", "/"); |
| 826 | testDirnamePosix("/", "/"); | 830 | testDirnamePosix("/", null); |
| 827 | testDirnamePosix("////", "/"); | 831 | testDirnamePosix("//", null); |
| | 832 | testDirnamePosix("///", null); |
| | 833 | testDirnamePosix("////", null); |
| 828 | testDirnamePosix("", null); | 834 | testDirnamePosix("", null); |
| 829 | testDirnamePosix("a", null); | 835 | testDirnamePosix("a", null); |
| 830 | testDirnamePosix("a/", null); | 836 | testDirnamePosix("a/", null); |
| ... | @@ -832,27 +838,27 @@ test "dirnamePosix" { | ... | @@ -832,27 +838,27 @@ test "dirnamePosix" { |
| 832 | } | 838 | } |
| 833 | | 839 | |
| 834 | test "dirnameWindows" { | 840 | test "dirnameWindows" { |
| 835 | testDirnameWindows("c:\\", "c:\\"); | 841 | testDirnameWindows("c:\\", null); |
| 836 | testDirnameWindows("c:\\foo", "c:\\"); | 842 | testDirnameWindows("c:\\foo", "c:\\"); |
| 837 | testDirnameWindows("c:\\foo\\", "c:\\"); | 843 | testDirnameWindows("c:\\foo\\", "c:\\"); |
| 838 | testDirnameWindows("c:\\foo\\bar", "c:\\foo"); | 844 | testDirnameWindows("c:\\foo\\bar", "c:\\foo"); |
| 839 | testDirnameWindows("c:\\foo\\bar\\", "c:\\foo"); | 845 | testDirnameWindows("c:\\foo\\bar\\", "c:\\foo"); |
| 840 | testDirnameWindows("c:\\foo\\bar\\baz", "c:\\foo\\bar"); | 846 | testDirnameWindows("c:\\foo\\bar\\baz", "c:\\foo\\bar"); |
| 841 | testDirnameWindows("\\", "\\"); | 847 | testDirnameWindows("\\", null); |
| 842 | testDirnameWindows("\\foo", "\\"); | 848 | testDirnameWindows("\\foo", "\\"); |
| 843 | testDirnameWindows("\\foo\\", "\\"); | 849 | testDirnameWindows("\\foo\\", "\\"); |
| 844 | testDirnameWindows("\\foo\\bar", "\\foo"); | 850 | testDirnameWindows("\\foo\\bar", "\\foo"); |
| 845 | testDirnameWindows("\\foo\\bar\\", "\\foo"); | 851 | testDirnameWindows("\\foo\\bar\\", "\\foo"); |
| 846 | testDirnameWindows("\\foo\\bar\\baz", "\\foo\\bar"); | 852 | testDirnameWindows("\\foo\\bar\\baz", "\\foo\\bar"); |
| 847 | testDirnameWindows("c:", "c:"); | 853 | testDirnameWindows("c:", null); |
| 848 | testDirnameWindows("c:foo", "c:"); | 854 | testDirnameWindows("c:foo", null); |
| 849 | testDirnameWindows("c:foo\\", "c:"); | 855 | testDirnameWindows("c:foo\\", null); |
| 850 | testDirnameWindows("c:foo\\bar", "c:foo"); | 856 | testDirnameWindows("c:foo\\bar", "c:foo"); |
| 851 | testDirnameWindows("c:foo\\bar\\", "c:foo"); | 857 | testDirnameWindows("c:foo\\bar\\", "c:foo"); |
| 852 | testDirnameWindows("c:foo\\bar\\baz", "c:foo\\bar"); | 858 | testDirnameWindows("c:foo\\bar\\baz", "c:foo\\bar"); |
| 853 | testDirnameWindows("file:stream", null); | 859 | testDirnameWindows("file:stream", null); |
| 854 | testDirnameWindows("dir\\file:stream", "dir"); | 860 | testDirnameWindows("dir\\file:stream", "dir"); |
| 855 | testDirnameWindows("\\\\unc\\share", "\\\\unc\\share"); | 861 | testDirnameWindows("\\\\unc\\share", null); |
| 856 | testDirnameWindows("\\\\unc\\share\\foo", "\\\\unc\\share\\"); | 862 | testDirnameWindows("\\\\unc\\share\\foo", "\\\\unc\\share\\"); |
| 857 | testDirnameWindows("\\\\unc\\share\\foo\\", "\\\\unc\\share\\"); | 863 | testDirnameWindows("\\\\unc\\share\\foo\\", "\\\\unc\\share\\"); |
| 858 | testDirnameWindows("\\\\unc\\share\\foo\\bar", "\\\\unc\\share\\foo"); | 864 | testDirnameWindows("\\\\unc\\share\\foo\\bar", "\\\\unc\\share\\foo"); |
| ... | @@ -862,8 +868,8 @@ test "dirnameWindows" { | ... | @@ -862,8 +868,8 @@ test "dirnameWindows" { |
| 862 | testDirnameWindows("/a/b", "/a"); | 868 | testDirnameWindows("/a/b", "/a"); |
| 863 | testDirnameWindows("/a", "/"); | 869 | testDirnameWindows("/a", "/"); |
| 864 | testDirnameWindows("", null); | 870 | testDirnameWindows("", null); |
| 865 | testDirnameWindows("/", "/"); | 871 | testDirnameWindows("/", null); |
| 866 | testDirnameWindows("////", "/"); | 872 | testDirnameWindows("////", null); |
| 867 | testDirnameWindows("foo", null); | 873 | testDirnameWindows("foo", null); |
| 868 | } | 874 | } |
| 869 | | 875 | |