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...@@ -738,9 +738,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
738 }738 }
739739
740 /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room.740 /// 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 ///
742 /// This operation is O(N).744 /// This operation is O(N).
745 ///
743 /// Asserts that the list has capacity for one additional item.746 /// Asserts that the list has capacity for one additional item.
747 ///
744 /// Asserts that the index is in bounds or equal to the length.748 /// Asserts that the index is in bounds or equal to the length.
745 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {749 pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void {
746 assert(self.items.len < self.capacity);750 assert(self.items.len < self.capacity);
...@@ -750,6 +754,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -750,6 +754,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
750 self.items[i] = item;754 self.items[i] = item;
751 }755 }
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
753 /// Add `count` new elements at position `index`, which have772 /// Add `count` new elements at position `index`, which have
754 /// `undefined` values. Returns a slice pointing to the newly allocated773 /// `undefined` values. Returns a slice pointing to the newly allocated
755 /// elements, which becomes invalid after various `ArrayList`774 /// elements, which becomes invalid after various `ArrayList`
...@@ -788,6 +807,23 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -788,6 +807,23 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
788 return result;807 return result;
789 }808 }
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
791 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.827 /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
792 /// This operation is O(N).828 /// This operation is O(N).
793 /// Invalidates pre-existing pointers to elements at and after `index`.829 /// Invalidates pre-existing pointers to elements at and after `index`.
...@@ -831,7 +867,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -831,7 +867,9 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
831 }867 }
832868
833 /// Grows or shrinks the list as necessary.869 /// Grows or shrinks the list as necessary.
870 ///
834 /// Never invalidates element pointers.871 /// Never invalidates element pointers.
872 ///
835 /// Asserts the capacity is enough for additional items.873 /// Asserts the capacity is enough for additional items.
836 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {874 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {
837 const after_range = start + len;875 const after_range = start + len;
...@@ -855,6 +893,17 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -855,6 +893,17 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
855 }893 }
856 }894 }
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
858 /// Extend the list by 1 element. Allocates more memory as necessary.907 /// Extend the list by 1 element. Allocates more memory as necessary.
859 /// Invalidates element pointers if additional memory is needed.908 /// Invalidates element pointers if additional memory is needed.
860 pub fn append(self: *Self, gpa: Allocator, item: T) Allocator.Error!void {909 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...@@ -863,12 +912,25 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
863 }912 }
864913
865 /// Extend the list by 1 element.914 /// Extend the list by 1 element.
915 ///
866 /// Never invalidates element pointers.916 /// Never invalidates element pointers.
917 ///
867 /// Asserts that the list can hold one additional item.918 /// Asserts that the list can hold one additional item.
868 pub fn appendAssumeCapacity(self: *Self, item: T) void {919 pub fn appendAssumeCapacity(self: *Self, item: T) void {
869 self.addOneAssumeCapacity().* = item;920 self.addOneAssumeCapacity().* = item;
870 }921 }
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
872 /// Remove the element at index `i` from the list and return its value.934 /// Remove the element at index `i` from the list and return its value.
873 /// Invalidates pointers to the last element.935 /// Invalidates pointers to the last element.
874 /// This operation is O(N).936 /// This operation is O(N).
...@@ -903,6 +965,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -903,6 +965,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
903 }965 }
904966
905 /// Append the slice of items to the list.967 /// Append the slice of items to the list.
968 ///
906 /// Asserts that the list can hold the additional items.969 /// Asserts that the list can hold the additional items.
907 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {970 pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
908 const old_len = self.items.len;971 const old_len = self.items.len;
...@@ -912,6 +975,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -912,6 +975,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
912 @memcpy(self.items[old_len..][0..items.len], items);975 @memcpy(self.items[old_len..][0..items.len], items);
913 }976 }
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
915 /// Append the slice of items to the list. Allocates more986 /// Append the slice of items to the list. Allocates more
916 /// memory as necessary. Only call this function if a call to `appendSlice` instead would987 /// memory as necessary. Only call this function if a call to `appendSlice` instead would
917 /// be a compile error.988 /// be a compile error.
...@@ -922,8 +993,10 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -922,8 +993,10 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
922 }993 }
923994
924 /// Append an unaligned slice of items to the list.995 /// Append an unaligned slice of items to the list.
925 /// Only call this function if a call to `appendSliceAssumeCapacity`996 ///
926 /// instead would be a compile error.997 /// Intended to be used only when `appendSliceAssumeCapacity` would be
998 /// a compile error.
999 ///
927 /// Asserts that the list can hold the additional items.1000 /// Asserts that the list can hold the additional items.
928 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {1001 pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
929 const old_len = self.items.len;1002 const old_len = self.items.len;
...@@ -933,6 +1006,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -933,6 +1006,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
933 @memcpy(self.items[old_len..][0..items.len], items);1006 @memcpy(self.items[old_len..][0..items.len], items);
934 }1007 }
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
936 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {1021 pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
937 comptime assert(T == u8);1022 comptime assert(T == u8);
938 try self.ensureUnusedCapacity(gpa, fmt.len);1023 try self.ensureUnusedCapacity(gpa, fmt.len);
...@@ -950,6 +1035,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -950,6 +1035,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
950 self.items.len += w.end;1035 self.items.len += w.end;
951 }1036 }
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
953 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.1045 /// Deprecated in favor of `print` or `std.io.Writer.Allocating`.
954 pub const WriterContext = struct {1046 pub const WriterContext = struct {
955 self: *Self,1047 self: *Self,
...@@ -1004,9 +1096,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1004,9 +1096,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1004 }1096 }
10051097
1006 /// Append a value to the list `n` times.1098 /// Append a value to the list `n` times.
1099 ///
1007 /// Never invalidates element pointers.1100 /// Never invalidates element pointers.
1101 ///
1008 /// The function is inline so that a comptime-known `value` parameter will1102 /// The function is inline so that a comptime-known `value` parameter will
1009 /// have better memset codegen in case it has a repeated byte pattern.1103 /// have better memset codegen in case it has a repeated byte pattern.
1104 ///
1010 /// Asserts that the list can hold the additional items.1105 /// Asserts that the list can hold the additional items.
1011 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {1106 pub inline fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void {
1012 const new_len = self.items.len + n;1107 const new_len = self.items.len + n;
...@@ -1015,6 +1110,22 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1015,6 +1110,22 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1015 self.items.len = new_len;1110 self.items.len = new_len;
1016 }1111 }
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
1018 /// Adjust the list length to `new_len`.1129 /// Adjust the list length to `new_len`.
1019 /// Additional elements contain the value `undefined`.1130 /// Additional elements contain the value `undefined`.
1020 /// Invalidates element pointers if additional memory is needed.1131 /// Invalidates element pointers if additional memory is needed.
...@@ -1140,8 +1251,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1140,8 +1251,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1140 }1251 }
11411252
1142 /// Increase length by 1, returning pointer to the new item.1253 /// Increase length by 1, returning pointer to the new item.
1254 ///
1143 /// Never invalidates element pointers.1255 /// Never invalidates element pointers.
1256 ///
1144 /// The returned element pointer becomes invalid when the list is resized.1257 /// The returned element pointer becomes invalid when the list is resized.
1258 ///
1145 /// Asserts that the list can hold one additional item.1259 /// Asserts that the list can hold one additional item.
1146 pub fn addOneAssumeCapacity(self: *Self) *T {1260 pub fn addOneAssumeCapacity(self: *Self) *T {
1147 assert(self.items.len < self.capacity);1261 assert(self.items.len < self.capacity);
...@@ -1150,6 +1264,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1150,6 +1264,18 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1150 return &self.items[self.items.len - 1];1264 return &self.items[self.items.len - 1];
1151 }1265 }
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
1153 /// Resize the array, adding `n` new elements, which have `undefined` values.1279 /// Resize the array, adding `n` new elements, which have `undefined` values.
1154 /// The return value is an array pointing to the newly allocated elements.1280 /// The return value is an array pointing to the newly allocated elements.
1155 /// The returned pointer becomes invalid when the list is resized.1281 /// The returned pointer becomes invalid when the list is resized.
...@@ -1160,9 +1286,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1160,9 +1286,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1160 }1286 }
11611287
1162 /// Resize the array, adding `n` new elements, which have `undefined` values.1288 /// Resize the array, adding `n` new elements, which have `undefined` values.
1289 ///
1163 /// The return value is an array pointing to the newly allocated elements.1290 /// The return value is an array pointing to the newly allocated elements.
1291 ///
1164 /// Never invalidates element pointers.1292 /// Never invalidates element pointers.
1293 ///
1165 /// The returned pointer becomes invalid when the list is resized.1294 /// The returned pointer becomes invalid when the list is resized.
1295 ///
1166 /// Asserts that the list can hold the additional items.1296 /// Asserts that the list can hold the additional items.
1167 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {1297 pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T {
1168 assert(self.items.len + n <= self.capacity);1298 assert(self.items.len + n <= self.capacity);
...@@ -1171,6 +1301,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1171,6 +1301,21 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1171 return self.items[prev_len..][0..n];1301 return self.items[prev_len..][0..n];
1172 }1302 }
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
1174 /// Resize the array, adding `n` new elements, which have `undefined` values.1319 /// Resize the array, adding `n` new elements, which have `undefined` values.
1175 /// The return value is a slice pointing to the newly allocated elements.1320 /// The return value is a slice pointing to the newly allocated elements.
1176 /// The returned pointer becomes invalid when the list is resized.1321 /// The returned pointer becomes invalid when the list is resized.
...@@ -1181,10 +1326,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1181,10 +1326,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1181 return self.items[prev_len..][0..n];1326 return self.items[prev_len..][0..n];
1182 }1327 }
11831328
1184 /// Resize the array, adding `n` new elements, which have `undefined` values.1329 /// Resizes the array, adding `n` new elements, which have `undefined`
1185 /// The return value is a slice pointing to the newly allocated elements.1330 /// values, returning a slice pointing to the newly allocated elements.
1186 /// Never invalidates element pointers.1331 ///
1187 /// The returned pointer becomes invalid when the list is resized.1332 /// Never invalidates element pointers. The returned pointer becomes
1333 /// invalid when the list is resized.
1334 ///
1188 /// Asserts that the list can hold the additional items.1335 /// Asserts that the list can hold the additional items.
1189 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {1336 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
1190 assert(self.items.len + n <= self.capacity);1337 assert(self.items.len + n <= self.capacity);
...@@ -1193,6 +1340,19 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig...@@ -1193,6 +1340,19 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?mem.Alig
1193 return self.items[prev_len..][0..n];1340 return self.items[prev_len..][0..n];
1194 }1341 }
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
1196 /// Remove and return the last element from the list.1356 /// Remove and return the last element from the list.
1197 /// If the list is empty, returns `null`.1357 /// If the list is empty, returns `null`.
1198 /// Invalidates pointers to last element.1358 /// Invalidates pointers to last element.