authorgravatar for ybham6@gmail.comYusuf Bham <ybham6@gmail.com> 2022-04-17 11:43:45-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-21 14:39:41-04:00
log41654a318db526465754ae084cc37896382eb0d2
treef13196351334d77a321850b4675823f09ad71da4
parent6d0283e6bc0493ca40fc752433973d50210023d2

std.mem: add concatWithSentinel


1 files changed, 41 insertions(+), 1 deletions(-)

lib/std/mem.zig+41-1
...@@ -1941,13 +1941,29 @@ test "joinZ" {...@@ -1941,13 +1941,29 @@ test "joinZ" {
19411941
1942/// Copies each T from slices into a new slice that exactly holds all the elements.1942/// Copies each T from slices into a new slice that exactly holds all the elements.
1943pub fn concat(allocator: Allocator, comptime T: type, slices: []const []const T) ![]T {1943pub fn concat(allocator: Allocator, comptime T: type, slices: []const []const T) ![]T {
1944 if (slices.len == 0) return &[0]T{};1944 return concatMaybeSentinel(allocator, T, slices, null);
1945}
1946
1947/// Copies each T from slices into a new slice that exactly holds all the elements.
1948pub fn concatWithSentinel(allocator: Allocator, comptime T: type, slices: []const []const T, comptime s: T) ![:s]T {
1949 const ret = try concatMaybeSentinel(allocator, T, slices, s);
1950 return ret[0 .. ret.len - 1 :s];
1951}
1952
1953/// Copies each T from slices into a new slice that exactly holds all the elements as well as the sentinel.
1954pub fn concatMaybeSentinel(allocator: Allocator, comptime T: type, slices: []const []const T, comptime s: ?T) ![]T {
1955 if (slices.len == 0) return if (s) |sentinel| try allocator.dupe(T, &[1]T{sentinel}) else &[0]T{};
19451956
1946 const total_len = blk: {1957 const total_len = blk: {
1947 var sum: usize = 0;1958 var sum: usize = 0;
1948 for (slices) |slice| {1959 for (slices) |slice| {
1949 sum += slice.len;1960 sum += slice.len;
1950 }1961 }
1962
1963 if (s) |_| {
1964 sum += 1;
1965 }
1966
1951 break :blk sum;1967 break :blk sum;
1952 };1968 };
19531969
...@@ -1960,6 +1976,10 @@ pub fn concat(allocator: Allocator, comptime T: type, slices: []const []const T)...@@ -1960,6 +1976,10 @@ pub fn concat(allocator: Allocator, comptime T: type, slices: []const []const T)
1960 buf_index += slice.len;1976 buf_index += slice.len;
1961 }1977 }
19621978
1979 if (s) |sentinel| {
1980 buf[buf.len - 1] = sentinel;
1981 }
1982
1963 // No need for shrink since buf is exactly the correct size.1983 // No need for shrink since buf is exactly the correct size.
1964 return buf;1984 return buf;
1965}1985}
...@@ -1980,6 +2000,26 @@ test "concat" {...@@ -1980,6 +2000,26 @@ test "concat" {
1980 defer testing.allocator.free(str);2000 defer testing.allocator.free(str);
1981 try testing.expect(eql(u32, str, &[_]u32{ 0, 1, 2, 3, 4, 5 }));2001 try testing.expect(eql(u32, str, &[_]u32{ 0, 1, 2, 3, 4, 5 }));
1982 }2002 }
2003 {
2004 const str = try concatWithSentinel(testing.allocator, u8, &[_][]const u8{ "abc", "def", "ghi" }, 0);
2005 defer testing.allocator.free(str);
2006 try testing.expectEqualSentinel(u8, 0, str, "abcdefghi");
2007 }
2008 {
2009 const slice = try concatWithSentinel(testing.allocator, u8, &[_][]const u8{}, 0);
2010 defer testing.allocator.free(slice);
2011 try testing.expectEqualSentinel(u8, 0, slice, &[_:0]u8{});
2012 }
2013 {
2014 const slice = try concatWithSentinel(testing.allocator, u32, &[_][]const u32{
2015 &[_]u32{ 0, 1 },
2016 &[_]u32{ 2, 3, 4 },
2017 &[_]u32{},
2018 &[_]u32{5},
2019 }, 2);
2020 defer testing.allocator.free(slice);
2021 try testing.expectEqualSentinel(u32, 2, slice, &[_:2]u32{ 0, 1, 2, 3, 4, 5 });
2022 }
1983}2023}
19842024
1985test "testStringEquality" {2025test "testStringEquality" {