Commit 6c2b23593b

Andrew Kelley <andrew@ziglang.org>
2020-03-15 20:46:56
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.
1 parent 701aaf0
Changed files (1)
lib
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 {