| ... | @@ -913,8 +913,9 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type { | ... | @@ -913,8 +913,9 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type { |
| 913 | .pointer => |ptr_info| { | 913 | .pointer => |ptr_info| { |
| 914 | const Elem = std.meta.Elem(T); | 914 | const Elem = std.meta.Elem(T); |
| 915 | const have_sentinel: bool = switch (ptr_info.size) { | 915 | const have_sentinel: bool = switch (ptr_info.size) { |
| 916 | .one, .slice, .many => if (std.meta.sentinel(T)) |s| s == end else false, | 916 | .one, .slice => if (std.meta.sentinel(T)) |s| s == end else false, |
| 917 | .c => false, | 917 | .many => if (std.meta.sentinel(T)) |s| s == end else true, |
| | 918 | .c => true, |
| 918 | }; | 919 | }; |
| 919 | return @Pointer(.slice, .{ | 920 | return @Pointer(.slice, .{ |
| 920 | .@"const" = ptr_info.is_const, | 921 | .@"const" = ptr_info.is_const, |
| ... | @@ -929,11 +930,14 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type { | ... | @@ -929,11 +930,14 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type { |
| 929 | @compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(T)); | 930 | @compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(T)); |
| 930 | } | 931 | } |
| 931 | | 932 | |
| 932 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice and iterates searching for | 933 | /// Takes a pointer to an array, a many-item pointer, or a slice, and returns a |
| 933 | /// the first occurrence of `end`, returning the scanned slice. | 934 | /// slice of the items up to the first occurrence of `end`. |
| 934 | /// If `end` is not found, the full length of the array/slice/sentinel terminated pointer is returned. | 935 | /// If `end` is not found, the resulting slice will include all items up to the |
| 935 | /// If the pointer type is sentinel terminated and `end` matches that terminator, the | 936 | /// input's length or sentinel. |
| 936 | /// resulting slice is also sentinel terminated. | 937 | /// If the pointer type is unbounded (no length or sentinel), `end` will be the |
| | 938 | /// sentinel for the resulting slice. |
| | 939 | /// If the pointer type is sentinel-terminated by `end`, the resulting slice |
| | 940 | /// will also be sentinel-terminated by `end`. |
| 937 | /// Pointer properties such as mutability and alignment are preserved. | 941 | /// Pointer properties such as mutability and alignment are preserved. |
| 938 | /// C pointers are assumed to be non-null. | 942 | /// C pointers are assumed to be non-null. |
| 939 | pub fn sliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) SliceTo(@TypeOf(ptr), end) { | 943 | pub fn sliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) SliceTo(@TypeOf(ptr), end) { |
| ... | @@ -961,8 +965,15 @@ test sliceTo { | ... | @@ -961,8 +965,15 @@ test sliceTo { |
| 961 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(&array, 3)); | 965 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(&array, 3)); |
| 962 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(array[0..3], 3)); | 966 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(array[0..3], 3)); |
| 963 | | 967 | |
| | 968 | const many_ptr: [*]u16 = &array; |
| | 969 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(many_ptr, 3)); |
| | 970 | try testing.expectEqual([:3]u16, @TypeOf(sliceTo(many_ptr, 3))); |
| | 971 | |
| 964 | const sentinel_ptr = @as([*:5]u16, @ptrCast(&array)); | 972 | const sentinel_ptr = @as([*:5]u16, @ptrCast(&array)); |
| 965 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(sentinel_ptr, 3)); | 973 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(sentinel_ptr, 3)); |
| | 974 | try testing.expectEqual([]u16, @TypeOf(sliceTo(sentinel_ptr, 3))); |
| | 975 | try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 5)); |
| | 976 | try testing.expectEqual([:5]u16, @TypeOf(sliceTo(sentinel_ptr, 5))); |
| 966 | try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 99)); | 977 | try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 99)); |
| 967 | | 978 | |
| 968 | const optional_sentinel_ptr = @as(?[*:5]u16, @ptrCast(&array)); | 979 | const optional_sentinel_ptr = @as(?[*:5]u16, @ptrCast(&array)); |
| ... | @@ -971,6 +982,7 @@ test sliceTo { | ... | @@ -971,6 +982,7 @@ test sliceTo { |
| 971 | | 982 | |
| 972 | const c_ptr = @as([*c]u16, &array); | 983 | const c_ptr = @as([*c]u16, &array); |
| 973 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(c_ptr, 3)); | 984 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(c_ptr, 3)); |
| | 985 | try testing.expectEqual([:3]u16, @TypeOf(sliceTo(c_ptr, 3))); |
| 974 | | 986 | |
| 975 | const slice: []u16 = &array; | 987 | const slice: []u16 = &array; |
| 976 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(slice, 3)); | 988 | try testing.expectEqualSlices(u16, array[0..2], sliceTo(slice, 3)); |
| ... | @@ -1015,6 +1027,8 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize { | ... | @@ -1015,6 +1027,8 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize { |
| 1015 | var i: usize = 0; | 1027 | var i: usize = 0; |
| 1016 | while (ptr[i] != end and ptr[i] != s) i += 1; | 1028 | while (ptr[i] != end and ptr[i] != s) i += 1; |
| 1017 | return i; | 1029 | return i; |
| | 1030 | } else { |
| | 1031 | return findSentinel(ptr_info.child, end, @ptrCast(ptr)); |
| 1018 | }, | 1032 | }, |
| 1019 | .c => { | 1033 | .c => { |
| 1020 | assert(ptr != null); | 1034 | assert(ptr != null); |