Skip to content

Commit c47ec4f

Browse files
committed
std.array_list: add bounded methods
1 parent 6f54568 commit c47ec4f

File tree

1 file changed

+167
-7
lines changed

1 file changed

+167
-7
lines changed

lib/std/array_list.zig

Lines changed: 167 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

0 commit comments

Comments
 (0)