Application Context Implementation #4
|
@ -600,7 +600,7 @@ pub const FileSystem = union(enum) {
|
||||||
const last_sequence_index = sequences.len - 1;
|
const last_sequence_index = sequences.len - 1;
|
||||||
|
|
||||||
for (sequences) |sequence, index| if (sequence.len != 0) {
|
for (sequences) |sequence, index| if (sequence.len != 0) {
|
||||||
var components = ona.mem.Spliterator(u8){
|
var components = ona.io.Spliterator(u8){
|
||||||
.source = sequence,
|
.source = sequence,
|
||||||
.delimiter = "/",
|
.delimiter = "/",
|
||||||
};
|
};
|
||||||
|
|
|
@ -97,6 +97,78 @@ pub const FileAccess = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns a state machine for lazily computing all `Element` components of a given source input
|
||||||
|
/// that match a delimiting pattern.
|
||||||
|
///
|
||||||
|
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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Opaque interface to a "writable" resource, such as a block device, memory buffer, or network
|
/// Opaque interface to a "writable" resource, such as a block device, memory buffer, or network
|
||||||
/// socket.
|
/// socket.
|
||||||
|
@ -214,6 +286,20 @@ pub const Writer = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Writer that silently throws consumed data away and never fails.
|
/// Writer that silently throws consumed data away and never fails.
|
||||||
///
|
///
|
||||||
|
|
|
@ -4,11 +4,6 @@
|
||||||
///
|
///
|
||||||
pub const io = @import("./io.zig");
|
pub const io = @import("./io.zig");
|
||||||
|
|
||||||
///
|
|
||||||
/// Memory utilities.
|
|
||||||
///
|
|
||||||
pub const mem = @import("./mem.zig");
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Metaprogramming introspection utilities
|
/// Metaprogramming introspection utilities
|
||||||
///
|
///
|
||||||
|
@ -26,7 +21,6 @@ pub const table = @import("./table.zig");
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = io;
|
_ = io;
|
||||||
_ = mem;
|
|
||||||
_ = meta;
|
_ = meta;
|
||||||
_ = stack;
|
_ = stack;
|
||||||
_ = table;
|
_ = table;
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
Loading…
Reference in New Issue