Commit cc2981edfc

Travis <tssund93@gmail.com>
2020-11-11 00:15:08
update path.join to recognize any separators that isSep does
1 parent 1295525
Changed files (1)
lib
std
lib/std/fs/path.zig
@@ -39,7 +39,7 @@ pub fn isSep(byte: u8) bool {
 
 /// This is different from mem.join in that the separator will not be repeated if
 /// it is found at the end or beginning of a pair of consecutive paths.
-fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u8 {
+fn joinSep(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8) ![]u8 {
     if (paths.len == 0) return &[0]u8{};
 
     const total_len = blk: {
@@ -48,8 +48,8 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
         while (i < paths.len) : (i += 1) {
             const prev_path = paths[i - 1];
             const this_path = paths[i];
-            const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
-            const this_sep = (this_path.len != 0 and this_path[0] == separator);
+            const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
+            const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
             sum += @boolToInt(!prev_sep and !this_sep);
             sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
         }
@@ -65,8 +65,8 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
     while (i < paths.len) : (i += 1) {
         const prev_path = paths[i - 1];
         const this_path = paths[i];
-        const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
-        const this_sep = (this_path.len != 0 and this_path[0] == separator);
+        const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
+        const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
         if (!prev_sep and !this_sep) {
             buf[buf_index] = separator;
             buf_index += 1;
@@ -80,28 +80,30 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
     return buf;
 }
 
-pub const join = if (builtin.os.tag == .windows) joinWindows else joinPosix;
-
-/// Naively combines a series of paths with the native path seperator.
-/// Allocates memory for the result, which must be freed by the caller.
-pub fn joinWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
-    return joinSep(allocator, sep_windows, paths);
-}
-
 /// Naively combines a series of paths with the native path seperator.
 /// Allocates memory for the result, which must be freed by the caller.
-pub fn joinPosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
-    return joinSep(allocator, sep_posix, paths);
+pub fn join(allocator: *Allocator, paths: []const []const u8) ![]u8 {
+    return joinSep(allocator, sep, isSep, paths);
 }
 
 fn testJoinWindows(paths: []const []const u8, expected: []const u8) void {
-    const actual = joinWindows(testing.allocator, paths) catch @panic("fail");
+    const windowsIsSep = struct {
+        fn isSep(byte: u8) bool {
+            return byte == '/' or byte == '\\';
+        }
+    }.isSep;
+    const actual = joinSep(testing.allocator, sep_windows, windowsIsSep, paths) catch @panic("fail");
     defer testing.allocator.free(actual);
     testing.expectEqualSlices(u8, expected, actual);
 }
 
 fn testJoinPosix(paths: []const []const u8, expected: []const u8) void {
-    const actual = joinPosix(testing.allocator, paths) catch @panic("fail");
+    const posixIsSep = struct {
+        fn isSep(byte: u8) bool {
+            return byte == '/';
+        }
+    }.isSep;
+    const actual = joinSep(testing.allocator, sep_posix, posixIsSep, paths) catch @panic("fail");
     defer testing.allocator.free(actual);
     testing.expectEqualSlices(u8, expected, actual);
 }
@@ -119,6 +121,9 @@ test "join" {
         "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig",
     );
 
+    testJoinWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c");
+    testJoinWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c");
+
     testJoinPosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c");
     testJoinPosix(&[_][]const u8{ "/a/b/", "c" }, "/a/b/c");