| ... | ... | @@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 496 | 496 | return true; |
| 497 | 497 | } |
| 498 | 498 | |
| 499 | | /// Deprecated. Use `span`. |
| 499 | /// Deprecated. Use `spanZ`. |
| 500 | 500 | pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T { |
| 501 | | return ptr[0..len(ptr) :0]; |
| 501 | return ptr[0..lenZ(ptr) :0]; |
| 502 | 502 | } |
| 503 | 503 | |
| 504 | | /// Deprecated. Use `span`. |
| 504 | /// Deprecated. Use `spanZ`. |
| 505 | 505 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { |
| 506 | | return ptr[0..len(ptr) :0]; |
| 506 | return ptr[0..lenZ(ptr) :0]; |
| 507 | 507 | } |
| 508 | 508 | |
| 509 | 509 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and |
| ... | ... | @@ -548,6 +548,9 @@ test "Span" { |
| 548 | 548 | /// returns a slice. If there is a sentinel on the input type, there will be a |
| 549 | 549 | /// sentinel on the output type. The constness of the output type matches |
| 550 | 550 | /// the constness of the input type. |
| 551 | /// |
| 552 | /// When there is both a sentinel and an array length or slice length, the |
| 553 | /// length value is used instead of the sentinel. |
| 551 | 554 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 552 | 555 | const Result = Span(@TypeOf(ptr)); |
| 553 | 556 | const l = len(ptr); |
| ... | ... | @@ -565,11 +568,74 @@ test "span" { |
| 565 | 568 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| 566 | 569 | } |
| 567 | 570 | |
| 571 | /// Same as `span`, except when there is both a sentinel and an array |
| 572 | /// length or slice length, scans the memory for the sentinel value |
| 573 | /// rather than using the length. |
| 574 | pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { |
| 575 | const Result = Span(@TypeOf(ptr)); |
| 576 | const l = lenZ(ptr); |
| 577 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| 578 | return ptr[0..l :s]; |
| 579 | } else { |
| 580 | return ptr[0..l]; |
| 581 | } |
| 582 | } |
| 583 | |
| 584 | test "spanZ" { |
| 585 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| 586 | const ptr = @as([*:3]u16, array[0..2 :3]); |
| 587 | testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 })); |
| 588 | testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| 589 | } |
| 590 | |
| 591 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |
| 592 | /// or a slice, and returns the length. |
| 593 | /// In the case of a sentinel-terminated array, it uses the array length. |
| 594 | /// For C pointers it assumes it is a pointer-to-many with a 0 sentinel. |
| 595 | pub fn len(ptr: var) usize { |
| 596 | return switch (@typeInfo(@TypeOf(ptr))) { |
| 597 | .Array => |info| info.len, |
| 598 | .Pointer => |info| switch (info.size) { |
| 599 | .One => switch (@typeInfo(info.child)) { |
| 600 | .Array => ptr.len, |
| 601 | else => @compileError("invalid type given to std.mem.len"), |
| 602 | }, |
| 603 | .Many => if (info.sentinel) |sentinel| |
| 604 | indexOfSentinel(info.child, sentinel, ptr) |
| 605 | else |
| 606 | @compileError("length of pointer with no sentinel"), |
| 607 | .C => indexOfSentinel(info.child, 0, ptr), |
| 608 | .Slice => ptr.len, |
| 609 | }, |
| 610 | else => @compileError("invalid type given to std.mem.len"), |
| 611 | }; |
| 612 | } |
| 613 | |
| 614 | test "len" { |
| 615 | testing.expect(len("aoeu") == 4); |
| 616 | |
| 617 | { |
| 618 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| 619 | testing.expect(len(&array) == 5); |
| 620 | testing.expect(len(array[0..3]) == 3); |
| 621 | array[2] = 0; |
| 622 | const ptr = @as([*:0]u16, array[0..2 :0]); |
| 623 | testing.expect(len(ptr) == 2); |
| 624 | } |
| 625 | { |
| 626 | var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 }; |
| 627 | testing.expect(len(&array) == 5); |
| 628 | array[2] = 0; |
| 629 | testing.expect(len(&array) == 5); |
| 630 | } |
| 631 | } |
| 632 | |
| 568 | 633 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |
| 569 | 634 | /// or a slice, and returns the length. |
| 570 | 635 | /// In the case of a sentinel-terminated array, it scans the array |
| 571 | 636 | /// for a sentinel and uses that for the length, rather than using the array length. |
| 572 | | pub fn len(ptr: var) usize { |
| 637 | /// For C pointers it assumes it is a pointer-to-many with a 0 sentinel. |
| 638 | pub fn lenZ(ptr: var) usize { |
| 573 | 639 | return switch (@typeInfo(@TypeOf(ptr))) { |
| 574 | 640 | .Array => |info| if (info.sentinel) |sentinel| |
| 575 | 641 | indexOfSentinel(info.child, sentinel, &ptr) |
| ... | ... | @@ -581,35 +647,38 @@ pub fn len(ptr: var) usize { |
| 581 | 647 | indexOfSentinel(x.child, sentinel, ptr) |
| 582 | 648 | else |
| 583 | 649 | ptr.len, |
| 584 | | else => @compileError("invalid type given to std.mem.length"), |
| 650 | else => @compileError("invalid type given to std.mem.lenZ"), |
| 585 | 651 | }, |
| 586 | 652 | .Many => if (info.sentinel) |sentinel| |
| 587 | 653 | indexOfSentinel(info.child, sentinel, ptr) |
| 588 | 654 | else |
| 589 | 655 | @compileError("length of pointer with no sentinel"), |
| 590 | 656 | .C => indexOfSentinel(info.child, 0, ptr), |
| 591 | | .Slice => ptr.len, |
| 657 | .Slice => if (info.sentinel) |sentinel| |
| 658 | indexOfSentinel(info.child, sentinel, ptr.ptr) |
| 659 | else |
| 660 | ptr.len, |
| 592 | 661 | }, |
| 593 | | else => @compileError("invalid type given to std.mem.length"), |
| 662 | else => @compileError("invalid type given to std.mem.lenZ"), |
| 594 | 663 | }; |
| 595 | 664 | } |
| 596 | 665 | |
| 597 | | test "len" { |
| 598 | | testing.expect(len("aoeu") == 4); |
| 666 | test "lenZ" { |
| 667 | testing.expect(lenZ("aoeu") == 4); |
| 599 | 668 | |
| 600 | 669 | { |
| 601 | 670 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| 602 | | testing.expect(len(&array) == 5); |
| 603 | | testing.expect(len(array[0..3]) == 3); |
| 671 | testing.expect(lenZ(&array) == 5); |
| 672 | testing.expect(lenZ(array[0..3]) == 3); |
| 604 | 673 | array[2] = 0; |
| 605 | 674 | const ptr = @as([*:0]u16, array[0..2 :0]); |
| 606 | | testing.expect(len(ptr) == 2); |
| 675 | testing.expect(lenZ(ptr) == 2); |
| 607 | 676 | } |
| 608 | 677 | { |
| 609 | 678 | var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 }; |
| 610 | | testing.expect(len(&array) == 5); |
| 679 | testing.expect(lenZ(&array) == 5); |
| 611 | 680 | array[2] = 0; |
| 612 | | testing.expect(len(&array) == 2); |
| 681 | testing.expect(lenZ(&array) == 2); |
| 613 | 682 | } |
| 614 | 683 | } |
| 615 | 684 | |