authorgravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2022-07-25 21:04:30+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-25 22:04:30+03:00
logcff5d9c805aa3433cc2562c3cb29bd3201817214
treeaa7bedeeb92523806f79887159d66b8b2934f375
parent2f34d06d01189ae6349e9c6341ba85ec50b92bb0
signature Signed by PGP key 4AEE18F83AFDEB23

std.mem: add `first` method to `SplitIterator` and `SplitBackwardsIterator`


14 files changed, 70 insertions(+), 49 deletions(-)

build.zig+4-4
......@@ -210,9 +210,9 @@ pub fn build(b: *Builder) !void {
210210 2 => {
211211 // Untagged development build (e.g. 0.9.0-dev.2025+ecf0050a9).
212212 var it = mem.split(u8, git_describe, "-");
213 const tagged_ancestor = it.next() orelse unreachable;
214 const commit_height = it.next() orelse unreachable;
215 const commit_id = it.next() orelse unreachable;
213 const tagged_ancestor = it.first();
214 const commit_height = it.next().?;
215 const commit_id = it.next().?;
216216
217217 const ancestor_ver = try std.builtin.Version.parse(tagged_ancestor);
218218 if (zig_version.order(ancestor_ver) != .gt) {
......@@ -764,7 +764,7 @@ fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeCon
764764 inline for (mappings) |mapping| {
765765 if (mem.startsWith(u8, line, mapping.prefix)) {
766766 var it = mem.split(u8, line, "\"");
767 _ = it.next().?; // skip the stuff before the quote
767 _ = it.first(); // skip the stuff before the quote
768768 const quoted = it.next().?; // the stuff inside the quote
769769 @field(ctx, mapping.field) = toNativePathSep(b, quoted);
770770 }
lib/std/SemanticVersion.zig+1-1
......@@ -88,7 +88,7 @@ pub fn parse(text: []const u8) !Version {
8888 const required = text[0..(extra_index orelse text.len)];
8989 var it = std.mem.split(u8, required, ".");
9090 var ver = Version{
91 .major = try parseNum(it.next() orelse return error.InvalidVersion),
91 .major = try parseNum(it.first()),
9292 .minor = try parseNum(it.next() orelse return error.InvalidVersion),
9393 .patch = try parseNum(it.next() orelse return error.InvalidVersion),
9494 };
lib/std/builtin.zig+1-1
......@@ -503,7 +503,7 @@ pub const Version = struct {
503503
504504 var it = std.mem.split(u8, text[0..end], ".");
505505 // substring is not empty, first call will succeed
506 const major = it.next().?;
506 const major = it.first();
507507 if (major.len == 0) return error.InvalidVersion;
508508 const minor = it.next() orelse "0";
509509 // ignore 'patch' if 'minor' is invalid
lib/std/crypto/phc_encoding.zig+1-1
......@@ -253,7 +253,7 @@ fn serializeTo(params: anytype, out: anytype) !void {
253253// Split a `key=value` string into `key` and `value`
254254fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {
255255 var it = mem.split(u8, str, kv_delimiter);
256 const key = it.next() orelse return Error.InvalidEncoding;
256 const key = it.first();
257257 const value = it.next() orelse return Error.InvalidEncoding;
258258 const ret = .{ .key = key, .value = value };
259259 return ret;
lib/std/crypto/scrypt.zig+1-1
......@@ -289,7 +289,7 @@ const crypt_format = struct {
289289
290290 var it = mem.split(u8, str[14..], "$");
291291
292 const salt = it.next() orelse return EncodingError.InvalidEncoding;
292 const salt = it.first();
293293 if (@hasField(T, "salt")) out.salt = salt;
294294
295295 const hash_str = it.next() orelse return EncodingError.InvalidEncoding;
lib/std/mem.zig+46-22
......@@ -1597,12 +1597,15 @@ test "byteSwapAllFields" {
15971597
15981598/// Returns an iterator that iterates over the slices of `buffer` that are not
15991599/// any of the bytes in `delimiter_bytes`.
1600/// tokenize(u8, " abc def ghi ", " ")
1601/// Will return slices for "abc", "def", "ghi", null, in that order.
1600///
1601/// `tokenize(u8, " abc def ghi ", " ")` will return slices
1602/// for "abc", "def", "ghi", null, in that order.
1603///
16021604/// If `buffer` is empty, the iterator will return null.
16031605/// If `delimiter_bytes` does not exist in buffer,
16041606/// the iterator will return `buffer`, null, in that order.
1605/// See also the related function `split`.
1607///
1608/// See also: `split` and `splitBackwards`.
16061609pub fn tokenize(comptime T: type, buffer: []const T, delimiter_bytes: []const T) TokenIterator(T) {
16071610 return .{
16081611 .index = 0,
......@@ -1696,12 +1699,15 @@ test "tokenize (reset)" {
16961699
16971700/// Returns an iterator that iterates over the slices of `buffer` that
16981701/// are separated by bytes in `delimiter`.
1699/// split(u8, "abc|def||ghi", "|")
1700/// will return slices for "abc", "def", "", "ghi", null, in that order.
1702///
1703/// `split(u8, "abc|def||ghi", "|")` will return slices
1704/// for "abc", "def", "", "ghi", null, in that order.
1705///
17011706/// If `delimiter` does not exist in buffer,
17021707/// the iterator will return `buffer`, null, in that order.
17031708/// The delimiter length must not be zero.
1704/// See also the related function `tokenize`.
1709///
1710/// See also: `tokenize` and `splitBackwards`.
17051711pub fn split(comptime T: type, buffer: []const T, delimiter: []const T) SplitIterator(T) {
17061712 assert(delimiter.len != 0);
17071713 return .{
......@@ -1714,7 +1720,7 @@ pub fn split(comptime T: type, buffer: []const T, delimiter: []const T) SplitIte
17141720test "split" {
17151721 var it = split(u8, "abc|def||ghi", "|");
17161722 try testing.expectEqualSlices(u8, it.rest(), "abc|def||ghi");
1717 try testing.expectEqualSlices(u8, it.next().?, "abc");
1723 try testing.expectEqualSlices(u8, it.first(), "abc");
17181724
17191725 try testing.expectEqualSlices(u8, it.rest(), "def||ghi");
17201726 try testing.expectEqualSlices(u8, it.next().?, "def");
......@@ -1729,16 +1735,16 @@ test "split" {
17291735 try testing.expect(it.next() == null);
17301736
17311737 it = split(u8, "", "|");
1732 try testing.expectEqualSlices(u8, it.next().?, "");
1738 try testing.expectEqualSlices(u8, it.first(), "");
17331739 try testing.expect(it.next() == null);
17341740
17351741 it = split(u8, "|", "|");
1736 try testing.expectEqualSlices(u8, it.next().?, "");
1742 try testing.expectEqualSlices(u8, it.first(), "");
17371743 try testing.expectEqualSlices(u8, it.next().?, "");
17381744 try testing.expect(it.next() == null);
17391745
17401746 it = split(u8, "hello", " ");
1741 try testing.expectEqualSlices(u8, it.next().?, "hello");
1747 try testing.expectEqualSlices(u8, it.first(), "hello");
17421748 try testing.expect(it.next() == null);
17431749
17441750 var it16 = split(
......@@ -1746,13 +1752,13 @@ test "split" {
17461752 std.unicode.utf8ToUtf16LeStringLiteral("hello"),
17471753 std.unicode.utf8ToUtf16LeStringLiteral(" "),
17481754 );
1749 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("hello"));
1755 try testing.expectEqualSlices(u16, it16.first(), std.unicode.utf8ToUtf16LeStringLiteral("hello"));
17501756 try testing.expect(it16.next() == null);
17511757}
17521758
17531759test "split (multibyte)" {
17541760 var it = split(u8, "a, b ,, c, d, e", ", ");
1755 try testing.expectEqualSlices(u8, it.next().?, "a");
1761 try testing.expectEqualSlices(u8, it.first(), "a");
17561762 try testing.expectEqualSlices(u8, it.rest(), "b ,, c, d, e");
17571763 try testing.expectEqualSlices(u8, it.next().?, "b ,");
17581764 try testing.expectEqualSlices(u8, it.next().?, "c");
......@@ -1765,7 +1771,7 @@ test "split (multibyte)" {
17651771 std.unicode.utf8ToUtf16LeStringLiteral("a, b ,, c, d, e"),
17661772 std.unicode.utf8ToUtf16LeStringLiteral(", "),
17671773 );
1768 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("a"));
1774 try testing.expectEqualSlices(u16, it16.first(), std.unicode.utf8ToUtf16LeStringLiteral("a"));
17691775 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("b ,"));
17701776 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("c"));
17711777 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("d"));
......@@ -1775,11 +1781,15 @@ test "split (multibyte)" {
17751781
17761782/// Returns an iterator that iterates backwards over the slices of `buffer`
17771783/// that are separated by bytes in `delimiter`.
1778/// splitBackwards(u8, "abc|def||ghi", "|")
1779/// will return slices for "ghi", "", "def", "abc", null, in that order.
1784///
1785/// `splitBackwards(u8, "abc|def||ghi", "|")` will return slices
1786/// for "ghi", "", "def", "abc", null, in that order.
1787///
17801788/// If `delimiter` does not exist in buffer,
17811789/// the iterator will return `buffer`, null, in that order.
17821790/// The delimiter length must not be zero.
1791///
1792/// See also: `tokenize` and `split`.
17831793pub fn splitBackwards(comptime T: type, buffer: []const T, delimiter: []const T) SplitBackwardsIterator(T) {
17841794 assert(delimiter.len != 0);
17851795 return SplitBackwardsIterator(T){
......@@ -1792,7 +1802,7 @@ pub fn splitBackwards(comptime T: type, buffer: []const T, delimiter: []const T)
17921802test "splitBackwards" {
17931803 var it = splitBackwards(u8, "abc|def||ghi", "|");
17941804 try testing.expectEqualSlices(u8, it.rest(), "abc|def||ghi");
1795 try testing.expectEqualSlices(u8, it.next().?, "ghi");
1805 try testing.expectEqualSlices(u8, it.first(), "ghi");
17961806
17971807 try testing.expectEqualSlices(u8, it.rest(), "abc|def|");
17981808 try testing.expectEqualSlices(u8, it.next().?, "");
......@@ -1807,16 +1817,16 @@ test "splitBackwards" {
18071817 try testing.expect(it.next() == null);
18081818
18091819 it = splitBackwards(u8, "", "|");
1810 try testing.expectEqualSlices(u8, it.next().?, "");
1820 try testing.expectEqualSlices(u8, it.first(), "");
18111821 try testing.expect(it.next() == null);
18121822
18131823 it = splitBackwards(u8, "|", "|");
1814 try testing.expectEqualSlices(u8, it.next().?, "");
1824 try testing.expectEqualSlices(u8, it.first(), "");
18151825 try testing.expectEqualSlices(u8, it.next().?, "");
18161826 try testing.expect(it.next() == null);
18171827
18181828 it = splitBackwards(u8, "hello", " ");
1819 try testing.expectEqualSlices(u8, it.next().?, "hello");
1829 try testing.expectEqualSlices(u8, it.first(), "hello");
18201830 try testing.expect(it.next() == null);
18211831
18221832 var it16 = splitBackwards(
......@@ -1824,14 +1834,14 @@ test "splitBackwards" {
18241834 std.unicode.utf8ToUtf16LeStringLiteral("hello"),
18251835 std.unicode.utf8ToUtf16LeStringLiteral(" "),
18261836 );
1827 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("hello"));
1837 try testing.expectEqualSlices(u16, it16.first(), std.unicode.utf8ToUtf16LeStringLiteral("hello"));
18281838 try testing.expect(it16.next() == null);
18291839}
18301840
18311841test "splitBackwards (multibyte)" {
18321842 var it = splitBackwards(u8, "a, b ,, c, d, e", ", ");
18331843 try testing.expectEqualSlices(u8, it.rest(), "a, b ,, c, d, e");
1834 try testing.expectEqualSlices(u8, it.next().?, "e");
1844 try testing.expectEqualSlices(u8, it.first(), "e");
18351845
18361846 try testing.expectEqualSlices(u8, it.rest(), "a, b ,, c, d");
18371847 try testing.expectEqualSlices(u8, it.next().?, "d");
......@@ -1853,7 +1863,7 @@ test "splitBackwards (multibyte)" {
18531863 std.unicode.utf8ToUtf16LeStringLiteral("a, b ,, c, d, e"),
18541864 std.unicode.utf8ToUtf16LeStringLiteral(", "),
18551865 );
1856 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("e"));
1866 try testing.expectEqualSlices(u16, it16.first(), std.unicode.utf8ToUtf16LeStringLiteral("e"));
18571867 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("d"));
18581868 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("c"));
18591869 try testing.expectEqualSlices(u16, it16.next().?, std.unicode.utf8ToUtf16LeStringLiteral("b ,"));
......@@ -1944,6 +1954,13 @@ pub fn SplitIterator(comptime T: type) type {
19441954
19451955 const Self = @This();
19461956
1957 /// Returns a slice of the first field. This never fails.
1958 /// Call this only to get the first field and then use `next` to get all subsequent fields.
1959 pub fn first(self: *Self) []const T {
1960 assert(self.index.? == 0);
1961 return self.next().?;
1962 }
1963
19471964 /// Returns a slice of the next field, or null if splitting is complete.
19481965 pub fn next(self: *Self) ?[]const T {
19491966 const start = self.index orelse return null;
......@@ -1974,6 +1991,13 @@ pub fn SplitBackwardsIterator(comptime T: type) type {
19741991
19751992 const Self = @This();
19761993
1994 /// Returns a slice of the first field. This never fails.
1995 /// Call this only to get the first field and then use `next` to get all subsequent fields.
1996 pub fn first(self: *Self) []const T {
1997 assert(self.index.? == self.buffer.len);
1998 return self.next().?;
1999 }
2000
19772001 /// Returns a slice of the next field, or null if splitting is complete.
19782002 pub fn next(self: *Self) ?[]const T {
19792003 const end = self.index orelse return null;
lib/std/net.zig+3-3
......@@ -1154,7 +1154,7 @@ fn linuxLookupNameFromHosts(
11541154 else => |e| return e,
11551155 }) |line| {
11561156 var split_it = mem.split(u8, line, "#");
1157 const no_comment_line = split_it.next().?;
1157 const no_comment_line = split_it.first();
11581158
11591159 var line_it = mem.tokenize(u8, no_comment_line, " \t");
11601160 const ip_text = line_it.next() orelse continue;
......@@ -1356,7 +1356,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
13561356 }) |line| {
13571357 const no_comment_line = no_comment_line: {
13581358 var split = mem.split(u8, line, "#");
1359 break :no_comment_line split.next().?;
1359 break :no_comment_line split.first();
13601360 };
13611361 var line_it = mem.tokenize(u8, no_comment_line, " \t");
13621362
......@@ -1364,7 +1364,7 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void {
13641364 if (mem.eql(u8, token, "options")) {
13651365 while (line_it.next()) |sub_tok| {
13661366 var colon_it = mem.split(u8, sub_tok, ":");
1367 const name = colon_it.next().?;
1367 const name = colon_it.first();
13681368 const value_txt = colon_it.next() orelse continue;
13691369 const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) {
13701370 // TODO https://github.com/ziglang/zig/issues/11812
lib/std/process.zig+1-1
......@@ -306,7 +306,7 @@ pub fn getEnvMap(allocator: Allocator) !EnvMap {
306306 for (environ) |env| {
307307 const pair = mem.sliceTo(env, 0);
308308 var parts = mem.split(u8, pair, "=");
309 const key = parts.next().?;
309 const key = parts.first();
310310 const value = parts.next().?;
311311 try result.put(key, value);
312312 }
lib/std/zig/CrossTarget.zig+5-5
......@@ -231,7 +231,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
231231 };
232232
233233 var it = mem.split(u8, args.arch_os_abi, "-");
234 const arch_name = it.next().?;
234 const arch_name = it.first();
235235 const arch_is_native = mem.eql(u8, arch_name, "native");
236236 if (!arch_is_native) {
237237 result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse
......@@ -249,7 +249,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
249249 const opt_abi_text = it.next();
250250 if (opt_abi_text) |abi_text| {
251251 var abi_it = mem.split(u8, abi_text, ".");
252 const abi = std.meta.stringToEnum(Target.Abi, abi_it.next().?) orelse
252 const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse
253253 return error.UnknownApplicationBinaryInterface;
254254 result.abi = abi;
255255 diags.abi = abi;
......@@ -330,7 +330,7 @@ pub fn parse(args: ParseOptions) !CrossTarget {
330330/// target CPU architecture in order to fully populate `ParseOptions`.
331331pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
332332 var it = mem.split(u8, args.arch_os_abi, "-");
333 const arch_name = it.next().?;
333 const arch_name = it.first();
334334 const arch_is_native = mem.eql(u8, arch_name, "native");
335335 if (arch_is_native) {
336336 return builtin.cpu.arch;
......@@ -632,7 +632,7 @@ pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {
632632
633633fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void {
634634 var it = mem.split(u8, text, ".");
635 const os_name = it.next().?;
635 const os_name = it.first();
636636 diags.os_name = os_name;
637637 const os_is_native = mem.eql(u8, os_name, "native");
638638 if (!os_is_native) {
......@@ -711,7 +711,7 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
711711 .windows => {
712712 var range_it = mem.split(u8, version_text, "...");
713713
714 const min_text = range_it.next().?;
714 const min_text = range_it.first();
715715 const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
716716 return error.InvalidOperatingSystemVersion;
717717 result.os_version_min = .{ .windows = min_ver };
lib/std/zig/render.zig+1-1
......@@ -1820,7 +1820,7 @@ fn renderArrayInit(
18201820 } else {
18211821 var by_line = std.mem.split(u8, expr_text, "\n");
18221822 var last_line_was_empty = false;
1823 try ais.writer().writeAll(by_line.next().?);
1823 try ais.writer().writeAll(by_line.first());
18241824 while (by_line.next()) |line| {
18251825 if (std.mem.startsWith(u8, line, "//") and last_line_was_empty) {
18261826 try ais.insertNewline();
src/Compilation.zig+1-1
......@@ -4392,7 +4392,7 @@ pub fn hasSharedLibraryExt(filename: []const u8) bool {
43924392 }
43934393 // Look for .so.X, .so.X.Y, .so.X.Y.Z
43944394 var it = mem.split(u8, filename, ".");
4395 _ = it.next().?;
4395 _ = it.first();
43964396 var so_txt = it.next() orelse return false;
43974397 while (!mem.eql(u8, so_txt, "so")) {
43984398 so_txt = it.next() orelse return false;
src/libc_installation.zig+1-4
......@@ -64,10 +64,7 @@ pub const LibCInstallation = struct {
6464 while (it.next()) |line| {
6565 if (line.len == 0 or line[0] == '#') continue;
6666 var line_it = std.mem.split(u8, line, "=");
67 const name = line_it.next() orelse {
68 log.err("missing equal sign after field name\n", .{});
69 return error.ParseError;
70 };
67 const name = line_it.first();
7168 const value = line_it.rest();
7269 inline for (fields) |field, i| {
7370 if (std.mem.eql(u8, name, field.name)) {
src/test.zig+3-3
......@@ -303,7 +303,7 @@ const TestManifest = struct {
303303
304304 // Parse key=value(s)
305305 var kv_it = std.mem.split(u8, trimmed, "=");
306 const key = kv_it.next() orelse return error.MissingKeyForConfig;
306 const key = kv_it.first();
307307 try manifest.config_map.putNoClobber(key, kv_it.next() orelse return error.MissingValuesForConfig);
308308 }
309309
......@@ -697,7 +697,7 @@ pub const TestContext = struct {
697697 }
698698 // example: "file.zig:1:2: error: bad thing happened"
699699 var it = std.mem.split(u8, err_msg_line, ":");
700 const src_path = it.next() orelse @panic("missing colon");
700 const src_path = it.first();
701701 const line_text = it.next() orelse @panic("missing line");
702702 const col_text = it.next() orelse @panic("missing column");
703703 const kind_text = it.next() orelse @panic("missing 'error'/'note'");
......@@ -1698,7 +1698,7 @@ pub const TestContext = struct {
16981698 var fib = std.io.fixedBufferStream(&buf);
16991699 try msg.renderToWriter(.no_color, fib.writer(), "error", .Red, 0);
17001700 var it = std.mem.split(u8, fib.getWritten(), "error: ");
1701 _ = it.next();
1701 _ = it.first();
17021702 const rendered = it.rest();
17031703 break :blk rendered[0 .. rendered.len - 1]; // trim final newline
17041704 };
tools/update_spirv_features.zig+1-1
......@@ -21,7 +21,7 @@ const Version = struct {
2121 fn parse(str: []const u8) !Version {
2222 var it = std.mem.split(u8, str, ".");
2323
24 const major = it.next() orelse return error.InvalidVersion;
24 const major = it.first();
2525 const minor = it.next() orelse return error.InvalidVersion;
2626
2727 if (it.next() != null) return error.InvalidVersion;