authorgravatar for john.schmidt.h@gmail.comJohn Schmidt <john.schmidt.h@gmail.com> 2021-12-13 15:01:05+01:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-27 19:35:08+02:00
logf04007028ff0e9bc34267c5f0f27985917748496
tree51009b9f5795532daee32ada029ce3dbb4d2a903
parentd86b8663fc0daab7bceade7689bf95fc20503b51

Implement clone with initCapacity and appendSliceAssumeCapacity

`ArrayList.ensureTotalCapacityPrecise` uses `Allocator.reallocAtLeast` under the hood, which can return more than `new_capacity` bytes if `alignment != @alignOf(T)`. This implementation of `clone` assures that the case of `ensureTotalCapacityPrecise` is handled correctly. Thanks @Vexu and @squeek502 for pointing this out.

1 files changed, 8 insertions(+), 17 deletions(-)

lib/std/array_list.zig+8-17
...@@ -110,14 +110,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -110,14 +110,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
110110
111 /// Creates a copy of this ArrayList, using the same allocator.111 /// Creates a copy of this ArrayList, using the same allocator.
112 pub fn clone(self: *Self) !Self {112 pub fn clone(self: *Self) !Self {
113 var items_copy = try self.allocator.alloc(T, self.capacity);113 var cloned = try ArrayList(T).initCapacity(self.allocator, self.capacity);
114 mem.copy(T, items_copy, self.items);114 cloned.appendSliceAssumeCapacity(self.items);
115 items_copy.len = self.items.len;115 return cloned;
116 return Self{
117 .items = items_copy,
118 .capacity = self.capacity,
119 .allocator = self.allocator,
120 };
121 }116 }
122117
123 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.118 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.
...@@ -503,13 +498,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -503,13 +498,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
503498
504 /// Creates a copy of this ArrayList.499 /// Creates a copy of this ArrayList.
505 pub fn clone(self: *Self, allocator: Allocator) !Self {500 pub fn clone(self: *Self, allocator: Allocator) !Self {
506 var items_copy = try allocator.alloc(T, self.capacity);501 var cloned = try ArrayListUnmanaged(T).initCapacity(allocator, self.capacity);
507 mem.copy(T, items_copy, self.items);502 cloned.appendSliceAssumeCapacity(self.items);
508 items_copy.len = self.items.len;503 return cloned;
509 return Self{
510 .items = items_copy,
511 .capacity = self.capacity,
512 };
513 }504 }
514505
515 /// Insert `item` at index `n`. Moves `list[n .. list.len]`506 /// Insert `item` at index `n`. Moves `list[n .. list.len]`
...@@ -837,8 +828,8 @@ test "std.ArrayList/ArrayListUnmanaged.clone" {...@@ -837,8 +828,8 @@ test "std.ArrayList/ArrayListUnmanaged.clone" {
837 defer cloned.deinit();828 defer cloned.deinit();
838829
839 try testing.expectEqualSlices(i32, array.items, cloned.items);830 try testing.expectEqualSlices(i32, array.items, cloned.items);
840 try testing.expectEqual(array.capacity, cloned.capacity);
841 try testing.expectEqual(array.allocator, cloned.allocator);831 try testing.expectEqual(array.allocator, cloned.allocator);
832 try testing.expect(cloned.capacity >= array.capacity);
842833
843 array.deinit();834 array.deinit();
844835
...@@ -856,7 +847,7 @@ test "std.ArrayList/ArrayListUnmanaged.clone" {...@@ -856,7 +847,7 @@ test "std.ArrayList/ArrayListUnmanaged.clone" {
856 defer cloned.deinit(a);847 defer cloned.deinit(a);
857848
858 try testing.expectEqualSlices(i32, array.items, cloned.items);849 try testing.expectEqualSlices(i32, array.items, cloned.items);
859 try testing.expectEqual(array.capacity, cloned.capacity);850 try testing.expect(cloned.capacity >= array.capacity);
860851
861 array.deinit(a);852 array.deinit(a);
862853