//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 fetchEntry(ivars *C.lucy_InverterIVARS, fieldGo string) *C.lucy_InverterEntry { field := (*C.cfish_String)(clownfish.GoToClownfish(fieldGo, unsafe.Pointer(C.CFISH_STRING), false)) defer C.cfish_decref(unsafe.Pointer(field)) schema := ivars.schema fieldNum := C.LUCY_Seg_Field_Num(ivars.segment, field) if fieldNum == 0 { // This field seems not to be in the segment yet. Try to find it in // the Schema. if C.LUCY_Schema_Fetch_Type(schema, field) != nil { // The field is in the Schema. Get a field num from the Segment. fieldNum = C.LUCY_Seg_Add_Field(ivars.segment, field) } else { // We've truly failed to find the field. The user must // not have spec'd it. fieldGo := clownfish.CFStringToGo(unsafe.Pointer(field)) err := clownfish.NewErr("Unknown field name: '" + fieldGo + "'") panic(err) } } entry := C.CFISH_Vec_Fetch(ivars.entry_pool, C.size_t(fieldNum)) if entry == nil { newEntry := C.lucy_InvEntry_new(schema, field, fieldNum) C.CFISH_Vec_Store(ivars.entry_pool, C.size_t(fieldNum), (*C.cfish_Obj)(unsafe.Pointer(entry))) return newEntry } return (*C.lucy_InverterEntry)(unsafe.Pointer(entry)) }
// Turn a Vector of Clownfish Strings into a slice of Go string. NULL // elements in the Vector are not allowed. func vecToStringSlice(v *C.cfish_Vector) []string { if v == nil { return nil } length := int(C.CFISH_Vec_Get_Size(v)) slice := make([]string, length) for i := 0; i < length; i++ { slice[i] = clownfish.CFStringToGo(unsafe.Pointer(C.CFISH_Vec_Fetch(v, C.size_t(i)))) } return slice }
//export GOLUCY_RegexTokenizer_init func GOLUCY_RegexTokenizer_init(rt *C.lucy_RegexTokenizer, pattern *C.cfish_String) *C.lucy_RegexTokenizer { C.lucy_Analyzer_init(((*C.lucy_Analyzer)(unsafe.Pointer(rt)))) ivars := C.lucy_RegexTokenizer_IVARS(rt) ivars.pattern = C.CFISH_Str_Clone(pattern) var patternGo string if pattern == nil { patternGo = "\\w+(?:['\\x{2019}]\\w+)*" } else { patternGo = clownfish.CFStringToGo(unsafe.Pointer(pattern)) } rx, err := regexp.Compile(patternGo) if err != nil { panic(err) } rxID := registry.store(rx) ivars.token_re = unsafe.Pointer(rxID) return rt }
func (obj *IndexerIMP) findFieldC(name string) *C.cfish_String { self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR()))) if obj.fieldNames == nil { obj.fieldNames = make(map[string]clownfish.String) } f, ok := obj.fieldNames[name] if !ok { schema := C.LUCY_Indexer_Get_Schema(self) fieldList := C.LUCY_Schema_All_Fields(schema) defer C.cfish_dec_refcount(unsafe.Pointer(fieldList)) for i := 0; i < int(C.CFISH_Vec_Get_Size(fieldList)); i++ { cfString := unsafe.Pointer(C.CFISH_Vec_Fetch(fieldList, C.size_t(i))) field := clownfish.CFStringToGo(cfString) if strings.EqualFold(name, field) { C.cfish_inc_refcount(cfString) f = clownfish.WRAPString(cfString) obj.fieldNames[name] = f } } } return (*C.cfish_String)(unsafe.Pointer(f.TOPTR())) }
//export GOLUCY_RegexTokenizer_Tokenize_Utf8 func GOLUCY_RegexTokenizer_Tokenize_Utf8(rt *C.lucy_RegexTokenizer, str *C.char, stringLen C.size_t, inversion *C.lucy_Inversion) { ivars := C.lucy_RegexTokenizer_IVARS(rt) rxID := uintptr(ivars.token_re) rx, ok := registry.fetch(rxID).(*regexp.Regexp) if !ok { mess := fmt.Sprintf("Failed to Fetch *RegExp with id %d and pattern %s", rxID, clownfish.CFStringToGo(unsafe.Pointer(ivars.pattern))) panic(clownfish.NewErr(mess)) } buf := C.GoBytes(unsafe.Pointer(str), C.int(stringLen)) found := rx.FindAllIndex(buf, int(stringLen)) lastEnd := 0 cpCount := 0 for _, startEnd := range found { cpCount = int(C.push_token(str, C.int(startEnd[0]), C.int(startEnd[1]), C.int(lastEnd), C.int(cpCount), inversion)) lastEnd = startEnd[1] } }
func (obj *IndexerIMP) findRealField(name string) (string, error) { self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR()))) if obj.fieldNames == nil { obj.fieldNames = make(map[string]string) } if field, ok := obj.fieldNames[name]; ok { return field, nil } else { schema := C.LUCY_Indexer_Get_Schema(self) fieldList := C.LUCY_Schema_All_Fields(schema) defer C.cfish_dec_refcount(unsafe.Pointer(fieldList)) for i := 0; i < int(C.CFISH_Vec_Get_Size(fieldList)); i++ { cfString := unsafe.Pointer(C.CFISH_Vec_Fetch(fieldList, C.size_t(i))) field := clownfish.CFStringToGo(cfString) if strings.EqualFold(name, field) { obj.fieldNames[name] = field return field, nil } } } return "", clownfish.NewErr(fmt.Sprintf("Unknown field: '%v'", name)) }
//export GOLUCY_Doc_Extract func GOLUCY_Doc_Extract(d *C.lucy_Doc, field *C.cfish_String) *C.cfish_Obj { fields := fetchDocFields(d) fieldGo := clownfish.CFStringToGo(unsafe.Pointer(field)) return (*C.cfish_Obj)(clownfish.GoToClownfish(fields[fieldGo], unsafe.Pointer(C.CFISH_OBJ), true)) }
//export GOLUCY_Doc_Store func GOLUCY_Doc_Store(d *C.lucy_Doc, field *C.cfish_String, value *C.cfish_Obj) { fields := fetchDocFields(d) fieldGo := clownfish.CFStringToGo(unsafe.Pointer(field)) valGo := clownfish.ToGo(unsafe.Pointer(value)) fields[fieldGo] = valGo }
func (e *LockErrIMP) Error() string { self := ((*C.lucy_LockErr)(unsafe.Pointer(e.TOPTR()))) return clownfish.CFStringToGo(unsafe.Pointer(C.LUCY_LockErr_Get_Mess(self))) }