hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mslices/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));