authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-27 20:04:19+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-07-27 20:04:19+00:00
logbd9b3fe1e63539edbacacb0871470b5da4f10012
tree1a68f805eb4597a6db0a3aaf50c44cdd46a3821a
parentbf273b7aec8fe9957967c635bd01b2b92909b192
parent3fba076f920c35ad26b462cf11f9b16b550e97ab
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5511 from jessrud/arraylist-replaceRange

add replaceRange() function to ArrayList

1 files changed, 68 insertions(+), 0 deletions(-)

lib/std/array_list.zig+68
......@@ -108,6 +108,33 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
108108 mem.copy(T, self.items[i .. i + items.len], items);
109109 }
110110
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
111138 /// Extend the list by 1 element. Allocates more memory as necessary.
112139 pub fn append(self: *Self, item: T) !void {
113140 const new_item_ptr = try self.addOne();
......@@ -366,6 +393,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
366393 mem.copy(T, self.items[i .. i + items.len], items);
367394 }
368395
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
369405 /// Extend the list by 1 element. Allocates more memory as necessary.
370406 pub fn append(self: *Self, allocator: *Allocator, item: T) !void {
371407 const new_item_ptr = try self.addOne(allocator);
......@@ -714,6 +750,38 @@ test "std.ArrayList.insertSlice" {
714750 testing.expect(list.items[0] == 1);
715751}
716752
753test "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
717785const Item = struct {
718786 integer: i32,
719787 sub_items: ArrayList(Item),