authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-15 15:46:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-15 15:46:56-04:00
log6c2b23593b97aef6f375bd7d81beeaf0f66f5682
tree928e581db83b81c6799063335c2ce605e308f7b1
parent701aaf0ddf618edffa182db1e888172b6cae4ab1

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 files changed, 16 insertions(+), 2 deletions(-)

lib/std/mem.zig+16-2
...@@ -567,12 +567,20 @@ test "span" {...@@ -567,12 +567,20 @@ test "span" {
567567
568/// Takes a pointer to an array, an array, a sentinel-terminated pointer,568/// Takes a pointer to an array, an array, a sentinel-terminated pointer,
569/// or a slice, and returns the length.569/// or a slice, and returns the length.
570/// In the case of a sentinel-terminated array, it scans the array
571/// for a sentinel and uses that for the length, rather than using the array length.
570pub fn len(ptr: var) usize {572pub fn len(ptr: var) usize {
571 return switch (@typeInfo(@TypeOf(ptr))) {573 return switch (@typeInfo(@TypeOf(ptr))) {
572 .Array => |info| info.len,574 .Array => |info| if (info.sentinel) |sentinel|
575 indexOfSentinel(info.child, sentinel, &ptr)
576 else
577 info.len,
573 .Pointer => |info| switch (info.size) {578 .Pointer => |info| switch (info.size) {
574 .One => switch (@typeInfo(info.child)) {579 .One => switch (@typeInfo(info.child)) {
575 .Array => |x| x.len,580 .Array => |x| if (x.sentinel) |sentinel|
581 indexOfSentinel(x.child, sentinel, ptr)
582 else
583 ptr.len,
576 else => @compileError("invalid type given to std.mem.length"),584 else => @compileError("invalid type given to std.mem.length"),
577 },585 },
578 .Many => if (info.sentinel) |sentinel|586 .Many => if (info.sentinel) |sentinel|
...@@ -597,6 +605,12 @@ test "len" {...@@ -597,6 +605,12 @@ test "len" {
597 const ptr = array[0..2 :0].ptr;605 const ptr = array[0..2 :0].ptr;
598 testing.expect(len(ptr) == 2);606 testing.expect(len(ptr) == 2);
599 }607 }
608 {
609 var array: [5:0]u16 = [_]u16{ 1, 2, 3, 4, 5 };
610 testing.expect(len(&array) == 5);
611 array[2] = 0;
612 testing.expect(len(&array) == 2);
613 }
600}614}
601615
602pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {616pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {