const std = @import("std"); pub const IntersectionIterator = struct { ref: std.mem.TokenIterator(u8), rest: []const []const u8, /// Returns the next occurrence or null. Returned value is owned by originally passed slice pub fn next(self: *IntersectionIterator) ?[]const u8 { // If this returns null, there's no more items to check. We're finished. const needle = self.ref.next() orelse return null; // Search into every one of the strings haystack: for (self.rest) |haystack| { // The items are separated by spaces, iterate through those var haystack_iter = std.mem.tokenize(u8, haystack, " "); // If the word is found, it short circuits and tries the next haystack while (haystack_iter.next()) |hay_blade| { if (std.mem.eql(u8, hay_blade, needle)) continue :haystack; } // If this point is reached, the needle wasn't found. // Try the next one return self.next(); } // If we got here, no not-matching haysack was found. A match! return needle; } }; /// Finds the common tokens inside space separated strings /// and returns a slice to the first token that matches pub fn intersection(slices: []const []const u8) IntersectionIterator { // Tokenize the first entry and save the rest as references to check return IntersectionIterator{ .ref = std.mem.tokenize(u8, slices[0], " "), .rest = slices[1..], }; } pub fn readUntilDelimiterAllocZ( reader: anytype, // TODO: Fix this and set the correct type, I got no clue rn allocator: std.mem.Allocator, delimiter: u8, max_size: usize, ) ![:0]u8 { var array_list = std.ArrayList(u8).init(allocator); defer array_list.deinit(); try reader.readUntilDelimiterArrayList(&array_list, delimiter, max_size); return array_list.toOwnedSliceSentinel(0); }