Tune and test Go bindings for Simple.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/e101acad Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/e101acad Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/e101acad Branch: refs/heads/master Commit: e101acade8d9d2f1235b71e23db661e44359cf3d Parents: cc7219e Author: Marvin Humphrey <[email protected]> Authored: Mon Nov 9 20:16:04 2015 -0800 Committer: Marvin Humphrey <[email protected]> Committed: Fri Nov 20 16:43:37 2015 -0800 ---------------------------------------------------------------------- core/Lucy/Simple.c | 5 ++ core/Lucy/Simple.cfh | 3 ++ go/build.go | 9 ++++ go/lucy/simple.go | 120 ++++++++++++++++++++++++++++++++++++++++++++ go/lucy/simple_test.go | 62 +++++++++++++++++++++++ 5 files changed, 199 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/e101acad/core/Lucy/Simple.c ---------------------------------------------------------------------- diff --git a/core/Lucy/Simple.c b/core/Lucy/Simple.c index 2271984..1287bcc 100644 --- a/core/Lucy/Simple.c +++ b/core/Lucy/Simple.c @@ -170,6 +170,11 @@ Simple_Get_Indexer_IMP(Simple *self) { return ivars->indexer; } +Hits* +Simple_Get_Hits_IMP(Simple *self) { + return Simple_IVARS(self)->hits; +} + void Simple_Finish_Indexing_IMP(Simple *self) { SimpleIVARS *const ivars = Simple_IVARS(self); http://git-wip-us.apache.org/repos/asf/lucy/blob/e101acad/core/Lucy/Simple.cfh ---------------------------------------------------------------------- diff --git a/core/Lucy/Simple.cfh b/core/Lucy/Simple.cfh index 3680ce5..d3cdcfa 100644 --- a/core/Lucy/Simple.cfh +++ b/core/Lucy/Simple.cfh @@ -90,6 +90,9 @@ public class Lucy::Simple { Indexer* Get_Indexer(Simple *self); + nullable Hits* + Get_Hits(Simple *self); + void Finish_Indexing(Simple *self); http://git-wip-us.apache.org/repos/asf/lucy/blob/e101acad/go/build.go ---------------------------------------------------------------------- diff --git a/go/build.go b/go/build.go index 05231fc..5981016 100644 --- a/go/build.go +++ b/go/build.go @@ -136,6 +136,15 @@ func runCFC() { } func specClasses(parcel *cfc.Parcel) { + simpleBinding := cfc.NewGoClass(parcel, "Lucy::Simple") + simpleBinding.SpecMethod("Add_Doc", "AddDoc(doc interface{}) error") + simpleBinding.SpecMethod("Search", "Search(string, int, int) (int, error)") + simpleBinding.SpecMethod("Next", "Next(hit interface{}) bool") + simpleBinding.SpecMethod("", "Error() error") + simpleBinding.SetSuppressCtor(true) + simpleBinding.SetSuppressStruct(true) + simpleBinding.Register() + tokenBinding := cfc.NewGoClass(parcel, "Lucy::Analysis::Token") tokenBinding.SpecMethod("", "SetText(string)") tokenBinding.SpecMethod("", "GetText() string") http://git-wip-us.apache.org/repos/asf/lucy/blob/e101acad/go/lucy/simple.go ---------------------------------------------------------------------- diff --git a/go/lucy/simple.go b/go/lucy/simple.go new file mode 100644 index 0000000..b4e6ff4 --- /dev/null +++ b/go/lucy/simple.go @@ -0,0 +1,120 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lucy + +/* + +#include "Lucy/Simple.h" + +*/ +import "C" +import "unsafe" +import "reflect" +import "fmt" + +import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish" + +type SimpleIMP struct { + clownfish.ObjIMP + err error +} + +func OpenSimple(index interface{}, language string) (s Simple, err error) { + indexC := (*C.cfish_Obj)(clownfish.GoToClownfish(index, unsafe.Pointer(C.CFISH_OBJ), false)) + defer C.cfish_decref(unsafe.Pointer(indexC)) + languageC := (*C.cfish_String)(clownfish.GoToClownfish(language, unsafe.Pointer(C.CFISH_STRING), false)) + defer C.cfish_decref(unsafe.Pointer(languageC)) + err = clownfish.TrapErr(func() { + cfObj := C.lucy_Simple_new(indexC, languageC) + s = WRAPSimple(unsafe.Pointer(cfObj)) + }) + return s, err +} + +func (s *SimpleIMP) AddDoc(doc interface{}) error { + self := (*C.lucy_Simple)(clownfish.Unwrap(s, "s")) + indexer := s.getIndexer() + var docToIndex Doc + stockDoc := indexer.getStockDoc() + stockDocC := (*C.lucy_Doc)(clownfish.Unwrap(stockDoc, "stockDoc")) + docFields := fetchDocFields(stockDocC) + for field := range docFields { + delete(docFields, field) + } + + switch d := doc.(type) { + case map[string]interface{}: + for k, v := range d { + docFields[k] = v + } + docToIndex = stockDoc + case Doc: + docToIndex = d + default: + docToIndex = stockDoc + // Get reflection value and type for the supplied struct. + var docValue reflect.Value + var success bool + if reflect.ValueOf(doc).Kind() == reflect.Ptr { + temp := reflect.ValueOf(doc).Elem() + if temp.Kind() == reflect.Struct { + docValue = temp + success = true + } + } + if !success { + mess := fmt.Sprintf("Unexpected type for doc: %T", doc) + return clownfish.NewErr(mess) + } + + // Copy field values into stockDoc. + docType := docValue.Type() + for i := 0; i < docValue.NumField(); i++ { + field := docType.Field(i).Name + value := docValue.Field(i).String() + docFields[field] = value + } + } + + return clownfish.TrapErr(func(){ + docC := (*C.lucy_Doc)(clownfish.Unwrap(docToIndex, "docToIndex")) + C.LUCY_Simple_Add_Doc(self, docC) + }) +} + +func (s *SimpleIMP) Search(query string, offset, numWanted int) (totalHits int, err error) { + err = clownfish.TrapErr(func() { + self := (*C.lucy_Simple)(clownfish.Unwrap(s, "s")) + qStringC := (*C.cfish_String)(clownfish.GoToClownfish(query, unsafe.Pointer(C.CFISH_STRING), false)) + defer C.cfish_decref(unsafe.Pointer(qStringC)) + totalHits = int(C.LUCY_Simple_Search(self, qStringC, C.uint32_t(offset), C.uint32_t(numWanted))) + }) + return totalHits, err +} + +func (s *SimpleIMP) Next(hit interface{}) bool { + var retval bool + if hits := s.getHits(); hits != nil { + retval = hits.Next(hit) + s.err = hits.Error() + } + return retval +} + +func (s *SimpleIMP) Error() error { + return s.err +} http://git-wip-us.apache.org/repos/asf/lucy/blob/e101acad/go/lucy/simple_test.go ---------------------------------------------------------------------- diff --git a/go/lucy/simple_test.go b/go/lucy/simple_test.go new file mode 100644 index 0000000..cf2081e --- /dev/null +++ b/go/lucy/simple_test.go @@ -0,0 +1,62 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lucy + +import "testing" + +func TestSimpleBasics(t *testing.T) { + var err error + simple, err := OpenSimple(NewRAMFolder(""), "en") + if simple == nil || err != nil { + t.Errorf("OpenSimple: %v", err) + } + + docStruct := &testDoc{Content: "foo"} + docMap := map[string]interface{}{"Content": "foo"} + docDoc := NewDoc(0) + docDoc.Store("Content", "foo") + + err = simple.AddDoc(docStruct) + if err != nil { + t.Errorf("AddDoc with struct: %v", err) + } + err = simple.AddDoc(docMap) + if err != nil { + t.Errorf("AddDoc with map: %v", err) + } + err = simple.AddDoc(docDoc) + if err != nil { + t.Errorf("AddDoc with Doc: %v", err) + } + + count, err := simple.Search("foo", 0, 10) + if count != 3 || err != nil { + t.Errorf("Search: %d, %v", count, err) + } + docStruct.Content = "" + if !simple.Next(docStruct) || docStruct.Content != "foo" { + t.Errorf("Next with struct: %v", simple.Error()) + } + delete(docMap, "Content") + if !simple.Next(docMap) || docMap["Content"].(string) != "foo" { + t.Errorf("Next with map: %v", simple.Error()) + } + docDoc.Store("Content", "") + if !simple.Next(docDoc) { + t.Errorf("Next with Doc: %v", simple.Error()) + } +}
