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