mirror of
https://github.com/ziglang/zig.git
synced 2024-11-16 00:57:04 +00:00
std: format contents of sentinel terminated many pointers
std: add std.meta.Sentinel to get sentinel of a type
This commit is contained in:
parent
b99c6d56da
commit
0b0de22fd1
@ -28,7 +28,7 @@ test "cstr fns" {
|
|||||||
|
|
||||||
fn testCStrFnsImpl() void {
|
fn testCStrFnsImpl() void {
|
||||||
testing.expect(cmp("aoeu", "aoez") == -1);
|
testing.expect(cmp("aoeu", "aoez") == -1);
|
||||||
testing.expect(mem.len(u8, "123456789") == 9);
|
testing.expect(mem.len(u8, "123456789".*) == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable, null-terminated slice with the same length as `slice`.
|
/// Returns a mutable, null-terminated slice with the same length as `slice`.
|
||||||
|
@ -441,10 +441,14 @@ pub fn formatType(
|
|||||||
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
|
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
|
||||||
},
|
},
|
||||||
.Many, .C => {
|
.Many, .C => {
|
||||||
|
if (ptr_info.sentinel) |sentinel| {
|
||||||
|
const slice = mem.pointerToSlice([:sentinel]const ptr_info.child, value);
|
||||||
|
return formatType(slice, fmt, options, context, Errors, output, max_depth);
|
||||||
|
}
|
||||||
if (ptr_info.child == u8) {
|
if (ptr_info.child == u8) {
|
||||||
if (fmt.len > 0 and fmt[0] == 's') {
|
if (fmt.len > 0 and fmt[0] == 's') {
|
||||||
const len = mem.len(u8, value);
|
const slice = mem.pointerToSlice([:0]const u8, @as([*:0]const u8, value));
|
||||||
return formatText(value[0..len], fmt, options, context, Errors, output);
|
return formatText(slice, fmt, options, context, Errors, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
|
return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
|
||||||
|
@ -470,18 +470,31 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(comptime T: type, ptr: [*:0]const T) usize {
|
pub fn len(comptime T: type, ptr: var) usize {
|
||||||
|
const sentinel: T = comptime meta.Sentinel(@TypeOf(ptr));
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (ptr[count] != 0) : (count += 1) {}
|
while (ptr[count] != sentinel) : (count += 1) {}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
|
/// Given a sentintel-terminated pointer-to-many, find the sentintel and return a slice.
|
||||||
return ptr[0..len(T, ptr) :0];
|
pub fn pointerToSlice(comptime T: type, ptr: blk: {
|
||||||
|
var info = @typeInfo(T).Pointer;
|
||||||
|
info.size = .Many;
|
||||||
|
break :blk @Type(std.builtin.TypeInfo{ .Pointer = info });
|
||||||
|
}) T {
|
||||||
|
const sentinel = comptime meta.Sentinel(T);
|
||||||
|
return ptr[0..len(meta.Child(T), ptr) :sentinel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deprecated; use pointerToSlice instead
|
||||||
|
pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
|
||||||
|
return pointerToSlice([:0]const T, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deprecated; use pointerToSlice instead
|
||||||
pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
|
pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
|
||||||
return ptr[0..len(T, ptr) :0];
|
return pointerToSlice([:0]T, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if all elements in a slice are equal to the scalar value provided
|
/// Returns true if all elements in a slice are equal to the scalar value provided
|
||||||
|
@ -115,6 +115,32 @@ test "std.meta.Child" {
|
|||||||
testing.expect(Child(?u8) == u8);
|
testing.expect(Child(?u8) == u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel
|
||||||
|
pub fn Sentinel(comptime T: type) Child(T) {
|
||||||
|
// comptime asserts that ptr has a sentinel
|
||||||
|
switch (@typeInfo(T)) {
|
||||||
|
.Array => |arrayInfo| {
|
||||||
|
return comptime arrayInfo.sentinel.?;
|
||||||
|
},
|
||||||
|
.Pointer => |ptrInfo| {
|
||||||
|
switch (ptrInfo.size) {
|
||||||
|
.Many, .Slice => {
|
||||||
|
return comptime ptrInfo.sentinel.?;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
@compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "std.meta.Sentinel" {
|
||||||
|
testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));
|
||||||
|
testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));
|
||||||
|
testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
|
pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
|
||||||
return switch (@typeInfo(T)) {
|
return switch (@typeInfo(T)) {
|
||||||
.Struct => |info| info.layout,
|
.Struct => |info| info.layout,
|
||||||
|
@ -792,7 +792,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
|
fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
|
||||||
try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
|
try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
|
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
|
||||||
@ -863,12 +863,12 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
\\ZIG_DIA_GUIDS_LIB {}
|
\\ZIG_DIA_GUIDS_LIB {}
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),
|
c.ZIG_CMAKE_BINARY_DIR,
|
||||||
std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),
|
c.ZIG_CXX_COMPILER,
|
||||||
std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),
|
c.ZIG_LLD_INCLUDE_PATH,
|
||||||
std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),
|
c.ZIG_LLD_LIBRARIES,
|
||||||
std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
|
c.ZIG_LLVM_CONFIG_EXE,
|
||||||
std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),
|
c.ZIG_DIA_GUIDS_LIB,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ test "string concatenation" {
|
|||||||
comptime expect(@TypeOf(a) == *const [12:0]u8);
|
comptime expect(@TypeOf(a) == *const [12:0]u8);
|
||||||
comptime expect(@TypeOf(b) == *const [12:0]u8);
|
comptime expect(@TypeOf(b) == *const [12:0]u8);
|
||||||
|
|
||||||
const len = mem.len(u8, b);
|
const len = b.len;
|
||||||
const len_with_null = len + 1;
|
const len_with_null = len + 1;
|
||||||
{
|
{
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user