60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package xx
|
|
|
|
import (
|
|
"runtime"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"git.brut.systems/judah/xx/mem"
|
|
)
|
|
|
|
// Copy copies src number of bytes into dst.
|
|
// Returns dst.
|
|
//
|
|
// Copy panics if src is smaller than dst.
|
|
func Copy[TDst any, TSrc any](dst *TDst, src *TSrc) *TDst {
|
|
if mem.Sizeof[TSrc]() < mem.Sizeof[TDst]() {
|
|
panic("copy: size of src must be >= dst")
|
|
}
|
|
mem.Copy(unsafe.Pointer(dst), unsafe.Pointer(src), mem.Sizeof[TDst]())
|
|
return dst
|
|
}
|
|
|
|
// Clone returns a newly allocated shallow copy of the given value.
|
|
func Clone[T any](value *T) *T {
|
|
return Copy(new(T), value)
|
|
}
|
|
|
|
// BoolUint converts a boolean to an integer.
|
|
func BoolUint(b bool) uint {
|
|
return uint(*(*uint8)(unsafe.Pointer(&b)))
|
|
}
|
|
|
|
// CallerLocation returns the source location of the function CallerLocation is called in.
|
|
func CallerLocation() (file string, line int) {
|
|
_, file, line, _ = runtime.Caller(2)
|
|
|
|
// @todo: I'm sure there's a better way to do this
|
|
// Special-case when CallerLocation is called from main
|
|
if strings.Contains(file, "runtime") && strings.Contains(file, "proc.go") {
|
|
_, file, line, _ = runtime.Caller(1)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// HashLocation returns a hash of file and line, most likely returned from [CallerLocation].
|
|
func HashLocation(file string, line int) uint64 {
|
|
const (
|
|
FNV64_PRIME uint64 = 0x100000001B3
|
|
FNV64_BIAS uint64 = 0xCBF29CE484222325
|
|
)
|
|
|
|
h := FNV64_BIAS
|
|
for _, c := range file {
|
|
h = (h ^ uint64(c)) * FNV64_PRIME
|
|
}
|
|
|
|
h = (h ^ uint64(line)) * FNV64_PRIME
|
|
return h
|
|
}
|