| ... | ... | @@ -65,16 +65,23 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 65 | 65 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { |
| 66 | 66 | var self = Self.init(allocator); |
| 67 | 67 | |
| 68 | | const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least); |
| 69 | | self.items.ptr = new_memory.ptr; |
| 70 | | self.capacity = new_memory.len; |
| 68 | if (@sizeOf(T) > 0) { |
| 69 | const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least); |
| 70 | self.items.ptr = new_memory.ptr; |
| 71 | self.capacity = new_memory.len; |
| 72 | } else { |
| 73 | // If `T` is a zero-sized type, then we do not need to allocate memory. |
| 74 | self.capacity = std.math.maxInt(usize); |
| 75 | } |
| 71 | 76 | |
| 72 | 77 | return self; |
| 73 | 78 | } |
| 74 | 79 | |
| 75 | 80 | /// Release all allocated memory. |
| 76 | 81 | pub fn deinit(self: Self) void { |
| 77 | | self.allocator.free(self.allocatedSlice()); |
| 82 | if (@sizeOf(T) > 0) { |
| 83 | self.allocator.free(self.allocatedSlice()); |
| 84 | } |
| 78 | 85 | } |
| 79 | 86 | |
| 80 | 87 | pub const span = @compileError("deprecated: use `items` field directly"); |
| ... | ... | @@ -279,13 +286,17 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 279 | 286 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 280 | 287 | assert(new_len <= self.items.len); |
| 281 | 288 | |
| 282 | | self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) { |
| 283 | | error.OutOfMemory => { // no problem, capacity is still correct then. |
| 284 | | self.items.len = new_len; |
| 285 | | return; |
| 286 | | }, |
| 287 | | }; |
| 288 | | self.capacity = new_len; |
| 289 | if (@sizeOf(T) > 0) { |
| 290 | self.items = self.allocator.realloc(self.allocatedSlice(), new_len) catch |e| switch (e) { |
| 291 | error.OutOfMemory => { // no problem, capacity is still correct then. |
| 292 | self.items.len = new_len; |
| 293 | return; |
| 294 | }, |
| 295 | }; |
| 296 | self.capacity = new_len; |
| 297 | } else { |
| 298 | self.items.len = new_len; |
| 299 | } |
| 289 | 300 | } |
| 290 | 301 | |
| 291 | 302 | /// Reduce length to `new_len`. |
| ... | ... | @@ -313,18 +324,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 313 | 324 | /// Modify the array so that it can hold at least `new_capacity` items. |
| 314 | 325 | /// Invalidates pointers if additional memory is needed. |
| 315 | 326 | pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void { |
| 316 | | var better_capacity = self.capacity; |
| 317 | | if (better_capacity >= new_capacity) return; |
| 327 | if (@sizeOf(T) > 0) { |
| 328 | var better_capacity = self.capacity; |
| 329 | if (better_capacity >= new_capacity) return; |
| 318 | 330 | |
| 319 | | while (true) { |
| 320 | | better_capacity += better_capacity / 2 + 8; |
| 321 | | if (better_capacity >= new_capacity) break; |
| 322 | | } |
| 331 | while (true) { |
| 332 | better_capacity += better_capacity / 2 + 8; |
| 333 | if (better_capacity >= new_capacity) break; |
| 334 | } |
| 323 | 335 | |
| 324 | | // TODO This can be optimized to avoid needlessly copying undefined memory. |
| 325 | | const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity); |
| 326 | | self.items.ptr = new_memory.ptr; |
| 327 | | self.capacity = new_memory.len; |
| 336 | // TODO This can be optimized to avoid needlessly copying undefined memory. |
| 337 | const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity); |
| 338 | self.items.ptr = new_memory.ptr; |
| 339 | self.capacity = new_memory.len; |
| 340 | } else { |
| 341 | self.capacity = std.math.maxInt(usize); |
| 342 | } |
| 328 | 343 | } |
| 329 | 344 | |
| 330 | 345 | /// Modify the array so that it can hold at least `additional_count` **more** items. |
| ... | ... | @@ -1299,3 +1314,23 @@ test "ArrayListAligned/ArrayListAlignedUnmanaged accepts unaligned slices" { |
| 1299 | 1314 | try testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 }); |
| 1300 | 1315 | } |
| 1301 | 1316 | } |
| 1317 | |
| 1318 | test "std.ArrayList(u0)" { |
| 1319 | // An ArrayList on zero-sized types should not need to allocate |
| 1320 | const a = &testing.FailingAllocator.init(testing.allocator, 0).allocator; |
| 1321 | |
| 1322 | var list = ArrayList(u0).init(a); |
| 1323 | defer list.deinit(); |
| 1324 | |
| 1325 | try list.append(0); |
| 1326 | try list.append(0); |
| 1327 | try list.append(0); |
| 1328 | try testing.expectEqual(list.items.len, 3); |
| 1329 | |
| 1330 | var count: usize = 0; |
| 1331 | for (list.items) |x| { |
| 1332 | try testing.expectEqual(x, 0); |
| 1333 | count += 1; |
| 1334 | } |
| 1335 | try testing.expectEqual(count, 3); |
| 1336 | } |