authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-25 11:38:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-25 11:38:38-07:00
log14e227d8a6dd692ba0707aa070b8bac22a9a822e
tree191f4da339c891dc501d16cdda42d0a2046cb815
parent97bef50dc32e332839efe1a9c5cbf51364a431dc

std.mem: add cutLast and cutScalarLast


2 files changed, 51 insertions(+), 15 deletions(-)

lib/std/mem.zig+49-12
...@@ -1017,7 +1017,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {...@@ -1017,7 +1017,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {
1017 return indexOfSentinel(array_info.child, end, ptr);1017 return indexOfSentinel(array_info.child, end, ptr);
1018 }1018 }
1019 }1019 }
1020 return indexOfScalar(array_info.child, ptr, end) orelse array_info.len;1020 return findScalar(array_info.child, ptr, end) orelse array_info.len;
1021 },1021 },
1022 else => {},1022 else => {},
1023 },1023 },
...@@ -1042,7 +1042,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {...@@ -1042,7 +1042,7 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {
1042 return indexOfSentinel(ptr_info.child, s, ptr);1042 return indexOfSentinel(ptr_info.child, s, ptr);
1043 }1043 }
1044 }1044 }
1045 return indexOfScalar(ptr_info.child, ptr, end) orelse ptr.len;1045 return findScalar(ptr_info.child, ptr, end) orelse ptr.len;
1046 },1046 },
1047 },1047 },
1048 else => {},1048 else => {},
...@@ -1229,7 +1229,7 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {...@@ -1229,7 +1229,7 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
1229/// Remove a set of values from the beginning of a slice.1229/// Remove a set of values from the beginning of a slice.
1230pub fn trimStart(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {1230pub fn trimStart(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
1231 var begin: usize = 0;1231 var begin: usize = 0;
1232 while (begin < slice.len and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}1232 while (begin < slice.len and findScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
1233 return slice[begin..];1233 return slice[begin..];
1234}1234}
12351235
...@@ -1243,7 +1243,7 @@ pub const trimLeft = trimStart;...@@ -1243,7 +1243,7 @@ pub const trimLeft = trimStart;
1243/// Remove a set of values from the end of a slice.1243/// Remove a set of values from the end of a slice.
1244pub fn trimEnd(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {1244pub fn trimEnd(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
1245 var end: usize = slice.len;1245 var end: usize = slice.len;
1246 while (end > 0 and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}1246 while (end > 0 and findScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
1247 return slice[0..end];1247 return slice[0..end];
1248}1248}
12491249
...@@ -1258,8 +1258,8 @@ pub const trimRight = trimEnd;...@@ -1258,8 +1258,8 @@ pub const trimRight = trimEnd;
1258pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {1258pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
1259 var begin: usize = 0;1259 var begin: usize = 0;
1260 var end: usize = slice.len;1260 var end: usize = slice.len;
1261 while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}1261 while (begin < end and findScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
1262 while (end > begin and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}1262 while (end > begin and findScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
1263 return slice[begin..end];1263 return slice[begin..end];
1264}1264}
12651265
...@@ -3145,15 +3145,15 @@ test cutSuffix {...@@ -3145,15 +3145,15 @@ test cutSuffix {
3145 try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));3145 try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));
3146}3146}
31473147
3148/// Returns slice of `haystack` before and after `needle`, or `null` if not3148/// Returns slice of `haystack` before and after first occurrence of `needle`,
3149/// found.3149/// or `null` if not found.
3150///3150///
3151/// See also:3151/// See also:
3152/// * `cutScalar`3152/// * `cutScalar`
3153/// * `split`3153/// * `split`
3154/// * `tokenizeAny`3154/// * `tokenizeAny`
3155pub fn cut(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {3155pub fn cut(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
3156 const index = indexOf(T, haystack, needle) orelse return null;3156 const index = find(T, haystack, needle) orelse return null;
3157 return .{ haystack[0..index], haystack[index + needle.len ..] };3157 return .{ haystack[0..index], haystack[index + needle.len ..] };
3158}3158}
31593159
...@@ -3164,15 +3164,33 @@ test cut {...@@ -3164,15 +3164,33 @@ test cut {
3164 try testing.expectEqualStrings(" c", after);3164 try testing.expectEqualStrings(" c", after);
3165}3165}
31663166
3167/// Returns slice of `haystack` before and after `needle`, or `null` if not3167/// Returns slice of `haystack` before and after last occurrence of `needle`,
3168/// found.3168/// or `null` if not found.
3169///
3170/// See also:
3171/// * `cut`
3172/// * `cutScalarLast`
3173pub fn cutLast(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
3174 const index = findLast(T, haystack, needle) orelse return null;
3175 return .{ haystack[0..index], haystack[index + needle.len ..] };
3176}
3177
3178test cutLast {
3179 try testing.expectEqual(null, cutLast(u8, "a b c", "B"));
3180 const before, const after = cutLast(u8, "a be c be d", "be") orelse return error.TestFailed;
3181 try testing.expectEqualStrings("a be c ", before);
3182 try testing.expectEqualStrings(" d", after);
3183}
3184
3185/// Returns slice of `haystack` before and after first occurrence `needle`, or
3186/// `null` if not found.
3169///3187///
3170/// See also:3188/// See also:
3171/// * `cut`3189/// * `cut`
3172/// * `splitScalar`3190/// * `splitScalar`
3173/// * `tokenizeScalar`3191/// * `tokenizeScalar`
3174pub fn cutScalar(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {3192pub fn cutScalar(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
3175 const index = indexOfScalar(T, haystack, needle) orelse return null;3193 const index = findScalar(T, haystack, needle) orelse return null;
3176 return .{ haystack[0..index], haystack[index + 1 ..] };3194 return .{ haystack[0..index], haystack[index + 1 ..] };
3177}3195}
31783196
...@@ -3183,6 +3201,25 @@ test cutScalar {...@@ -3183,6 +3201,25 @@ test cutScalar {
3183 try testing.expectEqualStrings(" c", after);3201 try testing.expectEqualStrings(" c", after);
3184}3202}
31853203
3204/// Returns slice of `haystack` before and after last occurrence of `needle`,
3205/// or `null` if not found.
3206///
3207/// See also:
3208/// * `cut`
3209/// * `splitScalar`
3210/// * `tokenizeScalar`
3211pub fn cutScalarLast(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
3212 const index = findScalarLast(T, haystack, needle) orelse return null;
3213 return .{ haystack[0..index], haystack[index + 1 ..] };
3214}
3215
3216test cutScalarLast {
3217 try testing.expectEqual(null, cutScalarLast(u8, "a b c", 'B'));
3218 const before, const after = cutScalarLast(u8, "a b c b d", 'b') orelse return error.TestFailed;
3219 try testing.expectEqualStrings("a b c ", before);
3220 try testing.expectEqualStrings(" d", after);
3221}
3222
3186/// Delimiter type for tokenization and splitting operations.3223/// Delimiter type for tokenization and splitting operations.
3187pub const DelimiterType = enum { sequence, any, scalar };3224pub const DelimiterType = enum { sequence, any, scalar };
31883225
src/main.zig+2-3
...@@ -1057,9 +1057,8 @@ fn buildOutputType(...@@ -1057,9 +1057,8 @@ fn buildOutputType(
1057 fatal("unexpected end-of-parameter mark: --", .{});1057 fatal("unexpected end-of-parameter mark: --", .{});
1058 }1058 }
1059 } else if (mem.eql(u8, arg, "--dep")) {1059 } else if (mem.eql(u8, arg, "--dep")) {
1060 var it = mem.splitScalar(u8, args_iter.nextOrFatal(), '=');1060 const next_arg = args_iter.nextOrFatal();
1061 const key = it.first();1061 const key, const value = mem.cutScalar(u8, next_arg, '=') orelse .{ next_arg, next_arg };
1062 const value = if (it.peek() != null) it.rest() else key;
1063 if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) {1062 if (mem.eql(u8, key, "std") and !mem.eql(u8, value, "std")) {
1064 fatal("unable to import as '{s}': conflicts with builtin module", .{1063 fatal("unable to import as '{s}': conflicts with builtin module", .{
1065 key,1064 key,