From cc2981edfc4c0e36d3ce6d564f7a36caae9b61b7 Mon Sep 17 00:00:00 2001 From: Travis Date: Tue, 10 Nov 2020 17:15:08 -0600 Subject: [PATCH] update path.join to recognize any separators that isSep does --- lib/std/fs/path.zig | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig index 1852f4531c..c04b9dff66 100644 --- a/lib/std/fs/path.zig +++ b/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");