authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2019-07-25 19:59:34-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-29 16:32:26-04:00
logbc982e65cf77aa6551029620ceaec8f3ae49202f
tree3b53ffc17828a8aa6a1a847b0914ec74a827c1ca
parent8736a5be2ac280db8fd34c86efd1b764a255f23c

fix std.fmt to handle std.SegmentedList

- add guards for use of prealloc_exp in SegmentedList - define prealloc_exp even when invalid because std.fmt comptime triggers lazy-init - fix std.fmt to print arrays of length 0 as style "[0]<typename>" because "<typename>@address" is n/a without address

2 files changed, 21 insertions(+), 11 deletions(-)

std/fmt.zig+3
...@@ -426,6 +426,9 @@ pub fn formatType(...@@ -426,6 +426,9 @@ pub fn formatType(
426 if (info.child == u8) {426 if (info.child == u8) {
427 return formatText(value, fmt, options, context, Errors, output);427 return formatText(value, fmt, options, context, Errors, output);
428 }428 }
429 if (value.len == 0) {
430 return format(context, Errors, output, "[0]{}", @typeName(T.Child));
431 }
429 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));432 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
430 },433 },
431 .Fn => {434 .Fn => {
std/segmented_list.zig+18-11
...@@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator;...@@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator;
77pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {77pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {
78 return struct {78 return struct {
79 const Self = @This();79 const Self = @This();
80 const prealloc_exp = blk: {80 const ShelfIndex = std.math.Log2Int(usize);
81 // we don't use the prealloc_exp constant when prealloc_item_count is 0.
82 assert(prealloc_item_count != 0);
83 assert(std.math.isPowerOfTwo(prealloc_item_count));
8481
85 const value = std.math.log2_int(usize, prealloc_item_count);82 const prealloc_exp: ShelfIndex = blk: {
86 break :blk @typeOf(1)(value);83 // we don't use the prealloc_exp constant when prealloc_item_count is 0
84 // but lazy-init may still be triggered by other code so supply a value
85 if (prealloc_item_count == 0) {
86 break :blk 0;
87 } else {
88 assert(std.math.isPowerOfTwo(prealloc_item_count));
89 const value = std.math.log2_int(usize, prealloc_item_count);
90 break :blk value;
91 }
87 };92 };
88 const ShelfIndex = std.math.Log2Int(usize);
8993
90 prealloc_segment: [prealloc_item_count]T,94 prealloc_segment: [prealloc_item_count]T,
91 dynamic_segments: [][*]T,95 dynamic_segments: [][*]T,
...@@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
157161
158 /// Grows or shrinks capacity to match usage.162 /// Grows or shrinks capacity to match usage.
159 pub fn setCapacity(self: *Self, new_capacity: usize) !void {163 pub fn setCapacity(self: *Self, new_capacity: usize) !void {
160 if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) {164 if (prealloc_item_count != 0) {
161 return self.shrinkCapacity(new_capacity);165 if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) {
162 } else {166 return self.shrinkCapacity(new_capacity);
163 return self.growCapacity(new_capacity);167 }
164 }168 }
169 return self.growCapacity(new_capacity);
165 }170 }
166171
167 /// Only grows capacity, or retains current capacity172 /// Only grows capacity, or retains current capacity
...@@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {...@@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
399 testing.expect(item == i);404 testing.expect(item == i);
400 list.shrinkCapacity(list.len);405 list.shrinkCapacity(list.len);
401 }406 }
407
408 try list.setCapacity(0);
402}409}