authorgravatar for austinclementsbass@gmail.comAustin Clements <austinclementsbass@gmail.com> 2021-07-26 16:03:30-05:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-07-28 09:51:48+03:00
logeb010ce65ddddb23ceddae86d377432cf1b2b01c
tree325490de7a49404c64aa186e47ff67240848bbf4
parenta8e8927c4926176c683a4b66f86c8b011064e7b7

Skip empty strings in std.fs.path.join function


1 files changed, 37 insertions(+), 11 deletions(-)

lib/std/fs/path.zig+37-11
...@@ -43,17 +43,32 @@ pub fn isSep(byte: u8) bool {...@@ -43,17 +43,32 @@ pub fn isSep(byte: u8) bool {
43fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {43fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
44 if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};44 if (paths.len == 0) return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
4545
46 // Find first non-empty path index.
47 const first_path_index = blk: {
48 for (paths) |path, index| {
49 if (path.len == 0) continue else break :blk index;
50 }
51
52 // All paths provided were empty, so return early.
53 return if (zero) try allocator.dupe(u8, &[1]u8{0}) else &[0]u8{};
54 };
55
56 // Calculate length needed for resulting joined path buffer.
46 const total_len = blk: {57 const total_len = blk: {
47 var sum: usize = paths[0].len;58 var sum: usize = paths[first_path_index].len;
48 var i: usize = 1;59 var prev_path = paths[first_path_index];
60 assert(prev_path.len > 0);
61 var i: usize = first_path_index + 1;
49 while (i < paths.len) : (i += 1) {62 while (i < paths.len) : (i += 1) {
50 const prev_path = paths[i - 1];
51 const this_path = paths[i];63 const this_path = paths[i];
52 const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));64 if (this_path.len == 0) continue;
53 const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));65 const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
66 const this_sep = sepPredicate(this_path[0]);
54 sum += @boolToInt(!prev_sep and !this_sep);67 sum += @boolToInt(!prev_sep and !this_sep);
55 sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;68 sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
69 prev_path = this_path;
56 }70 }
71
57 if (zero) sum += 1;72 if (zero) sum += 1;
58 break :blk sum;73 break :blk sum;
59 };74 };
...@@ -61,14 +76,16 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo...@@ -61,14 +76,16 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
61 const buf = try allocator.alloc(u8, total_len);76 const buf = try allocator.alloc(u8, total_len);
62 errdefer allocator.free(buf);77 errdefer allocator.free(buf);
6378
64 mem.copy(u8, buf, paths[0]);79 mem.copy(u8, buf, paths[first_path_index]);
65 var buf_index: usize = paths[0].len;80 var buf_index: usize = paths[first_path_index].len;
66 var i: usize = 1;81 var prev_path = paths[first_path_index];
82 assert(prev_path.len > 0);
83 var i: usize = first_path_index + 1;
67 while (i < paths.len) : (i += 1) {84 while (i < paths.len) : (i += 1) {
68 const prev_path = paths[i - 1];
69 const this_path = paths[i];85 const this_path = paths[i];
70 const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));86 if (this_path.len == 0) continue;
71 const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));87 const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
88 const this_sep = sepPredicate(this_path[0]);
72 if (!prev_sep and !this_sep) {89 if (!prev_sep and !this_sep) {
73 buf[buf_index] = separator;90 buf[buf_index] = separator;
74 buf_index += 1;91 buf_index += 1;
...@@ -76,6 +93,7 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo...@@ -76,6 +93,7 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
76 const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;93 const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;
77 mem.copy(u8, buf[buf_index..], adjusted_path);94 mem.copy(u8, buf[buf_index..], adjusted_path);
78 buf_index += adjusted_path.len;95 buf_index += adjusted_path.len;
96 prev_path = this_path;
79 }97 }
8098
81 if (zero) buf[buf.len - 1] = 0;99 if (zero) buf[buf.len - 1] = 0;
...@@ -148,6 +166,10 @@ test "join" {...@@ -148,6 +166,10 @@ test "join" {
148 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero);166 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero);
149 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c", zero);167 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c", zero);
150168
169 try testJoinMaybeZWindows(&[_][]const u8{ "", "c:\\", "", "", "a", "b\\", "c", "" }, "c:\\a\\b\\c", zero);
170 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "", "b\\", "", "/c" }, "c:\\a/b\\c", zero);
171 try testJoinMaybeZWindows(&[_][]const u8{ "", "" }, "", zero);
172
151 try testJoinMaybeZPosix(&[_][]const u8{}, "", zero);173 try testJoinMaybeZPosix(&[_][]const u8{}, "", zero);
152 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c", zero);174 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c", zero);
153 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b/", "c" }, "/a/b/c", zero);175 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b/", "c" }, "/a/b/c", zero);
...@@ -163,6 +185,10 @@ test "join" {...@@ -163,6 +185,10 @@ test "join" {
163185
164 try testJoinMaybeZPosix(&[_][]const u8{ "a", "/c" }, "a/c", zero);186 try testJoinMaybeZPosix(&[_][]const u8{ "a", "/c" }, "a/c", zero);
165 try testJoinMaybeZPosix(&[_][]const u8{ "a/", "/c" }, "a/c", zero);187 try testJoinMaybeZPosix(&[_][]const u8{ "a/", "/c" }, "a/c", zero);
188
189 try testJoinMaybeZPosix(&[_][]const u8{ "", "/", "a", "", "b/", "c", "" }, "/a/b/c", zero);
190 try testJoinMaybeZPosix(&[_][]const u8{ "/a/", "", "", "b/", "c" }, "/a/b/c", zero);
191 try testJoinMaybeZPosix(&[_][]const u8{ "", "" }, "", zero);
166 }192 }
167}193}
168194