| author | |
| committer | |
| log | 0b0de22fd1b0391f0cf1c7d821afc6522041c699 |
| tree | f00dfb75125a1efa6cd3c6c5b5632e289c440f82 |
| parent | b99c6d56da3d2db995c268fb07f48548ea6d1148 |
| signature |
std: add std.meta.Sentinel to get sentinel of a type6 files changed, 58 insertions(+), 15 deletions(-)
lib/std/cstr.zig+1-1| ... | @@ -28,7 +28,7 @@ test "cstr fns" { | ... | @@ -28,7 +28,7 @@ test "cstr fns" { |
| 28 | 28 | ||
| 29 | fn testCStrFnsImpl() void { | 29 | fn testCStrFnsImpl() void { |
| 30 | testing.expect(cmp("aoeu", "aoez") == -1); | 30 | testing.expect(cmp("aoeu", "aoez") == -1); |
| 31 | testing.expect(mem.len(u8, "123456789") == 9); | 31 | testing.expect(mem.len(u8, "123456789".*) == 9); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | /// Returns a mutable, null-terminated slice with the same length as `slice`. | 34 | /// 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( | ... | @@ -441,10 +441,14 @@ pub fn formatType( |
| 441 | else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), | 441 | else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), |
| 442 | }, | 442 | }, |
| 443 | .Many, .C => { | 443 | .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 | } | ||
| 444 | if (ptr_info.child == u8) { | 448 | if (ptr_info.child == u8) { |
| 445 | if (fmt.len > 0 and fmt[0] == 's') { | 449 | if (fmt.len > 0 and fmt[0] == 's') { |
| 446 | const len = mem.len(u8, value); | 450 | const slice = mem.pointerToSlice([:0]const u8, @as([*:0]const u8, value)); |
| 447 | return formatText(value[0..len], fmt, options, context, Errors, output); | 451 | return formatText(slice, fmt, options, context, Errors, output); |
| 448 | } | 452 | } |
| 449 | } | 453 | } |
| 450 | return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); | 454 | 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 { | ... | @@ -470,18 +470,31 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool { |
| 470 | return true; | 470 | return true; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | pub fn len(comptime T: type, ptr: [*:0]const T) usize { | 473 | pub fn len(comptime T: type, ptr: var) usize { |
| 474 | const sentinel: T = comptime meta.Sentinel(@TypeOf(ptr)); | ||
| 474 | var count: usize = 0; | 475 | var count: usize = 0; |
| 475 | while (ptr[count] != 0) : (count += 1) {} | 476 | while (ptr[count] != sentinel) : (count += 1) {} |
| 476 | return count; | 477 | return count; |
| 477 | } | 478 | } |
| 478 | 479 | ||
| 480 | /// Given a sentintel-terminated pointer-to-many, find the sentintel and return a slice. | ||
| 481 | pub 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 | ||
| 479 | pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T { | 491 | pub 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); |
| 481 | } | 493 | } |
| 482 | 494 | ||
| 495 | /// Deprecated; use pointerToSlice instead | ||
| 483 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { | 496 | pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { |
| 484 | return ptr[0..len(T, ptr) :0]; | 497 | return pointerToSlice([:0]T, ptr); |
| 485 | } | 498 | } |
| 486 | 499 | ||
| 487 | /// Returns true if all elements in a slice are equal to the scalar value provided | 500 | /// 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" { | ... | @@ -115,6 +115,32 @@ test "std.meta.Child" { |
| 115 | testing.expect(Child(?u8) == u8); | 115 | testing.expect(Child(?u8) == u8); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | /// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel | ||
| 119 | pub 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 | |||
| 138 | test "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 | |||
| 118 | pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { | 144 | pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { |
| 119 | return switch (@typeInfo(T)) { | 145 | return switch (@typeInfo(T)) { |
| 120 | .Struct => |info| info.layout, | 146 | .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 | ... | @@ -792,7 +792,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro |
| 792 | } | 792 | } |
| 793 | 793 | ||
| 794 | fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { | 794 | fn 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}); |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { | 798 | fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { |
| ... | @@ -863,12 +863,12 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void { | ... | @@ -863,12 +863,12 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void { |
| 863 | \\ZIG_DIA_GUIDS_LIB {} | 863 | \\ZIG_DIA_GUIDS_LIB {} |
| 864 | \\ | 864 | \\ |
| 865 | , .{ | 865 | , .{ |
| 866 | std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR), | 866 | c.ZIG_CMAKE_BINARY_DIR, |
| 867 | std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER), | 867 | c.ZIG_CXX_COMPILER, |
| 868 | std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH), | 868 | c.ZIG_LLD_INCLUDE_PATH, |
| 869 | std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES), | 869 | c.ZIG_LLD_LIBRARIES, |
| 870 | std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE), | 870 | c.ZIG_LLVM_CONFIG_EXE, |
| 871 | std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB), | 871 | c.ZIG_DIA_GUIDS_LIB, |
| 872 | }); | 872 | }); |
| 873 | } | 873 | } |
| 874 | 874 |
test/stage1/behavior/misc.zig+1-1| ... | @@ -335,7 +335,7 @@ test "string concatenation" { | ... | @@ -335,7 +335,7 @@ test "string concatenation" { |
| 335 | comptime expect(@TypeOf(a) == *const [12:0]u8); | 335 | comptime expect(@TypeOf(a) == *const [12:0]u8); |
| 336 | comptime expect(@TypeOf(b) == *const [12:0]u8); | 336 | comptime expect(@TypeOf(b) == *const [12:0]u8); |
| 337 | 337 | ||
| 338 | const len = mem.len(u8, b); | 338 | const len = b.len; |
| 339 | const len_with_null = len + 1; | 339 | const len_with_null = len + 1; |
| 340 | { | 340 | { |
| 341 | var i: u32 = 0; | 341 | var i: u32 = 0; |