commit ac7517aae812a350cb1ec21e4189aad724f34b46
parent 800542bd3b04a89e2d9b84c10bd8d6078d46f798
Author: Sebastian <sebastian@sebsite.pw>
Date: Mon, 9 May 2022 18:38:34 -0400
slices: add static_* functions
deletefrom has also been renamed to static_deletefrom, and a new
deletefrom function which reallocates memory has been added.
Documentation for the non-static variants has been updated to clarify
allocation behavior.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
M | slices/void.ha | | | 75 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 66 insertions(+), 9 deletions(-)
diff --git a/slices/void.ha b/slices/void.ha
@@ -3,7 +3,7 @@
use rt;
use types;
-// Appends an item, or multiple items, to a slice.
+// Appends an item, or multiple items, to a slice, reallocating if necessary.
export fn appendto(sl: *[]void, itemsz: size, items: const *void...) void = {
const repr = sl: *types::slice;
insertinto(sl, itemsz, repr.length, items...);
@@ -21,7 +21,19 @@ export fn appendto(sl: *[]void, itemsz: size, items: const *void...) void = {
free(input);
};
-// Inserts an item, or multiple items, to a slice, in O(n) time.
+// Appends an item, or multiple items, to a slice. Aborts if the slice's
+// capacity isn't large enough to fit the items.
+export fn static_appendto(
+ sl: *[]void,
+ itemsz: size,
+ items: const *void...
+) void = {
+ const repr = sl: *types::slice;
+ static_insertinto(sl, itemsz, repr.length, items...);
+};
+
+// Inserts an item, or multiple items, to a slice, in O(n) time, reallocating if
+// necessary.
export fn insertinto(
sl: *[]void,
itemsz: size,
@@ -51,17 +63,44 @@ export fn insertinto(
free(input);
};
-// Deletes a range of items from a slice, in O(n) time, without freeing memory.
-export fn deletefrom(sl: *[]void, itemsz: size, start: size, end: size) void = {
- assert(start <= end);
- if (start == end) {
+// Inserts an item, or multiple items, into a slice, in O(n) time. Aborts if the
+// slice's capacity isn't large enough to fit the items.
+export fn static_insertinto(
+ sl: *[]void,
+ itemsz: size,
+ idx: size,
+ items: const *void...
+) void = {
+ if (len(items) == 0) {
return;
};
let sl = sl: *types::slice;
+ sl.length += len(items);
+ assert(sl.length <= sl.capacity,
+ "static insert/append exceeds slice capacity");
let data = sl.data: *[*]u8;
- rt::memmove(&data[start * itemsz], &data[end * itemsz],
- (sl.length - start) * itemsz);
- sl.length -= end - start;
+ rt::memmove(&data[(idx + len(items)) * itemsz], &data[idx * itemsz],
+ (sl.length - len(items) - idx) * itemsz);
+ for (let i = 0z; i < len(items); i += 1) {
+ rt::memcpy(&data[(idx + i) * itemsz], items[i], itemsz);
+ };
+};
+
+// Deletes a range of items from a slice, in O(n) time. The slice may be
+// reallocated. Reallocation will never fail.
+export fn deletefrom(sl: *[]void, itemsz: size, start: size, end: size) void = {
+ static_deletefrom(sl, itemsz, start, end);
+ let sl = sl: *types::slice;
+ if (sl.length <= sl.capacity / 2) {
+ // TODO: switch to using alloc() once it's possible to handle
+ // copy allocation errors
+ match (rt::realloc(sl.data, sl.length * itemsz)) {
+ case null => void;
+ case let p: *void =>
+ sl.data = p;
+ sl.capacity = sl.length;
+ };
+ };
};
@test fn deletefrom() void = {
@@ -74,6 +113,24 @@ export fn deletefrom(sl: *[]void, itemsz: size, start: size, end: size) void = {
free(input);
};
+// Deletes a range of items from a slice, in O(n) time, without freeing memory.
+export fn static_deletefrom(
+ sl: *[]void,
+ itemsz: size,
+ start: size,
+ end: size,
+) void = {
+ assert(start <= end);
+ if (start == end) {
+ return;
+ };
+ let sl = sl: *types::slice;
+ let data = sl.data: *[*]u8;
+ rt::memmove(&data[start * itemsz], &data[end * itemsz],
+ (sl.length - start) * itemsz);
+ sl.length -= end - start;
+};
+
// Swaps two elements of a slice.
export fn swap(sl: []void, itemsz: size, a: size, b: size) void = {
assert(a < len(sl) && b < len(sl));