| ... | ... | @@ -567,12 +567,20 @@ test "span" { |
| 567 | 567 | |
| 568 | 568 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |
| 569 | 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. |
| 570 | 572 | pub fn len(ptr: var) usize { |
| 571 | 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 | 578 | .Pointer => |info| switch (info.size) { |
| 574 | 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 | 584 | else => @compileError("invalid type given to std.mem.length"), |
| 577 | 585 | }, |
| 578 | 586 | .Many => if (info.sentinel) |sentinel| |
| ... | ... | @@ -597,6 +605,12 @@ test "len" { |
| 597 | 605 | const ptr = array[0..2 :0].ptr; |
| 598 | 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 | } |
| 601 | 615 | |
| 602 | 616 | pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize { |