| ... | ... | @@ -10,7 +10,7 @@ const Allocator = mem.Allocator; |
| 10 | 10 | /// This is a wrapper around an array of T values. Initialize with `init`. |
| 11 | 11 | /// |
| 12 | 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 | 14 | pub fn ArrayList(comptime T: type) type { |
| 15 | 15 | return ArrayListAligned(T, null); |
| 16 | 16 | } |
| ... | ... | @@ -21,7 +21,7 @@ pub fn ArrayList(comptime T: type) type { |
| 21 | 21 | /// Initialize with `init`. |
| 22 | 22 | /// |
| 23 | 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 | 25 | pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 26 | 26 | if (alignment) |a| { |
| 27 | 27 | if (a == @alignOf(T)) { |
| ... | ... | @@ -30,15 +30,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 30 | 30 | } |
| 31 | 31 | return struct { |
| 32 | 32 | 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. |
| 37 | 35 | /// |
| 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. |
| 42 | 40 | items: Slice, |
| 43 | 41 | /// How many T values this list can hold without allocating |
| 44 | 42 | /// additional memory. |
| ... | ... | @@ -144,18 +142,19 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 144 | 142 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 145 | 143 | /// If `i` is equal to the length of the list this operation is equivalent to append. |
| 146 | 144 | /// 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. |
| 149 | 147 | pub fn insert(self: *Self, i: usize, item: T) Allocator.Error!void { |
| 150 | 148 | const dst = try self.addManyAt(i, 1); |
| 151 | 149 | dst[0] = item; |
| 152 | 150 | } |
| 153 | 151 | |
| 154 | 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 | 155 | /// 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. |
| 159 | 158 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| 160 | 159 | assert(self.items.len < self.capacity); |
| 161 | 160 | self.items.len += 1; |
| ... | ... | @@ -171,7 +170,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 171 | 170 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 172 | 171 | /// Invalidates all pre-existing element pointers if capacity must be |
| 173 | 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 | 174 | pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T { |
| 176 | 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 | 207 | /// `undefined` values. Returns a slice pointing to the newly allocated |
| 209 | 208 | /// elements, which becomes invalid after various `ArrayList` |
| 210 | 209 | /// operations. |
| 210 | /// Asserts that there is enough capacity for the new elements. |
| 211 | 211 | /// Invalidates pre-existing pointers to elements at and after `index`, but |
| 212 | 212 | /// 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. |
| 215 | 214 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 216 | 215 | const new_len = self.items.len + count; |
| 217 | 216 | assert(self.capacity >= new_len); |
| ... | ... | @@ -228,7 +227,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 228 | 227 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 229 | 228 | /// Invalidates all pre-existing element pointers if capacity must be |
| 230 | 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 | 231 | pub fn insertSlice( |
| 233 | 232 | self: *Self, |
| 234 | 233 | index: usize, |
| ... | ... | @@ -241,8 +240,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 241 | 240 | /// Replace range of elements `list[start..][0..len]` with `new_items`. |
| 242 | 241 | /// Grows list if `len < new_items.len`. |
| 243 | 242 | /// 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. |
| 246 | 245 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void { |
| 247 | 246 | const after_range = try addOrOom(start, len); |
| 248 | 247 | const range = self.items[start..after_range]; |
| ... | ... | @@ -268,15 +267,15 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 268 | 267 | } |
| 269 | 268 | |
| 270 | 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 | 271 | pub fn append(self: *Self, item: T) Allocator.Error!void { |
| 273 | 272 | const new_item_ptr = try self.addOne(); |
| 274 | 273 | new_item_ptr.* = item; |
| 275 | 274 | } |
| 276 | 275 | |
| 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. |
| 280 | 279 | pub fn appendAssumeCapacity(self: *Self, item: T) void { |
| 281 | 280 | const new_item_ptr = self.addOneAssumeCapacity(); |
| 282 | 281 | new_item_ptr.* = item; |
| ... | ... | @@ -284,11 +283,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 284 | 283 | |
| 285 | 284 | /// Remove the element at index `i`, shift elements after index |
| 286 | 285 | /// `i` forward, and return the removed element. |
| 287 | | /// Invalidates pointers to end of list. |
| 286 | /// Invalidates element pointers to end of list. |
| 288 | 287 | /// This operation is O(N). |
| 289 | 288 | /// 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. |
| 292 | 291 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 293 | 292 | const newlen = self.items.len - 1; |
| 294 | 293 | if (newlen == i) return self.pop(); |
| ... | ... | @@ -304,8 +303,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 304 | 303 | /// The empty slot is filled from the end of the list. |
| 305 | 304 | /// This operation is O(1). |
| 306 | 305 | /// 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. |
| 309 | 308 | pub fn swapRemove(self: *Self, i: usize) T { |
| 310 | 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 | 315 | |
| 317 | 316 | /// Append the slice of items to the list. Allocates more |
| 318 | 317 | /// memory as necessary. |
| 319 | | /// Invalidates pointers if additional memory is needed. |
| 318 | /// Invalidates element pointers if additional memory is needed. |
| 320 | 319 | pub fn appendSlice(self: *Self, items: []const T) Allocator.Error!void { |
| 321 | 320 | try self.ensureUnusedCapacity(items.len); |
| 322 | 321 | self.appendSliceAssumeCapacity(items); |
| 323 | 322 | } |
| 324 | 323 | |
| 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. |
| 327 | 327 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 328 | 328 | const old_len = self.items.len; |
| 329 | 329 | const new_len = old_len + items.len; |
| ... | ... | @@ -335,16 +335,18 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 335 | 335 | /// Append an unaligned slice of items to the list. Allocates more |
| 336 | 336 | /// memory as necessary. Only call this function if calling |
| 337 | 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 | 339 | pub fn appendUnalignedSlice(self: *Self, items: []align(1) const T) Allocator.Error!void { |
| 340 | 340 | try self.ensureUnusedCapacity(items.len); |
| 341 | 341 | self.appendUnalignedSliceAssumeCapacity(items); |
| 342 | 342 | } |
| 343 | 343 | |
| 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. |
| 348 | 350 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { |
| 349 | 351 | const old_len = self.items.len; |
| 350 | 352 | const new_len = old_len + items.len; |
| ... | ... | @@ -366,7 +368,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 366 | 368 | |
| 367 | 369 | /// Same as `append` except it returns the number of bytes written, which is always the same |
| 368 | 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 | 372 | fn appendWrite(self: *Self, m: []const u8) Allocator.Error!usize { |
| 371 | 373 | try self.appendSlice(m); |
| 372 | 374 | return m.len; |
| ... | ... | @@ -374,20 +376,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 374 | 376 | |
| 375 | 377 | /// Append a value to the list `n` times. |
| 376 | 378 | /// Allocates more memory as necessary. |
| 377 | | /// Invalidates pointers if additional memory is needed. |
| 379 | /// Invalidates element pointers if additional memory is needed. |
| 378 | 380 | /// The function is inline so that a comptime-known `value` parameter will |
| 379 | 381 | /// have a more optimal memset codegen in case it has a repeated byte pattern. |
| 380 | 382 | pub inline fn appendNTimes(self: *Self, value: T, n: usize) Allocator.Error!void { |
| 381 | 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 | 385 | @memset(self.items[old_len..self.items.len], value); |
| 384 | 386 | } |
| 385 | 387 | |
| 386 | 388 | /// Append a value to the list `n` times. |
| 387 | | /// Does not invalidate pointers. |
| 389 | /// Never invalidates element pointers. |
| 388 | 390 | /// The function is inline so that a comptime-known `value` parameter will |
| 389 | 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 | 393 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { |
| 392 | 394 | const new_len = self.items.len + n; |
| 393 | 395 | assert(new_len <= self.capacity); |
| ... | ... | @@ -395,9 +397,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 395 | 397 | self.items.len = new_len; |
| 396 | 398 | } |
| 397 | 399 | |
| 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. |
| 401 | 403 | pub fn resize(self: *Self, new_len: usize) Allocator.Error!void { |
| 402 | 404 | try self.ensureTotalCapacity(new_len); |
| 403 | 405 | self.items.len = new_len; |
| ... | ... | @@ -405,7 +407,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 405 | 407 | |
| 406 | 408 | /// Reduce allocated capacity to `new_len`. |
| 407 | 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 | 411 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { |
| 410 | 412 | var unmanaged = self.moveToUnmanaged(); |
| 411 | 413 | unmanaged.shrinkAndFree(self.allocator, new_len); |
| ... | ... | @@ -413,8 +415,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 413 | 415 | } |
| 414 | 416 | |
| 415 | 417 | /// 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. |
| 418 | 420 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 419 | 421 | assert(new_len <= self.items.len); |
| 420 | 422 | self.items.len = new_len; |
| ... | ... | @@ -434,7 +436,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 434 | 436 | |
| 435 | 437 | /// If the current capacity is less than `new_capacity`, this function will |
| 436 | 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 | 440 | pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) Allocator.Error!void { |
| 439 | 441 | if (@sizeOf(T) == 0) { |
| 440 | 442 | self.capacity = math.maxInt(usize); |
| ... | ... | @@ -449,7 +451,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 449 | 451 | |
| 450 | 452 | /// If the current capacity is less than `new_capacity`, this function will |
| 451 | 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 | 455 | pub fn ensureTotalCapacityPrecise(self: *Self, new_capacity: usize) Allocator.Error!void { |
| 454 | 456 | if (@sizeOf(T) == 0) { |
| 455 | 457 | self.capacity = math.maxInt(usize); |
| ... | ... | @@ -476,13 +478,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 476 | 478 | } |
| 477 | 479 | |
| 478 | 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 | 482 | pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) Allocator.Error!void { |
| 481 | 483 | return self.ensureTotalCapacity(try addOrOom(self.items.len, additional_count)); |
| 482 | 484 | } |
| 483 | 485 | |
| 484 | 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 | 489 | pub fn expandToCapacity(self: *Self) void { |
| 487 | 490 | self.items.len = self.capacity; |
| 488 | 491 | } |
| ... | ... | @@ -496,8 +499,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 496 | 499 | |
| 497 | 500 | /// Increase length by 1, returning pointer to the new item. |
| 498 | 501 | /// 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. |
| 501 | 504 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 502 | 505 | assert(self.items.len < self.capacity); |
| 503 | 506 | self.items.len += 1; |
| ... | ... | @@ -516,9 +519,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 516 | 519 | |
| 517 | 520 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 518 | 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 | 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 | 525 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 523 | 526 | assert(self.items.len + n <= self.capacity); |
| 524 | 527 | const prev_len = self.items.len; |
| ... | ... | @@ -538,9 +541,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 538 | 541 | |
| 539 | 542 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 540 | 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 | 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 | 547 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 545 | 548 | assert(self.items.len + n <= self.capacity); |
| 546 | 549 | const prev_len = self.items.len; |
| ... | ... | @@ -549,8 +552,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 549 | 552 | } |
| 550 | 553 | |
| 551 | 554 | /// 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. |
| 554 | 557 | pub fn pop(self: *Self) T { |
| 555 | 558 | const val = self.items[self.items.len - 1]; |
| 556 | 559 | self.items.len -= 1; |
| ... | ... | @@ -559,7 +562,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 559 | 562 | |
| 560 | 563 | /// Remove and return the last element from the list, or |
| 561 | 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 | 566 | pub fn popOrNull(self: *Self) ?T { |
| 564 | 567 | if (self.items.len == 0) return null; |
| 565 | 568 | return self.pop(); |
| ... | ... | @@ -581,7 +584,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 581 | 584 | } |
| 582 | 585 | |
| 583 | 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 | 588 | pub fn getLast(self: Self) T { |
| 586 | 589 | const val = self.items[self.items.len - 1]; |
| 587 | 590 | return val; |
| ... | ... | @@ -596,17 +599,20 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 596 | 599 | } |
| 597 | 600 | |
| 598 | 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 | 603 | /// the entire lifetime of an ArrayListUnmanaged. Initialize directly or with |
| 601 | 604 | /// `initCapacity`, and deinitialize with `deinit` or use `toOwnedSlice`. |
| 602 | 605 | pub fn ArrayListUnmanaged(comptime T: type) type { |
| 603 | 606 | return ArrayListAlignedUnmanaged(T, null); |
| 604 | 607 | } |
| 605 | 608 | |
| 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`. |
| 610 | 616 | pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type { |
| 611 | 617 | if (alignment) |a| { |
| 612 | 618 | if (a == @alignOf(T)) { |
| ... | ... | @@ -615,15 +621,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 615 | 621 | } |
| 616 | 622 | return struct { |
| 617 | 623 | 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. |
| 622 | 626 | /// |
| 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. |
| 627 | 631 | items: Slice = &[_]T{}, |
| 628 | 632 | /// How many T values this list can hold without allocating |
| 629 | 633 | /// additional memory. |
| ... | ... | @@ -646,8 +650,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 646 | 650 | |
| 647 | 651 | /// Initialize with externally-managed memory. The buffer determines the |
| 648 | 652 | /// 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. |
| 651 | 655 | pub fn initBuffer(buffer: Slice) Self { |
| 652 | 656 | return .{ |
| 653 | 657 | .items = buffer[0..0], |
| ... | ... | @@ -722,8 +726,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 722 | 726 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 723 | 727 | /// If `i` is equal to the length of the list this operation is equivalent to append. |
| 724 | 728 | /// 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. |
| 727 | 731 | pub fn insert(self: *Self, allocator: Allocator, i: usize, item: T) Allocator.Error!void { |
| 728 | 732 | const dst = try self.addManyAt(allocator, i, 1); |
| 729 | 733 | dst[0] = item; |
| ... | ... | @@ -732,8 +736,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 732 | 736 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. |
| 733 | 737 | /// If in` is equal to the length of the list this operation is equivalent to append. |
| 734 | 738 | /// 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. |
| 737 | 741 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { |
| 738 | 742 | assert(self.items.len < self.capacity); |
| 739 | 743 | self.items.len += 1; |
| ... | ... | @@ -749,7 +753,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 749 | 753 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 750 | 754 | /// Invalidates all pre-existing element pointers if capacity must be |
| 751 | 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 | 757 | pub fn addManyAt( |
| 754 | 758 | self: *Self, |
| 755 | 759 | allocator: Allocator, |
| ... | ... | @@ -767,8 +771,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 767 | 771 | /// operations. |
| 768 | 772 | /// Invalidates pre-existing pointers to elements at and after `index`, but |
| 769 | 773 | /// 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. |
| 772 | 776 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 773 | 777 | const new_len = self.items.len + count; |
| 774 | 778 | assert(self.capacity >= new_len); |
| ... | ... | @@ -785,7 +789,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 785 | 789 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 786 | 790 | /// Invalidates all pre-existing element pointers if capacity must be |
| 787 | 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 | 793 | pub fn insertSlice( |
| 790 | 794 | self: *Self, |
| 791 | 795 | allocator: Allocator, |
| ... | ... | @@ -803,8 +807,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 803 | 807 | /// Replace range of elements `list[start..][0..len]` with `new_items` |
| 804 | 808 | /// Grows list if `len < new_items.len`. |
| 805 | 809 | /// 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. |
| 808 | 812 | pub fn replaceRange( |
| 809 | 813 | self: *Self, |
| 810 | 814 | allocator: Allocator, |
| ... | ... | @@ -818,14 +822,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 818 | 822 | } |
| 819 | 823 | |
| 820 | 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 | 826 | pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void { |
| 823 | 827 | const new_item_ptr = try self.addOne(allocator); |
| 824 | 828 | new_item_ptr.* = item; |
| 825 | 829 | } |
| 826 | 830 | |
| 827 | 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 | 834 | pub fn appendAssumeCapacity(self: *Self, item: T) void { |
| 830 | 835 | const new_item_ptr = self.addOneAssumeCapacity(); |
| 831 | 836 | new_item_ptr.* = item; |
| ... | ... | @@ -834,8 +839,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 834 | 839 | /// Remove the element at index `i` from the list and return its value. |
| 835 | 840 | /// Invalidates pointers to the last element. |
| 836 | 841 | /// 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. |
| 839 | 844 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 840 | 845 | const newlen = self.items.len - 1; |
| 841 | 846 | if (newlen == i) return self.pop(); |
| ... | ... | @@ -851,8 +856,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 851 | 856 | /// The empty slot is filled from the end of the list. |
| 852 | 857 | /// Invalidates pointers to last element. |
| 853 | 858 | /// 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. |
| 856 | 861 | pub fn swapRemove(self: *Self, i: usize) T { |
| 857 | 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 | 868 | |
| 864 | 869 | /// Append the slice of items to the list. Allocates more |
| 865 | 870 | /// memory as necessary. |
| 866 | | /// Invalidates pointers if additional memory is needed. |
| 871 | /// Invalidates element pointers if additional memory is needed. |
| 867 | 872 | pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void { |
| 868 | 873 | try self.ensureUnusedCapacity(allocator, items.len); |
| 869 | 874 | self.appendSliceAssumeCapacity(items); |
| 870 | 875 | } |
| 871 | 876 | |
| 872 | 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 | 879 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 875 | 880 | const old_len = self.items.len; |
| 876 | 881 | const new_len = old_len + items.len; |
| ... | ... | @@ -882,7 +887,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 882 | 887 | /// Append the slice of items to the list. Allocates more |
| 883 | 888 | /// memory as necessary. Only call this function if a call to `appendSlice` instead would |
| 884 | 889 | /// be a compile error. |
| 885 | | /// Invalidates pointers if additional memory is needed. |
| 890 | /// Invalidates element pointers if additional memory is needed. |
| 886 | 891 | pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void { |
| 887 | 892 | try self.ensureUnusedCapacity(allocator, items.len); |
| 888 | 893 | self.appendUnalignedSliceAssumeCapacity(items); |
| ... | ... | @@ -891,7 +896,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 891 | 896 | /// Append an unaligned slice of items to the list. |
| 892 | 897 | /// Only call this function if a call to `appendSliceAssumeCapacity` |
| 893 | 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 | 900 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { |
| 896 | 901 | const old_len = self.items.len; |
| 897 | 902 | const new_len = old_len + items.len; |
| ... | ... | @@ -918,7 +923,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 918 | 923 | |
| 919 | 924 | /// Same as `append` except it returns the number of bytes written, which is always the same |
| 920 | 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 | 927 | fn appendWrite(context: WriterContext, m: []const u8) Allocator.Error!usize { |
| 923 | 928 | try context.self.appendSlice(context.allocator, m); |
| 924 | 929 | return m.len; |
| ... | ... | @@ -926,20 +931,20 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 926 | 931 | |
| 927 | 932 | /// Append a value to the list `n` times. |
| 928 | 933 | /// Allocates more memory as necessary. |
| 929 | | /// Invalidates pointers if additional memory is needed. |
| 934 | /// Invalidates element pointers if additional memory is needed. |
| 930 | 935 | /// The function is inline so that a comptime-known `value` parameter will |
| 931 | 936 | /// have a more optimal memset codegen in case it has a repeated byte pattern. |
| 932 | 937 | pub inline fn appendNTimes(self: *Self, allocator: Allocator, value: T, n: usize) Allocator.Error!void { |
| 933 | 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 | 940 | @memset(self.items[old_len..self.items.len], value); |
| 936 | 941 | } |
| 937 | 942 | |
| 938 | 943 | /// Append a value to the list `n` times. |
| 939 | | /// **Does not** invalidate pointers. |
| 944 | /// Never invalidates element pointers. |
| 940 | 945 | /// The function is inline so that a comptime-known `value` parameter will |
| 941 | 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 | 948 | pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { |
| 944 | 949 | const new_len = self.items.len + n; |
| 945 | 950 | assert(new_len <= self.capacity); |
| ... | ... | @@ -947,9 +952,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 947 | 952 | self.items.len = new_len; |
| 948 | 953 | } |
| 949 | 954 | |
| 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. |
| 953 | 958 | pub fn resize(self: *Self, allocator: Allocator, new_len: usize) Allocator.Error!void { |
| 954 | 959 | try self.ensureTotalCapacity(allocator, new_len); |
| 955 | 960 | self.items.len = new_len; |
| ... | ... | @@ -957,7 +962,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 957 | 962 | |
| 958 | 963 | /// Reduce allocated capacity to `new_len`. |
| 959 | 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 | 966 | pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void { |
| 962 | 967 | assert(new_len <= self.items.len); |
| 963 | 968 | |
| ... | ... | @@ -990,7 +995,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 990 | 995 | /// Reduce length to `new_len`. |
| 991 | 996 | /// Invalidates pointers to elements `items[new_len..]`. |
| 992 | 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 | 999 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 995 | 1000 | assert(new_len <= self.items.len); |
| 996 | 1001 | self.items.len = new_len; |
| ... | ... | @@ -1010,7 +1015,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1010 | 1015 | |
| 1011 | 1016 | /// If the current capacity is less than `new_capacity`, this function will |
| 1012 | 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 | 1019 | pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1015 | 1020 | if (self.capacity >= new_capacity) return; |
| 1016 | 1021 | |
| ... | ... | @@ -1020,7 +1025,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1020 | 1025 | |
| 1021 | 1026 | /// If the current capacity is less than `new_capacity`, this function will |
| 1022 | 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 | 1029 | pub fn ensureTotalCapacityPrecise(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1025 | 1030 | if (@sizeOf(T) == 0) { |
| 1026 | 1031 | self.capacity = math.maxInt(usize); |
| ... | ... | @@ -1047,7 +1052,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1047 | 1052 | } |
| 1048 | 1053 | |
| 1049 | 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 | 1056 | pub fn ensureUnusedCapacity( |
| 1052 | 1057 | self: *Self, |
| 1053 | 1058 | allocator: Allocator, |
| ... | ... | @@ -1058,13 +1063,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1058 | 1063 | |
| 1059 | 1064 | /// Increases the array's length to match the full capacity that is already allocated. |
| 1060 | 1065 | /// The new elements have `undefined` values. |
| 1061 | | /// Does not invalidate pointers. |
| 1066 | /// Never invalidates element pointers. |
| 1062 | 1067 | pub fn expandToCapacity(self: *Self) void { |
| 1063 | 1068 | self.items.len = self.capacity; |
| 1064 | 1069 | } |
| 1065 | 1070 | |
| 1066 | 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 | 1073 | pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T { |
| 1069 | 1074 | const newlen = try addOrOom(self.items.len, 1); |
| 1070 | 1075 | try self.ensureTotalCapacity(allocator, newlen); |
| ... | ... | @@ -1072,9 +1077,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1072 | 1077 | } |
| 1073 | 1078 | |
| 1074 | 1079 | /// 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. |
| 1078 | 1083 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 1079 | 1084 | assert(self.items.len < self.capacity); |
| 1080 | 1085 | |
| ... | ... | @@ -1093,9 +1098,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1093 | 1098 | |
| 1094 | 1099 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1095 | 1100 | /// The return value is an array pointing to the newly allocated elements. |
| 1096 | | /// **Does not** invalidate pointers. |
| 1101 | /// Never invalidates element pointers. |
| 1097 | 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 | 1104 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 1100 | 1105 | assert(self.items.len + n <= self.capacity); |
| 1101 | 1106 | const prev_len = self.items.len; |
| ... | ... | @@ -1115,9 +1120,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1115 | 1120 | |
| 1116 | 1121 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1117 | 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 | 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 | 1126 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 1122 | 1127 | assert(self.items.len + n <= self.capacity); |
| 1123 | 1128 | const prev_len = self.items.len; |
| ... | ... | @@ -1127,7 +1132,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1127 | 1132 | |
| 1128 | 1133 | /// Remove and return the last element from the list. |
| 1129 | 1134 | /// Invalidates pointers to last element. |
| 1130 | | /// **Asserts that the list is not empty.** |
| 1135 | /// Asserts that the list is not empty. |
| 1131 | 1136 | pub fn pop(self: *Self) T { |
| 1132 | 1137 | const val = self.items[self.items.len - 1]; |
| 1133 | 1138 | self.items.len -= 1; |
| ... | ... | @@ -1157,7 +1162,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 1157 | 1162 | } |
| 1158 | 1163 | |
| 1159 | 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 | 1166 | pub fn getLast(self: Self) T { |
| 1162 | 1167 | const val = self.items[self.items.len - 1]; |
| 1163 | 1168 | return val; |
| ... | ... | @@ -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. |
| 1187 | | /// This is equivalent to `math.add`. See #18467 for why it is used. |
| 1191 | /// Integer addition returning `error.OutOfMemory` on overflow. |
| 1188 | 1192 | fn 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; |
| 1192 | 1196 | } |
| 1193 | 1197 | |
| 1194 | 1198 | test "std.ArrayList/ArrayListUnmanaged.init" { |
| ... | ... | @@ -1985,47 +1989,49 @@ test "std.ArrayList(u32).getLastOrNull()" { |
| 1985 | 1989 | } |
| 1986 | 1990 | |
| 1987 | 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 | 1992 | const a = testing.allocator; |
| 1993 | const new_item: u32 = 42; |
| 1992 | 1994 | |
| 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 | } |
| 2031 | 2037 | } |