mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
implement zeroes for non extern structs and native types
This commit is contained in:
parent
dca19b6757
commit
0972b2a8fe
124
lib/std/mem.zig
124
lib/std/mem.zig
@ -279,15 +279,69 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
|
||||
/// Zero initializes the type.
|
||||
/// This can be used to zero initialize a C-struct.
|
||||
pub fn zeroes(comptime T: type) T {
|
||||
if (@sizeOf(T) == 0) return T{};
|
||||
|
||||
if (comptime meta.containerLayout(T) != .Extern) {
|
||||
@compileError("TODO: Currently this only works for extern types");
|
||||
switch (@typeInfo(T)) {
|
||||
.ComptimeInt, .Int, .ComptimeFloat, .Float => {
|
||||
return @as(T, 0);
|
||||
},
|
||||
.Enum, .EnumLiteral => {
|
||||
return @intToEnum(T, 0);
|
||||
},
|
||||
.Void => {
|
||||
return {};
|
||||
},
|
||||
.Bool => {
|
||||
return false;
|
||||
},
|
||||
.Optional, .Null => {
|
||||
return null;
|
||||
},
|
||||
.Struct => {
|
||||
if (@sizeOf(T) == 0) return T{};
|
||||
if (comptime meta.containerLayout(T) == .Extern) {
|
||||
var item: T = undefined;
|
||||
@memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
|
||||
return item;
|
||||
} else {
|
||||
var structure: T = undefined;
|
||||
comptime var field_i = 0;
|
||||
inline while (field_i < @memberCount(T)) : (field_i += 1) {
|
||||
@field(structure, @memberName(T, field_i)) = zeroes(@TypeOf(@field(structure, @memberName(T, field_i))));
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
},
|
||||
.Pointer => |ptr_info| {
|
||||
if (ptr_info.is_allowzero) {
|
||||
return null;
|
||||
} else {
|
||||
switch (ptr_info.size) {
|
||||
.Slice => {
|
||||
return &[_]ptr_info.child{};
|
||||
},
|
||||
.One, .Many, .C => {
|
||||
@compileError("Can't set a non nullable pointer to zero.");
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
.Array => |info| {
|
||||
var array: T = undefined;
|
||||
for (array) |*element| {
|
||||
element.* = zeroes(info.child);
|
||||
}
|
||||
return array;
|
||||
},
|
||||
.Vector => |info| {
|
||||
var vector: T = undefined;
|
||||
for (vector) |*element| {
|
||||
*element = zeroes(info.child);
|
||||
}
|
||||
return vector;
|
||||
},
|
||||
.ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => {
|
||||
@compileError("Can't set a "++ @typeName(T) ++" to zero.");
|
||||
},
|
||||
}
|
||||
|
||||
var item: T = undefined;
|
||||
@memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
|
||||
return item;
|
||||
}
|
||||
|
||||
test "mem.zeroes" {
|
||||
@ -301,6 +355,60 @@ test "mem.zeroes" {
|
||||
|
||||
testing.expect(a.x == 0);
|
||||
testing.expect(a.y == 10);
|
||||
|
||||
const ZigStruct = struct {
|
||||
const IntegralTypes = struct {
|
||||
integer_0: i0,
|
||||
integer_8: i8,
|
||||
integer_16: i16,
|
||||
integer_32: i32,
|
||||
integer_64: i64,
|
||||
integer_128: i128,
|
||||
unsigned_0: u0,
|
||||
unsigned_8: u8,
|
||||
unsigned_16: u16,
|
||||
unsigned_32: u32,
|
||||
unsigned_64: u64,
|
||||
unsigned_128: u128,
|
||||
|
||||
float_32: f32,
|
||||
float_64: f64,
|
||||
};
|
||||
|
||||
integral_types: IntegralTypes,
|
||||
|
||||
const Pointers = struct {
|
||||
optional: ?*u8,
|
||||
slice: []u8,
|
||||
};
|
||||
pointers: Pointers,
|
||||
|
||||
array: [2]u32,
|
||||
optional_int: ?u8,
|
||||
empty: void,
|
||||
};
|
||||
|
||||
const b = zeroes(ZigStruct);
|
||||
testing.expectEqual(@as(i8, 0), b.integral_types.integer_0);
|
||||
testing.expectEqual(@as(i8, 0), b.integral_types.integer_8);
|
||||
testing.expectEqual(@as(i16, 0), b.integral_types.integer_16);
|
||||
testing.expectEqual(@as(i32, 0), b.integral_types.integer_32);
|
||||
testing.expectEqual(@as(i64, 0), b.integral_types.integer_64);
|
||||
testing.expectEqual(@as(i128, 0), b.integral_types.integer_128);
|
||||
testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_0);
|
||||
testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_8);
|
||||
testing.expectEqual(@as(u16, 0), b.integral_types.unsigned_16);
|
||||
testing.expectEqual(@as(u32, 0), b.integral_types.unsigned_32);
|
||||
testing.expectEqual(@as(u64, 0), b.integral_types.unsigned_64);
|
||||
testing.expectEqual(@as(u128, 0), b.integral_types.unsigned_128);
|
||||
testing.expectEqual(@as(f32, 0), b.integral_types.float_32);
|
||||
testing.expectEqual(@as(f64, 0), b.integral_types.float_64);
|
||||
testing.expectEqual(@as(?*u8, null), b.pointers.optional);
|
||||
testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);
|
||||
for (b.array) |e| {
|
||||
testing.expectEqual(@as(u32, 0), e);
|
||||
}
|
||||
testing.expectEqual(@as(?u8, null), b.optional_int);
|
||||
}
|
||||
|
||||
pub fn secureZero(comptime T: type, s: []T) void {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user