authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-12-27 14:31:20+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-01 13:04:29-05:00
log0b0de22fd1b0391f0cf1c7d821afc6522041c699
treef00dfb75125a1efa6cd3c6c5b5632e289c440f82
parentb99c6d56da3d2db995c268fb07f48548ea6d1148
signaturelock-open Commit is signed but in an unrecognized format.

std: format contents of sentinel terminated many pointers

std: add std.meta.Sentinel to get sentinel of a type

6 files changed, 58 insertions(+), 15 deletions(-)

lib/std/cstr.zig+1-1
......@@ -28,7 +28,7 @@ test "cstr fns" {
2828
2929fn testCStrFnsImpl() void {
3030 testing.expect(cmp("aoeu", "aoez") == -1);
31 testing.expect(mem.len(u8, "123456789") == 9);
31 testing.expect(mem.len(u8, "123456789".*) == 9);
3232}
3333
3434/// Returns a mutable, null-terminated slice with the same length as `slice`.
lib/std/fmt.zig+6-2
......@@ -441,10 +441,14 @@ pub fn formatType(
441441 else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
442442 },
443443 .Many, .C => {
444 if (ptr_info.sentinel) |sentinel| {
445 const slice = mem.pointerToSlice([:sentinel]const ptr_info.child, value);
446 return formatType(slice, fmt, options, context, Errors, output, max_depth);
447 }
444448 if (ptr_info.child == u8) {
445449 if (fmt.len > 0 and fmt[0] == 's') {
446 const len = mem.len(u8, value);
447 return formatText(value[0..len], fmt, options, context, Errors, output);
450 const slice = mem.pointerToSlice([:0]const u8, @as([*:0]const u8, value));
451 return formatText(slice, fmt, options, context, Errors, output);
448452 }
449453 }
450454 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
lib/std/mem.zig+17-4
......@@ -470,18 +470,31 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
470470 return true;
471471}
472472
473pub fn len(comptime T: type, ptr: [*:0]const T) usize {
473pub fn len(comptime T: type, ptr: var) usize {
474 const sentinel: T = comptime meta.Sentinel(@TypeOf(ptr));
474475 var count: usize = 0;
475 while (ptr[count] != 0) : (count += 1) {}
476 while (ptr[count] != sentinel) : (count += 1) {}
476477 return count;
477478}
478479
480/// Given a sentintel-terminated pointer-to-many, find the sentintel and return a slice.
481pub fn pointerToSlice(comptime T: type, ptr: blk: {
482 var info = @typeInfo(T).Pointer;
483 info.size = .Many;
484 break :blk @Type(std.builtin.TypeInfo{ .Pointer = info });
485}) T {
486 const sentinel = comptime meta.Sentinel(T);
487 return ptr[0..len(meta.Child(T), ptr) :sentinel];
488}
489
490/// Deprecated; use pointerToSlice instead
479491pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
480 return ptr[0..len(T, ptr) :0];
492 return pointerToSlice([:0]const T, ptr);
481493}
482494
495/// Deprecated; use pointerToSlice instead
483496pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
484 return ptr[0..len(T, ptr) :0];
497 return pointerToSlice([:0]T, ptr);
485498}
486499
487500/// Returns true if all elements in a slice are equal to the scalar value provided
lib/std/meta.zig+26
......@@ -115,6 +115,32 @@ test "std.meta.Child" {
115115 testing.expect(Child(?u8) == u8);
116116}
117117
118/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel
119pub fn Sentinel(comptime T: type) Child(T) {
120 // comptime asserts that ptr has a sentinel
121 switch (@typeInfo(T)) {
122 .Array => |arrayInfo| {
123 return comptime arrayInfo.sentinel.?;
124 },
125 .Pointer => |ptrInfo| {
126 switch (ptrInfo.size) {
127 .Many, .Slice => {
128 return comptime ptrInfo.sentinel.?;
129 },
130 else => {},
131 }
132 },
133 else => {},
134 }
135 @compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");
136}
137
138test "std.meta.Sentinel" {
139 testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));
140 testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));
141 testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));
142}
143
118144pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
119145 return switch (@typeInfo(T)) {
120146 .Struct => |info| info.layout,
src-self-hosted/main.zig+7-7
......@@ -792,7 +792,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
792792}
793793
794794fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
795 try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
795 try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});
796796}
797797
798798fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
......@@ -863,12 +863,12 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
863863 \\ZIG_DIA_GUIDS_LIB {}
864864 \\
865865 , .{
866 std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),
867 std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),
868 std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),
869 std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),
870 std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
871 std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),
866 c.ZIG_CMAKE_BINARY_DIR,
867 c.ZIG_CXX_COMPILER,
868 c.ZIG_LLD_INCLUDE_PATH,
869 c.ZIG_LLD_LIBRARIES,
870 c.ZIG_LLVM_CONFIG_EXE,
871 c.ZIG_DIA_GUIDS_LIB,
872872 });
873873}
874874
test/stage1/behavior/misc.zig+1-1
......@@ -335,7 +335,7 @@ test "string concatenation" {
335335 comptime expect(@TypeOf(a) == *const [12:0]u8);
336336 comptime expect(@TypeOf(b) == *const [12:0]u8);
337337
338 const len = mem.len(u8, b);
338 const len = b.len;
339339 const len_with_null = len + 1;
340340 {
341341 var i: u32 = 0;