1
Fork 0

ErrCtx: splitRev

main
Motiejus Jakštys 2022-06-22 15:36:22 +03:00
parent 675125be05
commit 62b643dbc2
2 changed files with 51 additions and 1 deletions

View File

@ -6,6 +6,7 @@ const mem = std.mem;
const math = std.math;
const BoundedArray = std.BoundedArray;
const assert = std.debug.assert;
const capacity = 1 << 16; // 64K
const ErrCtx = @This();
@ -44,6 +45,12 @@ pub fn iterator(self: *const ErrCtx) mem.SplitIterator(u8) {
return mem.split(u8, slice[0..last_byte], "\x00");
}
pub fn rev(self: *const ErrCtx) SplitIteratorRev(u8) {
const slice = self.buf.constSlice();
const last_byte = if (slice[slice.len - 1] == '0') slice.len - 1 else slice.len;
return splitRev(u8, slice[0..last_byte], "\x00");
}
const testing = std.testing;
test "basics" {
@ -63,6 +70,11 @@ test "basics" {
try testing.expectEqual(@as(usize, capacity - 2 - 20), long.len);
try testing.expectEqual(it.next(), null);
try testing.expect(ctx.overflow);
var it_rev = ctx.rev();
try testing.expectEqualSlices(u8, it_rev.next().?, "3" ** (capacity - 22));
try testing.expectEqualSlices(u8, it_rev.next().?, "1" ** 10);
try testing.expectEqualSlices(u8, it_rev.next().?, "0" ** 10);
}
test "almost overflow" {
@ -76,4 +88,42 @@ test "almost overflow" {
try testing.expectEqualSlices(u8, it.next().?, "0" ** (capacity - 2));
try testing.expectEqualSlices(u8, it.next().?, "1");
try testing.expectEqual(it.next(), null);
var it_rev = ctx.rev();
try testing.expectEqualSlices(u8, it_rev.next().?, "1");
try testing.expectEqualSlices(u8, it_rev.next().?, "0" ** (capacity - 2));
try testing.expectEqual(it.next(), null);
}
// copied form https://github.com/ziglang/zig/pull/11908
pub fn splitRev(comptime T: type, buffer: []const T, delimiter: []const T) SplitIteratorRev(T) {
assert(delimiter.len != 0);
return SplitIteratorRev(T){
.index = buffer.len,
.buffer = buffer,
.delimiter = delimiter,
};
}
pub fn SplitIteratorRev(comptime T: type) type {
return struct {
buffer: []const T,
index: ?usize,
delimiter: []const T,
const Self = @This();
/// Returns a slice of the next field, or null if splitting is complete.
pub fn next(self: *Self) ?[]const T {
const end = self.index orelse return null;
const start = if (mem.lastIndexOf(T, self.buffer[0..end], self.delimiter)) |delim_start| blk: {
self.index = delim_start;
break :blk delim_start + self.delimiter.len;
} else blk: {
self.index = null;
break :blk 0;
};
return self.buffer[start..end];
}
};
}

View File

@ -128,7 +128,7 @@ test "invalid argument" {
}
test "smoke test" {
//if (true) return error.SkipZigTest;
if (true) return error.SkipZigTest;
const allocator = testing.allocator;
var stderr = ArrayList(u8).init(allocator);