mirror of
https://github.com/ziglang/zig.git
synced 2025-12-07 23:03:08 +00:00
Fill out more cases for std.meta.sizeof
This commit is contained in:
parent
e8740a90b9
commit
3d4eeafb47
@ -979,9 +979,59 @@ test "std.meta.cast" {
|
|||||||
/// Given a value returns its size as C's sizeof operator would.
|
/// Given a value returns its size as C's sizeof operator would.
|
||||||
/// This is for translate-c and is not intended for general use.
|
/// This is for translate-c and is not intended for general use.
|
||||||
pub fn sizeof(target: anytype) usize {
|
pub fn sizeof(target: anytype) usize {
|
||||||
switch (@typeInfo(@TypeOf(target))) {
|
const T: type = if (@TypeOf(target) == type) target else @TypeOf(target);
|
||||||
.Type => return @sizeOf(target),
|
switch (@typeInfo(T)) {
|
||||||
.Float, .Int, .Struct, .Union, .Enum => return @sizeOf(@TypeOf(target)),
|
.Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T),
|
||||||
|
.Fn => {
|
||||||
|
// sizeof(main) returns 1, sizeof(&main) returns pointer size.
|
||||||
|
// We cannot distinguish those types in Zig, so use pointer size.
|
||||||
|
return @sizeOf(T);
|
||||||
|
},
|
||||||
|
.Null => return @sizeOf(*c_void),
|
||||||
|
.Void => {
|
||||||
|
// Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC.
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
.Opaque => {
|
||||||
|
if (T == c_void) {
|
||||||
|
// Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC.
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
@compileError("Cannot use C sizeof on opaque type "++@typeName(T));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Optional => |opt| {
|
||||||
|
if (@typeInfo(opt.child) == .Pointer) {
|
||||||
|
return sizeof(opt.child);
|
||||||
|
} else {
|
||||||
|
@compileError("Cannot use C sizeof on non-pointer optional "++@typeName(T));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Pointer => |ptr| {
|
||||||
|
if (ptr.size == .Slice) {
|
||||||
|
@compileError("Cannot use C sizeof on slice type "++@typeName(T));
|
||||||
|
}
|
||||||
|
// for strings, sizeof("a") returns 2.
|
||||||
|
// normal pointer decay scenarios from C are handled
|
||||||
|
// in the .Array case above, but strings remain literals
|
||||||
|
// and are therefore always pointers, so they need to be
|
||||||
|
// specially handled here.
|
||||||
|
if (ptr.size == .One and ptr.is_const and @typeInfo(ptr.child) == .Array) {
|
||||||
|
const array_info = @typeInfo(ptr.child).Array;
|
||||||
|
if ((array_info.child == u8 or array_info.child == u16) and
|
||||||
|
array_info.sentinel != null and
|
||||||
|
array_info.sentinel.? == 0) {
|
||||||
|
// length of the string plus one for the null terminator.
|
||||||
|
return (array_info.len + 1) * @sizeOf(array_info.child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// When zero sized pointers are removed, this case will no
|
||||||
|
// longer be reachable and can be deleted.
|
||||||
|
if (@sizeOf(T) == 0) {
|
||||||
|
return @sizeOf(*c_void);
|
||||||
|
}
|
||||||
|
return @sizeOf(T);
|
||||||
|
},
|
||||||
.ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999
|
.ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999
|
||||||
.ComptimeInt => {
|
.ComptimeInt => {
|
||||||
// TODO to get the correct result we have to translate
|
// TODO to get the correct result we have to translate
|
||||||
@ -991,7 +1041,7 @@ pub fn sizeof(target: anytype) usize {
|
|||||||
// TODO test if target fits in int, long or long long
|
// TODO test if target fits in int, long or long long
|
||||||
return @sizeOf(c_int);
|
return @sizeOf(c_int);
|
||||||
},
|
},
|
||||||
else => @compileError("TODO implement std.meta.sizeof for type " ++ @typeName(@TypeOf(target))),
|
else => @compileError("std.meta.sizeof does not support type " ++ @typeName(T)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,12 +1049,45 @@ test "sizeof" {
|
|||||||
const E = extern enum(c_int) { One, _ };
|
const E = extern enum(c_int) { One, _ };
|
||||||
const S = extern struct { a: u32 };
|
const S = extern struct { a: u32 };
|
||||||
|
|
||||||
|
const ptr_size = @sizeOf(*c_void);
|
||||||
|
|
||||||
testing.expect(sizeof(u32) == 4);
|
testing.expect(sizeof(u32) == 4);
|
||||||
testing.expect(sizeof(@as(u32, 2)) == 4);
|
testing.expect(sizeof(@as(u32, 2)) == 4);
|
||||||
testing.expect(sizeof(2) == @sizeOf(c_int));
|
testing.expect(sizeof(2) == @sizeOf(c_int));
|
||||||
|
|
||||||
|
testing.expect(sizeof(2.0) == @sizeOf(f64));
|
||||||
|
|
||||||
testing.expect(sizeof(E) == @sizeOf(c_int));
|
testing.expect(sizeof(E) == @sizeOf(c_int));
|
||||||
testing.expect(sizeof(E.One) == @sizeOf(c_int));
|
testing.expect(sizeof(E.One) == @sizeOf(c_int));
|
||||||
|
|
||||||
testing.expect(sizeof(S) == 4);
|
testing.expect(sizeof(S) == 4);
|
||||||
|
|
||||||
|
testing.expect(sizeof([_]u32{4, 5, 6}) == 12);
|
||||||
|
testing.expect(sizeof([3]u32) == 12);
|
||||||
|
testing.expect(sizeof([3:0]u32) == 16);
|
||||||
|
testing.expect(sizeof(&[_]u32{4, 5, 6}) == ptr_size);
|
||||||
|
|
||||||
|
testing.expect(sizeof(*u32) == ptr_size);
|
||||||
|
testing.expect(sizeof([*]u32) == ptr_size);
|
||||||
|
testing.expect(sizeof([*c]u32) == ptr_size);
|
||||||
|
testing.expect(sizeof(?*u32) == ptr_size);
|
||||||
|
testing.expect(sizeof(?[*]u32) == ptr_size);
|
||||||
|
testing.expect(sizeof(*c_void) == ptr_size);
|
||||||
|
testing.expect(sizeof(*void) == ptr_size);
|
||||||
|
testing.expect(sizeof(null) == ptr_size);
|
||||||
|
|
||||||
|
testing.expect(sizeof("foobar") == 7);
|
||||||
|
testing.expect(sizeof(&[_:0]u16{'f','o','o','b','a','r'}) == 14);
|
||||||
|
testing.expect(sizeof(*const [4:0]u8) == 5);
|
||||||
|
testing.expect(sizeof(*[4:0]u8) == ptr_size);
|
||||||
|
testing.expect(sizeof([*]const [4:0]u8) == ptr_size);
|
||||||
|
testing.expect(sizeof(*const *const [4:0]u8) == ptr_size);
|
||||||
|
testing.expect(sizeof(*const [4]u8) == ptr_size);
|
||||||
|
|
||||||
|
testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof)));
|
||||||
|
|
||||||
|
testing.expect(sizeof(void) == 1);
|
||||||
|
testing.expect(sizeof(c_void) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a given function type, returns a tuple type which fields will
|
/// For a given function type, returns a tuple type which fields will
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user