authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-04 23:37:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-05 09:56:02-07:00
logc47ec4f3d7a6bf79be3adcffa33aa51bcc26ed0b
tree1fdc6c0a3e4571505e080ab257791a5b6a1d7e50
parent6f545683f3d53917df816ca6cd5c9c20474071f3

std.array_list: add bounded methods


1 files changed, 167 insertions(+), 7 deletions(-)

lib/std/array_list.zig+167-7
......@@ -738,9 +738,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
738738 }
739739
740740 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.
741 /// If in` is equal to the length of the list this operation is equivalent to append.
741 ///
742 /// If `i` is equal to the length of the list this operation is equivalent to append.
743 ///
742744 /// This operation is O(N).
745 ///
743746 /// Asserts that the list has capacity for one additional item.
747 ///
744748 /// Asserts that the index is in bounds or equal to the length.
745749 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
746750 assert(self.items.len < self.capacity);
......@@ -750,6 +754,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
750754 self.items[i] = item;
751755 }
752756
757 /// Insert `item` at index `i`, moving `list[i .. list.len]` to higher indices to make room.
758 ///
759 /// If `i` is equal to the length of the list this operation is equivalent to append.
760 ///
761 /// This operation is O(N).
762 ///
763 /// If the list lacks unused capacity for the additional item, returns
764 /// `error.OutOfMemory`.
765 ///
766 /// Asserts that the index is in bounds or equal to the length.
767 pub fn insertBounded(self: *Self, i: usize, item: T) error{OutOfMemory}!void {
768 if (self.capacity - self.items.len == 0) return error.OutOfMemory;
769 return insertAssumeCapacity(self, i, item);
770 }
771
753772 /// Add `count` new elements at position `index`, which have
754773 /// `undefined` values. Returns a slice pointing to the newly allocated
755774 /// elements, which becomes invalid after various `ArrayList`
......@@ -788,6 +807,23 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
788807 return result;
789808 }
790809
810 /// Add `count` new elements at position `index`, which have
811 /// `undefined` values, returning a slice pointing to the newly
812 /// allocated elements, which becomes invalid after various `ArrayList`
813 /// operations.
814 ///
815 /// Invalidates pre-existing pointers to elements at and after `index`, but
816 /// does not invalidate any before that.
817 ///
818 /// If the list lacks unused capacity for the additional items, returns
819 /// `error.OutOfMemory`.
820 ///
821 /// Asserts that the index is in bounds or equal to the length.
822 pub fn addManyAtBounded(self: *Self, index: usize, count: usize) error{OutOfMemory}![]T {
823 if (self.capacity - self.items.len < count) return error.OutOfMemory;
824 return addManyAtAssumeCapacity(self, index, count);
825 }
826
791827 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
792828 /// This operation is O(N).
793829 /// Invalidates pre-existing pointers to elements at and after `index`.
......@@ -831,7 +867,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
831867 }
832868
833869 /// Grows or shrinks the list as necessary.
870 ///
834871 /// Never invalidates element pointers.
872 ///
835873 /// Asserts the capacity is enough for additional items.
836874 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {
837875 const after_range = start + len;
......@@ -855,6 +893,17 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
855893 }
856894 }
857895
896 /// Grows or shrinks the list as necessary.
897 ///
898 /// Never invalidates element pointers.
899 ///
900 /// If the unused capacity is insufficient for additional items,
901 /// returns `error.OutOfMemory`.
902 pub fn replaceRangeBounded(self: *Self, start: usize, len: usize, new_items: []const T) error{OutOfMemory}!void {
903 if (self.capacity - self.items.len < new_items.len -| len) return error.OutOfMemory;
904 return replaceRangeAssumeCapacity(self, start, len, new_items);
905 }
906
858907 /// Extend the list by 1 element. Allocates more memory as necessary.
859908 /// Invalidates element pointers if additional memory is needed.
860909 pub fn append(self: *Self, gpa: Allocator, item: T) Allocator.Error!void {
......@@ -863,12 +912,25 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
863912 }
864913
865914 /// Extend the list by 1 element.
915 ///
866916 /// Never invalidates element pointers.
917 ///
867918 /// Asserts that the list can hold one additional item.
868919 pub fn appendAssumeCapacity(self: *Self, item: T) void {
869920 self.addOneAssumeCapacity().* = item;
870921 }
871922
923 /// Extend the list by 1 element.
924 ///
925 /// Never invalidates element pointers.
926 ///
927 /// If the list lacks unused capacity for the additional item, returns
928 /// `error.OutOfMemory`.
929 pub fn appendBounded(self: *Self, item: T) error{OutOfMemory}!void {
930 if (self.capacity - self.items.len == 0) return error.OutOfMemory;
931 return appendAssumeCapacity(self, item);
932 }
933
872934 /// Remove the element at index `i` from the list and return its value.
873935 /// Invalidates pointers to the last element.
874936 /// This operation is O(N).
......@@ -903,6 +965,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
903965 }
904966
905967 /// Append the slice of items to the list.
968 ///
906969 /// Asserts that the list can hold the additional items.
907970 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
908971 const old_len = self.items.len;
......@@ -912,6 +975,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
912975 @memcpy(self.items[old_len..][0..items.len], items);
913976 }
914977
978 /// Append the slice of items to the list.
979 ///
980 /// If the list lacks unused capacity for the additional items, returns `error.OutOfMemory`.
981 pub fn appendSliceBounded(self: *Self, items: []const T) error{OutOfMemory}!void {
982 if (self.capacity - self.items.len < items.len) return error.OutOfMemory;
983 return appendSliceAssumeCapacity(self, items);
984 }
985
915986 /// Append the slice of items to the list. Allocates more
916987 /// memory as necessary. Only call this function if a call to `appendSlice` instead would
917988 /// be a compile error.
......@@ -922,8 +993,10 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
922993 }
923994
924995 /// Append an unaligned slice of items to the list.
925 /// Only call this function if a call to `appendSliceAssumeCapacity`
926 /// instead would be a compile error.
996 ///
997 /// Intended to be used only when `appendSliceAssumeCapacity` would be
998 /// a compile error.
999 ///
9271000 /// Asserts that the list can hold the additional items.
9281001 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
9291002 const old_len = self.items.len;
......@@ -933,6 +1006,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
9331006 @memcpy(self.items[old_len..][0..items.len], items);
9341007 }
9351008
1009 /// Append an unaligned slice of items to the list.
1010 ///
1011 /// Intended to be used only when `appendSliceAssumeCapacity` would be
1012 /// a compile error.
1013 ///
1014 /// If the list lacks unused capacity for the additional items, returns
1015 /// `error.OutOfMemory`.
1016 pub fn appendUnalignedSliceBounded(self: *Self, items: []align(1) const T) error{OutOfMemory}!void {
1017 if (self.capacity - self.items.len < items.len) return error.OutOfMemory;
1018 return appendUnalignedSliceAssumeCapacity(self, items);
1019 }
1020
9361021 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
9371022 comptime assert(T == u8);
9381023 try self.ensureUnusedCapacity(gpa, fmt.len);
......@@ -950,6 +1035,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
9501035 self.items.len += w.end;
9511036 }
9521037
1038 pub fn printBounded(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
1039 comptime assert(T == u8);
1040 var w: std.io.Writer = .fixed(self.unusedCapacitySlice());
1041 w.print(fmt, args) catch return error.OutOfMemory;
1042 self.items.len += w.end;
1043 }
1044
9531045 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
9541046 pub const WriterContext = struct {
9551047 self: *Self,
......@@ -1004,9 +1096,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
10041096 }
10051097
10061098 /// Append a value to the list `n` times.
1099 ///
10071100 /// Never invalidates element pointers.
1101 ///
10081102 /// The function is inline so that a comptime-known `value` parameter will
10091103 /// have better memset codegen in case it has a repeated byte pattern.
1104 ///
10101105 /// Asserts that the list can hold the additional items.
10111106 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
10121107 const new_len = self.items.len + n;
......@@ -1015,6 +1110,22 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
10151110 self.items.len = new_len;
10161111 }
10171112
1113 /// Append a value to the list `n` times.
1114 ///
1115 /// Never invalidates element pointers.
1116 ///
1117 /// The function is inline so that a comptime-known `value` parameter will
1118 /// have better memset codegen in case it has a repeated byte pattern.
1119 ///
1120 /// If the list lacks unused capacity for the additional items, returns
1121 /// `error.OutOfMemory`.
1122 pub inline fn appendNTimesBounded(self: *Self, value: T, n: usize) error{OutOfMemory}!void {
1123 const new_len = self.items.len + n;
1124 if (self.capacity < new_len) return error.OutOfMemory;
1125 @memset(self.items.ptr[self.items.len..new_len], value);
1126 self.items.len = new_len;
1127 }
1128
10181129 /// Adjust the list length to `new_len`.
10191130 /// Additional elements contain the value `undefined`.
10201131 /// Invalidates element pointers if additional memory is needed.
......@@ -1140,8 +1251,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11401251 }
11411252
11421253 /// Increase length by 1, returning pointer to the new item.
1254 ///
11431255 /// Never invalidates element pointers.
1256 ///
11441257 /// The returned element pointer becomes invalid when the list is resized.
1258 ///
11451259 /// Asserts that the list can hold one additional item.
11461260 pub fn addOneAssumeCapacity(self: *Self) *T {
11471261 assert(self.items.len < self.capacity);
......@@ -1150,6 +1264,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11501264 return &self.items[self.items.len - 1];
11511265 }
11521266
1267 /// Increase length by 1, returning pointer to the new item.
1268 ///
1269 /// Never invalidates element pointers.
1270 ///
1271 /// The returned element pointer becomes invalid when the list is resized.
1272 ///
1273 /// If the list lacks unused capacity for the additional item, returns `error.OutOfMemory`.
1274 pub fn addOneBounded(self: *Self) error{OutOfMemory}!*T {
1275 if (self.capacity - self.items.len < 1) return error.OutOfMemory;
1276 return addOneAssumeCapacity(self);
1277 }
1278
11531279 /// Resize the array, adding `n` new elements, which have `undefined` values.
11541280 /// The return value is an array pointing to the newly allocated elements.
11551281 /// The returned pointer becomes invalid when the list is resized.
......@@ -1160,9 +1286,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11601286 }
11611287
11621288 /// Resize the array, adding `n` new elements, which have `undefined` values.
1289 ///
11631290 /// The return value is an array pointing to the newly allocated elements.
1291 ///
11641292 /// Never invalidates element pointers.
1293 ///
11651294 /// The returned pointer becomes invalid when the list is resized.
1295 ///
11661296 /// Asserts that the list can hold the additional items.
11671297 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
11681298 assert(self.items.len + n <= self.capacity);
......@@ -1171,6 +1301,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11711301 return self.items[prev_len..][0..n];
11721302 }
11731303
1304 /// Resize the array, adding `n` new elements, which have `undefined` values.
1305 ///
1306 /// The return value is an array pointing to the newly allocated elements.
1307 ///
1308 /// Never invalidates element pointers.
1309 ///
1310 /// The returned pointer becomes invalid when the list is resized.
1311 ///
1312 /// If the list lacks unused capacity for the additional items, returns
1313 /// `error.OutOfMemory`.
1314 pub fn addManyAsArrayBounded(self: *Self, comptime n: usize) error{OutOfMemory}!*[n]T {
1315 if (self.capacity - self.items.len < n) return error.OutOfMemory;
1316 return addManyAsArrayAssumeCapacity(self, n);
1317 }
1318
11741319 /// Resize the array, adding `n` new elements, which have `undefined` values.
11751320 /// The return value is a slice pointing to the newly allocated elements.
11761321 /// The returned pointer becomes invalid when the list is resized.
......@@ -1181,10 +1326,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11811326 return self.items[prev_len..][0..n];
11821327 }
11831328
1184 /// Resize the array, adding `n` new elements, which have `undefined` values.
1185 /// The return value is a slice pointing to the newly allocated elements.
1186 /// Never invalidates element pointers.
1187 /// The returned pointer becomes invalid when the list is resized.
1329 /// Resizes the array, adding `n` new elements, which have `undefined`
1330 /// values, returning a slice pointing to the newly allocated elements.
1331 ///
1332 /// Never invalidates element pointers. The returned pointer becomes
1333 /// invalid when the list is resized.
1334 ///
11881335 /// Asserts that the list can hold the additional items.
11891336 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
11901337 assert(self.items.len + n <= self.capacity);
......@@ -1193,6 +1340,19 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
11931340 return self.items[prev_len..][0..n];
11941341 }
11951342
1343 /// Resizes the array, adding `n` new elements, which have `undefined`
1344 /// values, returning a slice pointing to the newly allocated elements.
1345 ///
1346 /// Never invalidates element pointers. The returned pointer becomes
1347 /// invalid when the list is resized.
1348 ///
1349 /// If the list lacks unused capacity for the additional items, returns
1350 /// `error.OutOfMemory`.
1351 pub fn addManyAsSliceBounded(self: *Self, n: usize) error{OutOfMemory}![]T {
1352 if (self.capacity - self.items.len < n) return error.OutOfMemory;
1353 return addManyAsSliceAssumeCapacity(self, n);
1354 }
1355
11961356 /// Remove and return the last element from the list.
11971357 /// If the list is empty, returns `null`.
11981358 /// Invalidates pointers to last element.