Add additional memory utils to core module
This commit is contained in:
parent
7599ce61f2
commit
b4816a34f6
138
src/core/io.zig
138
src/core/io.zig
|
@ -7,102 +7,6 @@ const std = @import("std");
|
|||
///
|
||||
pub const Allocator = std.mem.Allocator;
|
||||
|
||||
///
|
||||
/// File-system agnostic abstraction for manipulating a file.
|
||||
///
|
||||
pub const FileAccess = struct {
|
||||
context: *anyopaque,
|
||||
implementation: *const Implementation,
|
||||
|
||||
///
|
||||
/// Provides a set of implementation-specific behaviors to a [FileAccess] instance.
|
||||
///
|
||||
pub const Implementation = struct {
|
||||
close: fn (*anyopaque) void,
|
||||
queryCursor: fn (*anyopaque) Error!u64,
|
||||
queryLength: fn (*anyopaque) Error!u64,
|
||||
read: fn (*anyopaque, []u8) Error!usize,
|
||||
seek: fn (*anyopaque, u64) Error!void,
|
||||
seekToEnd: fn (*anyopaque) Error!void,
|
||||
skip: fn (*anyopaque, i64) Error!void,
|
||||
};
|
||||
|
||||
///
|
||||
/// [Error.FileInaccessible] is a generic catch-all for a [FileAccess] reference no longer
|
||||
/// pointing to a file or the file becomming invalid for whatever reason.
|
||||
///
|
||||
pub const Error = error {
|
||||
FileInaccessible,
|
||||
};
|
||||
|
||||
///
|
||||
/// Close the file referenced by `file_access` on the main thread, invalidating the reference to
|
||||
/// it and releasing any associated resources.
|
||||
///
|
||||
/// Freeing an invalid `file_access` has no effect on the file and logs a warning over the
|
||||
/// wasted effort.
|
||||
///
|
||||
pub fn close(file_access: FileAccess) void {
|
||||
return file_access.implementation.close(file_access.context);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to query the current cursor position for the file referenced by `file_access`.
|
||||
///
|
||||
/// Returns the number of bytes into the file that the cursor is relative to its beginning or a
|
||||
/// [Error] on failure.
|
||||
///
|
||||
pub fn queryCursor(file_access: FileAccess) Error!u64 {
|
||||
return file_access.implementation.queryCursor(file_access.context);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to query the current length for the file referenced by `file_access`.
|
||||
///
|
||||
/// Returns the current length of the file at the time of the operation or a [Error] if the file
|
||||
/// failed to be queried.
|
||||
///
|
||||
pub fn queryLength(file_access: FileAccess) Error!u64 {
|
||||
return file_access.implementation.queryLength(file_access.context);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to read `file_access` from the its current position into `buffer`.
|
||||
///
|
||||
/// Returns the number of bytes that were available to be read, otherwise an [Error] on failure.
|
||||
///
|
||||
pub fn read(file_access: FileAccess, buffer: []u8) Error!usize {
|
||||
return file_access.implementation.read(file_access.context, buffer);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to seek `file_access` from the beginning of the file to `cursor` bytes.
|
||||
///
|
||||
/// Returns [Error] on failure.
|
||||
///
|
||||
pub fn seek(file_access: FileAccess, cursor: u64) Error!void {
|
||||
return file_access.implementation.seek(file_access.context, cursor);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to seek `file_access` to the end of the file.
|
||||
///
|
||||
/// Returns [Error] on failure.
|
||||
///
|
||||
pub fn seekToEnd(file_access: FileAccess) Error!void {
|
||||
return file_access.implementation.seekToEnd(file_access.context);
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempts to seek `file_access` by `offset` from the current file position.
|
||||
///
|
||||
/// Returns [Error] on failure;
|
||||
///
|
||||
pub fn skip(file_access: FileAccess, offset: i64) Error!void {
|
||||
return file_access.implementation.skip(file_access.context, offset);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// Closure that captures a reference to readable resources like block devices, memory buffers,
|
||||
/// network sockets, and more.
|
||||
|
@ -161,7 +65,7 @@ test "Spliterating text" {
|
|||
var index = @as(usize, 0);
|
||||
|
||||
while (spliterator.next()) |split| : (index += 1) {
|
||||
try testing.expect(std.mem.eql(u8, split, components[index]));
|
||||
try testing.expect(equals(u8, split, components[index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +80,7 @@ test "Spliterating text" {
|
|||
var index = @as(usize, 0);
|
||||
|
||||
while (spliterator.next()) |split| : (index += 1) {
|
||||
try testing.expect(std.mem.eql(u8, split, components[index]));
|
||||
try testing.expect(equals(u8, split, components[index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +113,7 @@ test "Check memory begins with" {
|
|||
///
|
||||
/// **Note** that passing a slice will convert it to a byte slice.
|
||||
///
|
||||
pub fn bytes(pointer: anytype) switch (@typeInfo(@TypeOf(pointer))) {
|
||||
pub fn bytesOf(pointer: anytype) switch (@typeInfo(@TypeOf(pointer))) {
|
||||
.Pointer => |info| if (info.is_const) []const u8 else []u8,
|
||||
else => @compileError("`pointer` must be a pointer type"),
|
||||
} {
|
||||
|
@ -233,7 +137,35 @@ test "Bytes of types" {
|
|||
|
||||
var foo: u32 = 10;
|
||||
|
||||
testing.expectEqual(bytes(&foo), 0x0a);
|
||||
testing.expectEqual(bytesOf(&foo), 0x0a);
|
||||
}
|
||||
|
||||
///
|
||||
/// Compares `this` to `that`, returning the difference between the first byte deviation in the two
|
||||
/// sequences, otherwise `0` if they are identical.
|
||||
///
|
||||
pub fn compareBytes(this: []const u8, that: []const u8) isize {
|
||||
var cursor: usize = 0;
|
||||
|
||||
while (cursor != this.len) : (cursor += 1) {
|
||||
const this_byte = this[cursor];
|
||||
|
||||
if (cursor != that.len) return this_byte;
|
||||
|
||||
const that_byte = that[cursor];
|
||||
|
||||
if (this_byte != that_byte) return (this_byte - that_byte);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "Compare bytes" {
|
||||
const testing = std.testing;
|
||||
|
||||
try testing.expectEquals(compareBytes(&.{69, 42, 0}, &.{69, 42, 0}), 0);
|
||||
try testing.expectEquals(compareBytes(&.{69, 42, 0}, &.{69, 42}), 42);
|
||||
try testing.expectEquals(compareBytes(&.{69, 42}, &.{69, 42, 0}), -42);
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -243,11 +175,9 @@ test "Bytes of types" {
|
|||
pub fn equals(comptime Element: type, this: []const Element, that: []const Element) bool {
|
||||
if (this.len != that.len) return false;
|
||||
|
||||
{
|
||||
var i = std.mem.zeroes(usize);
|
||||
var i = std.mem.zeroes(usize);
|
||||
|
||||
while (i < this.len) : (i += 1) if (this[i] != that[i]) return false;
|
||||
}
|
||||
while (i < this.len) : (i += 1) if (this[i] != that[i]) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue