| ... | @@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | ... | @@ -496,14 +496,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 496 | return true; | 496 | return true; |
| 497 | } | 497 | } |
| 498 | | 498 | |
| 499 | /// Deprecated. Use `span`. | 499 | /// Deprecated. Use `spanZ`. |
| 500 | pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T { | 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 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { | 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 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and | 509 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and |
| ... | @@ -548,6 +548,9 @@ test "Span" { | ... | @@ -548,6 +548,9 @@ test "Span" { |
| 548 | /// returns a slice. If there is a sentinel on the input type, there will be a | 548 | /// returns a slice. If there is a sentinel on the input type, there will be a |
| 549 | /// sentinel on the output type. The constness of the output type matches | 549 | /// sentinel on the output type. The constness of the output type matches |
| 550 | /// the constness of the input type. | 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 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { | 554 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 552 | const Result = Span(@TypeOf(ptr)); | 555 | const Result = Span(@TypeOf(ptr)); |
| 553 | const l = len(ptr); | 556 | const l = len(ptr); |
| ... | @@ -565,11 +568,74 @@ test "span" { | ... | @@ -565,11 +568,74 @@ test "span" { |
| 565 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); | 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 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, | 633 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |
| 569 | /// or a slice, and returns the length. | 634 | /// or a slice, and returns the length. |
| 570 | /// In the case of a sentinel-terminated array, it scans the array | 635 | /// 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. | 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 | return switch (@typeInfo(@TypeOf(ptr))) { | 639 | return switch (@typeInfo(@TypeOf(ptr))) { |
| 574 | .Array => |info| if (info.sentinel) |sentinel| | 640 | .Array => |info| if (info.sentinel) |sentinel| |
| 575 | indexOfSentinel(info.child, sentinel, &ptr) | 641 | indexOfSentinel(info.child, sentinel, &ptr) |
| ... | @@ -581,35 +647,38 @@ pub fn len(ptr: var) usize { | ... | @@ -581,35 +647,38 @@ pub fn len(ptr: var) usize { |
| 581 | indexOfSentinel(x.child, sentinel, ptr) | 647 | indexOfSentinel(x.child, sentinel, ptr) |
| 582 | else | 648 | else |
| 583 | ptr.len, | 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 | .Many => if (info.sentinel) |sentinel| | 652 | .Many => if (info.sentinel) |sentinel| |
| 587 | indexOfSentinel(info.child, sentinel, ptr) | 653 | indexOfSentinel(info.child, sentinel, ptr) |
| 588 | else | 654 | else |
| 589 | @compileError("length of pointer with no sentinel"), | 655 | @compileError("length of pointer with no sentinel"), |
| 590 | .C => indexOfSentinel(info.child, 0, ptr), | 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" { | 666 | test "lenZ" { |
| 598 | testing.expect(len("aoeu") == 4); | 667 | testing.expect(lenZ("aoeu") == 4); |
| 599 | | 668 | |
| 600 | { | 669 | { |
| 601 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; | 670 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| 602 | testing.expect(len(&array) == 5); | 671 | testing.expect(lenZ(&array) == 5); |
| 603 | testing.expect(len(array[0..3]) == 3); | 672 | testing.expect(lenZ(array[0..3]) == 3); |
| 604 | array[2] = 0; | 673 | array[2] = 0; |
| 605 | const ptr = @as([*:0]u16, array[0..2 :0]); | 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 | var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 }; | 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 | array[2] = 0; | 680 | array[2] = 0; |
| 612 | testing.expect(len(&array) == 2); | 681 | testing.expect(lenZ(&array) == 2); |
| 613 | } | 682 | } |
| 614 | } | 683 | } |
| 615 | | 684 | |