mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
add Str.releaseExcessCapacity
This commit is contained in:
parent
a80b25d044
commit
48f17a8e2c
11 changed files with 115 additions and 0 deletions
|
@ -156,6 +156,7 @@ comptime {
|
|||
exportStrFn(str.withCapacity, "with_capacity");
|
||||
exportStrFn(str.strGraphemes, "graphemes");
|
||||
exportStrFn(str.strRefcountPtr, "refcount_ptr");
|
||||
exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity");
|
||||
|
||||
inline for (INTEGERS) |T| {
|
||||
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");
|
||||
|
|
|
@ -121,6 +121,22 @@ pub const RocStr = extern struct {
|
|||
}
|
||||
}
|
||||
|
||||
// allocate space for a (big or small) RocStr, but put nothing in it yet.
|
||||
// Will have the exact same capacity as length if it is not a small string.
|
||||
pub fn allocateExact(length: usize) RocStr {
|
||||
const result_is_big = length >= SMALL_STRING_SIZE;
|
||||
|
||||
if (result_is_big) {
|
||||
return RocStr.allocateBig(length, length);
|
||||
} else {
|
||||
var string = RocStr.empty();
|
||||
|
||||
string.asU8ptrMut()[@sizeOf(RocStr) - 1] = @intCast(u8, length) | 0b1000_0000;
|
||||
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns all ones if the list is a seamless slice.
|
||||
// Otherwise, it returns all zeros.
|
||||
// This is done without branching for optimization purposes.
|
||||
|
@ -2891,3 +2907,27 @@ pub fn strRefcountPtr(
|
|||
) callconv(.C) ?[*]u8 {
|
||||
return string.getRefcountPtr();
|
||||
}
|
||||
|
||||
pub fn strReleaseExcessCapacity(
|
||||
string: RocStr,
|
||||
) callconv(.C) RocStr {
|
||||
const old_length = string.len();
|
||||
// We use the direct list.capacity_or_ref_ptr to make sure both that there is no extra capacity and that it isn't a seamless slice.
|
||||
if (string.isSmallStr()) {
|
||||
// SmallStr has no excess capacity.
|
||||
return string;
|
||||
} else if (string.isUnique() and !string.isSeamlessSlice() and string.getCapacity() == old_length) {
|
||||
return string;
|
||||
} else if (old_length == 0) {
|
||||
string.decref();
|
||||
return RocStr.empty();
|
||||
} else {
|
||||
var output = RocStr.allocateExact(old_length);
|
||||
const source_ptr = string.asU8ptr();
|
||||
const dest_ptr = output.asU8ptrMut();
|
||||
|
||||
@memcpy(dest_ptr, source_ptr, old_length);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue