Add relptr
This commit is contained in:
parent
48ef1fb4b7
commit
c1c722e1f7
102
common/relptr/relptr.odin
Normal file
102
common/relptr/relptr.odin
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Relative pointer
|
||||||
|
package relptr
|
||||||
|
|
||||||
|
import "base:intrinsics"
|
||||||
|
|
||||||
|
Ptr :: struct($T: typeid) {
|
||||||
|
offset: uintptr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Slice :: struct($T: typeid) {
|
||||||
|
offset: uintptr,
|
||||||
|
len: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
SOA_Slice :: struct($T: typeid) {
|
||||||
|
// Offset for each field of SOA struct
|
||||||
|
offsets: [len(
|
||||||
|
T,
|
||||||
|
) when intrinsics.type_is_array(T) else intrinsics.type_struct_field_count(T)]uintptr,
|
||||||
|
len: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
from_rawptr :: #force_inline proc($T: typeid, addr: rawptr, base := context.user_ptr) -> Ptr(T) {
|
||||||
|
offset := uintptr(addr) - uintptr(base)
|
||||||
|
assert(offset >= 0, "ptr does not belong to this base")
|
||||||
|
|
||||||
|
return Ptr(T){offset = offset}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_ptr :: #force_inline proc(addr: ^$T, base := context.user_ptr) -> Ptr(T) {
|
||||||
|
offset := uintptr(rawptr(addr)) - uintptr(base)
|
||||||
|
assert(offset >= 0, "ptr does not belong to this base")
|
||||||
|
|
||||||
|
return Ptr(T){offset = offset}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_multi_ptr :: #force_inline proc(addr: [^]$T, base := context.user_ptr) -> Ptr(T) {
|
||||||
|
offset := uintptr(rawptr(addr)) - uintptr(base)
|
||||||
|
assert(offset >= 0, "ptr does not belong to this base")
|
||||||
|
|
||||||
|
return Ptr(T){offset = offset}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_slice :: #force_inline proc(slice: []$T, base := context.user_ptr) -> Slice(T) {
|
||||||
|
offset := uintptr(rawptr(raw_data(slice))) - uintptr(base)
|
||||||
|
assert(offset >= 0, "ptr does not belong to this base")
|
||||||
|
|
||||||
|
return Slice(T){offset = offset, len = len(slice)}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_soa_slice :: #force_inline proc(slice: #soa[]$T, base := context.user_ptr) -> SOA_Slice(T) {
|
||||||
|
slice := slice
|
||||||
|
|
||||||
|
result: SOA_Slice(T)
|
||||||
|
|
||||||
|
FIELD_COUNT ::
|
||||||
|
(len(T) when intrinsics.type_is_array(T) else intrinsics.type_struct_field_count(T))
|
||||||
|
|
||||||
|
// SOA slice is just an array of pointers to each member + a footer
|
||||||
|
src_ptrs := (transmute([^]uintptr)(&slice))[:FIELD_COUNT]
|
||||||
|
|
||||||
|
for i in 0 ..< len(result.offsets) {
|
||||||
|
result.offsets[i] = src_ptrs[i] - uintptr(base)
|
||||||
|
}
|
||||||
|
result.len = len(slice)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_ptr :: #force_inline proc(ptr: Ptr($T), base := context.user_ptr) -> ^T {
|
||||||
|
return transmute(^T)(uintptr(base) + ptr.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_multi_ptr :: #force_inline proc(ptr: Ptr($T), base := context.user_ptr) -> [^]T {
|
||||||
|
return transmute([^]T)(uintptr(base) + ptr.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_slice :: #force_inline proc(slice: Slice($T), base := context.user_ptr) -> []T {
|
||||||
|
return (transmute([^]T)(uintptr(base) + slice.offset))[:slice.len]
|
||||||
|
}
|
||||||
|
|
||||||
|
deref_soa_slice :: #force_inline proc(slice: SOA_Slice($T), base := context.user_ptr) -> #soa[]T {
|
||||||
|
result: #soa[]T
|
||||||
|
|
||||||
|
footer := raw_soa_footer_slice(&result)
|
||||||
|
|
||||||
|
FIELD_COUNT ::
|
||||||
|
(len(T) when intrinsics.type_is_array(T) else intrinsics.type_struct_field_count(T))
|
||||||
|
|
||||||
|
// Just in case SOA layout changes
|
||||||
|
#assert(size_of(result) == (FIELD_COUNT * size_of(rawptr)) + size_of(footer))
|
||||||
|
|
||||||
|
// SOA slice is just an array of pointers to each member + a footer
|
||||||
|
result_ptrs := (transmute([^]uintptr)(&result))[:FIELD_COUNT]
|
||||||
|
for i in 0 ..< len(slice.offsets) {
|
||||||
|
result_ptrs[i] = uintptr(base) + slice.offsets[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
footer.len = slice.len
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user