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 {
4343fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) bool, paths: []const []const u8, zero: bool) ![]u8 {
4444 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.
4657 const total_len = blk: {
47 var sum: usize = paths[0].len;
48 var i: usize = 1;
58 var sum: usize = paths[first_path_index].len;
59 var prev_path = paths[first_path_index];
60 assert(prev_path.len > 0);
61 var i: usize = first_path_index + 1;
4962 while (i < paths.len) : (i += 1) {
50 const prev_path = paths[i - 1];
5163 const this_path = paths[i];
52 const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
53 const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
64 if (this_path.len == 0) continue;
65 const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
66 const this_sep = sepPredicate(this_path[0]);
5467 sum += @boolToInt(!prev_sep and !this_sep);
5568 sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
69 prev_path = this_path;
5670 }
71
5772 if (zero) sum += 1;
5873 break :blk sum;
5974 };
......@@ -61,14 +76,16 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
6176 const buf = try allocator.alloc(u8, total_len);
6277 errdefer allocator.free(buf);
6378
64 mem.copy(u8, buf, paths[0]);
65 var buf_index: usize = paths[0].len;
66 var i: usize = 1;
79 mem.copy(u8, buf, paths[first_path_index]);
80 var buf_index: usize = paths[first_path_index].len;
81 var prev_path = paths[first_path_index];
82 assert(prev_path.len > 0);
83 var i: usize = first_path_index + 1;
6784 while (i < paths.len) : (i += 1) {
68 const prev_path = paths[i - 1];
6985 const this_path = paths[i];
70 const prev_sep = (prev_path.len != 0 and sepPredicate(prev_path[prev_path.len - 1]));
71 const this_sep = (this_path.len != 0 and sepPredicate(this_path[0]));
86 if (this_path.len == 0) continue;
87 const prev_sep = sepPredicate(prev_path[prev_path.len - 1]);
88 const this_sep = sepPredicate(this_path[0]);
7289 if (!prev_sep and !this_sep) {
7390 buf[buf_index] = separator;
7491 buf_index += 1;
......@@ -76,6 +93,7 @@ fn joinSepMaybeZ(allocator: *Allocator, separator: u8, sepPredicate: fn (u8) boo
7693 const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;
7794 mem.copy(u8, buf[buf_index..], adjusted_path);
7895 buf_index += adjusted_path.len;
96 prev_path = this_path;
7997 }
8098
8199 if (zero) buf[buf.len - 1] = 0;
......@@ -148,6 +166,10 @@ test "join" {
148166 try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero);
149167 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
151173 try testJoinMaybeZPosix(&[_][]const u8{}, "", zero);
152174 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b", "c" }, "/a/b/c", zero);
153175 try testJoinMaybeZPosix(&[_][]const u8{ "/a/b/", "c" }, "/a/b/c", zero);
......@@ -163,6 +185,10 @@ test "join" {
163185
164186 try testJoinMaybeZPosix(&[_][]const u8{ "a", "/c" }, "a/c", zero);
165187 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);
166192 }
167193}
168194