authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-25 11:11:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-25 11:11:46-07:00
log3411b5e4995db2b432a50842a665127e65ae1f1b
treef2a4b2fb9ac580a78efc1ecddc41cd7cc5e292cf
parentdd2f1cbebf5982c254e2e2ee7ba46c9aca32fd9e

std.mem: add cut and cutScalar and example usage


2 files changed, 40 insertions(+), 6 deletions(-)

lib/std/mem.zig+38
...@@ -3099,6 +3099,44 @@ test cutSuffix {...@@ -3099,6 +3099,44 @@ test cutSuffix {
3099 try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));3099 try testing.expectEqual(null, cutSuffix(u8, "foobar", "baz"));
3100}3100}
31013101
3102/// Returns slice of `haystack` before and after `needle`, or `null` if not
3103/// found.
3104///
3105/// See also:
3106/// * `cutScalar`
3107/// * `split`
3108/// * `tokenizeAny`
3109pub fn cut(comptime T: type, haystack: []const T, needle: []const T) ?struct { []const T, []const T } {
3110 const index = indexOf(T, haystack, needle) orelse return null;
3111 return .{ haystack[0..index], haystack[index + needle.len ..] };
3112}
3113
3114test cut {
3115 try testing.expectEqual(null, cut(u8, "a b c", "B"));
3116 const before, const after = cut(u8, "a be c", "be") orelse return error.TestFailed;
3117 try testing.expectEqualStrings("a ", before);
3118 try testing.expectEqualStrings(" c", after);
3119}
3120
3121/// Returns slice of `haystack` before and after `needle`, or `null` if not
3122/// found.
3123///
3124/// See also:
3125/// * `cut`
3126/// * `splitScalar`
3127/// * `tokenizeScalar`
3128pub fn cutScalar(comptime T: type, haystack: []const T, needle: T) ?struct { []const T, []const T } {
3129 const index = indexOfScalar(T, haystack, needle) orelse return null;
3130 return .{ haystack[0..index], haystack[index + 1 ..] };
3131}
3132
3133test cutScalar {
3134 try testing.expectEqual(null, cutScalar(u8, "a b c", 'B'));
3135 const before, const after = cutScalar(u8, "a b c", 'b') orelse return error.TestFailed;
3136 try testing.expectEqualStrings("a ", before);
3137 try testing.expectEqualStrings(" c", after);
3138}
3139
3102/// Delimiter type for tokenization and splitting operations.3140/// Delimiter type for tokenization and splitting operations.
3103pub const DelimiterType = enum { sequence, any, scalar };3141pub const DelimiterType = enum { sequence, any, scalar };
31043142
src/main.zig+2-6
...@@ -1077,9 +1077,7 @@ fn buildOutputType(...@@ -1077,9 +1077,7 @@ fn buildOutputType(
1077 .value = value,1077 .value = value,
1078 });1078 });
1079 } else if (mem.cutPrefix(u8, arg, "-M")) |rest| {1079 } else if (mem.cutPrefix(u8, arg, "-M")) |rest| {
1080 var it = mem.splitScalar(u8, rest, '=');1080 const mod_name, const root_src_orig = mem.cutScalar(u8, rest, '=') orelse .{ rest, null };
1081 const mod_name = it.first();
1082 const root_src_orig = if (it.peek() != null) it.rest() else null;
1083 try handleModArg(1081 try handleModArg(
1084 arena,1082 arena,
1085 mod_name,1083 mod_name,
...@@ -1343,9 +1341,7 @@ fn buildOutputType(...@@ -1343,9 +1341,7 @@ fn buildOutputType(
1343 } else {1341 } else {
1344 dev.check(.network_listen);1342 dev.check(.network_listen);
1345 // example: --listen 127.0.0.1:90001343 // example: --listen 127.0.0.1:9000
1346 var it = std.mem.splitScalar(u8, next_arg, ':');1344 const host, const port_text = mem.cutScalar(u8, next_arg, ':') orelse .{ next_arg, "14735" };
1347 const host = it.next().?;
1348 const port_text = it.next() orelse "14735";
1349 const port = std.fmt.parseInt(u16, port_text, 10) catch |err|1345 const port = std.fmt.parseInt(u16, port_text, 10) catch |err|
1350 fatal("invalid port number: '{s}': {s}", .{ port_text, @errorName(err) });1346 fatal("invalid port number: '{s}': {s}", .{ port_text, @errorName(err) });
1351 listen = .{ .ip4 = std.net.Ip4Address.parse(host, port) catch |err|1347 listen = .{ .ip4 = std.net.Ip4Address.parse(host, port) catch |err|