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 {
276276 d.* = value;
277277}
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.
279283/// 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.
281285pub fn zeroes(comptime T: type) T {
282286 switch (@typeInfo(T)) {
283287 .ComptimeInt, .Int, .ComptimeFloat, .Float => {
......@@ -295,7 +299,7 @@ pub fn zeroes(comptime T: type) T {
295299 .Optional, .Null => {
296300 return null;
297301 },
298 .Struct => {
302 .Struct => |struct_info| {
299303 if (@sizeOf(T) == 0) return T{};
300304 if (comptime meta.containerLayout(T) == .Extern) {
301305 var item: T = undefined;
......@@ -303,25 +307,23 @@ pub fn zeroes(comptime T: type) T {
303307 return item;
304308 } else {
305309 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))));
310 inline for (struct_info.fields) |field| {
311 @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
309312 }
310313 return structure;
311314 }
312315 },
313316 .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 }
317 switch (ptr_info.size) {
318 .Slice => {
319 return &[_]ptr_info.child{};
320 },
321 .C => {
322 return null;
323 },
324 .One, .Many => {
325 @compileError("Can't set a non nullable pointer to zero.");
326 },
325327 }
326328 },
327329 .Array => |info| {
......@@ -372,6 +374,7 @@ test "mem.zeroes" {
372374
373375 const Pointers = struct {
374376 optional: ?*u8,
377 c_pointer: [*c]u8,
375378 slice: []u8,
376379 };
377380 pointers: Pointers,
......@@ -397,6 +400,7 @@ test "mem.zeroes" {
397400 testing.expectEqual(@as(f32, 0), b.integral_types.float_32);
398401 testing.expectEqual(@as(f64, 0), b.integral_types.float_64);
399402 testing.expectEqual(@as(?*u8, null), b.pointers.optional);
403 testing.expectEqual(@as([*c]u8, null), b.pointers.c_pointer);
400404 testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);
401405 for (b.array) |e| {
402406 testing.expectEqual(@as(u32, 0), e);