From 6c2b23593b97aef6f375bd7d81beeaf0f66f5682 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 15 Mar 2020 15:46:56 -0400 Subject: [PATCH] fix std.mem.span handling of sentinel-terminated arrays previously this function would use the array length, but now it scans the array looking for the first sentinel that occurs. --- lib/std/mem.zig | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index c767765652..07fbebfb3b 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -567,12 +567,20 @@ test "span" { /// Takes a pointer to an array, an array, a sentinel-terminated pointer, /// or a slice, and returns the length. +/// In the case of a sentinel-terminated array, it scans the array +/// for a sentinel and uses that for the length, rather than using the array length. pub fn len(ptr: var) usize { return switch (@typeInfo(@TypeOf(ptr))) { - .Array => |info| info.len, + .Array => |info| if (info.sentinel) |sentinel| + indexOfSentinel(info.child, sentinel, &ptr) + else + info.len, .Pointer => |info| switch (info.size) { .One => switch (@typeInfo(info.child)) { - .Array => |x| x.len, + .Array => |x| if (x.sentinel) |sentinel| + indexOfSentinel(x.child, sentinel, ptr) + else + ptr.len, else => @compileError("invalid type given to std.mem.length"), }, .Many => if (info.sentinel) |sentinel| @@ -597,6 +605,12 @@ test "len" { const ptr = array[0..2 :0].ptr; testing.expect(len(ptr) == 2); } + { + var array: [5:0]u16 = [_]u16{ 1, 2, 3, 4, 5 }; + testing.expect(len(&array) == 5); + array[2] = 0; + testing.expect(len(&array) == 2); + } } pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {