| ... | @@ -314,32 +314,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -314,32 +314,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 314 | /// Reduce allocated capacity to `new_len`. | 314 | /// Reduce allocated capacity to `new_len`. |
| 315 | /// May invalidate element pointers. | 315 | /// May invalidate element pointers. |
| 316 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { | 316 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 317 | assert(new_len <= self.items.len); | 317 | var unmanaged = self.moveToUnmanaged(); |
| 318 | | 318 | unmanaged.shrinkAndFree(self.allocator, new_len); |
| 319 | if (@sizeOf(T) == 0) { | 319 | self.* = unmanaged.toManaged(self.allocator); |
| 320 | self.items.len = new_len; | | |
| 321 | return; | | |
| 322 | } | | |
| 323 | | | |
| 324 | const old_memory = self.allocatedSlice(); | | |
| 325 | if (self.allocator.resize(old_memory, new_len)) { | | |
| 326 | self.capacity = new_len; | | |
| 327 | self.items.len = new_len; | | |
| 328 | return; | | |
| 329 | } | | |
| 330 | | | |
| 331 | const new_memory = self.allocator.alignedAlloc(T, alignment, new_len) catch |e| switch (e) { | | |
| 332 | error.OutOfMemory => { | | |
| 333 | // No problem, capacity is still correct then. | | |
| 334 | self.items.len = new_len; | | |
| 335 | return; | | |
| 336 | }, | | |
| 337 | }; | | |
| 338 | | | |
| 339 | mem.copy(T, new_memory, self.items); | | |
| 340 | self.allocator.free(old_memory); | | |
| 341 | self.items = new_memory; | | |
| 342 | self.capacity = new_memory.len; | | |
| 343 | } | 320 | } |
| 344 | | 321 | |
| 345 | /// Reduce length to `new_len`. | 322 | /// Reduce length to `new_len`. |
| ... | @@ -782,7 +759,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -782,7 +759,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 782 | }, | 759 | }, |
| 783 | }; | 760 | }; |
| 784 | | 761 | |
| 785 | mem.copy(T, new_memory, self.items); | 762 | mem.copy(T, new_memory, self.items[0..new_len]); |
| 786 | allocator.free(old_memory); | 763 | allocator.free(old_memory); |
| 787 | self.items = new_memory; | 764 | self.items = new_memory; |
| 788 | self.capacity = new_memory.len; | 765 | self.capacity = new_memory.len; |
| ... | @@ -1488,14 +1465,18 @@ test "std.ArrayListUnmanaged(u8) implements writer" { | ... | @@ -1488,14 +1465,18 @@ test "std.ArrayListUnmanaged(u8) implements writer" { |
| 1488 | } | 1465 | } |
| 1489 | } | 1466 | } |
| 1490 | | 1467 | |
| 1491 | test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" { | 1468 | test "shrink still sets length when resizing is disabled" { |
| 1492 | // use an arena allocator to make sure realloc returns error.OutOfMemory | 1469 | // Use the testing allocator but with resize disabled. |
| 1493 | var arena = std.heap.ArenaAllocator.init(testing.allocator); | 1470 | var a = testing.allocator; |
| 1494 | defer arena.deinit(); | 1471 | a.vtable = &.{ |
| 1495 | const a = arena.allocator(); | 1472 | .alloc = a.vtable.alloc, |
| | 1473 | .resize = Allocator.noResize, |
| | 1474 | .free = a.vtable.free, |
| | 1475 | }; |
| 1496 | | 1476 | |
| 1497 | { | 1477 | { |
| 1498 | var list = ArrayList(i32).init(a); | 1478 | var list = ArrayList(i32).init(a); |
| | 1479 | defer list.deinit(); |
| 1499 | | 1480 | |
| 1500 | try list.append(1); | 1481 | try list.append(1); |
| 1501 | try list.append(2); | 1482 | try list.append(2); |
| ... | @@ -1506,6 +1487,7 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe | ... | @@ -1506,6 +1487,7 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe |
| 1506 | } | 1487 | } |
| 1507 | { | 1488 | { |
| 1508 | var list = ArrayListUnmanaged(i32){}; | 1489 | var list = ArrayListUnmanaged(i32){}; |
| | 1490 | defer list.deinit(a); |
| 1509 | | 1491 | |
| 1510 | try list.append(a, 1); | 1492 | try list.append(a, 1); |
| 1511 | try list.append(a, 2); | 1493 | try list.append(a, 2); |
| ... | @@ -1516,6 +1498,22 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe | ... | @@ -1516,6 +1498,22 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe |
| 1516 | } | 1498 | } |
| 1517 | } | 1499 | } |
| 1518 | | 1500 | |
| | 1501 | test "shrinkAndFree with a copy" { |
| | 1502 | // Use the testing allocator but with resize disabled. |
| | 1503 | var a = testing.allocator; |
| | 1504 | a.vtable = &.{ |
| | 1505 | .alloc = a.vtable.alloc, |
| | 1506 | .resize = Allocator.noResize, |
| | 1507 | .free = a.vtable.free, |
| | 1508 | }; |
| | 1509 | var list = ArrayList(i32).init(a); |
| | 1510 | defer list.deinit(); |
| | 1511 | |
| | 1512 | try list.appendNTimes(3, 16); |
| | 1513 | list.shrinkAndFree(4); |
| | 1514 | try testing.expect(mem.eql(i32, list.items, &.{ 3, 3, 3, 3 })); |
| | 1515 | } |
| | 1516 | |
| 1519 | test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { | 1517 | test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { |
| 1520 | const a = std.testing.allocator; | 1518 | const a = std.testing.allocator; |
| 1521 | { | 1519 | { |