88 lines
2.6 KiB
Zig
88 lines
2.6 KiB
Zig
const std = @import("std");
|
|
|
|
///
|
|
/// State machine for lazily computing all components of [Spliterator.source] that match the pattern
|
|
/// in [Spliterator.delimiter].
|
|
///
|
|
pub fn Spliterator(comptime Element: type) type {
|
|
return struct {
|
|
source: []const Element,
|
|
delimiter: []const Element,
|
|
|
|
const Self = @This();
|
|
|
|
///
|
|
/// Returns `true` if there is more data to be processed, otherwise `false`.
|
|
///
|
|
pub fn hasNext(self: Self) bool {
|
|
return (self.source.len != 0);
|
|
}
|
|
|
|
///
|
|
/// Iterates on `self` and returns the next view of [Spliterator.source] that matches
|
|
/// [Spliterator.delimiter], or `null` if there is no more data to be processed.
|
|
///
|
|
pub fn next(self: *Self) ?[]const Element {
|
|
if (!self.hasNext()) return null;
|
|
|
|
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];
|
|
}
|
|
|
|
defer self.source = self.source[self.source.len .. self.source.len];
|
|
|
|
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.
|
|
///
|
|
pub fn findFirst(comptime Data: type, data: []const Data, sought_datum: Data) ?usize {
|
|
for (data) |datum, index| if (datum == sought_datum) return index;
|
|
|
|
return null;
|
|
}
|
|
|
|
test {
|
|
try std.testing.expectEqual(findFirst(u8, "1234567890", '7'), 6);
|
|
}
|