authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 17:56:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-16 17:56:30-07:00
logc8ae581fef6506a8234cdba1355ba7f0f449031a
tree19b5e68b63e296e73bfd17032c5a46352eae38fc
parent5ff45b3f44e7f1272b655b366cee4089d0aa8509

std: deprecate ensureCapacity, add two other capacity functions

I've run into this footgun enough times, nearly every time I want `ensureUnusedCapacity`, not `ensureCapacity`. This commit deprecates `ensureCapacity` in favor of `ensureTotalCapacity` and introduces `ensureUnusedCapacity`.

1 files changed, 36 insertions(+), 14 deletions(-)

lib/std/array_list.zig+36-14
...@@ -132,7 +132,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -132,7 +132,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
132 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.132 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.
133 /// This operation is O(N).133 /// This operation is O(N).
134 pub fn insert(self: *Self, n: usize, item: T) !void {134 pub fn insert(self: *Self, n: usize, item: T) !void {
135 try self.ensureCapacity(self.items.len + 1);135 try self.ensureUnusedCapacity(1);
136 self.items.len += 1;136 self.items.len += 1;
137137
138 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);138 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);
...@@ -142,7 +142,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -142,7 +142,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
142 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.142 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
143 /// This operation is O(N).143 /// This operation is O(N).
144 pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void {144 pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void {
145 try self.ensureCapacity(self.items.len + items.len);145 try self.ensureUnusedCapacity(items.len);
146 self.items.len += items.len;146 self.items.len += items.len;
147147
148 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);148 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);
...@@ -221,7 +221,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -221,7 +221,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
221 /// Append the slice of items to the list. Allocates more221 /// Append the slice of items to the list. Allocates more
222 /// memory as necessary.222 /// memory as necessary.
223 pub fn appendSlice(self: *Self, items: SliceConst) !void {223 pub fn appendSlice(self: *Self, items: SliceConst) !void {
224 try self.ensureCapacity(self.items.len + items.len);224 try self.ensureUnusedCapacity(items.len);
225 self.appendSliceAssumeCapacity(items);225 self.appendSliceAssumeCapacity(items);
226 }226 }
227227
...@@ -270,7 +270,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -270,7 +270,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
270 /// Adjust the list's length to `new_len`.270 /// Adjust the list's length to `new_len`.
271 /// Does not initialize added items if any.271 /// Does not initialize added items if any.
272 pub fn resize(self: *Self, new_len: usize) !void {272 pub fn resize(self: *Self, new_len: usize) !void {
273 try self.ensureCapacity(new_len);273 try self.ensureTotalCapacity(new_len);
274 self.items.len = new_len;274 self.items.len = new_len;
275 }275 }
276276
...@@ -295,9 +295,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -295,9 +295,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
295 self.items.len = new_len;295 self.items.len = new_len;
296 }296 }
297297
298 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
299 pub const ensureCapacity = ensureTotalCapacity;
300
298 /// Modify the array so that it can hold at least `new_capacity` items.301 /// Modify the array so that it can hold at least `new_capacity` items.
299 /// Invalidates pointers if additional memory is needed.302 /// Invalidates pointers if additional memory is needed.
300 pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {303 pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void {
301 var better_capacity = self.capacity;304 var better_capacity = self.capacity;
302 if (better_capacity >= new_capacity) return;305 if (better_capacity >= new_capacity) return;
303306
...@@ -312,6 +315,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -312,6 +315,12 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
312 self.capacity = new_memory.len;315 self.capacity = new_memory.len;
313 }316 }
314317
318 /// Modify the array so that it can hold at least `additional_count` **more** items.
319 /// Invalidates pointers if additional memory is needed.
320 pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void {
321 return self.ensureTotalCapacity(self.items.len + additional_count);
322 }
323
315 /// Increases the array's length to match the full capacity that is already allocated.324 /// Increases the array's length to match the full capacity that is already allocated.
316 /// The new elements have `undefined` values. **Does not** invalidate pointers.325 /// The new elements have `undefined` values. **Does not** invalidate pointers.
317 pub fn expandToCapacity(self: *Self) void {326 pub fn expandToCapacity(self: *Self) void {
...@@ -322,7 +331,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -322,7 +331,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
322 /// The returned pointer becomes invalid when the list resized.331 /// The returned pointer becomes invalid when the list resized.
323 pub fn addOne(self: *Self) !*T {332 pub fn addOne(self: *Self) !*T {
324 const newlen = self.items.len + 1;333 const newlen = self.items.len + 1;
325 try self.ensureCapacity(newlen);334 try self.ensureTotalCapacity(newlen);
326 return self.addOneAssumeCapacity();335 return self.addOneAssumeCapacity();
327 }336 }
328337
...@@ -473,7 +482,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -473,7 +482,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
473 /// to higher indices to make room.482 /// to higher indices to make room.
474 /// This operation is O(N).483 /// This operation is O(N).
475 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {484 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {
476 try self.ensureCapacity(allocator, self.items.len + 1);485 try self.ensureUnusedCapacity(allocator, 1);
477 self.items.len += 1;486 self.items.len += 1;
478487
479 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);488 mem.copyBackwards(T, self.items[n + 1 .. self.items.len], self.items[n .. self.items.len - 1]);
...@@ -484,7 +493,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -484,7 +493,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
484 /// higher indicices make room.493 /// higher indicices make room.
485 /// This operation is O(N).494 /// This operation is O(N).
486 pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: SliceConst) !void {495 pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: SliceConst) !void {
487 try self.ensureCapacity(allocator, self.items.len + items.len);496 try self.ensureUnusedCapacity(allocator, items.len);
488 self.items.len += items.len;497 self.items.len += items.len;
489498
490 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);499 mem.copyBackwards(T, self.items[i + items.len .. self.items.len], self.items[i .. self.items.len - items.len]);
...@@ -544,7 +553,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -544,7 +553,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
544 /// Append the slice of items to the list. Allocates more553 /// Append the slice of items to the list. Allocates more
545 /// memory as necessary.554 /// memory as necessary.
546 pub fn appendSlice(self: *Self, allocator: *Allocator, items: SliceConst) !void {555 pub fn appendSlice(self: *Self, allocator: *Allocator, items: SliceConst) !void {
547 try self.ensureCapacity(allocator, self.items.len + items.len);556 try self.ensureUnusedCapacity(allocator, items.len);
548 self.appendSliceAssumeCapacity(items);557 self.appendSliceAssumeCapacity(items);
549 }558 }
550559
...@@ -579,7 +588,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -579,7 +588,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
579 /// Adjust the list's length to `new_len`.588 /// Adjust the list's length to `new_len`.
580 /// Does not initialize added items, if any.589 /// Does not initialize added items, if any.
581 pub fn resize(self: *Self, allocator: *Allocator, new_len: usize) !void {590 pub fn resize(self: *Self, allocator: *Allocator, new_len: usize) !void {
582 try self.ensureCapacity(allocator, new_len);591 try self.ensureTotalCapacity(allocator, new_len);
583 self.items.len = new_len;592 self.items.len = new_len;
584 }593 }
585594
...@@ -604,9 +613,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -604,9 +613,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
604 self.items.len = new_len;613 self.items.len = new_len;
605 }614 }
606615
616 /// Deprecated: call `ensureUnusedCapacity` or `ensureTotalCapacity`.
617 pub const ensureCapacity = ensureTotalCapacity;
618
607 /// Modify the array so that it can hold at least `new_capacity` items.619 /// Modify the array so that it can hold at least `new_capacity` items.
608 /// Invalidates pointers if additional memory is needed.620 /// Invalidates pointers if additional memory is needed.
609 pub fn ensureCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {621 pub fn ensureTotalCapacity(self: *Self, allocator: *Allocator, new_capacity: usize) !void {
610 var better_capacity = self.capacity;622 var better_capacity = self.capacity;
611 if (better_capacity >= new_capacity) return;623 if (better_capacity >= new_capacity) return;
612624
...@@ -620,6 +632,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -620,6 +632,16 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
620 self.capacity = new_memory.len;632 self.capacity = new_memory.len;
621 }633 }
622634
635 /// Modify the array so that it can hold at least `additional_count` **more** items.
636 /// Invalidates pointers if additional memory is needed.
637 pub fn ensureUnusedCapacity(
638 self: *Self,
639 allocator: *Allocator,
640 additional_count: usize,
641 ) !void {
642 return self.ensureTotalCapacity(allocator, self.items.len + additional_count);
643 }
644
623 /// Increases the array's length to match the full capacity that is already allocated.645 /// Increases the array's length to match the full capacity that is already allocated.
624 /// The new elements have `undefined` values.646 /// The new elements have `undefined` values.
625 /// **Does not** invalidate pointers.647 /// **Does not** invalidate pointers.
...@@ -631,7 +653,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -631,7 +653,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
631 /// The returned pointer becomes invalid when the list resized.653 /// The returned pointer becomes invalid when the list resized.
632 pub fn addOne(self: *Self, allocator: *Allocator) !*T {654 pub fn addOne(self: *Self, allocator: *Allocator) !*T {
633 const newlen = self.items.len + 1;655 const newlen = self.items.len + 1;
634 try self.ensureCapacity(allocator, newlen);656 try self.ensureTotalCapacity(allocator, newlen);
635 return self.addOneAssumeCapacity();657 return self.addOneAssumeCapacity();
636 }658 }
637659
...@@ -1186,7 +1208,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {...@@ -1186,7 +1208,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
1186 defer list.deinit();1208 defer list.deinit();
11871209
1188 (try list.addManyAsArray(4)).* = "aoeu".*;1210 (try list.addManyAsArray(4)).* = "aoeu".*;
1189 try list.ensureCapacity(8);1211 try list.ensureTotalCapacity(8);
1190 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;1212 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;
11911213
1192 testing.expectEqualSlices(u8, list.items, "aoeuasdf");1214 testing.expectEqualSlices(u8, list.items, "aoeuasdf");
...@@ -1196,7 +1218,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {...@@ -1196,7 +1218,7 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
1196 defer list.deinit(a);1218 defer list.deinit(a);
11971219
1198 (try list.addManyAsArray(a, 4)).* = "aoeu".*;1220 (try list.addManyAsArray(a, 4)).* = "aoeu".*;
1199 try list.ensureCapacity(a, 8);1221 try list.ensureTotalCapacity(a, 8);
1200 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;1222 list.addManyAsArrayAssumeCapacity(4).* = "asdf".*;
12011223
1202 testing.expectEqualSlices(u8, list.items, "aoeuasdf");1224 testing.expectEqualSlices(u8, list.items, "aoeuasdf");