authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-08 19:18:47-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-08 21:44:17-04:00
loge15e1e09f087b8d1f4d80d90a88e2944ead13332
treef51a253cfabadbba631f799bcdf49b0e8ea35bfe
parentdcf5c9074e8a0feab204200d74831fda10e6c625

os.path.basename implementation for windows


1 files changed, 72 insertions(+), 2 deletions(-)

std/os/path.zig+72-2
......@@ -610,9 +610,14 @@ fn testDirnameWindows(input: []const u8, expected_output: []const u8) {
610610}
611611
612612pub fn basename(path: []const u8) -> []const u8 {
613 if (builtin.os == builtin.Os.windows) {
614 @compileError("TODO implement os.path.basename for windows");
613 if (is_windows) {
614 return basenameWindows(path);
615 } else {
616 return basenamePosix(path);
615617 }
618}
619
620pub fn basenamePosix(path: []const u8) -> []const u8 {
616621 if (path.len == 0)
617622 return []u8{};
618623
......@@ -633,6 +638,38 @@ pub fn basename(path: []const u8) -> []const u8 {
633638 return path[start_index + 1..end_index];
634639}
635640
641pub fn basenameWindows(path: []const u8) -> []const u8 {
642 if (path.len == 0)
643 return []u8{};
644
645 var end_index: usize = path.len - 1;
646 while (true) {
647 const byte = path[end_index];
648 if (byte == '/' or byte == '\\') {
649 if (end_index == 0)
650 return []u8{};
651 end_index -= 1;
652 continue;
653 }
654 if (byte == ':' and end_index == 1) {
655 return []u8{};
656 }
657 break;
658 }
659
660 var start_index: usize = end_index;
661 end_index += 1;
662 while (path[start_index] != '/' and path[start_index] != '\\' and
663 !(path[start_index] == ':' and start_index == 1))
664 {
665 if (start_index == 0)
666 return path[0..end_index];
667 start_index -= 1;
668 }
669
670 return path[start_index + 1..end_index];
671}
672
636673test "os.path.basename" {
637674 testBasename("", "");
638675 testBasename("/", "");
......@@ -646,11 +683,44 @@ test "os.path.basename" {
646683 testBasename("/aaa/b", "b");
647684 testBasename("/a/b", "b");
648685 testBasename("//a", "a");
686
687 testBasenamePosix("\\dir\\basename.ext", "\\dir\\basename.ext");
688 testBasenamePosix("\\basename.ext", "\\basename.ext");
689 testBasenamePosix("basename.ext", "basename.ext");
690 testBasenamePosix("basename.ext\\", "basename.ext\\");
691 testBasenamePosix("basename.ext\\\\", "basename.ext\\\\");
692 testBasenamePosix("foo", "foo");
693
694 testBasenameWindows("\\dir\\basename.ext", "basename.ext");
695 testBasenameWindows("\\basename.ext", "basename.ext");
696 testBasenameWindows("basename.ext", "basename.ext");
697 testBasenameWindows("basename.ext\\", "basename.ext");
698 testBasenameWindows("basename.ext\\\\", "basename.ext");
699 testBasenameWindows("foo", "foo");
700 testBasenameWindows("C:", "");
701 testBasenameWindows("C:.", ".");
702 testBasenameWindows("C:\\", "");
703 testBasenameWindows("C:\\dir\\base.ext", "base.ext");
704 testBasenameWindows("C:\\basename.ext", "basename.ext");
705 testBasenameWindows("C:basename.ext", "basename.ext");
706 testBasenameWindows("C:basename.ext\\", "basename.ext");
707 testBasenameWindows("C:basename.ext\\\\", "basename.ext");
708 testBasenameWindows("C:foo", "foo");
709 testBasenameWindows("file:stream", "file:stream");
649710}
711
650712fn testBasename(input: []const u8, expected_output: []const u8) {
651713 assert(mem.eql(u8, basename(input), expected_output));
652714}
653715
716fn testBasenamePosix(input: []const u8, expected_output: []const u8) {
717 assert(mem.eql(u8, basenamePosix(input), expected_output));
718}
719
720fn testBasenameWindows(input: []const u8, expected_output: []const u8) {
721 assert(mem.eql(u8, basenameWindows(input), expected_output));
722}
723
654724/// Returns the relative path from ::from to ::to. If ::from and ::to each
655725/// resolve to the same path (after calling ::resolve on each), a zero-length
656726/// string is returned.