authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-15 23:43:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-15 23:44:36-07:00
logf2721a4cbc45cf4a7ef22800ed69550c3c5dd97d
treee085a7c2ce4a0af4077448e0a4bbc2b984f0a367
parent69461bcae4a78c835bdfe0aae85524342c0f8461

std.ArrayList: pedantic rewordings of documentation and unit tests


1 files changed, 174 insertions(+), 168 deletions(-)

lib/std/array_list.zig+174-168
......@@ -10,7 +10,7 @@ const Allocator = mem.Allocator;
1010/// This is a wrapper around an array of T values. Initialize with `init`.
1111///
1212/// This struct internally stores a `std.mem.Allocator` for memory management.
13/// To manually specify an allocator with each method call see `ArrayListUnmanaged`.
13/// To manually specify an allocator with each function call see `ArrayListUnmanaged`.
1414pub fn ArrayList(comptime T: type) type {
1515 return ArrayListAligned(T, null);
1616}
......@@ -21,7 +21,7 @@ pub fn ArrayList(comptime T: type) type {
2121/// Initialize with `init`.
2222///
2323/// This struct internally stores a `std.mem.Allocator` for memory management.
24/// To manually specify an allocator with each method call see `ArrayListAlignedUnmanaged`.
24/// To manually specify an allocator with each function call see `ArrayListAlignedUnmanaged`.
2525pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
2626 if (alignment) |a| {
2727 if (a == @alignOf(T)) {
......@@ -30,15 +30,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
3030 }
3131 return struct {
3232 const Self = @This();
33 /// Contents of the list. Pointers to elements in this slice are
34 /// **invalid after resizing operations** on the ArrayList unless the
35 /// operation explicitly either: (1) states otherwise or (2) lists the
36 /// invalidated pointers.
33 /// Contents of the list. This field is intended to be accessed
34 /// directly.
3735 ///
38 /// The allocator used determines how element pointers are
39 /// invalidated, so the behavior may vary between lists. To avoid
40 /// illegal behavior, take into account the above paragraph plus the
41 /// explicit statements given in each method.
36 /// Pointers to elements in this slice are invalidated by various
37 /// functions of this ArrayList in accordance with the respective
38 /// documentation. In all cases, "invalidated" means that the memory
39 /// has been passed to this allocator's resize or free function.
4240 items: Slice,
4341 /// How many T values this list can hold without allocating
4442 /// additional memory.
......@@ -144,18 +142,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
144142 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
145143 /// If `i` is equal to the length of the list this operation is equivalent to append.
146144 /// This operation is O(N).
147 /// Invalidates pointers if additional memory is needed.
148 /// **Asserts that `i <= self.items.len`.**
145 /// Invalidates element pointers if additional memory is needed.
146 /// Asserts that the index is in bounds or equal to the length.
149147 pub fn insert(self: *Self, i: usize, item: T) Allocator.Error!void {
150148 const dst = try self.addManyAt(i, 1);
151149 dst[0] = item;
152150 }
153151
154152 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
155 /// If `i` is equal to the length of the list this operation is equivalent to appendAssumeCapacity.
153 /// If `i` is equal to the length of the list this operation is
154 /// equivalent to appendAssumeCapacity.
156155 /// This operation is O(N).
157 /// **Asserts that `i <= self.items.len`.**
158 /// **Asserts that `self.items.len < self.capacity` .**
156 /// Asserts that there is enough capacity for the new item.
157 /// Asserts that the index is in bounds or equal to the length.
159158 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
160159 assert(self.items.len < self.capacity);
161160 self.items.len += 1;
......@@ -171,7 +170,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
171170 /// Invalidates pre-existing pointers to elements at and after `index`.
172171 /// Invalidates all pre-existing element pointers if capacity must be
173172 /// increased to accomodate the new elements.
174 /// **Asserts that `index <= self.items.len`.**
173 /// Asserts that the index is in bounds or equal to the length.
175174 pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T {
176175 const new_len = try addOrOom(self.items.len, count);
177176
......@@ -208,10 +207,10 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
208207 /// `undefined` values. Returns a slice pointing to the newly allocated
209208 /// elements, which becomes invalid after various `ArrayList`
210209 /// operations.
210 /// Asserts that there is enough capacity for the new elements.
211211 /// Invalidates pre-existing pointers to elements at and after `index`, but
212212 /// does not invalidate any before that.
213 /// **Asserts that `index <= self.items.len`.**
214 /// **Asserts that the list can hold `count` additional items.**
213 /// Asserts that the index is in bounds or equal to the length.
215214 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
216215 const new_len = self.items.len + count;
217216 assert(self.capacity >= new_len);
......@@ -228,7 +227,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
228227 /// Invalidates pre-existing pointers to elements at and after `index`.
229228 /// Invalidates all pre-existing element pointers if capacity must be
230229 /// increased to accomodate the new elements.
231 /// **Asserts that `index <= self.items.len`.**
230 /// Asserts that the index is in bounds or equal to the length.
232231 pub fn insertSlice(
233232 self: *Self,
234233 index: usize,
......@@ -241,8 +240,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
241240 /// Replace range of elements `list[start..][0..len]` with `new_items`.
242241 /// Grows list if `len < new_items.len`.
243242 /// Shrinks list if `len > new_items.len`.
244 /// Invalidates pointers if this ArrayList is resized.
245 /// **Asserts that `start <= self.items.len`.**
243 /// Invalidates element pointers if this ArrayList is resized.
244 /// Asserts that the start index is in bounds or equal to the length.
246245 pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void {
247246 const after_range = try addOrOom(start, len);
248247 const range = self.items[start..after_range];
......@@ -268,15 +267,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
268267 }
269268
270269 /// Extends the list by 1 element. Allocates more memory as necessary.
271 /// Invalidates pointers if additional memory is needed.
270 /// Invalidates element pointers if additional memory is needed.
272271 pub fn append(self: *Self, item: T) Allocator.Error!void {
273272 const new_item_ptr = try self.addOne();
274273 new_item_ptr.* = item;
275274 }
276275
277 /// Extends the list by 1 element. Does not
278 /// invalidate pointers.
279 /// **Asserts that the list can hold one additional item.**
276 /// Extends the list by 1 element.
277 /// Never invalidates element pointers.
278 /// Asserts that the list can hold one additional item.
280279 pub fn appendAssumeCapacity(self: *Self, item: T) void {
281280 const new_item_ptr = self.addOneAssumeCapacity();
282281 new_item_ptr.* = item;
......@@ -284,11 +283,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
284283
285284 /// Remove the element at index `i`, shift elements after index
286285 /// `i` forward, and return the removed element.
287 /// Invalidates pointers to end of list.
286 /// Invalidates element pointers to end of list.
288287 /// This operation is O(N).
289288 /// This preserves item order. Use `swapRemove` if order preservation is not important.
290 /// **Asserts that `i < self.items.len`.**
291 /// **Asserts that the list is not empty.**
289 /// Asserts that the index is in bounds.
290 /// Asserts that the list is not empty.
292291 pub fn orderedRemove(self: *Self, i: usize) T {
293292 const newlen = self.items.len - 1;
294293 if (newlen == i) return self.pop();
......@@ -304,8 +303,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
304303 /// The empty slot is filled from the end of the list.
305304 /// This operation is O(1).
306305 /// This may not preserve item order. Use `orderedRemove` if you need to preserve order.
307 /// **Asserts that `i < self.items.len`.**
308 /// **Asserts that the list is not empty.**
306 /// Asserts that the list is not empty.
307 /// Asserts that the index is in bounds.
309308 pub fn swapRemove(self: *Self, i: usize) T {
310309 if (self.items.len - 1 == i) return self.pop();
311310
......@@ -316,14 +315,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
316315
317316 /// Append the slice of items to the list. Allocates more
318317 /// memory as necessary.
319 /// Invalidates pointers if additional memory is needed.
318 /// Invalidates element pointers if additional memory is needed.
320319 pub fn appendSlice(self: *Self, items: []const T) Allocator.Error!void {
321320 try self.ensureUnusedCapacity(items.len);
322321 self.appendSliceAssumeCapacity(items);
323322 }
324323
325 /// Append the slice of items to the list. Does not invalidate pointers.
326 /// **Asserts that the list can hold `items.len` additional items.**
324 /// Append the slice of items to the list.
325 /// Never invalidates element pointers.
326 /// Asserts that the list can hold the additional items.
327327 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
328328 const old_len = self.items.len;
329329 const new_len = old_len + items.len;
......@@ -335,16 +335,18 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
335335 /// Append an unaligned slice of items to the list. Allocates more
336336 /// memory as necessary. Only call this function if calling
337337 /// `appendSlice` instead would be a compile error.
338 /// Invalidates pointers if additional memory is needed.
338 /// Invalidates element pointers if additional memory is needed.
339339 pub fn appendUnalignedSlice(self: *Self, items: []align(1) const T) Allocator.Error!void {
340340 try self.ensureUnusedCapacity(items.len);
341341 self.appendUnalignedSliceAssumeCapacity(items);
342342 }
343343
344 /// Append the slice of items to the list. **Does not** invalidate pointers.
345 /// Only call this function if calling `appendSliceAssumeCapacity` instead
346 /// would be a compile error.
347 /// **Asserts that the list can hold `items.len` additional items.**
344 /// Append the slice of items to the list.
345 /// Never invalidates element pointers.
346 /// This function is only needed when calling
347 /// `appendSliceAssumeCapacity` instead would be a compile error due to the
348 /// alignment of the `items` parameter.
349 /// Asserts that the list can hold the additional items.
348350 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
349351 const old_len = self.items.len;
350352 const new_len = old_len + items.len;
......@@ -366,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
366368
367369 /// Same as `append` except it returns the number of bytes written, which is always the same
368370 /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.
369 /// Invalidates pointers if additional memory is needed.
371 /// Invalidates element pointers if additional memory is needed.
370372 fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize {
371373 try self.appendSlice(m);
372374 return m.len;
......@@ -374,20 +376,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
374376
375377 /// Append a value to the list `n` times.
376378 /// Allocates more memory as necessary.
377 /// Invalidates pointers if additional memory is needed.
379 /// Invalidates element pointers if additional memory is needed.
378380 /// The function is inline so that a comptime-known `value` parameter will
379381 /// have a more optimal memset codegen in case it has a repeated byte pattern.
380382 pub inline fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void {
381383 const old_len = self.items.len;
382 try self.resize(try addOrOom(self.items.len, n));
384 try self.resize(try addOrOom(old_len, n));
383385 @memset(self.items[old_len..self.items.len], value);
384386 }
385387
386388 /// Append a value to the list `n` times.
387 /// Does not invalidate pointers.
389 /// Never invalidates element pointers.
388390 /// The function is inline so that a comptime-known `value` parameter will
389391 /// have a more optimal memset codegen in case it has a repeated byte pattern.
390 /// **Asserts that the list can hold `n` additional items.**
392 /// Asserts that the list can hold the additional items.
391393 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
392394 const new_len = self.items.len + n;
393395 assert(new_len <= self.capacity);
......@@ -395,9 +397,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
395397 self.items.len = new_len;
396398 }
397399
398 /// Adjust the list's length to `new_len`.
399 /// Does not initialize added items if any.
400 /// Invalidates pointers if additional memory is needed.
400 /// Adjust the list length to `new_len`.
401 /// Additional elements contain the value `undefined`.
402 /// Invalidates element pointers if additional memory is needed.
401403 pub fn resize(self: *Self, new_len: usize) Allocator.Error!void {
402404 try self.ensureTotalCapacity(new_len);
403405 self.items.len = new_len;
......@@ -405,7 +407,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
405407
406408 /// Reduce allocated capacity to `new_len`.
407409 /// May invalidate element pointers.
408 /// **Asserts that `new_len <= self.items.len`.**
410 /// Asserts that the new length is less than or equal to the previous length.
409411 pub fn shrinkAndFree(self: *Self, new_len: usize) void {
410412 var unmanaged = self.moveToUnmanaged();
411413 unmanaged.shrinkAndFree(self.allocator, new_len);
......@@ -413,8 +415,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
413415 }
414416
415417 /// Reduce length to `new_len`.
416 /// Invalidates pointers for the elements `items[new_len..]`.
417 /// **Asserts that `new_len <= self.items.len`.**
418 /// Invalidates element pointers for the elements `items[new_len..]`.
419 /// Asserts that the new length is less than or equal to the previous length.
418420 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
419421 assert(new_len <= self.items.len);
420422 self.items.len = new_len;
......@@ -434,7 +436,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
434436
435437 /// If the current capacity is less than `new_capacity`, this function will
436438 /// modify the array so that it can hold at least `new_capacity` items.
437 /// Invalidates pointers if additional memory is needed.
439 /// Invalidates element pointers if additional memory is needed.
438440 pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) Allocator.Error!void {
439441 if (@sizeOf(T) == 0) {
440442 self.capacity = math.maxInt(usize);
......@@ -449,7 +451,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
449451
450452 /// If the current capacity is less than `new_capacity`, this function will
451453 /// modify the array so that it can hold exactly `new_capacity` items.
452 /// Invalidates pointers if additional memory is needed.
454 /// Invalidates element pointers if additional memory is needed.
453455 pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void {
454456 if (@sizeOf(T) == 0) {
455457 self.capacity = math.maxInt(usize);
......@@ -476,13 +478,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
476478 }
477479
478480 /// Modify the array so that it can hold at least `additional_count` **more** items.
479 /// Invalidates pointers if additional memory is needed.
481 /// Invalidates element pointers if additional memory is needed.
480482 pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) Allocator.Error!void {
481483 return self.ensureTotalCapacity(try addOrOom(self.items.len, additional_count));
482484 }
483485
484486 /// Increases the array's length to match the full capacity that is already allocated.
485 /// The new elements have `undefined` values. **Does not** invalidate pointers.
487 /// The new elements have `undefined` values.
488 /// Never invalidates element pointers.
486489 pub fn expandToCapacity(self: *Self) void {
487490 self.items.len = self.capacity;
488491 }
......@@ -496,8 +499,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
496499
497500 /// Increase length by 1, returning pointer to the new item.
498501 /// The returned pointer becomes invalid when the list is resized.
499 /// Does not invalidate element pointers.
500 /// **Asserts that the list can hold one additional item.**
502 /// Never invalidates element pointers.
503 /// Asserts that the list can hold one additional item.
501504 pub fn addOneAssumeCapacity(self: *Self) *T {
502505 assert(self.items.len < self.capacity);
503506 self.items.len += 1;
......@@ -516,9 +519,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
516519
517520 /// Resize the array, adding `n` new elements, which have `undefined` values.
518521 /// The return value is an array pointing to the newly allocated elements.
519 /// Does not invalidate element pointers.
522 /// Never invalidates element pointers.
520523 /// The returned pointer becomes invalid when the list is resized.
521 /// **Asserts that the list can hold `n` additional items.**
524 /// Asserts that the list can hold the additional items.
522525 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
523526 assert(self.items.len + n <= self.capacity);
524527 const prev_len = self.items.len;
......@@ -538,9 +541,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
538541
539542 /// Resize the array, adding `n` new elements, which have `undefined` values.
540543 /// The return value is a slice pointing to the newly allocated elements.
541 /// Does not invalidate element pointers.
544 /// Never invalidates element pointers.
542545 /// The returned pointer becomes invalid when the list is resized.
543 /// **Asserts that the list can hold `n` additional items.**
546 /// Asserts that the list can hold the additional items.
544547 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
545548 assert(self.items.len + n <= self.capacity);
546549 const prev_len = self.items.len;
......@@ -549,8 +552,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
549552 }
550553
551554 /// Remove and return the last element from the list.
552 /// Invalidates pointers to the removed element.
553 /// **Asserts that the list is not empty.**
555 /// Invalidates element pointers to the removed element.
556 /// Asserts that the list is not empty.
554557 pub fn pop(self: *Self) T {
555558 const val = self.items[self.items.len - 1];
556559 self.items.len -= 1;
......@@ -559,7 +562,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
559562
560563 /// Remove and return the last element from the list, or
561564 /// return `null` if list is empty.
562 /// Invalidates pointers to the removed element, if any.
565 /// Invalidates element pointers to the removed element, if any.
563566 pub fn popOrNull(self: *Self) ?T {
564567 if (self.items.len == 0) return null;
565568 return self.pop();
......@@ -581,7 +584,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
581584 }
582585
583586 /// Returns the last element from the list.
584 /// **Asserts that the list is not empty.**
587 /// Asserts that the list is not empty.
585588 pub fn getLast(self: Self) T {
586589 const val = self.items[self.items.len - 1];
587590 return val;
......@@ -596,17 +599,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
596599}
597600
598601/// An ArrayList, but the allocator is passed as a parameter to the relevant functions
599/// rather than stored in the struct itself. The same allocator **must** be used throughout
602/// rather than stored in the struct itself. The same allocator must be used throughout
600603/// the entire lifetime of an ArrayListUnmanaged. Initialize directly or with
601604/// `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`.
602605pub fn ArrayListUnmanaged(comptime T: type) type {
603606 return ArrayListAlignedUnmanaged(T, null);
604607}
605608
606/// An ArrayListAligned, but the allocator is passed as a parameter to the relevant
607/// functions rather than stored in the struct itself. The same allocator **must**
608/// be used throughout the entire lifetime of an ArrayListAlignedUnmanaged.
609/// Initialize directly or with `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`.
609/// A contiguous, growable list of arbitrarily aligned items in memory.
610/// This is a wrapper around an array of T values aligned to `alignment`-byte
611/// addresses. If the specified alignment is `null`, then `@alignOf(T)` is used.
612///
613/// Functions that potentially allocate memory accept an `Allocator` parameter.
614/// Initialize directly or with `initCapacity`, and deinitialize with `deinit`
615/// or use `toOwnedSlice`.
610616pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type {
611617 if (alignment) |a| {
612618 if (a == @alignOf(T)) {
......@@ -615,15 +621,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
615621 }
616622 return struct {
617623 const Self = @This();
618 /// Contents of the list. Pointers to elements in this slice are
619 /// **invalid after resizing operations** on the ArrayList unless the
620 /// operation explicitly either: (1) states otherwise or (2) lists the
621 /// invalidated pointers.
624 /// Contents of the list. This field is intended to be accessed
625 /// directly.
622626 ///
623 /// The allocator used determines how element pointers are
624 /// invalidated, so the behavior may vary between lists. To avoid
625 /// illegal behavior, take into account the above paragraph plus the
626 /// explicit statements given in each method.
627 /// Pointers to elements in this slice are invalidated by various
628 /// functions of this ArrayList in accordance with the respective
629 /// documentation. In all cases, "invalidated" means that the memory
630 /// has been passed to an allocator's resize or free function.
627631 items: Slice = &[_]T{},
628632 /// How many T values this list can hold without allocating
629633 /// additional memory.
......@@ -646,8 +650,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
646650
647651 /// Initialize with externally-managed memory. The buffer determines the
648652 /// capacity, and the length is set to zero.
649 /// **When initialized this way, all methods that accept an Allocator
650 /// argument cause illegal behavior**.
653 /// When initialized this way, all functions that accept an Allocator
654 /// argument cause illegal behavior.
651655 pub fn initBuffer(buffer: Slice) Self {
652656 return .{
653657 .items = buffer[0..0],
......@@ -722,8 +726,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
722726 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
723727 /// If `i` is equal to the length of the list this operation is equivalent to append.
724728 /// This operation is O(N).
725 /// Invalidates pointers if additional memory is needed.
726 /// **Asserts that `i < self.items.len`.**
729 /// Invalidates element pointers if additional memory is needed.
730 /// Asserts that the index is in bounds or equal to the length.
727731 pub fn insert(self: *Self, allocator: Allocator, i: usize, item: T) Allocator.Error!void {
728732 const dst = try self.addManyAt(allocator, i, 1);
729733 dst[0] = item;
......@@ -732,8 +736,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
732736 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
733737 /// If in` is equal to the length of the list this operation is equivalent to append.
734738 /// This operation is O(N).
735 /// **Asserts that `i < self.items.len`.**
736 /// **Asserts that the list can hold one additional item.**
739 /// Asserts that the list has capacity for one additional item.
740 /// Asserts that the index is in bounds or equal to the length.
737741 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
738742 assert(self.items.len < self.capacity);
739743 self.items.len += 1;
......@@ -749,7 +753,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
749753 /// Invalidates pre-existing pointers to elements at and after `index`.
750754 /// Invalidates all pre-existing element pointers if capacity must be
751755 /// increased to accomodate the new elements.
752 /// **Asserts that `index <= self.items.len`.**
756 /// Asserts that the index is in bounds or equal to the length.
753757 pub fn addManyAt(
754758 self: *Self,
755759 allocator: Allocator,
......@@ -767,8 +771,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
767771 /// operations.
768772 /// Invalidates pre-existing pointers to elements at and after `index`, but
769773 /// does not invalidate any before that.
770 /// **Asserts that `index <= self.items.len`.**
771 /// **Asserts that the list can hold `count` additional items.**
774 /// Asserts that the list has capacity for the additional items.
775 /// Asserts that the index is in bounds or equal to the length.
772776 pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T {
773777 const new_len = self.items.len + count;
774778 assert(self.capacity >= new_len);
......@@ -785,7 +789,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
785789 /// Invalidates pre-existing pointers to elements at and after `index`.
786790 /// Invalidates all pre-existing element pointers if capacity must be
787791 /// increased to accomodate the new elements.
788 /// **Asserts that `index <= self.items.len`.**
792 /// Asserts that the index is in bounds or equal to the length.
789793 pub fn insertSlice(
790794 self: *Self,
791795 allocator: Allocator,
......@@ -803,8 +807,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
803807 /// Replace range of elements `list[start..][0..len]` with `new_items`
804808 /// Grows list if `len < new_items.len`.
805809 /// Shrinks list if `len > new_items.len`
806 /// Invalidates pointers if this ArrayList is resized.
807 /// **Asserts that `start <= self.items.len`.**
810 /// Invalidates element pointers if this ArrayList is resized.
811 /// Asserts that the start index is in bounds or equal to the length.
808812 pub fn replaceRange(
809813 self: *Self,
810814 allocator: Allocator,
......@@ -818,14 +822,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
818822 }
819823
820824 /// Extend the list by 1 element. Allocates more memory as necessary.
821 /// Invalidates pointers if additional memory is needed.
825 /// Invalidates element pointers if additional memory is needed.
822826 pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void {
823827 const new_item_ptr = try self.addOne(allocator);
824828 new_item_ptr.* = item;
825829 }
826830
827831 /// Extend the list by 1 element.
828 /// **Asserts that the list can hold one additional item.**
832 /// Never invalidates element pointers.
833 /// Asserts that the list can hold one additional item.
829834 pub fn appendAssumeCapacity(self: *Self, item: T) void {
830835 const new_item_ptr = self.addOneAssumeCapacity();
831836 new_item_ptr.* = item;
......@@ -834,8 +839,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
834839 /// Remove the element at index `i` from the list and return its value.
835840 /// Invalidates pointers to the last element.
836841 /// This operation is O(N).
837 /// **Asserts that `i < self.items.len`.**
838 /// **Asserts that the list is not empty.**
842 /// Asserts that the list is not empty.
843 /// Asserts that the index is in bounds.
839844 pub fn orderedRemove(self: *Self, i: usize) T {
840845 const newlen = self.items.len - 1;
841846 if (newlen == i) return self.pop();
......@@ -851,8 +856,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
851856 /// The empty slot is filled from the end of the list.
852857 /// Invalidates pointers to last element.
853858 /// This operation is O(1).
854 /// **Asserts that `i < self.items.len`.**
855 /// **Asserts that the list is not empty.**
859 /// Asserts that the list is not empty.
860 /// Asserts that the index is in bounds.
856861 pub fn swapRemove(self: *Self, i: usize) T {
857862 if (self.items.len - 1 == i) return self.pop();
858863
......@@ -863,14 +868,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
863868
864869 /// Append the slice of items to the list. Allocates more
865870 /// memory as necessary.
866 /// Invalidates pointers if additional memory is needed.
871 /// Invalidates element pointers if additional memory is needed.
867872 pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void {
868873 try self.ensureUnusedCapacity(allocator, items.len);
869874 self.appendSliceAssumeCapacity(items);
870875 }
871876
872877 /// Append the slice of items to the list.
873 /// **Asserts that the list can hold `items.len` additional items.**
878 /// Asserts that the list can hold the additional items.
874879 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
875880 const old_len = self.items.len;
876881 const new_len = old_len + items.len;
......@@ -882,7 +887,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
882887 /// Append the slice of items to the list. Allocates more
883888 /// memory as necessary. Only call this function if a call to `appendSlice` instead would
884889 /// be a compile error.
885 /// Invalidates pointers if additional memory is needed.
890 /// Invalidates element pointers if additional memory is needed.
886891 pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void {
887892 try self.ensureUnusedCapacity(allocator, items.len);
888893 self.appendUnalignedSliceAssumeCapacity(items);
......@@ -891,7 +896,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
891896 /// Append an unaligned slice of items to the list.
892897 /// Only call this function if a call to `appendSliceAssumeCapacity`
893898 /// instead would be a compile error.
894 /// **Asserts that the list can hold `items.len` additional items.**
899 /// Asserts that the list can hold the additional items.
895900 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
896901 const old_len = self.items.len;
897902 const new_len = old_len + items.len;
......@@ -918,7 +923,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
918923
919924 /// Same as `append` except it returns the number of bytes written, which is always the same
920925 /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API.
921 /// Invalidates pointers if additional memory is needed.
926 /// Invalidates element pointers if additional memory is needed.
922927 fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize {
923928 try context.self.appendSlice(context.allocator, m);
924929 return m.len;
......@@ -926,20 +931,20 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
926931
927932 /// Append a value to the list `n` times.
928933 /// Allocates more memory as necessary.
929 /// Invalidates pointers if additional memory is needed.
934 /// Invalidates element pointers if additional memory is needed.
930935 /// The function is inline so that a comptime-known `value` parameter will
931936 /// have a more optimal memset codegen in case it has a repeated byte pattern.
932937 pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void {
933938 const old_len = self.items.len;
934 try self.resize(allocator, try addOrOom(self.items.len, n));
939 try self.resize(allocator, try addOrOom(old_len, n));
935940 @memset(self.items[old_len..self.items.len], value);
936941 }
937942
938943 /// Append a value to the list `n` times.
939 /// **Does not** invalidate pointers.
944 /// Never invalidates element pointers.
940945 /// The function is inline so that a comptime-known `value` parameter will
941946 /// have better memset codegen in case it has a repeated byte pattern.
942 /// **Asserts that the list can hold `n` additional items.**
947 /// Asserts that the list can hold the additional items.
943948 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
944949 const new_len = self.items.len + n;
945950 assert(new_len <= self.capacity);
......@@ -947,9 +952,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
947952 self.items.len = new_len;
948953 }
949954
950 /// Adjust the list's length to `new_len`.
951 /// Does not initialize added items, if any.
952 /// Invalidates pointers if additional memory is needed.
955 /// Adjust the list length to `new_len`.
956 /// Additional elements contain the value `undefined`.
957 /// Invalidates element pointers if additional memory is needed.
953958 pub fn resize(self: *Self, allocator: Allocator, new_len: usize) Allocator.Error!void {
954959 try self.ensureTotalCapacity(allocator, new_len);
955960 self.items.len = new_len;
......@@ -957,7 +962,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
957962
958963 /// Reduce allocated capacity to `new_len`.
959964 /// May invalidate element pointers.
960 /// **Asserts that `new_len <= self.items.len`.**
965 /// Asserts that the new length is less than or equal to the previous length.
961966 pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void {
962967 assert(new_len <= self.items.len);
963968
......@@ -990,7 +995,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
990995 /// Reduce length to `new_len`.
991996 /// Invalidates pointers to elements `items[new_len..]`.
992997 /// Keeps capacity the same.
993 /// **Asserts that `new_len <= self.items.len`.**
998 /// Asserts that the new length is less than or equal to the previous length.
994999 pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
9951000 assert(new_len <= self.items.len);
9961001 self.items.len = new_len;
......@@ -1010,7 +1015,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10101015
10111016 /// If the current capacity is less than `new_capacity`, this function will
10121017 /// modify the array so that it can hold at least `new_capacity` items.
1013 /// Invalidates pointers if additional memory is needed.
1018 /// Invalidates element pointers if additional memory is needed.
10141019 pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void {
10151020 if (self.capacity >= new_capacity) return;
10161021
......@@ -1020,7 +1025,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10201025
10211026 /// If the current capacity is less than `new_capacity`, this function will
10221027 /// modify the array so that it can hold exactly `new_capacity` items.
1023 /// Invalidates pointers if additional memory is needed.
1028 /// Invalidates element pointers if additional memory is needed.
10241029 pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void {
10251030 if (@sizeOf(T) == 0) {
10261031 self.capacity = math.maxInt(usize);
......@@ -1047,7 +1052,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10471052 }
10481053
10491054 /// Modify the array so that it can hold at least `additional_count` **more** items.
1050 /// Invalidates pointers if additional memory is needed.
1055 /// Invalidates element pointers if additional memory is needed.
10511056 pub fn ensureUnusedCapacity(
10521057 self: *Self,
10531058 allocator: Allocator,
......@@ -1058,13 +1063,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10581063
10591064 /// Increases the array's length to match the full capacity that is already allocated.
10601065 /// The new elements have `undefined` values.
1061 /// Does not invalidate pointers.
1066 /// Never invalidates element pointers.
10621067 pub fn expandToCapacity(self: *Self) void {
10631068 self.items.len = self.capacity;
10641069 }
10651070
10661071 /// Increase length by 1, returning pointer to the new item.
1067 /// The returned pointer becomes invalid when the list resized.
1072 /// The returned element pointer becomes invalid when the list is resized.
10681073 pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T {
10691074 const newlen = try addOrOom(self.items.len, 1);
10701075 try self.ensureTotalCapacity(allocator, newlen);
......@@ -1072,9 +1077,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10721077 }
10731078
10741079 /// Increase length by 1, returning pointer to the new item.
1075 /// **Does not** invalidate pointers.
1076 /// The returned pointer becomes invalid when the list resized.
1077 /// **Asserts that the list can hold one additional item.**
1080 /// Never invalidates element pointers.
1081 /// The returned element pointer becomes invalid when the list is resized.
1082 /// Asserts that the list can hold one additional item.
10781083 pub fn addOneAssumeCapacity(self: *Self) *T {
10791084 assert(self.items.len < self.capacity);
10801085
......@@ -1093,9 +1098,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10931098
10941099 /// Resize the array, adding `n` new elements, which have `undefined` values.
10951100 /// The return value is an array pointing to the newly allocated elements.
1096 /// **Does not** invalidate pointers.
1101 /// Never invalidates element pointers.
10971102 /// The returned pointer becomes invalid when the list is resized.
1098 /// **Asserts that the list can hold `n` additional items.**
1103 /// Asserts that the list can hold the additional items.
10991104 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
11001105 assert(self.items.len + n <= self.capacity);
11011106 const prev_len = self.items.len;
......@@ -1115,9 +1120,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
11151120
11161121 /// Resize the array, adding `n` new elements, which have `undefined` values.
11171122 /// The return value is a slice pointing to the newly allocated elements.
1118 /// Does not invalidate element pointers.
1123 /// Never invalidates element pointers.
11191124 /// The returned pointer becomes invalid when the list is resized.
1120 /// **Asserts that the list can hold `n` additional items.**
1125 /// Asserts that the list can hold the additional items.
11211126 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
11221127 assert(self.items.len + n <= self.capacity);
11231128 const prev_len = self.items.len;
......@@ -1127,7 +1132,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
11271132
11281133 /// Remove and return the last element from the list.
11291134 /// Invalidates pointers to last element.
1130 /// **Asserts that the list is not empty.**
1135 /// Asserts that the list is not empty.
11311136 pub fn pop(self: *Self) T {
11321137 const val = self.items[self.items.len - 1];
11331138 self.items.len -= 1;
......@@ -1157,7 +1162,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
11571162 }
11581163
11591164 /// Return the last element from the list.
1160 /// **Asserts that the list is not empty.**
1165 /// Asserts that the list is not empty.
11611166 pub fn getLast(self: Self) T {
11621167 const val = self.items[self.items.len - 1];
11631168 return val;
......@@ -1183,12 +1188,11 @@ fn growCapacity(current: usize, minimum: usize) usize {
11831188 }
11841189}
11851190
1186/// Adds a and b, returning `error.OutOfMemory` if overflow occurred.
1187/// This is equivalent to `math.add`. See #18467 for why it is used.
1191/// Integer addition returning `error.OutOfMemory` on overflow.
11881192fn addOrOom(a: usize, b: usize) error{OutOfMemory}!usize {
1189 const ov = @addWithOverflow(a, b);
1190 if (ov[1] != 0) return error.OutOfMemory;
1191 return ov[0];
1193 const result, const overflow = @addWithOverflow(a, b);
1194 if (overflow != 0) return error.OutOfMemory;
1195 return result;
11921196}
11931197
11941198test "std.ArrayList/ArrayListUnmanaged.init" {
......@@ -1985,47 +1989,49 @@ test "std.ArrayList(u32).getLastOrNull()" {
19851989}
19861990
19871991test "return OutOfMemory when capacity would exceed maximum usize integer value" {
1988 // Because a portable way to create maxInt(usize)-sized slices does not seem to exist yet, this
1989 // will have to do.
1990
19911992 const a = testing.allocator;
1993 const new_item: u32 = 42;
19921994
1993 var alu = ArrayListUnmanaged(u32){
1994 .items = undefined,
1995 .capacity = math.maxInt(usize),
1996 };
1997 alu.items.len = math.maxInt(usize);
1998
1999 try testing.expectError(error.OutOfMemory, alu.append(a, undefined));
2000 try testing.expectError(error.OutOfMemory, alu.appendSlice(a, &.{undefined}));
2001 try testing.expectError(error.OutOfMemory, alu.appendNTimes(a, undefined, 1));
2002 try testing.expectError(error.OutOfMemory, alu.appendUnalignedSlice(a, &.{undefined}));
2003 try testing.expectError(error.OutOfMemory, alu.addOne(a));
2004 try testing.expectError(error.OutOfMemory, alu.addManyAt(a, 0, 1));
2005 try testing.expectError(error.OutOfMemory, alu.addManyAsArray(a, 1));
2006 try testing.expectError(error.OutOfMemory, alu.addManyAsSlice(a, 1));
2007 try testing.expectError(error.OutOfMemory, alu.insert(a, 0, undefined));
2008 try testing.expectError(error.OutOfMemory, alu.insertSlice(a, 0, &.{undefined}));
2009 try testing.expectError(error.OutOfMemory, alu.toOwnedSliceSentinel(a, 0));
2010 try testing.expectError(error.OutOfMemory, alu.ensureUnusedCapacity(a, 1));
2011
2012 var al = ArrayList(u32){
2013 .items = undefined,
2014 .capacity = math.maxInt(usize),
2015 .allocator = a,
2016 };
2017 al.items.len = math.maxInt(usize);
2018
2019 try testing.expectError(error.OutOfMemory, al.append(undefined));
2020 try testing.expectError(error.OutOfMemory, al.appendSlice(&.{undefined}));
2021 try testing.expectError(error.OutOfMemory, al.appendNTimes(undefined, 1));
2022 try testing.expectError(error.OutOfMemory, al.appendUnalignedSlice(&.{undefined}));
2023 try testing.expectError(error.OutOfMemory, al.addOne());
2024 try testing.expectError(error.OutOfMemory, al.addManyAt(0, 1));
2025 try testing.expectError(error.OutOfMemory, al.addManyAsArray(1));
2026 try testing.expectError(error.OutOfMemory, al.addManyAsSlice(1));
2027 try testing.expectError(error.OutOfMemory, al.insert(0, undefined));
2028 try testing.expectError(error.OutOfMemory, al.insertSlice(0, &.{undefined}));
2029 try testing.expectError(error.OutOfMemory, al.toOwnedSliceSentinel(0));
2030 try testing.expectError(error.OutOfMemory, al.ensureUnusedCapacity(1));
1995 {
1996 var list: ArrayListUnmanaged(u32) = .{
1997 .items = undefined,
1998 .capacity = math.maxInt(usize),
1999 };
2000 list.items.len = math.maxInt(usize);
2001
2002 try testing.expectError(error.OutOfMemory, list.append(a, new_item));
2003 try testing.expectError(error.OutOfMemory, list.appendSlice(a, &.{new_item}));
2004 try testing.expectError(error.OutOfMemory, list.appendNTimes(a, new_item, 1));
2005 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(a, &.{new_item}));
2006 try testing.expectError(error.OutOfMemory, list.addOne(a));
2007 try testing.expectError(error.OutOfMemory, list.addManyAt(a, 0, 1));
2008 try testing.expectError(error.OutOfMemory, list.addManyAsArray(a, 1));
2009 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(a, 1));
2010 try testing.expectError(error.OutOfMemory, list.insert(a, 0, new_item));
2011 try testing.expectError(error.OutOfMemory, list.insertSlice(a, 0, &.{new_item}));
2012 try testing.expectError(error.OutOfMemory, list.toOwnedSliceSentinel(a, 0));
2013 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(a, 1));
2014 }
2015
2016 {
2017 var list: ArrayList(u32) = .{
2018 .items = undefined,
2019 .capacity = math.maxInt(usize),
2020 .allocator = a,
2021 };
2022 list.items.len = math.maxInt(usize);
2023
2024 try testing.expectError(error.OutOfMemory, list.append(new_item));
2025 try testing.expectError(error.OutOfMemory, list.appendSlice(&.{new_item}));
2026 try testing.expectError(error.OutOfMemory, list.appendNTimes(new_item, 1));
2027 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(&.{new_item}));
2028 try testing.expectError(error.OutOfMemory, list.addOne());
2029 try testing.expectError(error.OutOfMemory, list.addManyAt(0, 1));
2030 try testing.expectError(error.OutOfMemory, list.addManyAsArray(1));
2031 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(1));
2032 try testing.expectError(error.OutOfMemory, list.insert(0, new_item));
2033 try testing.expectError(error.OutOfMemory, list.insertSlice(0, &.{new_item}));
2034 try testing.expectError(error.OutOfMemory, list.toOwnedSliceSentinel(0));
2035 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(1));
2036 }
20312037}