Skip to content

Commit

Permalink
add property query support
Browse files Browse the repository at this point in the history
  • Loading branch information
vaind committed Aug 18, 2021
1 parent ce1eb8a commit 448fc64
Show file tree
Hide file tree
Showing 6 changed files with 1,158 additions and 39 deletions.
266 changes: 228 additions & 38 deletions objectbox/c-arrays.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,6 @@ func (bytesArray *bytesArray) free() {
bytesArray.array = nil
}

func cBytesArrayToGo(cBytesArray *C.OBX_bytes_array) [][]byte {
size := int(cBytesArray.count)
plainBytesArray := make([][]byte, size)

if size > 0 {
var sliceOfCBytes []C.OBX_bytes
// see cVoidPtrToByteSlice for documentation of the following approach in general
header := (*reflect.SliceHeader)(unsafe.Pointer(&sliceOfCBytes))
header.Data = uintptr(unsafe.Pointer(cBytesArray.bytes))
header.Len = size
header.Cap = size

for i := 0; i < size; i++ {
cBytes := sliceOfCBytes[i]
cVoidPtrToByteSlice(unsafe.Pointer(cBytes.data), int(cBytes.size), &(plainBytesArray[i]))
}
}

return plainBytesArray
}

func goBytesArrayToC(goArray [][]byte) (*bytesArray, error) {
// for native calls/createError()
runtime.LockOSThread()
Expand Down Expand Up @@ -113,19 +92,6 @@ func (array *idsArray) free() {
array.ids = nil
}

func cIdsArrayToGo(cArray *C.OBX_id_array) []uint64 {
var size = uint(cArray.count)
var ids = make([]uint64, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.ids)
var cSize = unsafe.Sizeof(*cArray.ids)
for i := uint(0); i < size; i++ {
ids[i] = *(*uint64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cSize))
}
}
return ids
}

func goIdsArrayToC(ids []uint64) (*idsArray, error) {
// for native calls/createError()
runtime.LockOSThread()
Expand All @@ -140,20 +106,20 @@ func goIdsArrayToC(ids []uint64) (*idsArray, error) {
return &idsArray{ids, cArray}, err
}

type stringArray struct {
type charPtrsArray struct {
cArray **C.char
size int
}

func (array *stringArray) free() {
func (array *charPtrsArray) free() {
if array.cArray != nil {
C.freeCharArray(array.cArray, C.int(array.size))
array.cArray = nil
}
}

func goStringArrayToC(values []string) *stringArray {
result := &stringArray{
func goStringArrayToC(values []string) *charPtrsArray {
result := &charPtrsArray{
cArray: C.newCharArray(C.int(len(values))),
size: len(values),
}
Expand Down Expand Up @@ -191,6 +157,230 @@ func cBytesPtr(value []byte) unsafe.Pointer {
return unsafe.Pointer(&value[0])
}

/**
Functions for reading OBX_*_array to Go. The passed C array still needs to be freed manually.
Generics please!!!
*/

// WARN: this function doesn't create a copy of each byte-vector (item) but references it in the C source instead
// Therefore, it's only supposed to be used intra-library (usually inside a read transaction)
func cBytesArrayToGo(cArray *C.OBX_bytes_array) [][]byte {
size := int(cArray.count)
plainBytesArray := make([][]byte, size)

if size > 0 {
var sliceOfCBytes []C.OBX_bytes
// see cVoidPtrToByteSlice for documentation of the following approach in general
header := (*reflect.SliceHeader)(unsafe.Pointer(&sliceOfCBytes))
header.Data = uintptr(unsafe.Pointer(cArray.bytes))
header.Len = size
header.Cap = size

for i := 0; i < size; i++ {
cBytes := sliceOfCBytes[i]
cVoidPtrToByteSlice(unsafe.Pointer(cBytes.data), int(cBytes.size), &(plainBytesArray[i])) // reference
}
}

return plainBytesArray
}

func cStringsArrayToGo(cArray *C.OBX_string_array) []string {
var size = uint(cArray.count)
var items = make([]string, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
var cCharPtr = (**C.char)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize))
items[i] = C.GoString(*cCharPtr) // make a copy
}
}
return items
}

func cIdsArrayToGo(cArray *C.OBX_id_array) []uint64 {
var size = uint(cArray.count)
var items = make([]uint64, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.ids)
var cItemSize = unsafe.Sizeof(*cArray.ids)
for i := uint(0); i < size; i++ {
items[i] = *(*uint64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return items
}

func cIntsArrayToGo(cArray *C.OBX_int64_array) []int {
var size = uint(cArray.count)
var result = make([]int, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = int(*(*int64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize))) // make a copy
}
}
return result
}

func cUintsArrayToGo(cArray *C.OBX_int64_array) []uint {
var size = uint(cArray.count)
var result = make([]uint, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = uint(*(*uint64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize))) // make a copy
}
}
return result
}

func cInt64sArrayToGo(cArray *C.OBX_int64_array) []int64 {
var size = uint(cArray.count)
var result = make([]int64, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*int64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cUint64sArrayToGo(cArray *C.OBX_int64_array) []uint64 {
var size = uint(cArray.count)
var result = make([]uint64, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*uint64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cInt32sArrayToGo(cArray *C.OBX_int32_array) []int32 {
var size = uint(cArray.count)
var result = make([]int32, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*int32)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cUint32sArrayToGo(cArray *C.OBX_int32_array) []uint32 {
var size = uint(cArray.count)
var result = make([]uint32, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*uint32)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cInt16sArrayToGo(cArray *C.OBX_int16_array) []int16 {
var size = uint(cArray.count)
var result = make([]int16, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*int16)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cUint16sArrayToGo(cArray *C.OBX_int16_array) []uint16 {
var size = uint(cArray.count)
var result = make([]uint16, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*uint16)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cInt8sArrayToGo(cArray *C.OBX_int8_array) []int8 {
var size = uint(cArray.count)
var result = make([]int8, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*int8)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cUint8sArrayToGo(cArray *C.OBX_int8_array) []uint8 {
var size = uint(cArray.count)
var result = make([]uint8, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*uint8)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cBoolsArrayToGo(cArray *C.OBX_int8_array) []bool {
var size = uint(cArray.count)
var result = make([]bool, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = 1 == *(*uint8)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cFloat64sArrayToGo(cArray *C.OBX_double_array) []float64 {
var size = uint(cArray.count)
var result = make([]float64, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*float64)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

func cFloat32sArrayToGo(cArray *C.OBX_float_array) []float32 {
var size = uint(cArray.count)
var result = make([]float32, size)
if size > 0 {
var cArrayStart = unsafe.Pointer(cArray.items)
var cItemSize = unsafe.Sizeof(*cArray.items)
for i := uint(0); i < size; i++ {
result[i] = *(*float32)(unsafe.Pointer(uintptr(cArrayStart) + uintptr(i)*cItemSize)) // make a copy
}
}
return result
}

// Maps a C void* to the given byte-slice. The void* is not garbage collected and must be managed outside.
//
// Previous alternative without reflect https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices
Expand Down
Loading

0 comments on commit 448fc64

Please sign in to comment.