| ... | @@ -10,7 +10,7 @@ const Allocator = mem.Allocator; | ... | @@ -10,7 +10,7 @@ const Allocator = mem.Allocator; |
| 10 | /// This is a wrapper around an array of T values. Initialize with `init`. | 10 | /// This is a wrapper around an array of T values. Initialize with `init`. |
| 11 | /// | 11 | /// |
| 12 | /// This struct internally stores a `std.mem.Allocator` for memory management. | 12 | /// 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`. |
| 14 | pub fn ArrayList(comptime T: type) type { | 14 | pub fn ArrayList(comptime T: type) type { |
| 15 | return ArrayListAligned(T, null); | 15 | return ArrayListAligned(T, null); |
| 16 | } | 16 | } |
| ... | @@ -21,7 +21,7 @@ pub fn ArrayList(comptime T: type) type { | ... | @@ -21,7 +21,7 @@ pub fn ArrayList(comptime T: type) type { |
| 21 | /// Initialize with `init`. | 21 | /// Initialize with `init`. |
| 22 | /// | 22 | /// |
| 23 | /// This struct internally stores a `std.mem.Allocator` for memory management. | 23 | /// 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`. |
| 25 | pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | 25 | pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 26 | if (alignment) |a| { | 26 | if (alignment) |a| { |
| 27 | if (a == @alignOf(T)) { | 27 | if (a == @alignOf(T)) { |
| ... | @@ -30,15 +30,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -30,15 +30,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 30 | } | 30 | } |
| 31 | return struct { | 31 | return struct { |
| 32 | const Self = @This(); | 32 | const Self = @This(); |
| 33 | /// Contents of the list. Pointers to elements in this slice are | 33 | /// Contents of the list. This field is intended to be accessed |
| 34 | /// **invalid after resizing operations** on the ArrayList unless the | 34 | /// directly. |
| 35 | /// operation explicitly either: (1) states otherwise or (2) lists the | | |
| 36 | /// invalidated pointers. | | |
| 37 | /// | 35 | /// |
| 38 | /// The allocator used determines how element pointers are | 36 | /// Pointers to elements in this slice are invalidated by various |
| 39 | /// invalidated, so the behavior may vary between lists. To avoid | 37 | /// functions of this ArrayList in accordance with the respective |
| 40 | /// illegal behavior, take into account the above paragraph plus the | 38 | /// documentation. In all cases, "invalidated" means that the memory |
| 41 | /// explicit statements given in each method. | 39 | /// has been passed to this allocator's resize or free function. |
| 42 | items: Slice, | 40 | items: Slice, |
| 43 | /// How many T values this list can hold without allocating | 41 | /// How many T values this list can hold without allocating |
| 44 | /// additional memory. | 42 | /// additional memory. |
| ... | @@ -144,18 +142,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -144,18 +142,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 144 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | 142 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 145 | /// If `i` is equal to the length of the list this operation is equivalent to append. | 143 | /// If `i` is equal to the length of the list this operation is equivalent to append. |
| 146 | /// This operation is O(N). | 144 | /// This operation is O(N). |
| 147 | /// Invalidates pointers if additional memory is needed. | 145 | /// Invalidates element pointers if additional memory is needed. |
| 148 | /// **Asserts that `i <= self.items.len`.** | 146 | /// Asserts that the index is in bounds or equal to the length. |
| 149 | pub fn insert(self: *Self, i: usize, item: T) Allocator.Error!void { | 147 | pub fn insert(self: *Self, i: usize, item: T) Allocator.Error!void { |
| 150 | const dst = try self.addManyAt(i, 1); | 148 | const dst = try self.addManyAt(i, 1); |
| 151 | dst[0] = item; | 149 | dst[0] = item; |
| 152 | } | 150 | } |
| 153 | | 151 | |
| 154 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | 152 | /// 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. |
| 156 | /// This operation is O(N). | 155 | /// This operation is O(N). |
| 157 | /// **Asserts that `i <= self.items.len`.** | 156 | /// Asserts that there is enough capacity for the new item. |
| 158 | /// **Asserts that `self.items.len < self.capacity` .** | 157 | /// Asserts that the index is in bounds or equal to the length. |
| 159 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | 158 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| 160 | assert(self.items.len < self.capacity); | 159 | assert(self.items.len < self.capacity); |
| 161 | self.items.len += 1; | 160 | self.items.len += 1; |
| ... | @@ -171,7 +170,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -171,7 +170,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 171 | /// Invalidates pre-existing pointers to elements at and after `index`. | 170 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 172 | /// Invalidates all pre-existing element pointers if capacity must be | 171 | /// Invalidates all pre-existing element pointers if capacity must be |
| 173 | /// increased to accomodate the new elements. | 172 | /// 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. |
| 175 | pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T { | 174 | pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T { |
| 176 | const new_len = try addOrOom(self.items.len, count); | 175 | const new_len = try addOrOom(self.items.len, count); |
| 177 | | 176 | |
| ... | @@ -208,10 +207,10 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -208,10 +207,10 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 208 | /// `undefined` values. Returns a slice pointing to the newly allocated | 207 | /// `undefined` values. Returns a slice pointing to the newly allocated |
| 209 | /// elements, which becomes invalid after various `ArrayList` | 208 | /// elements, which becomes invalid after various `ArrayList` |
| 210 | /// operations. | 209 | /// operations. |
| | 210 | /// Asserts that there is enough capacity for the new elements. |
| 211 | /// Invalidates pre-existing pointers to elements at and after `index`, but | 211 | /// Invalidates pre-existing pointers to elements at and after `index`, but |
| 212 | /// does not invalidate any before that. | 212 | /// does not invalidate any before that. |
| 213 | /// **Asserts that `index <= self.items.len`.** | 213 | /// Asserts that the index is in bounds or equal to the length. |
| 214 | /// **Asserts that the list can hold `count` additional items.** | | |
| 215 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { | 214 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 216 | const new_len = self.items.len + count; | 215 | const new_len = self.items.len + count; |
| 217 | assert(self.capacity >= new_len); | 216 | assert(self.capacity >= new_len); |
| ... | @@ -228,7 +227,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -228,7 +227,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 228 | /// Invalidates pre-existing pointers to elements at and after `index`. | 227 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 229 | /// Invalidates all pre-existing element pointers if capacity must be | 228 | /// Invalidates all pre-existing element pointers if capacity must be |
| 230 | /// increased to accomodate the new elements. | 229 | /// 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. |
| 232 | pub fn insertSlice( | 231 | pub fn insertSlice( |
| 233 | self: *Self, | 232 | self: *Self, |
| 234 | index: usize, | 233 | index: usize, |
| ... | @@ -241,8 +240,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -241,8 +240,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 241 | /// Replace range of elements `list[start..][0..len]` with `new_items`. | 240 | /// Replace range of elements `list[start..][0..len]` with `new_items`. |
| 242 | /// Grows list if `len < new_items.len`. | 241 | /// Grows list if `len < new_items.len`. |
| 243 | /// Shrinks list if `len > new_items.len`. | 242 | /// Shrinks list if `len > new_items.len`. |
| 244 | /// Invalidates pointers if this ArrayList is resized. | 243 | /// Invalidates element pointers if this ArrayList is resized. |
| 245 | /// **Asserts that `start <= self.items.len`.** | 244 | /// Asserts that the start index is in bounds or equal to the length. |
| 246 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void { | 245 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void { |
| 247 | const after_range = try addOrOom(start, len); | 246 | const after_range = try addOrOom(start, len); |
| 248 | const range = self.items[start..after_range]; | 247 | const range = self.items[start..after_range]; |
| ... | @@ -268,15 +267,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -268,15 +267,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 268 | } | 267 | } |
| 269 | | 268 | |
| 270 | /// Extends the list by 1 element. Allocates more memory as necessary. | 269 | /// 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. |
| 272 | pub fn append(self: *Self, item: T) Allocator.Error!void { | 271 | pub fn append(self: *Self, item: T) Allocator.Error!void { |
| 273 | const new_item_ptr = try self.addOne(); | 272 | const new_item_ptr = try self.addOne(); |
| 274 | new_item_ptr.* = item; | 273 | new_item_ptr.* = item; |
| 275 | } | 274 | } |
| 276 | | 275 | |
| 277 | /// Extends the list by 1 element. Does not | 276 | /// Extends the list by 1 element. |
| 278 | /// invalidate pointers. | 277 | /// Never invalidates element pointers. |
| 279 | /// **Asserts that the list can hold one additional item.** | 278 | /// Asserts that the list can hold one additional item. |
| 280 | pub fn appendAssumeCapacity(self: *Self, item: T) void { | 279 | pub fn appendAssumeCapacity(self: *Self, item: T) void { |
| 281 | const new_item_ptr = self.addOneAssumeCapacity(); | 280 | const new_item_ptr = self.addOneAssumeCapacity(); |
| 282 | new_item_ptr.* = item; | 281 | new_item_ptr.* = item; |
| ... | @@ -284,11 +283,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -284,11 +283,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 284 | | 283 | |
| 285 | /// Remove the element at index `i`, shift elements after index | 284 | /// Remove the element at index `i`, shift elements after index |
| 286 | /// `i` forward, and return the removed element. | 285 | /// `i` forward, and return the removed element. |
| 287 | /// Invalidates pointers to end of list. | 286 | /// Invalidates element pointers to end of list. |
| 288 | /// This operation is O(N). | 287 | /// This operation is O(N). |
| 289 | /// This preserves item order. Use `swapRemove` if order preservation is not important. | 288 | /// This preserves item order. Use `swapRemove` if order preservation is not important. |
| 290 | /// **Asserts that `i < self.items.len`.** | 289 | /// Asserts that the index is in bounds. |
| 291 | /// **Asserts that the list is not empty.** | 290 | /// Asserts that the list is not empty. |
| 292 | pub fn orderedRemove(self: *Self, i: usize) T { | 291 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 293 | const newlen = self.items.len - 1; | 292 | const newlen = self.items.len - 1; |
| 294 | if (newlen == i) return self.pop(); | 293 | if (newlen == i) return self.pop(); |
| ... | @@ -304,8 +303,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -304,8 +303,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 304 | /// The empty slot is filled from the end of the list. | 303 | /// The empty slot is filled from the end of the list. |
| 305 | /// This operation is O(1). | 304 | /// This operation is O(1). |
| 306 | /// This may not preserve item order. Use `orderedRemove` if you need to preserve order. | 305 | /// This may not preserve item order. Use `orderedRemove` if you need to preserve order. |
| 307 | /// **Asserts that `i < self.items.len`.** | 306 | /// Asserts that the list is not empty. |
| 308 | /// **Asserts that the list is not empty.** | 307 | /// Asserts that the index is in bounds. |
| 309 | pub fn swapRemove(self: *Self, i: usize) T { | 308 | pub fn swapRemove(self: *Self, i: usize) T { |
| 310 | if (self.items.len - 1 == i) return self.pop(); | 309 | if (self.items.len - 1 == i) return self.pop(); |
| 311 | | 310 | |
| ... | @@ -316,14 +315,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -316,14 +315,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 316 | | 315 | |
| 317 | /// Append the slice of items to the list. Allocates more | 316 | /// Append the slice of items to the list. Allocates more |
| 318 | /// memory as necessary. | 317 | /// memory as necessary. |
| 319 | /// Invalidates pointers if additional memory is needed. | 318 | /// Invalidates element pointers if additional memory is needed. |
| 320 | pub fn appendSlice(self: *Self, items: []const T) Allocator.Error!void { | 319 | pub fn appendSlice(self: *Self, items: []const T) Allocator.Error!void { |
| 321 | try self.ensureUnusedCapacity(items.len); | 320 | try self.ensureUnusedCapacity(items.len); |
| 322 | self.appendSliceAssumeCapacity(items); | 321 | self.appendSliceAssumeCapacity(items); |
| 323 | } | 322 | } |
| 324 | | 323 | |
| 325 | /// Append the slice of items to the list. Does not invalidate pointers. | 324 | /// Append the slice of items to the list. |
| 326 | /// **Asserts that the list can hold `items.len` additional items.** | 325 | /// Never invalidates element pointers. |
| | 326 | /// Asserts that the list can hold the additional items. |
| 327 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { | 327 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 328 | const old_len = self.items.len; | 328 | const old_len = self.items.len; |
| 329 | const new_len = old_len + items.len; | 329 | const new_len = old_len + items.len; |
| ... | @@ -335,16 +335,18 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -335,16 +335,18 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 335 | /// Append an unaligned slice of items to the list. Allocates more | 335 | /// Append an unaligned slice of items to the list. Allocates more |
| 336 | /// memory as necessary. Only call this function if calling | 336 | /// memory as necessary. Only call this function if calling |
| 337 | /// `appendSlice` instead would be a compile error. | 337 | /// `appendSlice` instead would be a compile error. |
| 338 | /// Invalidates pointers if additional memory is needed. | 338 | /// Invalidates element pointers if additional memory is needed. |
| 339 | pub fn appendUnalignedSlice(self: *Self, items: []align(1) const T) Allocator.Error!void { | 339 | pub fn appendUnalignedSlice(self: *Self, items: []align(1) const T) Allocator.Error!void { |
| 340 | try self.ensureUnusedCapacity(items.len); | 340 | try self.ensureUnusedCapacity(items.len); |
| 341 | self.appendUnalignedSliceAssumeCapacity(items); | 341 | self.appendUnalignedSliceAssumeCapacity(items); |
| 342 | } | 342 | } |
| 343 | | 343 | |
| 344 | /// Append the slice of items to the list. **Does not** invalidate pointers. | 344 | /// Append the slice of items to the list. |
| 345 | /// Only call this function if calling `appendSliceAssumeCapacity` instead | 345 | /// Never invalidates element pointers. |
| 346 | /// would be a compile error. | 346 | /// This function is only needed when calling |
| 347 | /// **Asserts that the list can hold `items.len` additional items.** | 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. |
| 348 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { | 350 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { |
| 349 | const old_len = self.items.len; | 351 | const old_len = self.items.len; |
| 350 | const new_len = old_len + items.len; | 352 | const new_len = old_len + items.len; |
| ... | @@ -366,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -366,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 366 | | 368 | |
| 367 | /// Same as `append` except it returns the number of bytes written, which is always the same | 369 | /// Same as `append` except it returns the number of bytes written, which is always the same |
| 368 | /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API. | 370 | /// 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. |
| 370 | fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize { | 372 | fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize { |
| 371 | try self.appendSlice(m); | 373 | try self.appendSlice(m); |
| 372 | return m.len; | 374 | return m.len; |
| ... | @@ -374,20 +376,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -374,20 +376,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 374 | | 376 | |
| 375 | /// Append a value to the list `n` times. | 377 | /// Append a value to the list `n` times. |
| 376 | /// Allocates more memory as necessary. | 378 | /// Allocates more memory as necessary. |
| 377 | /// Invalidates pointers if additional memory is needed. | 379 | /// Invalidates element pointers if additional memory is needed. |
| 378 | /// The function is inline so that a comptime-known `value` parameter will | 380 | /// The function is inline so that a comptime-known `value` parameter will |
| 379 | /// have a more optimal memset codegen in case it has a repeated byte pattern. | 381 | /// have a more optimal memset codegen in case it has a repeated byte pattern. |
| 380 | pub inline fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void { | 382 | pub inline fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void { |
| 381 | const old_len = self.items.len; | 383 | 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)); |
| 383 | @memset(self.items[old_len..self.items.len], value); | 385 | @memset(self.items[old_len..self.items.len], value); |
| 384 | } | 386 | } |
| 385 | | 387 | |
| 386 | /// Append a value to the list `n` times. | 388 | /// Append a value to the list `n` times. |
| 387 | /// Does not invalidate pointers. | 389 | /// Never invalidates element pointers. |
| 388 | /// The function is inline so that a comptime-known `value` parameter will | 390 | /// The function is inline so that a comptime-known `value` parameter will |
| 389 | /// have a more optimal memset codegen in case it has a repeated byte pattern. | 391 | /// 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. |
| 391 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { | 393 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { |
| 392 | const new_len = self.items.len + n; | 394 | const new_len = self.items.len + n; |
| 393 | assert(new_len <= self.capacity); | 395 | assert(new_len <= self.capacity); |
| ... | @@ -395,9 +397,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -395,9 +397,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 395 | self.items.len = new_len; | 397 | self.items.len = new_len; |
| 396 | } | 398 | } |
| 397 | | 399 | |
| 398 | /// Adjust the list's length to `new_len`. | 400 | /// Adjust the list length to `new_len`. |
| 399 | /// Does not initialize added items if any. | 401 | /// Additional elements contain the value `undefined`. |
| 400 | /// Invalidates pointers if additional memory is needed. | 402 | /// Invalidates element pointers if additional memory is needed. |
| 401 | pub fn resize(self: *Self, new_len: usize) Allocator.Error!void { | 403 | pub fn resize(self: *Self, new_len: usize) Allocator.Error!void { |
| 402 | try self.ensureTotalCapacity(new_len); | 404 | try self.ensureTotalCapacity(new_len); |
| 403 | self.items.len = new_len; | 405 | self.items.len = new_len; |
| ... | @@ -405,7 +407,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -405,7 +407,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 405 | | 407 | |
| 406 | /// Reduce allocated capacity to `new_len`. | 408 | /// Reduce allocated capacity to `new_len`. |
| 407 | /// May invalidate element pointers. | 409 | /// 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. |
| 409 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { | 411 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 410 | var unmanaged = self.moveToUnmanaged(); | 412 | var unmanaged = self.moveToUnmanaged(); |
| 411 | unmanaged.shrinkAndFree(self.allocator, new_len); | 413 | unmanaged.shrinkAndFree(self.allocator, new_len); |
| ... | @@ -413,8 +415,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -413,8 +415,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 413 | } | 415 | } |
| 414 | | 416 | |
| 415 | /// Reduce length to `new_len`. | 417 | /// Reduce length to `new_len`. |
| 416 | /// Invalidates pointers for the elements `items[new_len..]`. | 418 | /// Invalidates element pointers for the elements `items[new_len..]`. |
| 417 | /// **Asserts that `new_len <= self.items.len`.** | 419 | /// Asserts that the new length is less than or equal to the previous length. |
| 418 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | 420 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 419 | assert(new_len <= self.items.len); | 421 | assert(new_len <= self.items.len); |
| 420 | self.items.len = new_len; | 422 | self.items.len = new_len; |
| ... | @@ -434,7 +436,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -434,7 +436,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 434 | | 436 | |
| 435 | /// If the current capacity is less than `new_capacity`, this function will | 437 | /// If the current capacity is less than `new_capacity`, this function will |
| 436 | /// modify the array so that it can hold at least `new_capacity` items. | 438 | /// 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. |
| 438 | pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) Allocator.Error!void { | 440 | pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) Allocator.Error!void { |
| 439 | if (@sizeOf(T) == 0) { | 441 | if (@sizeOf(T) == 0) { |
| 440 | self.capacity = math.maxInt(usize); | 442 | self.capacity = math.maxInt(usize); |
| ... | @@ -449,7 +451,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -449,7 +451,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 449 | | 451 | |
| 450 | /// If the current capacity is less than `new_capacity`, this function will | 452 | /// If the current capacity is less than `new_capacity`, this function will |
| 451 | /// modify the array so that it can hold exactly `new_capacity` items. | 453 | /// 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. |
| 453 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void { | 455 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void { |
| 454 | if (@sizeOf(T) == 0) { | 456 | if (@sizeOf(T) == 0) { |
| 455 | self.capacity = math.maxInt(usize); | 457 | self.capacity = math.maxInt(usize); |
| ... | @@ -476,13 +478,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -476,13 +478,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 476 | } | 478 | } |
| 477 | | 479 | |
| 478 | /// Modify the array so that it can hold at least `additional_count` **more** items. | 480 | /// 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. |
| 480 | pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) Allocator.Error!void { | 482 | pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) Allocator.Error!void { |
| 481 | return self.ensureTotalCapacity(try addOrOom(self.items.len, additional_count)); | 483 | return self.ensureTotalCapacity(try addOrOom(self.items.len, additional_count)); |
| 482 | } | 484 | } |
| 483 | | 485 | |
| 484 | /// Increases the array's length to match the full capacity that is already allocated. | 486 | /// 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. |
| 486 | pub fn expandToCapacity(self: *Self) void { | 489 | pub fn expandToCapacity(self: *Self) void { |
| 487 | self.items.len = self.capacity; | 490 | self.items.len = self.capacity; |
| 488 | } | 491 | } |
| ... | @@ -496,8 +499,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -496,8 +499,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 496 | | 499 | |
| 497 | /// Increase length by 1, returning pointer to the new item. | 500 | /// Increase length by 1, returning pointer to the new item. |
| 498 | /// The returned pointer becomes invalid when the list is resized. | 501 | /// The returned pointer becomes invalid when the list is resized. |
| 499 | /// Does not invalidate element pointers. | 502 | /// Never invalidates element pointers. |
| 500 | /// **Asserts that the list can hold one additional item.** | 503 | /// Asserts that the list can hold one additional item. |
| 501 | pub fn addOneAssumeCapacity(self: *Self) *T { | 504 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 502 | assert(self.items.len < self.capacity); | 505 | assert(self.items.len < self.capacity); |
| 503 | self.items.len += 1; | 506 | self.items.len += 1; |
| ... | @@ -516,9 +519,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -516,9 +519,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 516 | | 519 | |
| 517 | /// Resize the array, adding `n` new elements, which have `undefined` values. | 520 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 518 | /// The return value is an array pointing to the newly allocated elements. | 521 | /// The return value is an array pointing to the newly allocated elements. |
| 519 | /// Does not invalidate element pointers. | 522 | /// Never invalidates element pointers. |
| 520 | /// The returned pointer becomes invalid when the list is resized. | 523 | /// 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. |
| 522 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { | 525 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 523 | assert(self.items.len + n <= self.capacity); | 526 | assert(self.items.len + n <= self.capacity); |
| 524 | const prev_len = self.items.len; | 527 | const prev_len = self.items.len; |
| ... | @@ -538,9 +541,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -538,9 +541,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 538 | | 541 | |
| 539 | /// Resize the array, adding `n` new elements, which have `undefined` values. | 542 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 540 | /// The return value is a slice pointing to the newly allocated elements. | 543 | /// The return value is a slice pointing to the newly allocated elements. |
| 541 | /// Does not invalidate element pointers. | 544 | /// Never invalidates element pointers. |
| 542 | /// The returned pointer becomes invalid when the list is resized. | 545 | /// 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. |
| 544 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { | 547 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 545 | assert(self.items.len + n <= self.capacity); | 548 | assert(self.items.len + n <= self.capacity); |
| 546 | const prev_len = self.items.len; | 549 | const prev_len = self.items.len; |
| ... | @@ -549,8 +552,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -549,8 +552,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 549 | } | 552 | } |
| 550 | | 553 | |
| 551 | /// Remove and return the last element from the list. | 554 | /// Remove and return the last element from the list. |
| 552 | /// Invalidates pointers to the removed element. | 555 | /// Invalidates element pointers to the removed element. |
| 553 | /// **Asserts that the list is not empty.** | 556 | /// Asserts that the list is not empty. |
| 554 | pub fn pop(self: *Self) T { | 557 | pub fn pop(self: *Self) T { |
| 555 | const val = self.items[self.items.len - 1]; | 558 | const val = self.items[self.items.len - 1]; |
| 556 | self.items.len -= 1; | 559 | self.items.len -= 1; |
| ... | @@ -559,7 +562,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -559,7 +562,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 559 | | 562 | |
| 560 | /// Remove and return the last element from the list, or | 563 | /// Remove and return the last element from the list, or |
| 561 | /// return `null` if list is empty. | 564 | /// 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. |
| 563 | pub fn popOrNull(self: *Self) ?T { | 566 | pub fn popOrNull(self: *Self) ?T { |
| 564 | if (self.items.len == 0) return null; | 567 | if (self.items.len == 0) return null; |
| 565 | return self.pop(); | 568 | return self.pop(); |
| ... | @@ -581,7 +584,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -581,7 +584,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 581 | } | 584 | } |
| 582 | | 585 | |
| 583 | /// Returns the last element from the list. | 586 | /// Returns the last element from the list. |
| 584 | /// **Asserts that the list is not empty.** | 587 | /// Asserts that the list is not empty. |
| 585 | pub fn getLast(self: Self) T { | 588 | pub fn getLast(self: Self) T { |
| 586 | const val = self.items[self.items.len - 1]; | 589 | const val = self.items[self.items.len - 1]; |
| 587 | return val; | 590 | return val; |
| ... | @@ -596,17 +599,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -596,17 +599,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 596 | } | 599 | } |
| 597 | | 600 | |
| 598 | /// An ArrayList, but the allocator is passed as a parameter to the relevant functions | 601 | /// 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 |
| 600 | /// the entire lifetime of an ArrayListUnmanaged. Initialize directly or with | 603 | /// the entire lifetime of an ArrayListUnmanaged. Initialize directly or with |
| 601 | /// `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`. | 604 | /// `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`. |
| 602 | pub fn ArrayListUnmanaged(comptime T: type) type { | 605 | pub fn ArrayListUnmanaged(comptime T: type) type { |
| 603 | return ArrayListAlignedUnmanaged(T, null); | 606 | return ArrayListAlignedUnmanaged(T, null); |
| 604 | } | 607 | } |
| 605 | | 608 | |
| 606 | /// An ArrayListAligned, but the allocator is passed as a parameter to the relevant | 609 | /// A contiguous, growable list of arbitrarily aligned items in memory. |
| 607 | /// functions rather than stored in the struct itself. The same allocator **must** | 610 | /// This is a wrapper around an array of T values aligned to `alignment`-byte |
| 608 | /// be used throughout the entire lifetime of an ArrayListAlignedUnmanaged. | 611 | /// addresses. If the specified alignment is `null`, then `@alignOf(T)` is used. |
| 609 | /// Initialize directly or with `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`. | 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`. |
| 610 | pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type { | 616 | pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type { |
| 611 | if (alignment) |a| { | 617 | if (alignment) |a| { |
| 612 | if (a == @alignOf(T)) { | 618 | if (a == @alignOf(T)) { |
| ... | @@ -615,15 +621,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -615,15 +621,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 615 | } | 621 | } |
| 616 | return struct { | 622 | return struct { |
| 617 | const Self = @This(); | 623 | const Self = @This(); |
| 618 | /// Contents of the list. Pointers to elements in this slice are | 624 | /// Contents of the list. This field is intended to be accessed |
| 619 | /// **invalid after resizing operations** on the ArrayList unless the | 625 | /// directly. |
| 620 | /// operation explicitly either: (1) states otherwise or (2) lists the | | |
| 621 | /// invalidated pointers. | | |
| 622 | /// | 626 | /// |
| 623 | /// The allocator used determines how element pointers are | 627 | /// Pointers to elements in this slice are invalidated by various |
| 624 | /// invalidated, so the behavior may vary between lists. To avoid | 628 | /// functions of this ArrayList in accordance with the respective |
| 625 | /// illegal behavior, take into account the above paragraph plus the | 629 | /// documentation. In all cases, "invalidated" means that the memory |
| 626 | /// explicit statements given in each method. | 630 | /// has been passed to an allocator's resize or free function. |
| 627 | items: Slice = &[_]T{}, | 631 | items: Slice = &[_]T{}, |
| 628 | /// How many T values this list can hold without allocating | 632 | /// How many T values this list can hold without allocating |
| 629 | /// additional memory. | 633 | /// additional memory. |
| ... | @@ -646,8 +650,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -646,8 +650,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 646 | | 650 | |
| 647 | /// Initialize with externally-managed memory. The buffer determines the | 651 | /// Initialize with externally-managed memory. The buffer determines the |
| 648 | /// capacity, and the length is set to zero. | 652 | /// capacity, and the length is set to zero. |
| 649 | /// **When initialized this way, all methods that accept an Allocator | 653 | /// When initialized this way, all functions that accept an Allocator |
| 650 | /// argument cause illegal behavior**. | 654 | /// argument cause illegal behavior. |
| 651 | pub fn initBuffer(buffer: Slice) Self { | 655 | pub fn initBuffer(buffer: Slice) Self { |
| 652 | return .{ | 656 | return .{ |
| 653 | .items = buffer[0..0], | 657 | .items = buffer[0..0], |
| ... | @@ -722,8 +726,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -722,8 +726,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 722 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | 726 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 723 | /// If `i` is equal to the length of the list this operation is equivalent to append. | 727 | /// If `i` is equal to the length of the list this operation is equivalent to append. |
| 724 | /// This operation is O(N). | 728 | /// This operation is O(N). |
| 725 | /// Invalidates pointers if additional memory is needed. | 729 | /// Invalidates element pointers if additional memory is needed. |
| 726 | /// **Asserts that `i < self.items.len`.** | 730 | /// Asserts that the index is in bounds or equal to the length. |
| 727 | pub fn insert(self: *Self, allocator: Allocator, i: usize, item: T) Allocator.Error!void { | 731 | pub fn insert(self: *Self, allocator: Allocator, i: usize, item: T) Allocator.Error!void { |
| 728 | const dst = try self.addManyAt(allocator, i, 1); | 732 | const dst = try self.addManyAt(allocator, i, 1); |
| 729 | dst[0] = item; | 733 | dst[0] = item; |
| ... | @@ -732,8 +736,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -732,8 +736,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 732 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | 736 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 733 | /// If in` is equal to the length of the list this operation is equivalent to append. | 737 | /// If in` is equal to the length of the list this operation is equivalent to append. |
| 734 | /// This operation is O(N). | 738 | /// This operation is O(N). |
| 735 | /// **Asserts that `i < self.items.len`.** | 739 | /// Asserts that the list has capacity for one additional item. |
| 736 | /// **Asserts that the list can hold one additional item.** | 740 | /// Asserts that the index is in bounds or equal to the length. |
| 737 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | 741 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| 738 | assert(self.items.len < self.capacity); | 742 | assert(self.items.len < self.capacity); |
| 739 | self.items.len += 1; | 743 | self.items.len += 1; |
| ... | @@ -749,7 +753,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -749,7 +753,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 749 | /// Invalidates pre-existing pointers to elements at and after `index`. | 753 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 750 | /// Invalidates all pre-existing element pointers if capacity must be | 754 | /// Invalidates all pre-existing element pointers if capacity must be |
| 751 | /// increased to accomodate the new elements. | 755 | /// 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. |
| 753 | pub fn addManyAt( | 757 | pub fn addManyAt( |
| 754 | self: *Self, | 758 | self: *Self, |
| 755 | allocator: Allocator, | 759 | allocator: Allocator, |
| ... | @@ -767,8 +771,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -767,8 +771,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 767 | /// operations. | 771 | /// operations. |
| 768 | /// Invalidates pre-existing pointers to elements at and after `index`, but | 772 | /// Invalidates pre-existing pointers to elements at and after `index`, but |
| 769 | /// does not invalidate any before that. | 773 | /// does not invalidate any before that. |
| 770 | /// **Asserts that `index <= self.items.len`.** | 774 | /// Asserts that the list has capacity for the additional items. |
| 771 | /// **Asserts that the list can hold `count` additional items.** | 775 | /// Asserts that the index is in bounds or equal to the length. |
| 772 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { | 776 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 773 | const new_len = self.items.len + count; | 777 | const new_len = self.items.len + count; |
| 774 | assert(self.capacity >= new_len); | 778 | assert(self.capacity >= new_len); |
| ... | @@ -785,7 +789,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -785,7 +789,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 785 | /// Invalidates pre-existing pointers to elements at and after `index`. | 789 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 786 | /// Invalidates all pre-existing element pointers if capacity must be | 790 | /// Invalidates all pre-existing element pointers if capacity must be |
| 787 | /// increased to accomodate the new elements. | 791 | /// 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. |
| 789 | pub fn insertSlice( | 793 | pub fn insertSlice( |
| 790 | self: *Self, | 794 | self: *Self, |
| 791 | allocator: Allocator, | 795 | allocator: Allocator, |
| ... | @@ -803,8 +807,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -803,8 +807,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 803 | /// Replace range of elements `list[start..][0..len]` with `new_items` | 807 | /// Replace range of elements `list[start..][0..len]` with `new_items` |
| 804 | /// Grows list if `len < new_items.len`. | 808 | /// Grows list if `len < new_items.len`. |
| 805 | /// Shrinks list if `len > new_items.len` | 809 | /// Shrinks list if `len > new_items.len` |
| 806 | /// Invalidates pointers if this ArrayList is resized. | 810 | /// Invalidates element pointers if this ArrayList is resized. |
| 807 | /// **Asserts that `start <= self.items.len`.** | 811 | /// Asserts that the start index is in bounds or equal to the length. |
| 808 | pub fn replaceRange( | 812 | pub fn replaceRange( |
| 809 | self: *Self, | 813 | self: *Self, |
| 810 | allocator: Allocator, | 814 | allocator: Allocator, |
| ... | @@ -818,14 +822,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -818,14 +822,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 818 | } | 822 | } |
| 819 | | 823 | |
| 820 | /// Extend the list by 1 element. Allocates more memory as necessary. | 824 | /// 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. |
| 822 | pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void { | 826 | pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void { |
| 823 | const new_item_ptr = try self.addOne(allocator); | 827 | const new_item_ptr = try self.addOne(allocator); |
| 824 | new_item_ptr.* = item; | 828 | new_item_ptr.* = item; |
| 825 | } | 829 | } |
| 826 | | 830 | |
| 827 | /// Extend the list by 1 element. | 831 | /// 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. |
| 829 | pub fn appendAssumeCapacity(self: *Self, item: T) void { | 834 | pub fn appendAssumeCapacity(self: *Self, item: T) void { |
| 830 | const new_item_ptr = self.addOneAssumeCapacity(); | 835 | const new_item_ptr = self.addOneAssumeCapacity(); |
| 831 | new_item_ptr.* = item; | 836 | new_item_ptr.* = item; |
| ... | @@ -834,8 +839,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -834,8 +839,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 834 | /// Remove the element at index `i` from the list and return its value. | 839 | /// Remove the element at index `i` from the list and return its value. |
| 835 | /// Invalidates pointers to the last element. | 840 | /// Invalidates pointers to the last element. |
| 836 | /// This operation is O(N). | 841 | /// This operation is O(N). |
| 837 | /// **Asserts that `i < self.items.len`.** | 842 | /// Asserts that the list is not empty. |
| 838 | /// **Asserts that the list is not empty.** | 843 | /// Asserts that the index is in bounds. |
| 839 | pub fn orderedRemove(self: *Self, i: usize) T { | 844 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 840 | const newlen = self.items.len - 1; | 845 | const newlen = self.items.len - 1; |
| 841 | if (newlen == i) return self.pop(); | 846 | if (newlen == i) return self.pop(); |
| ... | @@ -851,8 +856,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -851,8 +856,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 851 | /// The empty slot is filled from the end of the list. | 856 | /// The empty slot is filled from the end of the list. |
| 852 | /// Invalidates pointers to last element. | 857 | /// Invalidates pointers to last element. |
| 853 | /// This operation is O(1). | 858 | /// This operation is O(1). |
| 854 | /// **Asserts that `i < self.items.len`.** | 859 | /// Asserts that the list is not empty. |
| 855 | /// **Asserts that the list is not empty.** | 860 | /// Asserts that the index is in bounds. |
| 856 | pub fn swapRemove(self: *Self, i: usize) T { | 861 | pub fn swapRemove(self: *Self, i: usize) T { |
| 857 | if (self.items.len - 1 == i) return self.pop(); | 862 | if (self.items.len - 1 == i) return self.pop(); |
| 858 | | 863 | |
| ... | @@ -863,14 +868,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -863,14 +868,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 863 | | 868 | |
| 864 | /// Append the slice of items to the list. Allocates more | 869 | /// Append the slice of items to the list. Allocates more |
| 865 | /// memory as necessary. | 870 | /// memory as necessary. |
| 866 | /// Invalidates pointers if additional memory is needed. | 871 | /// Invalidates element pointers if additional memory is needed. |
| 867 | pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void { | 872 | pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void { |
| 868 | try self.ensureUnusedCapacity(allocator, items.len); | 873 | try self.ensureUnusedCapacity(allocator, items.len); |
| 869 | self.appendSliceAssumeCapacity(items); | 874 | self.appendSliceAssumeCapacity(items); |
| 870 | } | 875 | } |
| 871 | | 876 | |
| 872 | /// Append the slice of items to the list. | 877 | /// 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. |
| 874 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { | 879 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 875 | const old_len = self.items.len; | 880 | const old_len = self.items.len; |
| 876 | const new_len = old_len + items.len; | 881 | const new_len = old_len + items.len; |
| ... | @@ -882,7 +887,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -882,7 +887,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 882 | /// Append the slice of items to the list. Allocates more | 887 | /// Append the slice of items to the list. Allocates more |
| 883 | /// memory as necessary. Only call this function if a call to `appendSlice` instead would | 888 | /// memory as necessary. Only call this function if a call to `appendSlice` instead would |
| 884 | /// be a compile error. | 889 | /// be a compile error. |
| 885 | /// Invalidates pointers if additional memory is needed. | 890 | /// Invalidates element pointers if additional memory is needed. |
| 886 | pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void { | 891 | pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void { |
| 887 | try self.ensureUnusedCapacity(allocator, items.len); | 892 | try self.ensureUnusedCapacity(allocator, items.len); |
| 888 | self.appendUnalignedSliceAssumeCapacity(items); | 893 | self.appendUnalignedSliceAssumeCapacity(items); |
| ... | @@ -891,7 +896,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -891,7 +896,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 891 | /// Append an unaligned slice of items to the list. | 896 | /// Append an unaligned slice of items to the list. |
| 892 | /// Only call this function if a call to `appendSliceAssumeCapacity` | 897 | /// Only call this function if a call to `appendSliceAssumeCapacity` |
| 893 | /// instead would be a compile error. | 898 | /// 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. |
| 895 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { | 900 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { |
| 896 | const old_len = self.items.len; | 901 | const old_len = self.items.len; |
| 897 | const new_len = old_len + items.len; | 902 | const new_len = old_len + items.len; |
| ... | @@ -918,7 +923,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -918,7 +923,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 918 | | 923 | |
| 919 | /// Same as `append` except it returns the number of bytes written, which is always the same | 924 | /// Same as `append` except it returns the number of bytes written, which is always the same |
| 920 | /// as `m.len`. The purpose of this function existing is to match `std.io.Writer` API. | 925 | /// 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. |
| 922 | fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize { | 927 | fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize { |
| 923 | try context.self.appendSlice(context.allocator, m); | 928 | try context.self.appendSlice(context.allocator, m); |
| 924 | return m.len; | 929 | return m.len; |
| ... | @@ -926,20 +931,20 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -926,20 +931,20 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 926 | | 931 | |
| 927 | /// Append a value to the list `n` times. | 932 | /// Append a value to the list `n` times. |
| 928 | /// Allocates more memory as necessary. | 933 | /// Allocates more memory as necessary. |
| 929 | /// Invalidates pointers if additional memory is needed. | 934 | /// Invalidates element pointers if additional memory is needed. |
| 930 | /// The function is inline so that a comptime-known `value` parameter will | 935 | /// The function is inline so that a comptime-known `value` parameter will |
| 931 | /// have a more optimal memset codegen in case it has a repeated byte pattern. | 936 | /// have a more optimal memset codegen in case it has a repeated byte pattern. |
| 932 | pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void { | 937 | pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void { |
| 933 | const old_len = self.items.len; | 938 | 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)); |
| 935 | @memset(self.items[old_len..self.items.len], value); | 940 | @memset(self.items[old_len..self.items.len], value); |
| 936 | } | 941 | } |
| 937 | | 942 | |
| 938 | /// Append a value to the list `n` times. | 943 | /// Append a value to the list `n` times. |
| 939 | /// **Does not** invalidate pointers. | 944 | /// Never invalidates element pointers. |
| 940 | /// The function is inline so that a comptime-known `value` parameter will | 945 | /// The function is inline so that a comptime-known `value` parameter will |
| 941 | /// have better memset codegen in case it has a repeated byte pattern. | 946 | /// 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. |
| 943 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { | 948 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { |
| 944 | const new_len = self.items.len + n; | 949 | const new_len = self.items.len + n; |
| 945 | assert(new_len <= self.capacity); | 950 | assert(new_len <= self.capacity); |
| ... | @@ -947,9 +952,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -947,9 +952,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 947 | self.items.len = new_len; | 952 | self.items.len = new_len; |
| 948 | } | 953 | } |
| 949 | | 954 | |
| 950 | /// Adjust the list's length to `new_len`. | 955 | /// Adjust the list length to `new_len`. |
| 951 | /// Does not initialize added items, if any. | 956 | /// Additional elements contain the value `undefined`. |
| 952 | /// Invalidates pointers if additional memory is needed. | 957 | /// Invalidates element pointers if additional memory is needed. |
| 953 | pub fn resize(self: *Self, allocator: Allocator, new_len: usize) Allocator.Error!void { | 958 | pub fn resize(self: *Self, allocator: Allocator, new_len: usize) Allocator.Error!void { |
| 954 | try self.ensureTotalCapacity(allocator, new_len); | 959 | try self.ensureTotalCapacity(allocator, new_len); |
| 955 | self.items.len = new_len; | 960 | self.items.len = new_len; |
| ... | @@ -957,7 +962,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -957,7 +962,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 957 | | 962 | |
| 958 | /// Reduce allocated capacity to `new_len`. | 963 | /// Reduce allocated capacity to `new_len`. |
| 959 | /// May invalidate element pointers. | 964 | /// 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. |
| 961 | pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void { | 966 | pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void { |
| 962 | assert(new_len <= self.items.len); | 967 | assert(new_len <= self.items.len); |
| 963 | | 968 | |
| ... | @@ -990,7 +995,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -990,7 +995,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 990 | /// Reduce length to `new_len`. | 995 | /// Reduce length to `new_len`. |
| 991 | /// Invalidates pointers to elements `items[new_len..]`. | 996 | /// Invalidates pointers to elements `items[new_len..]`. |
| 992 | /// Keeps capacity the same. | 997 | /// 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. |
| 994 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | 999 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 995 | assert(new_len <= self.items.len); | 1000 | assert(new_len <= self.items.len); |
| 996 | self.items.len = new_len; | 1001 | self.items.len = new_len; |
| ... | @@ -1010,7 +1015,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1010,7 +1015,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1010 | | 1015 | |
| 1011 | /// If the current capacity is less than `new_capacity`, this function will | 1016 | /// If the current capacity is less than `new_capacity`, this function will |
| 1012 | /// modify the array so that it can hold at least `new_capacity` items. | 1017 | /// 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. |
| 1014 | pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { | 1019 | pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1015 | if (self.capacity >= new_capacity) return; | 1020 | if (self.capacity >= new_capacity) return; |
| 1016 | | 1021 | |
| ... | @@ -1020,7 +1025,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1020,7 +1025,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1020 | | 1025 | |
| 1021 | /// If the current capacity is less than `new_capacity`, this function will | 1026 | /// If the current capacity is less than `new_capacity`, this function will |
| 1022 | /// modify the array so that it can hold exactly `new_capacity` items. | 1027 | /// 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. |
| 1024 | pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { | 1029 | pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1025 | if (@sizeOf(T) == 0) { | 1030 | if (@sizeOf(T) == 0) { |
| 1026 | self.capacity = math.maxInt(usize); | 1031 | self.capacity = math.maxInt(usize); |
| ... | @@ -1047,7 +1052,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1047,7 +1052,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1047 | } | 1052 | } |
| 1048 | | 1053 | |
| 1049 | /// Modify the array so that it can hold at least `additional_count` **more** items. | 1054 | /// 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. |
| 1051 | pub fn ensureUnusedCapacity( | 1056 | pub fn ensureUnusedCapacity( |
| 1052 | self: *Self, | 1057 | self: *Self, |
| 1053 | allocator: Allocator, | 1058 | allocator: Allocator, |
| ... | @@ -1058,13 +1063,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1058,13 +1063,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1058 | | 1063 | |
| 1059 | /// Increases the array's length to match the full capacity that is already allocated. | 1064 | /// Increases the array's length to match the full capacity that is already allocated. |
| 1060 | /// The new elements have `undefined` values. | 1065 | /// The new elements have `undefined` values. |
| 1061 | /// Does not invalidate pointers. | 1066 | /// Never invalidates element pointers. |
| 1062 | pub fn expandToCapacity(self: *Self) void { | 1067 | pub fn expandToCapacity(self: *Self) void { |
| 1063 | self.items.len = self.capacity; | 1068 | self.items.len = self.capacity; |
| 1064 | } | 1069 | } |
| 1065 | | 1070 | |
| 1066 | /// Increase length by 1, returning pointer to the new item. | 1071 | /// 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. |
| 1068 | pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T { | 1073 | pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T { |
| 1069 | const newlen = try addOrOom(self.items.len, 1); | 1074 | const newlen = try addOrOom(self.items.len, 1); |
| 1070 | try self.ensureTotalCapacity(allocator, newlen); | 1075 | try self.ensureTotalCapacity(allocator, newlen); |
| ... | @@ -1072,9 +1077,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1072,9 +1077,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1072 | } | 1077 | } |
| 1073 | | 1078 | |
| 1074 | /// Increase length by 1, returning pointer to the new item. | 1079 | /// Increase length by 1, returning pointer to the new item. |
| 1075 | /// **Does not** invalidate pointers. | 1080 | /// Never invalidates element pointers. |
| 1076 | /// The returned pointer becomes invalid when the list resized. | 1081 | /// The returned element pointer becomes invalid when the list is resized. |
| 1077 | /// **Asserts that the list can hold one additional item.** | 1082 | /// Asserts that the list can hold one additional item. |
| 1078 | pub fn addOneAssumeCapacity(self: *Self) *T { | 1083 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 1079 | assert(self.items.len < self.capacity); | 1084 | assert(self.items.len < self.capacity); |
| 1080 | | 1085 | |
| ... | @@ -1093,9 +1098,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1093,9 +1098,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1093 | | 1098 | |
| 1094 | /// Resize the array, adding `n` new elements, which have `undefined` values. | 1099 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1095 | /// The return value is an array pointing to the newly allocated elements. | 1100 | /// The return value is an array pointing to the newly allocated elements. |
| 1096 | /// **Does not** invalidate pointers. | 1101 | /// Never invalidates element pointers. |
| 1097 | /// The returned pointer becomes invalid when the list is resized. | 1102 | /// 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. |
| 1099 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { | 1104 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 1100 | assert(self.items.len + n <= self.capacity); | 1105 | assert(self.items.len + n <= self.capacity); |
| 1101 | const prev_len = self.items.len; | 1106 | const prev_len = self.items.len; |
| ... | @@ -1115,9 +1120,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1115,9 +1120,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1115 | | 1120 | |
| 1116 | /// Resize the array, adding `n` new elements, which have `undefined` values. | 1121 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1117 | /// The return value is a slice pointing to the newly allocated elements. | 1122 | /// The return value is a slice pointing to the newly allocated elements. |
| 1118 | /// Does not invalidate element pointers. | 1123 | /// Never invalidates element pointers. |
| 1119 | /// The returned pointer becomes invalid when the list is resized. | 1124 | /// 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. |
| 1121 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { | 1126 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 1122 | assert(self.items.len + n <= self.capacity); | 1127 | assert(self.items.len + n <= self.capacity); |
| 1123 | const prev_len = self.items.len; | 1128 | const prev_len = self.items.len; |
| ... | @@ -1127,7 +1132,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1127,7 +1132,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1127 | | 1132 | |
| 1128 | /// Remove and return the last element from the list. | 1133 | /// Remove and return the last element from the list. |
| 1129 | /// Invalidates pointers to last element. | 1134 | /// Invalidates pointers to last element. |
| 1130 | /// **Asserts that the list is not empty.** | 1135 | /// Asserts that the list is not empty. |
| 1131 | pub fn pop(self: *Self) T { | 1136 | pub fn pop(self: *Self) T { |
| 1132 | const val = self.items[self.items.len - 1]; | 1137 | const val = self.items[self.items.len - 1]; |
| 1133 | self.items.len -= 1; | 1138 | self.items.len -= 1; |
| ... | @@ -1157,7 +1162,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -1157,7 +1162,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1157 | } | 1162 | } |
| 1158 | | 1163 | |
| 1159 | /// Return the last element from the list. | 1164 | /// Return the last element from the list. |
| 1160 | /// **Asserts that the list is not empty.** | 1165 | /// Asserts that the list is not empty. |
| 1161 | pub fn getLast(self: Self) T { | 1166 | pub fn getLast(self: Self) T { |
| 1162 | const val = self.items[self.items.len - 1]; | 1167 | const val = self.items[self.items.len - 1]; |
| 1163 | return val; | 1168 | return val; |
| ... | @@ -1183,12 +1188,11 @@ fn growCapacity(current: usize, minimum: usize) usize { | ... | @@ -1183,12 +1188,11 @@ fn growCapacity(current: usize, minimum: usize) usize { |
| 1183 | } | 1188 | } |
| 1184 | } | 1189 | } |
| 1185 | | 1190 | |
| 1186 | /// Adds a and b, returning `error.OutOfMemory` if overflow occurred. | 1191 | /// Integer addition returning `error.OutOfMemory` on overflow. |
| 1187 | /// This is equivalent to `math.add`. See #18467 for why it is used. | | |
| 1188 | fn addOrOom(a: usize, b: usize) error{OutOfMemory}!usize { | 1192 | fn addOrOom(a: usize, b: usize) error{OutOfMemory}!usize { |
| 1189 | const ov = @addWithOverflow(a, b); | 1193 | const result, const overflow = @addWithOverflow(a, b); |
| 1190 | if (ov[1] != 0) return error.OutOfMemory; | 1194 | if (overflow != 0) return error.OutOfMemory; |
| 1191 | return ov[0]; | 1195 | return result; |
| 1192 | } | 1196 | } |
| 1193 | | 1197 | |
| 1194 | test "std.ArrayList/ArrayListUnmanaged.init" { | 1198 | test "std.ArrayList/ArrayListUnmanaged.init" { |
| ... | @@ -1985,47 +1989,49 @@ test "std.ArrayList(u32).getLastOrNull()" { | ... | @@ -1985,47 +1989,49 @@ test "std.ArrayList(u32).getLastOrNull()" { |
| 1985 | } | 1989 | } |
| 1986 | | 1990 | |
| 1987 | test "return OutOfMemory when capacity would exceed maximum usize integer value" { | 1991 | test "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 | | | |
| 1991 | const a = testing.allocator; | 1992 | const a = testing.allocator; |
| | 1993 | const new_item: u32 = 42; |
| 1992 | | 1994 | |
| 1993 | var alu = ArrayListUnmanaged(u32){ | 1995 | { |
| 1994 | .items = undefined, | 1996 | var list: ArrayListUnmanaged(u32) = .{ |
| 1995 | .capacity = math.maxInt(usize), | 1997 | .items = undefined, |
| 1996 | }; | 1998 | .capacity = math.maxInt(usize), |
| 1997 | alu.items.len = math.maxInt(usize); | 1999 | }; |
| 1998 | | 2000 | list.items.len = math.maxInt(usize); |
| 1999 | try testing.expectError(error.OutOfMemory, alu.append(a, undefined)); | 2001 | |
| 2000 | try testing.expectError(error.OutOfMemory, alu.appendSlice(a, &.{undefined})); | 2002 | try testing.expectError(error.OutOfMemory, list.append(a, new_item)); |
| 2001 | try testing.expectError(error.OutOfMemory, alu.appendNTimes(a, undefined, 1)); | 2003 | try testing.expectError(error.OutOfMemory, list.appendSlice(a, &.{new_item})); |
| 2002 | try testing.expectError(error.OutOfMemory, alu.appendUnalignedSlice(a, &.{undefined})); | 2004 | try testing.expectError(error.OutOfMemory, list.appendNTimes(a, new_item, 1)); |
| 2003 | try testing.expectError(error.OutOfMemory, alu.addOne(a)); | 2005 | try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(a, &.{new_item})); |
| 2004 | try testing.expectError(error.OutOfMemory, alu.addManyAt(a, 0, 1)); | 2006 | try testing.expectError(error.OutOfMemory, list.addOne(a)); |
| 2005 | try testing.expectError(error.OutOfMemory, alu.addManyAsArray(a, 1)); | 2007 | try testing.expectError(error.OutOfMemory, list.addManyAt(a, 0, 1)); |
| 2006 | try testing.expectError(error.OutOfMemory, alu.addManyAsSlice(a, 1)); | 2008 | try testing.expectError(error.OutOfMemory, list.addManyAsArray(a, 1)); |
| 2007 | try testing.expectError(error.OutOfMemory, alu.insert(a, 0, undefined)); | 2009 | try testing.expectError(error.OutOfMemory, list.addManyAsSlice(a, 1)); |
| 2008 | try testing.expectError(error.OutOfMemory, alu.insertSlice(a, 0, &.{undefined})); | 2010 | try testing.expectError(error.OutOfMemory, list.insert(a, 0, new_item)); |
| 2009 | try testing.expectError(error.OutOfMemory, alu.toOwnedSliceSentinel(a, 0)); | 2011 | try testing.expectError(error.OutOfMemory, list.insertSlice(a, 0, &.{new_item})); |
| 2010 | try testing.expectError(error.OutOfMemory, alu.ensureUnusedCapacity(a, 1)); | 2012 | try testing.expectError(error.OutOfMemory, list.toOwnedSliceSentinel(a, 0)); |
| 2011 | | 2013 | try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(a, 1)); |
| 2012 | var al = ArrayList(u32){ | 2014 | } |
| 2013 | .items = undefined, | 2015 | |
| 2014 | .capacity = math.maxInt(usize), | 2016 | { |
| 2015 | .allocator = a, | 2017 | var list: ArrayList(u32) = .{ |
| 2016 | }; | 2018 | .items = undefined, |
| 2017 | al.items.len = math.maxInt(usize); | 2019 | .capacity = math.maxInt(usize), |
| 2018 | | 2020 | .allocator = a, |
| 2019 | try testing.expectError(error.OutOfMemory, al.append(undefined)); | 2021 | }; |
| 2020 | try testing.expectError(error.OutOfMemory, al.appendSlice(&.{undefined})); | 2022 | list.items.len = math.maxInt(usize); |
| 2021 | try testing.expectError(error.OutOfMemory, al.appendNTimes(undefined, 1)); | 2023 | |
| 2022 | try testing.expectError(error.OutOfMemory, al.appendUnalignedSlice(&.{undefined})); | 2024 | try testing.expectError(error.OutOfMemory, list.append(new_item)); |
| 2023 | try testing.expectError(error.OutOfMemory, al.addOne()); | 2025 | try testing.expectError(error.OutOfMemory, list.appendSlice(&.{new_item})); |
| 2024 | try testing.expectError(error.OutOfMemory, al.addManyAt(0, 1)); | 2026 | try testing.expectError(error.OutOfMemory, list.appendNTimes(new_item, 1)); |
| 2025 | try testing.expectError(error.OutOfMemory, al.addManyAsArray(1)); | 2027 | try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(&.{new_item})); |
| 2026 | try testing.expectError(error.OutOfMemory, al.addManyAsSlice(1)); | 2028 | try testing.expectError(error.OutOfMemory, list.addOne()); |
| 2027 | try testing.expectError(error.OutOfMemory, al.insert(0, undefined)); | 2029 | try testing.expectError(error.OutOfMemory, list.addManyAt(0, 1)); |
| 2028 | try testing.expectError(error.OutOfMemory, al.insertSlice(0, &.{undefined})); | 2030 | try testing.expectError(error.OutOfMemory, list.addManyAsArray(1)); |
| 2029 | try testing.expectError(error.OutOfMemory, al.toOwnedSliceSentinel(0)); | 2031 | try testing.expectError(error.OutOfMemory, list.addManyAsSlice(1)); |
| 2030 | try testing.expectError(error.OutOfMemory, al.ensureUnusedCapacity(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 | } |
| 2031 | } | 2037 | } |