| ... | @@ -108,6 +108,33 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -108,6 +108,33 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 108 | mem.copy(T, self.items[i .. i + items.len], items); | 108 | mem.copy(T, self.items[i .. i + items.len], items); |
| 109 | } | 109 | } |
| 110 | | 110 | |
| | 111 | /// Replace range of elements `list[start..start+len]` with `new_items` |
| | 112 | /// grows list if `len < new_items.len`. may allocate |
| | 113 | /// shrinks list if `len > new_items.len` |
| | 114 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void { |
| | 115 | const after_range = start + len; |
| | 116 | const range = self.items[start..after_range]; |
| | 117 | |
| | 118 | if (range.len == new_items.len) |
| | 119 | mem.copy(T, range, new_items) |
| | 120 | else if (range.len < new_items.len) { |
| | 121 | const first = new_items[0..range.len]; |
| | 122 | const rest = new_items[range.len..]; |
| | 123 | |
| | 124 | mem.copy(T, range, first); |
| | 125 | try self.insertSlice(after_range, rest); |
| | 126 | } else { |
| | 127 | mem.copy(T, range, new_items); |
| | 128 | const after_subrange = start + new_items.len; |
| | 129 | |
| | 130 | for (self.items[after_range..]) |item, i| { |
| | 131 | self.items[after_subrange..][i] = item; |
| | 132 | } |
| | 133 | |
| | 134 | self.items.len -= len - new_items.len; |
| | 135 | } |
| | 136 | } |
| | 137 | |
| 111 | /// Extend the list by 1 element. Allocates more memory as necessary. | 138 | /// Extend the list by 1 element. Allocates more memory as necessary. |
| 112 | pub fn append(self: *Self, item: T) !void { | 139 | pub fn append(self: *Self, item: T) !void { |
| 113 | const new_item_ptr = try self.addOne(); | 140 | const new_item_ptr = try self.addOne(); |
| ... | @@ -366,6 +393,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -366,6 +393,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 366 | mem.copy(T, self.items[i .. i + items.len], items); | 393 | mem.copy(T, self.items[i .. i + items.len], items); |
| 367 | } | 394 | } |
| 368 | | 395 | |
| | 396 | /// Replace range of elements `list[start..start+len]` with `new_items` |
| | 397 | /// grows list if `len < new_items.len`. may allocate |
| | 398 | /// shrinks list if `len > new_items.len` |
| | 399 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void { |
| | 400 | var managed = self.toManaged(allocator); |
| | 401 | try managed.replaceRange(start, len, new_items); |
| | 402 | self.* = managed.toUnmanaged(); |
| | 403 | } |
| | 404 | |
| 369 | /// Extend the list by 1 element. Allocates more memory as necessary. | 405 | /// Extend the list by 1 element. Allocates more memory as necessary. |
| 370 | pub fn append(self: *Self, allocator: *Allocator, item: T) !void { | 406 | pub fn append(self: *Self, allocator: *Allocator, item: T) !void { |
| 371 | const new_item_ptr = try self.addOne(allocator); | 407 | const new_item_ptr = try self.addOne(allocator); |
| ... | @@ -714,6 +750,38 @@ test "std.ArrayList.insertSlice" { | ... | @@ -714,6 +750,38 @@ test "std.ArrayList.insertSlice" { |
| 714 | testing.expect(list.items[0] == 1); | 750 | testing.expect(list.items[0] == 1); |
| 715 | } | 751 | } |
| 716 | | 752 | |
| | 753 | test "std.ArrayList.replaceRange" { |
| | 754 | var arena = std.heap.ArenaAllocator.init(testing.allocator); |
| | 755 | defer arena.deinit(); |
| | 756 | |
| | 757 | const alloc = &arena.allocator; |
| | 758 | const init = [_]i32{ 1, 2, 3, 4, 5 }; |
| | 759 | const new = [_]i32{ 0, 0, 0 }; |
| | 760 | |
| | 761 | var list_zero = ArrayList(i32).init(alloc); |
| | 762 | var list_eq = ArrayList(i32).init(alloc); |
| | 763 | var list_lt = ArrayList(i32).init(alloc); |
| | 764 | var list_gt = ArrayList(i32).init(alloc); |
| | 765 | |
| | 766 | try list_zero.appendSlice(&init); |
| | 767 | try list_eq.appendSlice(&init); |
| | 768 | try list_lt.appendSlice(&init); |
| | 769 | try list_gt.appendSlice(&init); |
| | 770 | |
| | 771 | try list_zero.replaceRange(1, 0, &new); |
| | 772 | try list_eq.replaceRange(1, 3, &new); |
| | 773 | try list_lt.replaceRange(1, 2, &new); |
| | 774 | |
| | 775 | // after_range > new_items.len in function body |
| | 776 | testing.expect(1 + 4 > new.len); |
| | 777 | try list_gt.replaceRange(1, 4, &new); |
| | 778 | |
| | 779 | testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 }); |
| | 780 | testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 }); |
| | 781 | testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 }); |
| | 782 | testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 }); |
| | 783 | } |
| | 784 | |
| 717 | const Item = struct { | 785 | const Item = struct { |
| 718 | integer: i32, | 786 | integer: i32, |
| 719 | sub_items: ArrayList(Item), | 787 | sub_items: ArrayList(Item), |