First you need to get your type correct, note 0
and null
are different values.
I think in your case, your type is basically this, but without the optional:
So we end up with:
const result: [*:null][*:0]const u8 = @ptrCast(clib.string_split(allocator, str.ptr, delim.ptr));
A null result is equal to a null-sentinel-terminated slice of length zero, so optional would make us handle the same thing in two different ways.
Now we can convert the outer sentinel-terminated slice to a normal slice:
const results = std.mem.span(result);
if(results.len > 0) {
return results;
} else {
return CResult.Null;
}
Also your input types should be zero terminated, so you end up with:
pub fn stringSplit(allocator: *Callocator, str: [:0]const u8, delim: [:0]const u8) ![][:0]const u8 {
const result: [*:null][*:0]const u8 = @ptrCast(clib.string_split(allocator, str.ptr, delim.ptr));
const results = std.mem.span(result);
if(results.len > 0) {
return results;
} else {
return CResult.Null;
}
}
Personally I would stop here, because I find this is an easy middle ground where the types basically meet in the middle. I don’t think there is a big reason to go all the way to eliminate the inner sentinel terminated slices, instead I would just work with the inner sentinel terminated slices directly.
If you want to convert to all non-sentinel slices anyway you can use one of the approaches @dimdin pointed out.