aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2020-07-08 23:07:44 +0200
committerAndrew Kelley <andrew@ziglang.org>2020-07-12 22:17:40 +0000
commitef17af1270155e803a77955c9f37175dd09c43d4 (patch)
tree6acbd18cdd280d95e10f45b75df45da7cdb704cf /lib/std
parent5b570bceb531656c320684fbe42a87feff710a3b (diff)
downloadzig-ef17af1270155e803a77955c9f37175dd09c43d4.tar.gz
zig-ef17af1270155e803a77955c9f37175dd09c43d4.zip
std: add mem.joinZ
currently the only options are doing a second allocation and copying or implementing this yourself.
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/mem.zig38
1 files changed, 36 insertions, 2 deletions
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 2f17a83422..0fbe96942e 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -1674,12 +1674,23 @@ pub const SplitIterator = struct {
/// Naively combines a series of slices with a separator.
/// Allocates memory for the result, which must be freed by the caller.
pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 {
+ return joinMaybeZ(allocator, separator, slices, false);
+}
+
+/// Naively combines a series of slices with a separator and null terminator.
+/// Allocates memory for the result, which must be freed by the caller.
+pub fn joinZ(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![:0]u8 {
+ const out = try joinMaybeZ(allocator, separator, slices, true);
+ return out[0 .. out.len - 1 :0];
+}
+
+fn joinMaybeZ(allocator: *Allocator, separator: []const u8, slices: []const []const u8, zero: bool) ![]u8 {
if (slices.len == 0) return &[0]u8{};
const total_len = blk: {
var sum: usize = separator.len * (slices.len - 1);
- for (slices) |slice|
- sum += slice.len;
+ for (slices) |slice| sum += slice.len;
+ if (zero) sum += 1;
break :blk sum;
};
@@ -1695,6 +1706,8 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons
buf_index += slice.len;
}
+ if (zero) buf[buf.len - 1] = 0;
+
// No need for shrink since buf is exactly the correct size.
return buf;
}
@@ -1717,6 +1730,27 @@ test "mem.join" {
}
}
+test "mem.joinZ" {
+ {
+ const str = try joinZ(testing.allocator, ",", &[_][]const u8{ "a", "b", "c" });
+ defer testing.allocator.free(str);
+ testing.expect(eql(u8, str, "a,b,c"));
+ testing.expectEqual(str[str.len], 0);
+ }
+ {
+ const str = try joinZ(testing.allocator, ",", &[_][]const u8{"a"});
+ defer testing.allocator.free(str);
+ testing.expect(eql(u8, str, "a"));
+ testing.expectEqual(str[str.len], 0);
+ }
+ {
+ const str = try joinZ(testing.allocator, ",", &[_][]const u8{ "a", "", "b", "", "c" });
+ defer testing.allocator.free(str);
+ testing.expect(eql(u8, str, "a,,b,,c"));
+ testing.expectEqual(str[str.len], 0);
+ }
+}
+
/// Copies each T from slices into a new slice that exactly holds all the elements.
pub fn concat(allocator: *Allocator, comptime T: type, slices: []const []const T) ![]T {
if (slices.len == 0) return &[0]T{};