Commit 3411b5e499

Andrew Kelley <andrew@ziglang.org>
2025-09-25 20:11:46
std.mem: add cut and cutScalar and example usage
1 parent dd2f1cb
Changed files (2)
lib
src
lib/std/mem.zig
@@ -3099,6 +3099,44 @@ test cutSuffix {
     try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));
 }
 
+/// Returns slice of `haystack` before and after `needle`, or `null` if not
+/// found.
+///
+/// See also:
+/// * `cutScalar`
+/// * `split`
+/// * `tokenizeAny`
+pub fn cut(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
+    const index = indexOf(T, haystack, needle) orelse return null;
+    return .{ haystack[0..index], haystack[index + needle.len ..] };
+}
+
+test cut {
+    try testing.expectEqual(null, cut(u8, "a b c", "B"));
+    const before, const after = cut(u8, "a be c", "be") orelse return error.TestFailed;
+    try testing.expectEqualStrings("a ", before);
+    try testing.expectEqualStrings(" c", after);
+}
+
+/// Returns slice of `haystack` before and after `needle`, or `null` if not
+/// found.
+///
+/// See also:
+/// * `cut`
+/// * `splitScalar`
+/// * `tokenizeScalar`
+pub fn cutScalar(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
+    const index = indexOfScalar(T, haystack, needle) orelse return null;
+    return .{ haystack[0..index], haystack[index + 1 ..] };
+}
+
+test cutScalar {
+    try testing.expectEqual(null, cutScalar(u8, "a b c", 'B'));
+    const before, const after = cutScalar(u8, "a b c", 'b') orelse return error.TestFailed;
+    try testing.expectEqualStrings("a ", before);
+    try testing.expectEqualStrings(" c", after);
+}
+
 /// Delimiter type for tokenization and splitting operations.
 pub const DelimiterType = enum { sequence, any, scalar };
 
src/main.zig
@@ -1077,9 +1077,7 @@ fn buildOutputType(
                             .value = value,
                         });
                     } else if (mem.cutPrefix(u8, arg, "-M")) |rest| {
-                        var it = mem.splitScalar(u8, rest, '=');
-                        const mod_name = it.first();
-                        const root_src_orig = if (it.peek() != null) it.rest() else null;
+                        const mod_name, const root_src_orig = mem.cutScalar(u8, rest, '=') orelse .{ rest, null };
                         try handleModArg(
                             arena,
                             mod_name,
@@ -1343,9 +1341,7 @@ fn buildOutputType(
                         } else {
                             dev.check(.network_listen);
                             // example: --listen 127.0.0.1:9000
-                            var it = std.mem.splitScalar(u8, next_arg, ':');
-                            const host = it.next().?;
-                            const port_text = it.next() orelse "14735";
+                            const host, const port_text = mem.cutScalar(u8, next_arg, ':') orelse .{ next_arg, "14735" };
                             const port = std.fmt.parseInt(u16, port_text, 10) catch |err|
                                 fatal("invalid port number: '{s}': {s}", .{ port_text, @errorName(err) });
                             listen = .{ .ip4 = std.net.Ip4Address.parse(host, port) catch |err|