func goToHash(value interface{}, nullable bool) unsafe.Pointer { switch v := value.(type) { case map[string]interface{}: if v == nil { if nullable { return nil } } else { size := len(v) hash := C.cfish_Hash_new(C.size_t(size)) for key, val := range v { newVal := GoToClownfish(val, nil, true) keySize := len(key) keyStr := C.CString(key) cfKey := C.cfish_Str_new_steal_utf8(keyStr, C.size_t(keySize)) defer C.cfish_dec_refcount(unsafe.Pointer(cfKey)) C.CFISH_Hash_Store(hash, cfKey, (*C.cfish_Obj)(newVal)) } return unsafe.Pointer(hash) } case Obj: certifyCF(v, C.CFISH_HASH, nullable) return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR()))) } mess := fmt.Sprintf("Can't convert %T to clownfish.Hash", value) panic(NewErr(mess)) }
func goToString(value interface{}, nullable bool) unsafe.Pointer { switch v := value.(type) { case string: size := len(v) str := C.CString(v) return unsafe.Pointer(C.cfish_Str_new_steal_utf8(str, C.size_t(size))) case Obj: certifyCF(v, C.CFISH_STRING, nullable) return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR()))) } mess := fmt.Sprintf("Can't convert %T to clownfish.String", value) panic(NewErr(mess)) }
// Turn a slice of Go strings into a Vector of Clownfish Strings. func stringSliceToVec(strings []string) *C.cfish_Vector { if strings == nil { return nil } size := len(strings) vec := C.cfish_Vec_new(C.size_t(size)) for i := 0; i < size; i++ { str := C.CString(strings[i]) length := C.size_t(len(strings[i])) cfStr := C.cfish_Str_new_steal_utf8(str, length) C.CFISH_Vec_Push(vec, (*C.cfish_Obj)(unsafe.Pointer(cfStr))) } return vec }
func NewString(goString string) String { str := C.CString(goString) len := C.size_t(len(goString)) cfObj := C.cfish_Str_new_steal_utf8(str, len) return WRAPString(unsafe.Pointer(cfObj)) }
//export GOLUCY_DefDocReader_Fetch_Doc func GOLUCY_DefDocReader_Fetch_Doc(ddr *C.lucy_DefaultDocReader, docID C.int32_t) *C.lucy_HitDoc { ivars := C.lucy_DefDocReader_IVARS(ddr) schema := ivars.schema datInstream := ivars.dat_in ixInstream := ivars.ix_in fields := C.cfish_Hash_new(1) fieldNameCap := C.size_t(31) var fieldName *C.char = ((*C.char)(C.malloc(fieldNameCap + 1))) // Get data file pointer from index, read number of fields. C.LUCY_InStream_Seek(ixInstream, C.int64_t(docID*8)) start := C.LUCY_InStream_Read_U64(ixInstream) C.LUCY_InStream_Seek(datInstream, C.int64_t(start)) numFields := uint32(C.LUCY_InStream_Read_C32(datInstream)) // Decode stored data and build up the doc field by field. for i := uint32(0); i < numFields; i++ { // Read field name. fieldNameLen := C.size_t(C.LUCY_InStream_Read_C32(datInstream)) if fieldNameLen > fieldNameCap { fieldNameCap = fieldNameLen fieldName = ((*C.char)(C.realloc(unsafe.Pointer(fieldName), fieldNameCap+1))) } C.LUCY_InStream_Read_Bytes(datInstream, fieldName, fieldNameLen) // Find the Field's FieldType. // TODO: Creating and destroying a new string each time is // inefficient. The solution should be to add a privte // Schema_Fetch_Type_Utf8 method which takes char* and size_t. fieldNameStr := C.cfish_Str_new_from_utf8(fieldName, fieldNameLen) fieldType := C.LUCY_Schema_Fetch_Type(schema, fieldNameStr) C.cfish_dec_refcount(unsafe.Pointer(fieldNameStr)) // Read the field value. var value *C.cfish_Obj switch C.LUCY_FType_Primitive_ID(fieldType) & C.lucy_FType_PRIMITIVE_ID_MASK { case C.lucy_FType_TEXT: valueLen := C.size_t(C.LUCY_InStream_Read_C32(datInstream)) buf := ((*C.char)(C.malloc(valueLen + 1))) C.LUCY_InStream_Read_Bytes(datInstream, buf, valueLen) C.null_terminate_string(buf, valueLen) value = ((*C.cfish_Obj)(C.cfish_Str_new_steal_utf8(buf, valueLen))) case C.lucy_FType_BLOB: valueLen := C.size_t(C.LUCY_InStream_Read_C32(datInstream)) buf := ((*C.char)(C.malloc(valueLen))) C.LUCY_InStream_Read_Bytes(datInstream, buf, valueLen) value = ((*C.cfish_Obj)(C.cfish_Blob_new_steal(buf, valueLen))) case C.lucy_FType_FLOAT32: value = ((*C.cfish_Obj)(C.cfish_Float_new(C.double(C.LUCY_InStream_Read_F32(datInstream))))) case C.lucy_FType_FLOAT64: value = ((*C.cfish_Obj)(C.cfish_Float_new(C.LUCY_InStream_Read_F64(datInstream)))) case C.lucy_FType_INT32: value = ((*C.cfish_Obj)(C.cfish_Int_new(C.int64_t(C.LUCY_InStream_Read_C32(datInstream))))) case C.lucy_FType_INT64: value = ((*C.cfish_Obj)(C.cfish_Int_new(C.int64_t(C.LUCY_InStream_Read_C64(datInstream))))) default: value = nil panic(clownfish.NewErr("Internal Lucy error: bad type id for field " + C.GoStringN(fieldName, C.int(fieldNameLen)))) } // Store the value. C.CFISH_Hash_Store_Utf8(fields, fieldName, fieldNameLen, value) } C.free(unsafe.Pointer(fieldName)) retval := C.lucy_HitDoc_new(unsafe.Pointer(fields), docID, 0.0) C.cfish_dec_refcount(unsafe.Pointer(fields)) return retval }