authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-08 20:46:21+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-08 20:46:21+02:00
log893c0c50b2bfe3b1ba3060e39902de43471ad064
treea1a0738f9951aa48c72a27dea6e9aa07404cf370
parent9db2a97c0d9d807502b4a0cf206230f6ed92b73b
parent06d068bf7b84b8fd4e28edf3daffb3fca9079000

Merge pull request 'std.mem: introduce copySentinel and lessThanZ' (#36785) from mem.copySentinel into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36785

1 files changed, 46 insertions(+), 0 deletions(-)

lib/std/mem.zig+46
...@@ -269,6 +269,39 @@ pub fn copyBackwards(comptime T: type, dest: []T, source: []const T) void {...@@ -269,6 +269,39 @@ pub fn copyBackwards(comptime T: type, dest: []T, source: []const T) void {
269 }269 }
270}270}
271271
272/// Copy `source` into `dest`, excluding the sentinel.
273///
274/// Asserts no overlap. Asserts `dest.len` greater or equal to source len. Returns number of elements copied,
275/// not counting the sentinel.
276pub fn copySentinel(comptime T: type, comptime s: T, dest: []T, source: [*:s]const T) usize {
277 const i = findSentinel(T, s, source);
278 @memcpy(dest[0..i], source[0..i]);
279 return i;
280}
281
282test copySentinel {
283 var dst: [11]u8 = @splat(0xff);
284 const n = copySentinel(u8, 0, &dst, "hello this\x00is my null-terminated string");
285 try testing.expectEqualStrings("hello this\xff", &dst);
286 try testing.expectEqual(n, 10);
287}
288
289/// Copy `source` into `dest`, including the sentinel.
290///
291/// Asserts no overlap. Asserts `dest.len` greater or equal to source len, including room for the sentinel.
292/// Returns number of elements copied, including the sentinel.
293pub fn copySentinelInclusive(comptime T: type, comptime s: T, dest: []T, source: [*:s]const T) usize {
294 const i = findSentinel(T, s, source) + 1;
295 @memcpy(dest[0..i], source[0..i]);
296 return i;
297}
298
299test copySentinelInclusive {
300 var dst: [12]u8 = @splat(0xff);
301 const n = copySentinelInclusive(u8, 0, &dst, "hello this\x00is my null-terminated string");
302 try testing.expectEqualStrings("hello this\x00\xff", &dst);
303 try testing.expectEqual(n, 11);
304}
272/// Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function.305/// Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function.
273/// However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when306/// However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when
274/// interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this307/// interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this
...@@ -733,6 +766,19 @@ test lessThan {...@@ -733,6 +766,19 @@ test lessThan {
733 try testing.expect(lessThan(u8, "", "a"));766 try testing.expect(lessThan(u8, "", "a"));
734}767}
735768
769/// Returns `true` if `lhs < rhs`; `false` otherwise, operating on null-terminated arrays.
770pub fn lessThanZ(comptime T: type, lhs: [*:0]const T, rhs: [*:0]const T) bool {
771 return orderZ(T, lhs, rhs) == .lt;
772}
773
774test lessThanZ {
775 try testing.expect(lessThanZ(u8, "abcd", "bee"));
776 try testing.expect(!lessThanZ(u8, "abc", "abc"));
777 try testing.expect(lessThanZ(u8, "abc", "abc0"));
778 try testing.expect(!lessThanZ(u8, "", ""));
779 try testing.expect(lessThanZ(u8, "", "a"));
780}
781
736const use_vectors = switch (builtin.zig_backend) {782const use_vectors = switch (builtin.zig_backend) {
737 // These backends don't support vectors yet.783 // These backends don't support vectors yet.
738 .stage2_aarch64,784 .stage2_aarch64,