diff --git a/src/mem.zig b/src/mem.zig index d866b2c..3df40b9 100644 --- a/src/mem.zig +++ b/src/mem.zig @@ -14,9 +14,6 @@ pub fn Spliterator(comptime Element: type) type { /// /// Returns `true` if there is more data to be processed, otherwise `false`. /// - /// Note that [Spliterator.next] implicitly calls this function to determine if it should - /// return another slice or `null`. - /// pub fn hasNext(self: Self) bool { return (self.source.len != 0); } @@ -26,27 +23,55 @@ pub fn Spliterator(comptime Element: type) type { /// [Spliterator.delimiter], or `null` if there is no more data to be processed. /// pub fn next(self: *Self) ?[]const Element { - if (self.delimiter.len == 0) { - defer self.source = self.source[self.source.len .. 0]; + if (!self.hasNext()) return null; - return self.source; + if (std.mem.indexOfPos(Element, self.source, 0, self.delimiter)) |index| { + defer self.source = self.source[(index + self.delimiter.len) .. self.source.len]; + + return self.source[0 .. index]; } - while (self.hasNext()) { - var cursor = @as(usize, 0); - var window = self.source[cursor .. (self.source.len - cursor)]; + defer self.source = self.source[self.source.len .. self.source.len]; - defer self.source = window; - - if (std.mem.eql(Element, window, self.delimiter)) - return self.source[cursor .. self.delimiter.len]; - } - - return null; + return self.source; } }; } +test { + const testing = std.testing; + + // Single-character delimiter. + { + var spliterator = Spliterator(u8){ + .source = "single.character.separated.hello.world", + .delimiter = ".", + }; + + const components = [_][]const u8{"single", "character", "separated", "hello", "world"}; + var index = @as(usize, 0); + + while (spliterator.next()) |split| : (index += 1) { + try testing.expect(std.mem.eql(u8, split, components[index])); + } + } + + // Multi-character delimiter. + { + var spliterator = Spliterator(u8){ + .source = "finding a needle in a needle stack", + .delimiter = "needle", + }; + + const components = [_][]const u8{"finding a ", " in a ", " stack"}; + var index = @as(usize, 0); + + while (spliterator.next()) |split| : (index += 1) { + try testing.expect(std.mem.eql(u8, split, components[index])); + } + } +} + /// /// Searches the slice of `Data` referenced by `data` for the first instance of `sought_datum`, /// returning its index or `null` if it could not be found. @@ -56,3 +81,7 @@ pub fn findFirst(comptime Data: type, data: []const Data, sought_datum: Data) ?u return null; } + +test { + try std.testing.expectEqual(findFirst(u8, "1234567890", '7'), 6); +}