authorgravatar for spexguy070@gmail.comMartin Wickham <spexguy070@gmail.com> 2021-01-25 17:18:37-06:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-01-30 11:13:20+02:00
log3d4eeafb47f97e5057d36fe2c3ed061cf0c70a63
tree6ad431745b31a29584780ccc2e7c075d24a0b0f6
parente8740a90b9c1ec2b7043dc5a0aed5474bb648c3d

Fill out more cases for std.meta.sizeof


1 files changed, 87 insertions(+), 4 deletions(-)

lib/std/meta.zig+87-4
...@@ -979,9 +979,59 @@ test "std.meta.cast" {...@@ -979,9 +979,59 @@ test "std.meta.cast" {
979/// Given a value returns its size as C's sizeof operator would.979/// Given a value returns its size as C's sizeof operator would.
980/// This is for translate-c and is not intended for general use.980/// This is for translate-c and is not intended for general use.
981pub fn sizeof(target: anytype) usize {981pub fn sizeof(target: anytype) usize {
982 switch (@typeInfo(@TypeOf(target))) {982 const T: type = if (@TypeOf(target) == type) target else @TypeOf(target);
983 .Type => return @sizeOf(target),983 switch (@typeInfo(T)) {
984 .Float, .Int, .Struct, .Union, .Enum => return @sizeOf(@TypeOf(target)),984 .Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T),
985 .Fn => {
986 // sizeof(main) returns 1, sizeof(&main) returns pointer size.
987 // We cannot distinguish those types in Zig, so use pointer size.
988 return @sizeOf(T);
989 },
990 .Null => return @sizeOf(*c_void),
991 .Void => {
992 // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC.
993 return 1;
994 },
995 .Opaque => {
996 if (T == c_void) {
997 // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC.
998 return 1;
999 } else {
1000 @compileError("Cannot use C sizeof on opaque type "++@typeName(T));
1001 }
1002 },
1003 .Optional => |opt| {
1004 if (@typeInfo(opt.child) == .Pointer) {
1005 return sizeof(opt.child);
1006 } else {
1007 @compileError("Cannot use C sizeof on non-pointer optional "++@typeName(T));
1008 }
1009 },
1010 .Pointer => |ptr| {
1011 if (ptr.size == .Slice) {
1012 @compileError("Cannot use C sizeof on slice type "++@typeName(T));
1013 }
1014 // for strings, sizeof("a") returns 2.
1015 // normal pointer decay scenarios from C are handled
1016 // in the .Array case above, but strings remain literals
1017 // and are therefore always pointers, so they need to be
1018 // specially handled here.
1019 if (ptr.size == .One and ptr.is_const and @typeInfo(ptr.child) == .Array) {
1020 const array_info = @typeInfo(ptr.child).Array;
1021 if ((array_info.child == u8 or array_info.child == u16) and
1022 array_info.sentinel != null and
1023 array_info.sentinel.? == 0) {
1024 // length of the string plus one for the null terminator.
1025 return (array_info.len + 1) * @sizeOf(array_info.child);
1026 }
1027 }
1028 // When zero sized pointers are removed, this case will no
1029 // longer be reachable and can be deleted.
1030 if (@sizeOf(T) == 0) {
1031 return @sizeOf(*c_void);
1032 }
1033 return @sizeOf(T);
1034 },
985 .ComptimeFloat => return @sizeOf(f64), // TODO c_double #39991035 .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999
986 .ComptimeInt => {1036 .ComptimeInt => {
987 // TODO to get the correct result we have to translate1037 // TODO to get the correct result we have to translate
...@@ -991,7 +1041,7 @@ pub fn sizeof(target: anytype) usize {...@@ -991,7 +1041,7 @@ pub fn sizeof(target: anytype) usize {
991 // TODO test if target fits in int, long or long long1041 // TODO test if target fits in int, long or long long
992 return @sizeOf(c_int);1042 return @sizeOf(c_int);
993 },1043 },
994 else => @compileError("TODO implement std.meta.sizeof for type " ++ @typeName(@TypeOf(target))),1044 else => @compileError("std.meta.sizeof does not support type " ++ @typeName(T)),
995 }1045 }
996}1046}
9971047
...@@ -999,12 +1049,45 @@ test "sizeof" {...@@ -999,12 +1049,45 @@ test "sizeof" {
999 const E = extern enum(c_int) { One, _ };1049 const E = extern enum(c_int) { One, _ };
1000 const S = extern struct { a: u32 };1050 const S = extern struct { a: u32 };
10011051
1052 const ptr_size = @sizeOf(*c_void);
1053
1002 testing.expect(sizeof(u32) == 4);1054 testing.expect(sizeof(u32) == 4);
1003 testing.expect(sizeof(@as(u32, 2)) == 4);1055 testing.expect(sizeof(@as(u32, 2)) == 4);
1004 testing.expect(sizeof(2) == @sizeOf(c_int));1056 testing.expect(sizeof(2) == @sizeOf(c_int));
1057
1058 testing.expect(sizeof(2.0) == @sizeOf(f64));
1059
1005 testing.expect(sizeof(E) == @sizeOf(c_int));1060 testing.expect(sizeof(E) == @sizeOf(c_int));
1006 testing.expect(sizeof(E.One) == @sizeOf(c_int));1061 testing.expect(sizeof(E.One) == @sizeOf(c_int));
1062
1007 testing.expect(sizeof(S) == 4);1063 testing.expect(sizeof(S) == 4);
1064
1065 testing.expect(sizeof([_]u32{4, 5, 6}) == 12);
1066 testing.expect(sizeof([3]u32) == 12);
1067 testing.expect(sizeof([3:0]u32) == 16);
1068 testing.expect(sizeof(&[_]u32{4, 5, 6}) == ptr_size);
1069
1070 testing.expect(sizeof(*u32) == ptr_size);
1071 testing.expect(sizeof([*]u32) == ptr_size);
1072 testing.expect(sizeof([*c]u32) == ptr_size);
1073 testing.expect(sizeof(?*u32) == ptr_size);
1074 testing.expect(sizeof(?[*]u32) == ptr_size);
1075 testing.expect(sizeof(*c_void) == ptr_size);
1076 testing.expect(sizeof(*void) == ptr_size);
1077 testing.expect(sizeof(null) == ptr_size);
1078
1079 testing.expect(sizeof("foobar") == 7);
1080 testing.expect(sizeof(&[_:0]u16{'f','o','o','b','a','r'}) == 14);
1081 testing.expect(sizeof(*const [4:0]u8) == 5);
1082 testing.expect(sizeof(*[4:0]u8) == ptr_size);
1083 testing.expect(sizeof([*]const [4:0]u8) == ptr_size);
1084 testing.expect(sizeof(*const *const [4:0]u8) == ptr_size);
1085 testing.expect(sizeof(*const [4]u8) == ptr_size);
1086
1087 testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof)));
1088
1089 testing.expect(sizeof(void) == 1);
1090 testing.expect(sizeof(c_void) == 1);
1008}1091}
10091092
1010/// For a given function type, returns a tuple type which fields will1093/// For a given function type, returns a tuple type which fields will