| author | |
| committer | |
| log | 8ea0a00f406bb04c08a8fa4471c3a3895f82b24a |
| tree | db67660d2496e6b501ebb67bec9c2d4907e3fa51 |
| parent | 8d0ac6dc4d32daea3561e7de8eeee9ce34d2c5cb |
| signature |
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 | } |
| 1830 | 1830 | ||
| 1831 | pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { | 1831 | pub 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; | ||
| 1834 | 1833 | ||
| 1835 | // let's not give an undefined pointer to @ptrCast | 1834 | // let's not give an undefined pointer to @ptrCast |
| 1836 | // it may be equal to zero and fail a null check | 1835 | // 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 | } |
| 1840 | 1839 | ||
| 1841 | const sliceType = @TypeOf(actualSlice); | 1840 | const alignment = comptime meta.alignment(Slice); |
| 1842 | const alignment = comptime meta.alignment(sliceType); | ||
| 1843 | 1841 | ||
| 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; |
| 1845 | 1843 | ||
| 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 | } |
| 1848 | 1846 | ||
| 1849 | test "sliceAsBytes" { | 1847 | test "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 | } |
| 117 | 117 | ||
| 118 | /// Given a type with a sentinel e.g. `[:0]u8`, returns the sentinel | 118 | /// Given a type which can have a sentinel e.g. `[:0]u8`, returns the sentinel value, |
| 119 | pub fn Sentinel(comptime T: type) Child(T) { | 119 | /// or `null` if there is not one. |
| 120 | // comptime asserts that ptr has a sentinel | 120 | /// Types which cannot possibly have a sentinel will be a compile error. |
| 121 | pub 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 | } |
| 137 | 138 | ||
| 138 | test "std.meta.Sentinel" { | 139 | test "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 | } |
| 143 | 150 | ||
| 144 | pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { | 151 | pub 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`. |
| 1745 | fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 { | 1745 | fn 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 them | 1754 | // into their respective hex representation |
| 1755 | // into their respective hex representation | 1755 | 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 unreachable | 1757 | else |
| 1758 | else | 1758 | 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 | } |
| 1763 | 1761 |