authorgravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-02-24 22:15:04+01:00
committergravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-02-24 22:15:04+01:00
logf7aa4f5280e170966e8a7ed92468f76fa87963e1
treef49cd2e5c8ce14c839d67bebd7501a251a1294f0
parent195195d238bb1348dfd3d304b659e2039a1c3d9f

Processed review comments. Updated documentation, used the typinfo for field access, generate compile error on allowzero and set C poitners to null


1 files changed, 20 insertions(+), 16 deletions(-)

lib/std/mem.zig+20-16
...@@ -276,8 +276,12 @@ pub fn set(comptime T: type, dest: []T, value: T) void {...@@ -276,8 +276,12 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
276 d.* = value;276 d.* = value;
277}277}
278278
279/// Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function.
280/// However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when
281/// interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this
282/// function used, examine closely - it may be a code smell.
279/// Zero initializes the type.283/// Zero initializes the type.
280/// This can be used to zero initialize a C-struct.284/// This can be used to zero initialize a any type for which it makes sense. Structs will be initialized recursively.
281pub fn zeroes(comptime T: type) T {285pub fn zeroes(comptime T: type) T {
282 switch (@typeInfo(T)) {286 switch (@typeInfo(T)) {
283 .ComptimeInt, .Int, .ComptimeFloat, .Float => {287 .ComptimeInt, .Int, .ComptimeFloat, .Float => {
...@@ -295,7 +299,7 @@ pub fn zeroes(comptime T: type) T {...@@ -295,7 +299,7 @@ pub fn zeroes(comptime T: type) T {
295 .Optional, .Null => {299 .Optional, .Null => {
296 return null;300 return null;
297 },301 },
298 .Struct => {302 .Struct => |struct_info| {
299 if (@sizeOf(T) == 0) return T{};303 if (@sizeOf(T) == 0) return T{};
300 if (comptime meta.containerLayout(T) == .Extern) {304 if (comptime meta.containerLayout(T) == .Extern) {
301 var item: T = undefined;305 var item: T = undefined;
...@@ -303,25 +307,23 @@ pub fn zeroes(comptime T: type) T {...@@ -303,25 +307,23 @@ pub fn zeroes(comptime T: type) T {
303 return item;307 return item;
304 } else {308 } else {
305 var structure: T = undefined;309 var structure: T = undefined;
306 comptime var field_i = 0;310 inline for (struct_info.fields) |field| {
307 inline while (field_i < @memberCount(T)) : (field_i += 1) {311 @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
308 @field(structure, @memberName(T, field_i)) = zeroes(@TypeOf(@field(structure, @memberName(T, field_i))));
309 }312 }
310 return structure;313 return structure;
311 }314 }
312 },315 },
313 .Pointer => |ptr_info| {316 .Pointer => |ptr_info| {
314 if (ptr_info.is_allowzero) {317 switch (ptr_info.size) {
315 return null;318 .Slice => {
316 } else {319 return &[_]ptr_info.child{};
317 switch (ptr_info.size) {320 },
318 .Slice => {321 .C => {
319 return &[_]ptr_info.child{};322 return null;
320 },323 },
321 .One, .Many, .C => {324 .One, .Many => {
322 @compileError("Can't set a non nullable pointer to zero.");325 @compileError("Can't set a non nullable pointer to zero.");
323 },326 },
324 }
325 }327 }
326 },328 },
327 .Array => |info| {329 .Array => |info| {
...@@ -372,6 +374,7 @@ test "mem.zeroes" {...@@ -372,6 +374,7 @@ test "mem.zeroes" {
372374
373 const Pointers = struct {375 const Pointers = struct {
374 optional: ?*u8,376 optional: ?*u8,
377 c_pointer: [*c]u8,
375 slice: []u8,378 slice: []u8,
376 };379 };
377 pointers: Pointers,380 pointers: Pointers,
...@@ -397,6 +400,7 @@ test "mem.zeroes" {...@@ -397,6 +400,7 @@ test "mem.zeroes" {
397 testing.expectEqual(@as(f32, 0), b.integral_types.float_32);400 testing.expectEqual(@as(f32, 0), b.integral_types.float_32);
398 testing.expectEqual(@as(f64, 0), b.integral_types.float_64);401 testing.expectEqual(@as(f64, 0), b.integral_types.float_64);
399 testing.expectEqual(@as(?*u8, null), b.pointers.optional);402 testing.expectEqual(@as(?*u8, null), b.pointers.optional);
403 testing.expectEqual(@as([*c]u8, null), b.pointers.c_pointer);
400 testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);404 testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);
401 for (b.array) |e| {405 for (b.array) |e| {
402 testing.expectEqual(@as(u32, 0), e);406 testing.expectEqual(@as(u32, 0), e);