//export GOLUCY_Inverter_Invert_Doc func GOLUCY_Inverter_Invert_Doc(inverter *C.lucy_Inverter, doc *C.lucy_Doc) { ivars := C.lucy_Inverter_IVARS(inverter) fields := (*C.cfish_Hash)(C.LUCY_Doc_Get_Fields(doc)) // Prepare for the new doc. C.LUCY_Inverter_Set_Doc(inverter, doc) // Extract and invert the doc's fields. iter := C.cfish_HashIter_new(fields) for C.CFISH_HashIter_Next(iter) { field := C.CFISH_HashIter_Get_Key(iter) obj := C.CFISH_HashIter_Get_Value(iter) if obj == nil { mess := "Invalid nil value for field" + clownfish.CFStringToGo(unsafe.Pointer(field)) panic(clownfish.NewErr(mess)) } inventry := fetchEntry(ivars, field) inventryIvars := C.lucy_InvEntry_IVARS(inventry) fieldType := inventryIvars._type // Get the field value. var expectedType *C.cfish_Class switch C.LUCY_FType_Primitive_ID(fieldType) & C.lucy_FType_PRIMITIVE_ID_MASK { case C.lucy_FType_TEXT: expectedType = C.CFISH_STRING case C.lucy_FType_BLOB: expectedType = C.CFISH_BLOB case C.lucy_FType_INT32: expectedType = C.CFISH_INTEGER case C.lucy_FType_INT64: expectedType = C.CFISH_INTEGER case C.lucy_FType_FLOAT32: expectedType = C.CFISH_FLOAT case C.lucy_FType_FLOAT64: expectedType = C.CFISH_FLOAT default: panic(clownfish.NewErr("Internal Lucy error: bad type id for field " + clownfish.CFStringToGo(unsafe.Pointer(field)))) } if !C.cfish_Obj_is_a(obj, expectedType) { className := C.cfish_Obj_get_class_name((*C.cfish_Obj)(unsafe.Pointer(fieldType))) mess := fmt.Sprintf("Invalid type for field '%s': '%s'", clownfish.CFStringToGo(unsafe.Pointer(field)), clownfish.CFStringToGo(unsafe.Pointer(className))) panic(clownfish.NewErr(mess)) } if inventryIvars.value != obj { C.cfish_decref(unsafe.Pointer(inventryIvars.value)) inventryIvars.value = C.cfish_inc_refcount(unsafe.Pointer(obj)) } C.LUCY_Inverter_Add_Field(inverter, inventry) } C.cfish_dec_refcount(unsafe.Pointer(iter)) }
func (obj *HitsIMP) Next(hit interface{}) bool { self := ((*C.lucy_Hits)(unsafe.Pointer(obj.TOPTR()))) // TODO: accept a HitDoc object and populate score. // Get reflection value and type for the supplied struct. var hitValue reflect.Value if reflect.ValueOf(hit).Kind() == reflect.Ptr { temp := reflect.ValueOf(hit).Elem() if temp.Kind() == reflect.Struct { if temp.CanSet() { hitValue = temp } } } if hitValue == (reflect.Value{}) { mess := fmt.Sprintf("Arg not writeable struct pointer: %v", reflect.TypeOf(hit)) obj.err = clownfish.NewErr(mess) return false } var docC *C.lucy_HitDoc errCallingNext := clownfish.TrapErr(func() { docC = C.LUCY_Hits_Next(self) }) if errCallingNext != nil { obj.err = errCallingNext return false } if docC == nil { return false } defer C.cfish_dec_refcount(unsafe.Pointer(docC)) fields := (*C.cfish_Hash)(unsafe.Pointer(C.LUCY_HitDoc_Get_Fields(docC))) iterator := C.cfish_HashIter_new(fields) defer C.cfish_dec_refcount(unsafe.Pointer(iterator)) for C.CFISH_HashIter_Next(iterator) { keyC := C.CFISH_HashIter_Get_Key(iterator) valC := C.CFISH_HashIter_Get_Value(iterator) key := clownfish.CFStringToGo(unsafe.Pointer(keyC)) val := clownfish.CFStringToGo(unsafe.Pointer(valC)) match := func(name string) bool { return strings.EqualFold(key, name) } structField := hitValue.FieldByNameFunc(match) if structField != (reflect.Value{}) { structField.SetString(val) } } return true }
func HashToGo(ptr unsafe.Pointer) map[string]interface{} { hash := (*C.cfish_Hash)(ptr) if hash == nil { return nil } class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr)) if class != C.CFISH_HASH { mess := "Not a Hash: " + StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(class))) panic(NewErr(mess)) } size := C.CFISH_Hash_Get_Size(hash) m := make(map[string]interface{}, int(size)) iter := C.cfish_HashIter_new(hash) defer C.cfish_dec_refcount(unsafe.Pointer(iter)) for C.CFISH_HashIter_Next(iter) { key := C.CFISH_HashIter_Get_Key(iter) val := C.CFISH_HashIter_Get_Value(iter) m[StringToGo(unsafe.Pointer(key))] = ToGo(unsafe.Pointer(val)) } return m }