aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Thread.zig2
-rw-r--r--lib/std/bounded_array.zig6
-rw-r--r--lib/std/cstr.zig1
-rw-r--r--lib/std/fs.zig2
-rw-r--r--lib/std/io/fixed_buffer_stream.zig25
-rw-r--r--lib/std/mem.zig102
6 files changed, 50 insertions, 88 deletions
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index d27474584f..8004f94d7f 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -166,7 +166,7 @@ pub const GetNameError = error{
pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]const u8 {
buffer_ptr[max_name_len] = 0;
- var buffer = std.mem.span(buffer_ptr);
+ var buffer: [:0]u8 = buffer_ptr;
switch (target.os.tag) {
.linux => if (use_pthreads and is_gnu) {
diff --git a/lib/std/bounded_array.zig b/lib/std/bounded_array.zig
index 3d74e5e47f..7f1957d6dc 100644
--- a/lib/std/bounded_array.zig
+++ b/lib/std/bounded_array.zig
@@ -29,7 +29,11 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
}
/// View the internal array as a slice whose size was previously set.
- pub fn slice(self: anytype) mem.Span(@TypeOf(&self.buffer)) {
+ pub fn slice(self: anytype) switch (@TypeOf(&self.buffer)) {
+ *[buffer_capacity]T => []T,
+ *const [buffer_capacity]T => []const T,
+ else => unreachable,
+ } {
return self.buffer[0..self.len];
}
diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig
index 068fc419ac..52524c5084 100644
--- a/lib/std/cstr.zig
+++ b/lib/std/cstr.zig
@@ -28,7 +28,6 @@ test "cstr fns" {
fn testCStrFnsImpl() !void {
try testing.expect(cmp("aoeu", "aoez") == -1);
- try testing.expect(mem.len("123456789") == 9);
}
/// Returns a mutable, null-terminated slice with the same length as `slice`.
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 1b00064108..244f3a38ce 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -834,7 +834,7 @@ pub const IterableDir = struct {
self.end_index = self.index; // Force fd_readdir in the next loop.
continue :start_over;
}
- const name = mem.span(self.buf[name_index .. name_index + entry.d_namlen]);
+ const name = self.buf[name_index .. name_index + entry.d_namlen];
const next_index = name_index + entry.d_namlen;
self.index = next_index;
diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig
index f486356491..2fcb260c72 100644
--- a/lib/std/io/fixed_buffer_stream.zig
+++ b/lib/std/io/fixed_buffer_stream.zig
@@ -113,14 +113,27 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
};
}
-pub fn fixedBufferStream(buffer: anytype) FixedBufferStream(NonSentinelSpan(@TypeOf(buffer))) {
- return .{ .buffer = mem.span(buffer), .pos = 0 };
+pub fn fixedBufferStream(buffer: anytype) FixedBufferStream(Slice(@TypeOf(buffer))) {
+ return .{ .buffer = buffer, .pos = 0 };
}
-fn NonSentinelSpan(comptime T: type) type {
- var ptr_info = @typeInfo(mem.Span(T)).Pointer;
- ptr_info.sentinel = null;
- return @Type(.{ .Pointer = ptr_info });
+fn Slice(comptime T: type) type {
+ switch (@typeInfo(T)) {
+ .Pointer => |ptr_info| {
+ var new_ptr_info = ptr_info;
+ switch (ptr_info.size) {
+ .Slice => {},
+ .One => switch (@typeInfo(ptr_info.child)) {
+ .Array => |info| new_ptr_info.child = info.child,
+ else => @compileError("invalid type given to fixedBufferStream"),
+ },
+ else => @compileError("invalid type given to fixedBufferStream"),
+ }
+ new_ptr_info.size = .Slice;
+ return @Type(.{ .Pointer = new_ptr_info });
+ },
+ else => @compileError("invalid type given to fixedBufferStream"),
+ }
}
test "FixedBufferStream output" {
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 8691c5bbad..371ef8fd8d 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -636,12 +636,9 @@ test "indexOfDiff" {
try testing.expectEqual(indexOfDiff(u8, "xne", "one"), 0);
}
-/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
-/// returns a slice. If there is a sentinel on the input type, there will be a
-/// sentinel on the output type. The constness of the output type matches
-/// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated,
-/// and assumed to not allow null.
-pub fn Span(comptime T: type) type {
+/// Takes a sentinel-terminated pointer and returns a slice preserving pointer attributes.
+/// `[*c]` pointers are assumed to be 0-terminated and assumed to not be allowzero.
+fn Span(comptime T: type) type {
switch (@typeInfo(T)) {
.Optional => |optional_info| {
return ?Span(optional_info.child);
@@ -649,39 +646,22 @@ pub fn Span(comptime T: type) type {
.Pointer => |ptr_info| {
var new_ptr_info = ptr_info;
switch (ptr_info.size) {
- .One => switch (@typeInfo(ptr_info.child)) {
- .Array => |info| {
- new_ptr_info.child = info.child;
- new_ptr_info.sentinel = info.sentinel;
- },
- else => @compileError("invalid type given to std.mem.Span"),
- },
.C => {
new_ptr_info.sentinel = &@as(ptr_info.child, 0);
new_ptr_info.is_allowzero = false;
},
- .Many, .Slice => {},
+ .Many => if (ptr_info.sentinel == null) @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
+ .One, .Slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
}
new_ptr_info.size = .Slice;
return @Type(.{ .Pointer = new_ptr_info });
},
- else => @compileError("invalid type given to std.mem.Span"),
+ else => {},
}
+ @compileError("invalid type given to std.mem.span: " ++ @typeName(T));
}
test "Span" {
- try testing.expect(Span(*[5]u16) == []u16);
- try testing.expect(Span(?*[5]u16) == ?[]u16);
- try testing.expect(Span(*const [5]u16) == []const u16);
- try testing.expect(Span(?*const [5]u16) == ?[]const u16);
- try testing.expect(Span([]u16) == []u16);
- try testing.expect(Span(?[]u16) == ?[]u16);
- try testing.expect(Span([]const u8) == []const u8);
- try testing.expect(Span(?[]const u8) == ?[]const u8);
- try testing.expect(Span([:1]u16) == [:1]u16);
- try testing.expect(Span(?[:1]u16) == ?[:1]u16);
- try testing.expect(Span([:1]const u8) == [:1]const u8);
- try testing.expect(Span(?[:1]const u8) == ?[:1]const u8);
try testing.expect(Span([*:1]u16) == [:1]u16);
try testing.expect(Span(?[*:1]u16) == ?[:1]u16);
try testing.expect(Span([*:1]const u8) == [:1]const u8);
@@ -692,13 +672,10 @@ test "Span" {
try testing.expect(Span(?[*c]const u8) == ?[:0]const u8);
}
-/// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
-/// returns a slice. If there is a sentinel on the input type, there will be a
-/// sentinel on the output type. The constness of the output type matches
-/// the constness of the input type.
-///
-/// When there is both a sentinel and an array length or slice length, the
-/// length value is used instead of the sentinel.
+/// Takes a sentinel-terminated pointer and returns a slice, iterating over the
+/// memory to find the sentinel and determine the length.
+/// Ponter attributes such as const are preserved.
+/// `[*c]` pointers are assumed to be non-null and 0-terminated.
pub fn span(ptr: anytype) Span(@TypeOf(ptr)) {
if (@typeInfo(@TypeOf(ptr)) == .Optional) {
if (ptr) |non_null| {
@@ -722,7 +699,6 @@ test "span" {
var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
const ptr = @as([*:3]u16, array[0..2 :3]);
try testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 }));
- try testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
try testing.expectEqual(@as(?[:0]u16, null), span(@as(?[*:0]u16, null)));
}
@@ -919,22 +895,15 @@ test "lenSliceTo" {
}
}
-/// Takes a pointer to an array, an array, a vector, a sentinel-terminated pointer,
-/// a slice or a tuple, and returns the length.
-/// In the case of a sentinel-terminated array, it uses the array length.
-/// For C pointers it assumes it is a pointer-to-many with a 0 sentinel.
+/// Takes a sentinel-terminated pointer and iterates over the memory to find the
+/// sentinel and determine the length.
+/// `[*c]` pointers are assumed to be non-null and 0-terminated.
pub fn len(value: anytype) usize {
- return switch (@typeInfo(@TypeOf(value))) {
- .Array => |info| info.len,
- .Vector => |info| info.len,
+ switch (@typeInfo(@TypeOf(value))) {
.Pointer => |info| switch (info.size) {
- .One => switch (@typeInfo(info.child)) {
- .Array => value.len,
- else => @compileError("invalid type given to std.mem.len"),
- },
.Many => {
const sentinel_ptr = info.sentinel orelse
- @compileError("length of pointer with no sentinel");
+ @compileError("invalid type given to std.mem.len: " ++ @typeName(@TypeOf(value)));
const sentinel = @ptrCast(*align(1) const info.child, sentinel_ptr).*;
return indexOfSentinel(info.child, sentinel, value);
},
@@ -942,41 +911,18 @@ pub fn len(value: anytype) usize {
assert(value != null);
return indexOfSentinel(info.child, 0, value);
},
- .Slice => value.len,
+ else => @compileError("invalid type given to std.mem.len: " ++ @typeName(@TypeOf(value))),
},
- .Struct => |info| if (info.is_tuple) {
- return info.fields.len;
- } else @compileError("invalid type given to std.mem.len"),
- else => @compileError("invalid type given to std.mem.len"),
- };
+ else => @compileError("invalid type given to std.mem.len: " ++ @typeName(@TypeOf(value))),
+ }
}
test "len" {
- try testing.expect(len("aoeu") == 4);
-
- {
- var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
- try testing.expect(len(&array) == 5);
- try testing.expect(len(array[0..3]) == 3);
- array[2] = 0;
- const ptr = @as([*:0]u16, array[0..2 :0]);
- try testing.expect(len(ptr) == 2);
- }
- {
- var array: [5:0]u16 = [_:0]u16{ 1, 2, 3, 4, 5 };
- try testing.expect(len(&array) == 5);
- array[2] = 0;
- try testing.expect(len(&array) == 5);
- }
- {
- const vector: meta.Vector(2, u32) = [2]u32{ 1, 2 };
- try testing.expect(len(vector) == 2);
- }
- {
- const tuple = .{ 1, 2 };
- try testing.expect(len(tuple) == 2);
- try testing.expect(tuple[0] == 1);
- }
+ var array: [5]u16 = [_]u16{ 1, 2, 0, 4, 5 };
+ const ptr = @as([*:4]u16, array[0..3 :4]);
+ try testing.expect(len(ptr) == 3);
+ const c_ptr = @as([*c]u16, ptr);
+ try testing.expect(len(c_ptr) == 2);
}
pub fn indexOfSentinel(comptime Elem: type, comptime sentinel: Elem, ptr: [*:sentinel]const Elem) usize {