std: add mem.joinZ
currently the only options are doing a second allocation and copying or implementing this yourself.
This commit is contained in:
committed by
Andrew Kelley
parent
5b570bceb5
commit
ef17af1270
@@ -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{};
|
||||
|
||||
Reference in New Issue
Block a user