authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-17 18:54:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-19 09:53:54-04:00
log8ea0a00f406bb04c08a8fa4471c3a3895f82b24a
treedb67660d2496e6b501ebb67bec9c2d4907e3fa51
parent8d0ac6dc4d32daea3561e7de8eeee9ce34d2c5cb
signaturelock-open Commit is signed but in an unrecognized format.

improve std lib code for the new semantics


3 files changed, 39 insertions(+), 36 deletions(-)

lib/std/mem.zig+5-7
...@@ -1829,21 +1829,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {...@@ -1829,21 +1829,19 @@ fn SliceAsBytesReturnType(comptime sliceType: type) type {
1829}1829}
18301830
1831pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {1831pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
1832 const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice;1832 const Slice = @TypeOf(slice);
1833 const actualSliceTypeInfo = @typeInfo(@TypeOf(actualSlice)).Pointer;
18341833
1835 // let's not give an undefined pointer to @ptrCast1834 // let's not give an undefined pointer to @ptrCast
1836 // it may be equal to zero and fail a null check1835 // it may be equal to zero and fail a null check
1837 if (actualSlice.len == 0 and actualSliceTypeInfo.sentinel == null) {1836 if (slice.len == 0 and comptime meta.sentinel(Slice) == null) {
1838 return &[0]u8{};1837 return &[0]u8{};
1839 }1838 }
18401839
1841 const sliceType = @TypeOf(actualSlice);1840 const alignment = comptime meta.alignment(Slice);
1842 const alignment = comptime meta.alignment(sliceType);
18431841
1844 const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;1842 const cast_target = if (comptime trait.isConstPtr(Slice)) [*]align(alignment) const u8 else [*]align(alignment) u8;
18451843
1846 return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))];1844 return @ptrCast(cast_target, slice)[0 .. slice.len * @sizeOf(meta.Child(Slice))];
1847}1845}
18481846
1849test "sliceAsBytes" {1847test "sliceAsBytes" {
lib/std/meta.zig+22-15
...@@ -115,30 +115,37 @@ test "std.meta.Child" {...@@ -115,30 +115,37 @@ test "std.meta.Child" {
115 testing.expect(Child(?u8) == u8);115 testing.expect(Child(?u8) == u8);
116}116}
117117
118/// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel118/// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value,
119pub fn Sentinel(comptime T: type) Child(T) {119/// or `null` if there is not one.
120 // comptime asserts that ptr has a sentinel120/// Types which cannot possibly have a sentinel will be a compile error.
121pub fn sentinel(comptime T: type) ?Child(T) {
121 switch (@typeInfo(T)) {122 switch (@typeInfo(T)) {
122 .Array => |arrayInfo| {123 .Array => |info| return info.sentinel,
123 return comptime arrayInfo.sentinel.?;124 .Pointer => |info| {
124 },125 switch (info.size) {
125 .Pointer => |ptrInfo| {126 .Many, .Slice => return info.sentinel,
126 switch (ptrInfo.size) {127 .One => switch (info.child) {
127 .Many, .Slice => {128 .Array => |array_info| return array_info.sentinel,
128 return comptime ptrInfo.sentinel.?;129 else => {},
129 },130 },
130 else => {},131 else => {},
131 }132 }
132 },133 },
133 else => {},134 else => {},
134 }135 }
135 @compileError("not a sentinel type, found '" ++ @typeName(T) ++ "'");136 @compileError("type '" ++ @typeName(T) ++ "' cannot possibly have a sentinel");
136}137}
137138
138test "std.meta.Sentinel" {139test "std.meta.sentinel" {
139 testing.expectEqual(@as(u8, 0), Sentinel([:0]u8));140 testing.expectEqual(@as(u8, 0), sentinel([:0]u8).?);
140 testing.expectEqual(@as(u8, 0), Sentinel([*:0]u8));141 testing.expectEqual(@as(u8, 0), sentinel([*:0]u8).?);
141 testing.expectEqual(@as(u8, 0), Sentinel([5:0]u8));142 testing.expectEqual(@as(u8, 0), sentinel([5:0]u8).?);
143 testing.expectEqual(@as(u8, 0), sentinel(*const [5:0]u8).?);
144
145 testing.expect(sentinel([]u8) == null);
146 testing.expect(sentinel([*]u8) == null);
147 testing.expect(sentinel([5]u8) == null);
148 testing.expect(sentinel(*const [5]u8) == null);
142}149}
143150
144pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {151pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
src-self-hosted/translate_c.zig+12-14
...@@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {...@@ -1744,20 +1744,18 @@ fn writeEscapedString(buf: []u8, s: []const u8) void {
1744// Returns either a string literal or a slice of `buf`.1744// Returns either a string literal or a slice of `buf`.
1745fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {1745fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
1746 return switch (c) {1746 return switch (c) {
1747 '\"' => "\\\""[0..],1747 '\"' => "\\\"",
1748 '\'' => "\\'"[0..],1748 '\'' => "\\'",
1749 '\\' => "\\\\"[0..],1749 '\\' => "\\\\",
1750 '\n' => "\\n"[0..],1750 '\n' => "\\n",
1751 '\r' => "\\r"[0..],1751 '\r' => "\\r",
1752 '\t' => "\\t"[0..],1752 '\t' => "\\t",
1753 else => {1753 // Handle the remaining escapes Zig doesn't support by turning them
1754 // Handle the remaining escapes Zig doesn't support by turning them1754 // into their respective hex representation
1755 // into their respective hex representation1755 else => if (std.ascii.isCntrl(c))
1756 if (std.ascii.isCntrl(c))1756 std.fmt.bufPrint(char_buf, "\\x{x:0<2}", .{c}) catch unreachable
1757 return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable1757 else
1758 else1758 std.fmt.bufPrint(char_buf, "{c}", .{c}) catch unreachable,
1759 return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
1760 },
1761 };1759 };
1762}1760}
17631761