authorgravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-02-24 20:25:59+01:00
committergravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-02-24 20:38:33+01:00
log0972b2a8fefe8f2175dd95d80a53e356c77d1200
tree240894f0da63752e500b6a6204d3476f837a3aef
parentdca19b67573dc46260b318e9253370fbc628834d

implement zeroes for non extern structs and native types


1 files changed, 116 insertions(+), 8 deletions(-)

lib/std/mem.zig+116-8
......@@ -279,15 +279,69 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
279279/// Zero initializes the type.
280280/// This can be used to zero initialize a C-struct.
281281pub fn zeroes(comptime T: type) T {
282 if (@sizeOf(T) == 0) return T{};
283
284 if (comptime meta.containerLayout(T) != .Extern) {
285 @compileError("TODO: Currently this only works for extern types");
282 switch (@typeInfo(T)) {
283 .ComptimeInt, .Int, .ComptimeFloat, .Float => {
284 return @as(T, 0);
285 },
286 .Enum, .EnumLiteral => {
287 return @intToEnum(T, 0);
288 },
289 .Void => {
290 return {};
291 },
292 .Bool => {
293 return false;
294 },
295 .Optional, .Null => {
296 return null;
297 },
298 .Struct => {
299 if (@sizeOf(T) == 0) return T{};
300 if (comptime meta.containerLayout(T) == .Extern) {
301 var item: T = undefined;
302 @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
303 return item;
304 } else {
305 var structure: T = undefined;
306 comptime var field_i = 0;
307 inline while (field_i < @memberCount(T)) : (field_i += 1) {
308 @field(structure, @memberName(T, field_i)) = zeroes(@TypeOf(@field(structure, @memberName(T, field_i))));
309 }
310 return structure;
311 }
312 },
313 .Pointer => |ptr_info| {
314 if (ptr_info.is_allowzero) {
315 return null;
316 } else {
317 switch (ptr_info.size) {
318 .Slice => {
319 return &[_]ptr_info.child{};
320 },
321 .One, .Many, .C => {
322 @compileError("Can't set a non nullable pointer to zero.");
323 },
324 }
325 }
326 },
327 .Array => |info| {
328 var array: T = undefined;
329 for (array) |*element| {
330 element.* = zeroes(info.child);
331 }
332 return array;
333 },
334 .Vector => |info| {
335 var vector: T = undefined;
336 for (vector) |*element| {
337 *element = zeroes(info.child);
338 }
339 return vector;
340 },
341 .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => {
342 @compileError("Can't set a "++ @typeName(T) ++" to zero.");
343 },
286344 }
287
288 var item: T = undefined;
289 @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
290 return item;
291345}
292346
293347test "mem.zeroes" {
......@@ -301,6 +355,60 @@ test "mem.zeroes" {
301355
302356 testing.expect(a.x == 0);
303357 testing.expect(a.y == 10);
358
359 const ZigStruct = struct {
360 const IntegralTypes = struct {
361 integer_0: i0,
362 integer_8: i8,
363 integer_16: i16,
364 integer_32: i32,
365 integer_64: i64,
366 integer_128: i128,
367 unsigned_0: u0,
368 unsigned_8: u8,
369 unsigned_16: u16,
370 unsigned_32: u32,
371 unsigned_64: u64,
372 unsigned_128: u128,
373
374 float_32: f32,
375 float_64: f64,
376 };
377
378 integral_types: IntegralTypes,
379
380 const Pointers = struct {
381 optional: ?*u8,
382 slice: []u8,
383 };
384 pointers: Pointers,
385
386 array: [2]u32,
387 optional_int: ?u8,
388 empty: void,
389 };
390
391 const b = zeroes(ZigStruct);
392 testing.expectEqual(@as(i8, 0), b.integral_types.integer_0);
393 testing.expectEqual(@as(i8, 0), b.integral_types.integer_8);
394 testing.expectEqual(@as(i16, 0), b.integral_types.integer_16);
395 testing.expectEqual(@as(i32, 0), b.integral_types.integer_32);
396 testing.expectEqual(@as(i64, 0), b.integral_types.integer_64);
397 testing.expectEqual(@as(i128, 0), b.integral_types.integer_128);
398 testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_0);
399 testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_8);
400 testing.expectEqual(@as(u16, 0), b.integral_types.unsigned_16);
401 testing.expectEqual(@as(u32, 0), b.integral_types.unsigned_32);
402 testing.expectEqual(@as(u64, 0), b.integral_types.unsigned_64);
403 testing.expectEqual(@as(u128, 0), b.integral_types.unsigned_128);
404 testing.expectEqual(@as(f32, 0), b.integral_types.float_32);
405 testing.expectEqual(@as(f64, 0), b.integral_types.float_64);
406 testing.expectEqual(@as(?*u8, null), b.pointers.optional);
407 testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);
408 for (b.array) |e| {
409 testing.expectEqual(@as(u32, 0), e);
410 }
411 testing.expectEqual(@as(?u8, null), b.optional_int);
304412}
305413
306414pub fn secureZero(comptime T: type, s: []T) void {