authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2020-07-08 23:07:44+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-12 22:17:40+00:00
logef17af1270155e803a77955c9f37175dd09c43d4
tree6acbd18cdd280d95e10f45b75df45da7cdb704cf
parent5b570bceb531656c320684fbe42a87feff710a3b

std: add mem.joinZ

currently the only options are doing a second allocation and copying or implementing this yourself.

1 files changed, 36 insertions(+), 2 deletions(-)

lib/std/mem.zig+36-2
......@@ -1674,12 +1674,23 @@ pub const SplitIterator = struct {
16741674/// Naively combines a series of slices with a separator.
16751675/// Allocates memory for the result, which must be freed by the caller.
16761676pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 {
1677 return joinMaybeZ(allocator, separator, slices, false);
1678}
1679
1680/// Naively combines a series of slices with a separator and null terminator.
1681/// Allocates memory for the result, which must be freed by the caller.
1682pub fn joinZ(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![:0]u8 {
1683 const out = try joinMaybeZ(allocator, separator, slices, true);
1684 return out[0 .. out.len - 1 :0];
1685}
1686
1687fn joinMaybeZ(allocator: *Allocator, separator: []const u8, slices: []const []const u8, zero: bool) ![]u8 {
16771688 if (slices.len == 0) return &[0]u8{};
16781689
16791690 const total_len = blk: {
16801691 var sum: usize = separator.len * (slices.len - 1);
1681 for (slices) |slice|
1682 sum += slice.len;
1692 for (slices) |slice| sum += slice.len;
1693 if (zero) sum += 1;
16831694 break :blk sum;
16841695 };
16851696
......@@ -1695,6 +1706,8 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons
16951706 buf_index += slice.len;
16961707 }
16971708
1709 if (zero) buf[buf.len - 1] = 0;
1710
16981711 // No need for shrink since buf is exactly the correct size.
16991712 return buf;
17001713}
......@@ -1717,6 +1730,27 @@ test "mem.join" {
17171730 }
17181731}
17191732
1733test "mem.joinZ" {
1734 {
1735 const str = try joinZ(testing.allocator, ",", &[_][]const u8{ "a", "b", "c" });
1736 defer testing.allocator.free(str);
1737 testing.expect(eql(u8, str, "a,b,c"));
1738 testing.expectEqual(str[str.len], 0);
1739 }
1740 {
1741 const str = try joinZ(testing.allocator, ",", &[_][]const u8{"a"});
1742 defer testing.allocator.free(str);
1743 testing.expect(eql(u8, str, "a"));
1744 testing.expectEqual(str[str.len], 0);
1745 }
1746 {
1747 const str = try joinZ(testing.allocator, ",", &[_][]const u8{ "a", "", "b", "", "c" });
1748 defer testing.allocator.free(str);
1749 testing.expect(eql(u8, str, "a,,b,,c"));
1750 testing.expectEqual(str[str.len], 0);
1751 }
1752}
1753
17201754/// Copies each T from slices into a new slice that exactly holds all the elements.
17211755pub fn concat(allocator: *Allocator, comptime T: type, slices: []const []const T) ![]T {
17221756 if (slices.len == 0) return &[0]T{};