| ... | @@ -56,19 +56,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -56,19 +56,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 56 | } | 56 | } |
| 57 | | 57 | |
| 58 | /// Initialize with capacity to hold at least `num` elements. | 58 | /// Initialize with capacity to hold at least `num` elements. |
| | 59 | /// The resulting capacity is likely to be equal to `num`. |
| 59 | /// Deinitialize with `deinit` or use `toOwnedSlice`. | 60 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 60 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { | 61 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { |
| 61 | var self = Self.init(allocator); | 62 | var self = Self.init(allocator); |
| 62 | | 63 | try self.ensureTotalCapacityPrecise(num); |
| 63 | if (@sizeOf(T) > 0) { | | |
| 64 | const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least); | | |
| 65 | self.items.ptr = new_memory.ptr; | | |
| 66 | self.capacity = new_memory.len; | | |
| 67 | } else { | | |
| 68 | // If `T` is a zero-sized type, then we do not need to allocate memory. | | |
| 69 | self.capacity = std.math.maxInt(usize); | | |
| 70 | } | | |
| 71 | | | |
| 72 | return self; | 64 | return self; |
| 73 | } | 65 | } |
| 74 | | 66 | |
| ... | @@ -330,8 +322,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -330,8 +322,22 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 330 | if (better_capacity >= new_capacity) break; | 322 | if (better_capacity >= new_capacity) break; |
| 331 | } | 323 | } |
| 332 | | 324 | |
| | 325 | return self.ensureTotalCapacityPrecise(better_capacity); |
| | 326 | } else { |
| | 327 | self.capacity = std.math.maxInt(usize); |
| | 328 | } |
| | 329 | } |
| | 330 | |
| | 331 | /// Modify the array so that it can hold at least `new_capacity` items. |
| | 332 | /// Like `ensureTotalCapacity`, but the resulting capacity is much more likely |
| | 333 | /// (but not guaranteed) to be equal to `new_capacity`. |
| | 334 | /// Invalidates pointers if additional memory is needed. |
| | 335 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) !void { |
| | 336 | if (@sizeOf(T) > 0) { |
| | 337 | if (self.capacity >= new_capacity) return; |
| | 338 | |
| 333 | // TODO This can be optimized to avoid needlessly copying undefined memory. | 339 | // TODO This can be optimized to avoid needlessly copying undefined memory. |
| 334 | const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity); | 340 | const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), new_capacity); |
| 335 | self.items.ptr = new_memory.ptr; | 341 | self.items.ptr = new_memory.ptr; |
| 336 | self.capacity = new_memory.len; | 342 | self.capacity = new_memory.len; |
| 337 | } else { | 343 | } else { |
| ... | @@ -464,14 +470,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -464,14 +470,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 464 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; | 470 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; |
| 465 | | 471 | |
| 466 | /// Initialize with capacity to hold at least num elements. | 472 | /// Initialize with capacity to hold at least num elements. |
| | 473 | /// The resulting capacity is likely to be equal to `num`. |
| 467 | /// Deinitialize with `deinit` or use `toOwnedSlice`. | 474 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 468 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { | 475 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { |
| 469 | var self = Self{}; | 476 | var self = Self{}; |
| 470 | | 477 | try self.ensureTotalCapacityPrecise(allocator, num); |
| 471 | const new_memory = try allocator.allocAdvanced(T, alignment, num, .at_least); | | |
| 472 | self.items.ptr = new_memory.ptr; | | |
| 473 | self.capacity = new_memory.len; | | |
| 474 | | | |
| 475 | return self; | 478 | return self; |
| 476 | } | 479 | } |
| 477 | | 480 | |
| ... | @@ -685,7 +688,17 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -685,7 +688,17 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 685 | if (better_capacity >= new_capacity) break; | 688 | if (better_capacity >= new_capacity) break; |
| 686 | } | 689 | } |
| 687 | | 690 | |
| 688 | const new_memory = try allocator.reallocAtLeast(self.allocatedSlice(), better_capacity); | 691 | return self.ensureTotalCapacityPrecise(allocator, better_capacity); |
| | 692 | } |
| | 693 | |
| | 694 | /// Modify the array so that it can hold at least `new_capacity` items. |
| | 695 | /// Like `ensureTotalCapacity`, but the resulting capacity is much more likely |
| | 696 | /// (but not guaranteed) to be equal to `new_capacity`. |
| | 697 | /// Invalidates pointers if additional memory is needed. |
| | 698 | pub fn ensureTotalCapacityPrecise(self: *Self, allocator: *Allocator, new_capacity: usize) !void { |
| | 699 | if (self.capacity >= new_capacity) return; |
| | 700 | |
| | 701 | const new_memory = try allocator.reallocAtLeast(self.allocatedSlice(), new_capacity); |
| 689 | self.items.ptr = new_memory.ptr; | 702 | self.items.ptr = new_memory.ptr; |
| 690 | self.capacity = new_memory.len; | 703 | self.capacity = new_memory.len; |
| 691 | } | 704 | } |