You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2015/11/25 00:38:23 UTC

[01/13] lucy git commit: Add error to Go binding for MakeCompiler.

Repository: lucy
Updated Branches:
  refs/heads/master 19921d847 -> dc3a17e88


Add error to Go binding for MakeCompiler.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/dac0e2bd
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/dac0e2bd
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/dac0e2bd

Branch: refs/heads/master
Commit: dac0e2bd5d4f93f84842d393a59d3f84f215bf88
Parents: 6d0a55f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 14:30:20 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/build.go            |  4 ++++
 go/lucy/search.go      | 13 +++++++++++++
 go/lucy/search_test.go |  6 +++---
 3 files changed, 20 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/dac0e2bd/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index fc73f64..6dff074 100644
--- a/go/build.go
+++ b/go/build.go
@@ -228,6 +228,10 @@ func specClasses(parcel *cfc.Parcel) {
 	hitsBinding.SetSuppressStruct(true)
 	hitsBinding.Register()
 
+	queryBinding := cfc.NewGoClass(parcel, "Lucy::Search::Query")
+	queryBinding.SpecMethod("Make_Compiler", "MakeCompiler(Searcher, float32, bool) (Compiler, error)")
+	queryBinding.Register()
+
 	compilerBinding := cfc.NewGoClass(parcel, "Lucy::Search::Compiler")
 	compilerBinding.SpecMethod("Make_Matcher", "MakeMatcher(SegReader, bool) (Matcher, error)")
 	compilerBinding.Register()

http://git-wip-us.apache.org/repos/asf/lucy/blob/dac0e2bd/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index c539044..2db169b 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -245,6 +245,19 @@ func (td *TopDocsIMP) GetMatchDocs() []MatchDoc {
 	return slice
 }
 
+func (q *QueryIMP) MakeCompiler(searcher Searcher, boost float32,
+	subordinate bool) (retval Compiler, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Query)(clownfish.Unwrap(q, "q"))
+		searcherCF := (*C.lucy_Searcher)(clownfish.Unwrap(searcher, "searcher"))
+		retvalCF := C.LUCY_Query_Make_Compiler(self, searcherCF, C.float(boost), C.bool(subordinate))
+		if retvalCF != nil {
+			retval = clownfish.WRAPAny(unsafe.Pointer(retvalCF)).(Compiler)
+		}
+	})
+	return retval, err
+}
+
 func (c *CompilerIMP) MakeMatcher(reader SegReader, needScore bool) (retval Matcher, err error) {
 	err = clownfish.TrapErr(func() {
 		self := (*C.lucy_Compiler)(clownfish.Unwrap(c, "c"))

http://git-wip-us.apache.org/repos/asf/lucy/blob/dac0e2bd/go/lucy/search_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go
index a92708c..1127f72 100644
--- a/go/lucy/search_test.go
+++ b/go/lucy/search_test.go
@@ -55,9 +55,9 @@ func checkQueryEquals(t *testing.T, query Query) {
 func checkQueryMakeCompiler(t *testing.T, query Query) {
 	index := createTestIndex("foo", "bar", "baz")
 	searcher, _ := OpenIndexSearcher(index)
-	compiler := query.MakeCompiler(searcher, 1.0, false)
-	if got, ok := compiler.(Compiler); !ok {
-		t.Error("MakeCompiler failed: got '%v'", got)
+	compiler, err := query.MakeCompiler(searcher, 1.0, false)
+	if _, ok := compiler.(Compiler); !ok || err != nil {
+		t.Error("MakeCompiler for %v failed: %v", query, err)
 	}
 }
 


[13/13] lucy git commit: Merge branch 'LUCY-282-misc-go-pt1'

Posted by ma...@apache.org.
Merge branch 'LUCY-282-misc-go-pt1'

Tune and test Go bindings for a variety of classes and methods. Some
were overlooked during the first pass through the codebase creating
custom Go bindings.

This closes #29.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/dc3a17e8
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/dc3a17e8
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/dc3a17e8

Branch: refs/heads/master
Commit: dc3a17e8865769c7b27255a9a308dca133ec6e03
Parents: 19921d8 8208210
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Nov 24 15:28:31 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Nov 24 15:28:31 2015 -0800

----------------------------------------------------------------------
 core/Lucy/Simple.c       |   5 ++
 core/Lucy/Simple.cfh     |   3 ++
 go/build.go              |  54 +++++++++++++++++++
 go/lucy/analysis.go      |  22 ++++++++
 go/lucy/analysis_test.go |   4 ++
 go/lucy/document.go      |  21 ++++++++
 go/lucy/document_test.go |  87 ++++++++++++++++++++++++++++++
 go/lucy/index.go         |  31 +++++++++++
 go/lucy/index_test.go    |  17 +++---
 go/lucy/lucy.go          |   2 +-
 go/lucy/search.go        | 110 ++++++++++++++++++++++++++++----------
 go/lucy/search_test.go   |  30 ++++++++---
 go/lucy/simple.go        | 120 ++++++++++++++++++++++++++++++++++++++++++
 go/lucy/simple_test.go   |  62 ++++++++++++++++++++++
 go/lucy/store.go         |  21 ++++++++
 go/lucy/store_test.go    |   3 ++
 go/lucy/util.go          |  69 ++++++++++++++++++++++++
 go/lucy/util_test.go     |  53 +++++++++++++++++++
 18 files changed, 671 insertions(+), 43 deletions(-)
----------------------------------------------------------------------



[02/13] lucy git commit: Tune and test Go bindings for Simple.

Posted by ma...@apache.org.
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 <ma...@rectangular.com>
Authored: Mon Nov 9 20:16:04 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
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())
+	}
+}


[04/13] lucy git commit: Add error to Go binding for MakeMatcher.

Posted by ma...@apache.org.
Add error to Go binding for MakeMatcher.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/6d0a55f7
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/6d0a55f7
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/6d0a55f7

Branch: refs/heads/master
Commit: 6d0a55f7387df4714386b7ffce9ba554c0c384f4
Parents: 3d636a1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Nov 12 19:38:23 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/build.go            |  4 ++++
 go/lucy/search.go      | 16 ++++++++++++++++
 go/lucy/search_test.go |  5 +++++
 3 files changed, 25 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/6d0a55f7/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index ccd606b..fc73f64 100644
--- a/go/build.go
+++ b/go/build.go
@@ -228,6 +228,10 @@ func specClasses(parcel *cfc.Parcel) {
 	hitsBinding.SetSuppressStruct(true)
 	hitsBinding.Register()
 
+	compilerBinding := cfc.NewGoClass(parcel, "Lucy::Search::Compiler")
+	compilerBinding.SpecMethod("Make_Matcher", "MakeMatcher(SegReader, bool) (Matcher, error)")
+	compilerBinding.Register()
+
 	andQueryBinding := cfc.NewGoClass(parcel, "Lucy::Search::ANDQuery")
 	andQueryBinding.SetSuppressCtor(true)
 	andQueryBinding.Register()

http://git-wip-us.apache.org/repos/asf/lucy/blob/6d0a55f7/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index 147af63..c539044 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -25,6 +25,7 @@ package lucy
 #include "Lucy/Search/Hits.h"
 #include "Lucy/Search/IndexSearcher.h"
 #include "Lucy/Search/Query.h"
+#include "Lucy/Search/Compiler.h"
 #include "Lucy/Search/Searcher.h"
 #include "Lucy/Search/ANDQuery.h"
 #include "Lucy/Search/ORQuery.h"
@@ -244,6 +245,21 @@ func (td *TopDocsIMP) GetMatchDocs() []MatchDoc {
 	return slice
 }
 
+func (c *CompilerIMP) MakeMatcher(reader SegReader, needScore bool) (retval Matcher, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Compiler)(clownfish.Unwrap(c, "c"))
+		readerCF := (*C.lucy_SegReader)(clownfish.Unwrap(reader, "reader"))
+		retvalCF := C.LUCY_Compiler_Make_Matcher(self, readerCF, C.bool(needScore))
+		if retvalCF != nil {
+			retval = clownfish.WRAPAny(unsafe.Pointer(retvalCF)).(Matcher)
+		}
+	})
+	if err != nil || retval == nil {
+		return nil, err
+	}
+	return retval, err
+}
+
 func NewANDQuery(children []Query) ANDQuery {
 	vec := clownfish.NewVector(len(children))
 	for _, child := range children {

http://git-wip-us.apache.org/repos/asf/lucy/blob/6d0a55f7/go/lucy/search_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go
index 50d7fae..a92708c 100644
--- a/go/lucy/search_test.go
+++ b/go/lucy/search_test.go
@@ -95,6 +95,11 @@ func TestTermCompilerMisc(t *testing.T) {
 	checkQuerySerialize(t, compiler) 
 	checkQueryEquals(t, compiler)
 	checkQueryToStringHasFoo(t, compiler)
+	segReaders := searcher.GetReader().SegReaders()
+	matcher, err := compiler.MakeMatcher(segReaders[0].(SegReader), false)
+	if matcher == nil || err != nil {
+		t.Errorf("MakeMatcher: %v", err)
+	}
 }
 
 func TestTermCompilerWeighting(t *testing.T) {


[12/13] lucy git commit: Trap errors in Go bindings for Matcher_Next.

Posted by ma...@apache.org.
Trap errors in Go bindings for Matcher_Next.

Use the same design pattern as Hits_Next: trap errors in a Go struct
member and expect the user to check after iteration finishes.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/8208210b
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/8208210b
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/8208210b

Branch: refs/heads/master
Commit: 8208210b3f5877b2056fecd4fa19f4de94ccdd6e
Parents: 6612082
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 18:33:40 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 19:00:31 2015 -0800

----------------------------------------------------------------------
 go/build.go            |  6 ++++++
 go/lucy/search.go      | 21 +++++++++++++++++++++
 go/lucy/search_test.go |  3 +++
 3 files changed, 30 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/8208210b/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 8db2109..e1fef50 100644
--- a/go/build.go
+++ b/go/build.go
@@ -250,6 +250,12 @@ func specClasses(parcel *cfc.Parcel) {
 	orQueryBinding.SetSuppressCtor(true)
 	orQueryBinding.Register()
 
+	matcherBinding := cfc.NewGoClass(parcel, "Lucy::Search::Matcher")
+	matcherBinding.SpecMethod("Next", "Next() int32")
+	matcherBinding.SpecMethod("", "Error() error")
+	matcherBinding.SetSuppressStruct(true)
+	matcherBinding.Register()
+
 	andMatcherBinding := cfc.NewGoClass(parcel, "Lucy::Search::ANDMatcher")
 	andMatcherBinding.SetSuppressCtor(true)
 	andMatcherBinding.Register()

http://git-wip-us.apache.org/repos/asf/lucy/blob/8208210b/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index 2db169b..e202b9d 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -60,6 +60,11 @@ type HitsIMP struct {
 	err error
 }
 
+type MatcherIMP struct {
+	clownfish.ObjIMP
+	err error
+}
+
 func OpenIndexSearcher(index interface{}) (obj IndexSearcher, err error) {
 	indexC := (*C.cfish_Obj)(clownfish.GoToClownfish(index, unsafe.Pointer(C.CFISH_OBJ), false))
 	defer C.cfish_decref(unsafe.Pointer(indexC))
@@ -293,6 +298,22 @@ func NewORQuery(children []Query) ORQuery {
 	return WRAPORQuery(unsafe.Pointer(cfObj))
 }
 
+func (m *MatcherIMP) Next() int32 {
+	var retval int32
+	m.err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Matcher)(clownfish.Unwrap(m, "m"))
+		retval = int32(C.LUCY_Matcher_Next(self))
+	})
+	if m.err != nil {
+		return 0
+	}
+	return retval
+}
+
+func (m *MatcherIMP) Error() error {
+	return m.err
+}
+
 func NewANDMatcher(children []Matcher, sim Similarity) ANDMatcher {
 	simC := (*C.lucy_Similarity)(clownfish.UnwrapNullable(sim))
 	vec := clownfish.NewVector(len(children))

http://git-wip-us.apache.org/repos/asf/lucy/blob/8208210b/go/lucy/search_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go
index 1127f72..3d4fc50 100644
--- a/go/lucy/search_test.go
+++ b/go/lucy/search_test.go
@@ -273,6 +273,9 @@ func checkMatcher(t *testing.T, matcher Matcher, supportsScore bool) {
 	if got := matcher.Next(); got != 0 {
 		t.Error("Next (iteration finished): %d", got)
 	}
+	if got := matcher.Error(); got != nil {
+		t.Error("Error after iteration finished: %v", got)
+	}
 }
 
 func TestMockMatcherBasics(t *testing.T) {


[07/13] lucy git commit: Add error retval for SortCache Go bindings.

Posted by ma...@apache.org.
Add error retval for SortCache Go bindings.

Some methods need to trap exceptions and return error objects.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/3d636a19
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/3d636a19
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/3d636a19

Branch: refs/heads/master
Commit: 3d636a19d41e9f049aaa444db097de5e31895e9a
Parents: d483dd0
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Nov 12 19:11:48 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/build.go           |  6 ++++++
 go/lucy/index.go      | 31 +++++++++++++++++++++++++++++++
 go/lucy/index_test.go | 15 +++++++++------
 3 files changed, 46 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/3d636a19/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 2b94cc5..ccd606b 100644
--- a/go/build.go
+++ b/go/build.go
@@ -202,6 +202,12 @@ func specClasses(parcel *cfc.Parcel) {
 	segBinding.SpecMethod("Write_File", "WriteFile(Folder) error")
 	segBinding.Register()
 
+	sortCacheBinding := cfc.NewGoClass(parcel, "Lucy::Index::SortCache")
+	sortCacheBinding.SpecMethod("Value", "Value(int32) (interface{}, error)")
+	sortCacheBinding.SpecMethod("Ordinal", "Ordinal(int32) (int32, error)")
+	sortCacheBinding.SpecMethod("Find", "Find(interface{}) (int32, error)")
+	sortCacheBinding.Register()
+
 	schemaBinding := cfc.NewGoClass(parcel, "Lucy::Plan::Schema")
 	schemaBinding.SpecMethod("All_Fields", "AllFields() []string")
 	schemaBinding.Register()

http://git-wip-us.apache.org/repos/asf/lucy/blob/3d636a19/go/lucy/index.go
----------------------------------------------------------------------
diff --git a/go/lucy/index.go b/go/lucy/index.go
index f186f7d..230e050 100644
--- a/go/lucy/index.go
+++ b/go/lucy/index.go
@@ -23,6 +23,7 @@ package lucy
 #include "Lucy/Index/TermVector.h"
 #include "Lucy/Index/Segment.h"
 #include "Lucy/Index/Snapshot.h"
+#include "Lucy/Index/SortCache.h"
 #include "Lucy/Document/Doc.h"
 #include "Lucy/Plan/Schema.h"
 #include "Clownfish/Hash.h"
@@ -384,3 +385,33 @@ func (s *SegmentIMP) ReadFile(folder Folder) error {
 		C.LUCY_Seg_Read_File(self, folderC)
 	})
 }
+
+func (s *SortCacheIMP) Value(ord int32) (retval interface{}, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_SortCache)(clownfish.Unwrap(s, "s"))
+		retvalCF := C.LUCY_SortCache_Value(self, C.int32_t(ord))
+		defer C.cfish_decref(unsafe.Pointer(retvalCF))
+		retval = clownfish.ToGo(unsafe.Pointer(retvalCF))
+	})
+	return retval, err
+}
+
+func (s *SortCacheIMP) Ordinal(docId int32) (retval int32, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_SortCache)(clownfish.Unwrap(s, "s"))
+		retvalCF := C.LUCY_SortCache_Ordinal(self, C.int32_t(docId))
+		retval = int32(retvalCF)
+	})
+	return retval, err
+}
+
+func (s *SortCacheIMP) Find(term interface{}) (retval int32, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_SortCache)(clownfish.Unwrap(s, "s"))
+		termCF := (*C.cfish_Obj)(clownfish.GoToClownfish(term, unsafe.Pointer(C.CFISH_OBJ), true))
+		defer C.cfish_decref(unsafe.Pointer(termCF))
+		retvalCF := C.LUCY_SortCache_Find(self, termCF)
+		retval = int32(retvalCF)
+	})
+	return retval, err
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/3d636a19/go/lucy/index_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/index_test.go b/go/lucy/index_test.go
index 5fb4d8b..e7c93a9 100644
--- a/go/lucy/index_test.go
+++ b/go/lucy/index_test.go
@@ -386,6 +386,8 @@ func TestSnapshotMisc(t *testing.T) {
 }
 
 func TestSortCacheMisc(t *testing.T) {
+	var err error
+
 	schema := NewSchema()
 	spec := NewFullTextType(NewStandardTokenizer())
 	spec.SetSortable(true)
@@ -410,18 +412,19 @@ func TestSortCacheMisc(t *testing.T) {
 		t.Errorf("GetOrdWidth: %d", width)
 	}
 
-	if lowest, ok := sortCache.Value(0).(string); !ok || lowest != "bar" {
-		t.Errorf("Ord")
+	lowest, err := sortCache.Value(0)
+	if _, ok := lowest.(string); err != nil || !ok || lowest != "bar" {
+		t.Errorf("Value: %v", err)
 	}
-	if ord := sortCache.Ordinal(1); ord != 2 { // "foo" is ordinal 2
-		t.Errorf("Ordinal: %d", ord)
+	if ord, err := sortCache.Ordinal(1); err != nil || ord != 2 { // "foo" is ordinal 2
+		t.Errorf("Ordinal: %d, %v", ord, err)
 	}
 	if nullOrd := sortCache.GetNullOrd(); nullOrd != 3 {
 		t.Errorf("GetNullOrd: %d", nullOrd)
 	}
 
-	if ord := sortCache.Find("foo"); ord != 2 {
-		t.Errorf("Find: %d", ord)
+	if ord, err := sortCache.Find("foo"); err != nil || ord != 2 {
+		t.Errorf("Find: %d, %v", ord, err)
 	}
 
 	if sortCache.getNativeOrds() {


[09/13] lucy git commit: Tune and test Go bindings for Stepper.

Posted by ma...@apache.org.
Tune and test Go bindings for Stepper.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/d5063a51
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/d5063a51
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/d5063a51

Branch: refs/heads/master
Commit: d5063a519200d52c1abeec263bd008f176fa94bd
Parents: dd4328b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 16:11:22 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 18:49:34 2015 -0800

----------------------------------------------------------------------
 go/build.go          |  8 ++++++
 go/lucy/util.go      | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 go/lucy/util_test.go | 53 ++++++++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/d5063a51/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 6c55250..3b6fc68 100644
--- a/go/build.go
+++ b/go/build.go
@@ -365,6 +365,14 @@ func specClasses(parcel *cfc.Parcel) {
 	cfWriterBinding := cfc.NewGoClass(parcel, "Lucy::Store::CompoundFileWriter")
 	cfWriterBinding.SpecMethod("Consolidate", "Consolidate() error")
 	cfWriterBinding.Register()
+
+	stepperBinding := cfc.NewGoClass(parcel, "Lucy::Util::Stepper")
+	stepperBinding.SpecMethod("Write_Key_Frame", "WriteKeyFrame(OutStream, interface{}) error")
+	stepperBinding.SpecMethod("Write_Delta", "WriteDelta(OutStream, interface{}) error")
+	stepperBinding.SpecMethod("Read_Key_Frame", "ReadKeyFrame(InStream) error")
+	stepperBinding.SpecMethod("Read_Delta", "ReadDelta(InStream) error")
+	stepperBinding.SpecMethod("Read_Record", "readRecord(InStream) error")
+	stepperBinding.Register()
 }
 
 func build() {

http://git-wip-us.apache.org/repos/asf/lucy/blob/d5063a51/go/lucy/util.go
----------------------------------------------------------------------
diff --git a/go/lucy/util.go b/go/lucy/util.go
new file mode 100644
index 0000000..a57de89
--- /dev/null
+++ b/go/lucy/util.go
@@ -0,0 +1,69 @@
+/* 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/Util/Stepper.h"
+*/
+import "C"
+import "unsafe"
+
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+func (s *StepperIMP) WriteKeyFrame(outstream OutStream, value interface{}) error {
+	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Stepper)(clownfish.Unwrap(s, "s"))
+		outstreamCF := (*C.lucy_OutStream)(clownfish.Unwrap(outstream, "outstream"))
+		valueCF := (*C.cfish_Obj)(clownfish.GoToClownfish(value, unsafe.Pointer(C.CFISH_OBJ), false))
+		defer C.cfish_decref(unsafe.Pointer(valueCF))
+		C.LUCY_Stepper_Write_Key_Frame(self, outstreamCF, valueCF)
+	})
+}
+
+func (s *StepperIMP) WriteDelta(outstream OutStream, value interface{}) error {
+	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Stepper)(clownfish.Unwrap(s, "s"))
+		outstreamCF := (*C.lucy_OutStream)(clownfish.Unwrap(outstream, "outstream"))
+		valueCF := (*C.cfish_Obj)(clownfish.GoToClownfish(value, unsafe.Pointer(C.CFISH_OBJ), false))
+		defer C.cfish_decref(unsafe.Pointer(valueCF))
+		C.LUCY_Stepper_Write_Delta(self, outstreamCF, valueCF)
+	})
+}
+
+func (s *StepperIMP) ReadKeyFrame(instream InStream) error {
+	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Stepper)(clownfish.Unwrap(s, "s"))
+		instreamCF := (*C.lucy_InStream)(clownfish.Unwrap(instream, "instream"))
+		C.LUCY_Stepper_Read_Key_Frame(self, instreamCF)
+	})
+}
+
+func (s *StepperIMP) ReadDelta(instream InStream) error {
+	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Stepper)(clownfish.Unwrap(s, "s"))
+		instreamCF := (*C.lucy_InStream)(clownfish.Unwrap(instream, "instream"))
+		C.LUCY_Stepper_Read_Delta(self, instreamCF)
+	})
+}
+
+func (s *StepperIMP) readRecord(instream InStream) error {
+	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Stepper)(clownfish.Unwrap(s, "s"))
+		instreamCF := (*C.lucy_InStream)(clownfish.Unwrap(instream, "instream"))
+		C.LUCY_Stepper_Read_Record(self, instreamCF)
+	})
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/d5063a51/go/lucy/util_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/util_test.go b/go/lucy/util_test.go
new file mode 100644
index 0000000..38a4503
--- /dev/null
+++ b/go/lucy/util_test.go
@@ -0,0 +1,53 @@
+/* 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"
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+func TestStepperMisc(t *testing.T) {
+	var err error
+	stepper := NewTextTermStepper()
+	folder := NewRAMFolder("")
+	out, _ := folder.OpenOut("foo.dat")
+	err = stepper.WriteKeyFrame(out, "foo")
+	if err != nil {
+		t.Errorf("WriteKeyFrame: %v", err)
+	}
+
+	bb := clownfish.NewByteBuf(0)
+	//bb.Cat([]byte("food"))
+	err = stepper.WriteDelta(out, bb)
+	if err != nil {
+		t.Errorf("WriteDelta: %v", err)
+	}
+	out.Close()
+	stepper.Reset()
+	in, _ := folder.OpenIn("foo.dat")
+	err = stepper.ReadKeyFrame(in)
+	if err != nil {
+		t.Errorf("ReadKeyFrame: %v", err)
+	}
+	err = stepper.ReadDelta(in)
+	if err != nil {
+		t.Errorf("ReadDelta: %v", err)
+	}
+	err = stepper.ReadDelta(in)
+	if err == nil {
+		t.Errorf("Expected error when reading past EOF")
+	}
+}


[10/13] lucy git commit: Test Go bindings for HitDoc.

Posted by ma...@apache.org.
Test Go bindings for HitDoc.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/66120820
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/66120820
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/66120820

Branch: refs/heads/master
Commit: 66120820174ffd6bc2459179fe642d094cc3ad57
Parents: 91dd389
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 18:16:28 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 19:00:31 2015 -0800

----------------------------------------------------------------------
 go/lucy/document_test.go | 13 +++++++++++++
 1 file changed, 13 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/66120820/go/lucy/document_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/document_test.go b/go/lucy/document_test.go
index 2cf6313..4a82baa 100644
--- a/go/lucy/document_test.go
+++ b/go/lucy/document_test.go
@@ -49,6 +49,19 @@ func TestDocMisc(t *testing.T) {
 	checkdocDumpLoad(t, doc)
 }
 
+func TestHitDocMisc(t *testing.T) {
+	hitDoc := NewHitDoc(42, 1.5)
+	if got := hitDoc.GetScore(); got != 1.5 {
+		t.Errorf("GetScore: %f", got)
+	}
+	hitDoc.SetScore(2.0)
+	if got := hitDoc.GetScore(); got != 2.0 {
+		t.Errorf("Set/GetScore: %f", got)
+	}
+	checkDocSerialize(t, hitDoc)
+	checkdocDumpLoad(t, hitDoc)
+}
+
 func checkDocSerialize(t *testing.T, doc Doc) {
 	folder := NewRAMFolder("")
 	outStream, _ := folder.OpenOut("foo")


[05/13] lucy git commit: More custom Go for Searcher.

Posted by ma...@apache.org.
More custom Go for Searcher.

Hand-roll bindings for FetchDoc, fetchDocVec and topDocs to allow for
returning a tuple including an `error`.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/d483dd07
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/d483dd07
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/d483dd07

Branch: refs/heads/master
Commit: d483dd076c36f3e8c29d80de5ad6e401e5531ca0
Parents: e35becd
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Nov 10 20:04:44 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/build.go            |  3 +++
 go/lucy/index_test.go  |  2 +-
 go/lucy/search.go      | 31 +++++++++++++++++++++++++++++++
 go/lucy/search_test.go | 16 ++++++++++++----
 4 files changed, 47 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/d483dd07/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 5981016..2b94cc5 100644
--- a/go/build.go
+++ b/go/build.go
@@ -209,7 +209,10 @@ func specClasses(parcel *cfc.Parcel) {
 	searcherBinding := cfc.NewGoClass(parcel, "Lucy::Search::Searcher")
 	searcherBinding.SpecMethod("Hits",
 		"Hits(query interface{}, offset uint32, numWanted uint32, sortSpec SortSpec) (Hits, error)")
+	searcherBinding.SpecMethod("Top_Docs", "topDocs(Query, uint32, SortSpec) (TopDocs, error)")
 	searcherBinding.SpecMethod("Close", "Close() error")
+	searcherBinding.SpecMethod("Fetch_Doc", "FetchDoc(int32) (HitDoc, error)")
+	searcherBinding.SpecMethod("Fetch_Doc_Vec", "fetchDocVec(int32) (DocVector, error)")
 	searcherBinding.SpecMethod("", "ReadDoc(int32, interface{}) error")
 	searcherBinding.Register()
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/d483dd07/go/lucy/index_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/index_test.go b/go/lucy/index_test.go
index 4faab4e..5fb4d8b 100644
--- a/go/lucy/index_test.go
+++ b/go/lucy/index_test.go
@@ -334,7 +334,7 @@ func TestDocVectorMisc(t *testing.T) {
 	indexer.AddDoc(&testDoc{Content: "foo bar baz"})
 	indexer.Commit()
 	searcher, _ := OpenIndexSearcher(folder)
-	dv := searcher.fetchDocVec(1)
+	dv, _ := searcher.fetchDocVec(1)
 	fieldBuf := dv.fieldBuf("content");
 	if fieldBuf == nil {
 		t.Errorf("fieldBuf returned nil")

http://git-wip-us.apache.org/repos/asf/lucy/blob/d483dd07/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index 44f5054..147af63 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -88,6 +88,24 @@ func (s *SearcherIMP) ReadDoc(docID int32, doc interface{}) error {
 	}
 }
 
+func (s *SearcherIMP) FetchDoc(docID int32) (doc HitDoc, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
+		docC := C.LUCY_Searcher_Fetch_Doc(self, C.int32_t(docID))
+		doc = WRAPHitDoc(unsafe.Pointer(docC))
+	})
+	return doc, err
+}
+
+func (s *SearcherIMP) fetchDocVec(docID int32) (dv DocVector, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
+		dvC := C.LUCY_Searcher_Fetch_Doc_Vec(self, C.int32_t(docID))
+		dv = WRAPDocVector(unsafe.Pointer(dvC))
+	})
+	return dv, err
+}
+
 func (s *SearcherIMP) Close() error {
 	return clownfish.TrapErr(func() {
 		self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
@@ -109,6 +127,19 @@ func (s *SearcherIMP) Hits(query interface{}, offset uint32, numWanted uint32,
 	return hits, err
 }
 
+func (s *SearcherIMP) topDocs(query Query, numWanted uint32,
+	sortSpec SortSpec) (topDocs TopDocs, err error) {
+	err = clownfish.TrapErr(func() {
+		self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
+		sortSpecC := (*C.lucy_SortSpec)(clownfish.UnwrapNullable(sortSpec))
+		queryC := (*C.lucy_Query)(clownfish.Unwrap(query, "query"))
+		topDocsC := C.LUCY_Searcher_Top_Docs(self, queryC,
+			C.uint32_t(numWanted), sortSpecC)
+		topDocs = WRAPTopDocs(unsafe.Pointer(topDocsC))
+	})
+	return topDocs, err
+}
+
 type setScorer interface {
 	SetScore(float32)
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/d483dd07/go/lucy/search_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go
index fcd3c33..50d7fae 100644
--- a/go/lucy/search_test.go
+++ b/go/lucy/search_test.go
@@ -418,7 +418,7 @@ type simpleTestDoc struct {
 func TestHitsBasics(t *testing.T) {
 	index := createTestIndex("a", "b")
 	searcher, _ := OpenIndexSearcher(index)
-	topDocs := searcher.topDocs(NewTermQuery("content", "a"), 10, nil)
+	topDocs, _ := searcher.topDocs(NewTermQuery("content", "a"), 10, nil)
 	hits := NewHits(searcher, topDocs, 0)
 	if got := hits.TotalHits(); got != topDocs.getTotalHits() {
 		t.Errorf("TotalHits is off: %d", got)
@@ -604,8 +604,13 @@ func TestIndexSearcherMisc(t *testing.T) {
 	if _, ok := searcher.GetReader().(PolyReader); !ok {
 		t.Error("GetReader")
 	}
-	if _, ok := searcher.fetchDocVec(4).(DocVector); !ok {
-		t.Error("DocVector")
+	doc, err := searcher.FetchDoc(4)
+	if _, ok := doc.(Doc); !ok || err != nil {
+		t.Error("FetchDoc: %v", err)
+	}
+	docVec, err := searcher.fetchDocVec(4)
+	if _, ok := docVec.(DocVector); !ok || err != nil {
+		t.Error("FetchDocVec: %v", err)
 	}
 }
 
@@ -640,7 +645,10 @@ func TestIndexSearcherHits(t *testing.T) {
 func TestIndexSearcherTopDocs(t *testing.T) {
 	index := createTestIndex("a", "b")
 	searcher, _ := OpenIndexSearcher(index)
-	topDocs := searcher.topDocs(NewTermQuery("content", "b"), 10, nil)
+	topDocs, err := searcher.topDocs(NewTermQuery("content", "b"), 10, nil)
+	if err != nil {
+		t.Errorf("topDocs: %v", err)
+	}
 	matchDocs := topDocs.GetMatchDocs()
 	if docID := matchDocs[0].getDocID(); docID != 2 {
 		t.Errorf("TopDocs expected 2, got %d", docID)


[03/13] lucy git commit: Tune and test PolyAnalyzer Go bindings.

Posted by ma...@apache.org.
Tune and test PolyAnalyzer Go bindings.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/cc7219e6
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/cc7219e6
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/cc7219e6

Branch: refs/heads/master
Commit: cc7219e69aaab7aa215ed6c39106d89a7df7ee83
Parents: 19921d8
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 9 17:42:08 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/build.go              |  5 +++++
 go/lucy/analysis.go      | 22 ++++++++++++++++++++++
 go/lucy/analysis_test.go |  4 ++++
 3 files changed, 31 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/cc7219e6/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 6060f5b..05231fc 100644
--- a/go/build.go
+++ b/go/build.go
@@ -145,6 +145,11 @@ func specClasses(parcel *cfc.Parcel) {
 	analyzerBinding.SpecMethod("Split", "Split(string) []string")
 	analyzerBinding.Register()
 
+	polyAnalyzerBinding := cfc.NewGoClass(parcel, "Lucy::Analysis::PolyAnalyzer")
+	polyAnalyzerBinding.SpecMethod("Get_Analyzers", "GetAnalyzers() []Analyzer")
+	polyAnalyzerBinding.SetSuppressCtor(true)
+	polyAnalyzerBinding.Register()
+
 	indexerBinding := cfc.NewGoClass(parcel, "Lucy::Index::Indexer")
 	indexerBinding.SpecMethod("", "Close() error")
 	indexerBinding.SpecMethod("Add_Doc", "AddDoc(doc interface{}) error")

http://git-wip-us.apache.org/repos/asf/lucy/blob/cc7219e6/go/lucy/analysis.go
----------------------------------------------------------------------
diff --git a/go/lucy/analysis.go b/go/lucy/analysis.go
index 61465b4..68a379c 100644
--- a/go/lucy/analysis.go
+++ b/go/lucy/analysis.go
@@ -20,6 +20,7 @@ package lucy
 #include <stdlib.h>
 
 #include "Lucy/Analysis/Analyzer.h"
+#include "Lucy/Analysis/PolyAnalyzer.h"
 #include "Lucy/Analysis/Token.h"
 #include "Clownfish/Vector.h"
 */
@@ -59,3 +60,24 @@ func (a *AnalyzerIMP) Split(text string) []string {
 	defer C.cfish_decref(unsafe.Pointer(retvalCF))
 	return vecToStringSlice(retvalCF)
 }
+
+func NewPolyAnalyzer(children []Analyzer) PolyAnalyzer {
+	vec := clownfish.NewVector(len(children))
+	for i := 0; i < len(children); i++ {
+		vec.Push(children[i])
+	}
+	retvalCF := C.lucy_PolyAnalyzer_new(nil, (*C.cfish_Vector)(clownfish.Unwrap(vec, "vec")))
+	return WRAPPolyAnalyzer(unsafe.Pointer(retvalCF))
+}
+
+func (p *PolyAnalyzerIMP) GetAnalyzers() []Analyzer {
+	self := (*C.lucy_PolyAnalyzer)(clownfish.Unwrap(p, "p"))
+	retvalCF := C.LUCY_PolyAnalyzer_Get_Analyzers(self)
+	size := C.CFISH_Vec_Get_Size(retvalCF)
+	retval := make([]Analyzer, int(size))
+	for i := 0; i < int(size); i++ {
+		child := unsafe.Pointer(C.CFISH_Vec_Fetch(retvalCF, C.size_t(i)))
+		retval[i] = clownfish.WRAPAny(unsafe.Pointer(C.cfish_incref(child))).(Analyzer)
+	}
+	return retval
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/cc7219e6/go/lucy/analysis_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/analysis_test.go b/go/lucy/analysis_test.go
index 9470fbb..d9d9f2f 100644
--- a/go/lucy/analysis_test.go
+++ b/go/lucy/analysis_test.go
@@ -105,6 +105,10 @@ func TestCoreAnalyzers(t *testing.T) {
 	runAnalyzerTests(t, NewSnowballStemmer("en"))
 	runAnalyzerTests(t, NewSnowballStopFilter("en", nil))
 	runAnalyzerTests(t, NewStandardTokenizer())
+
+	children := []Analyzer{NewStandardTokenizer(), NewNormalizer("NFKC", true, false)}
+	polyAnalyzer := NewPolyAnalyzer(children)
+	runAnalyzerTests(t, polyAnalyzer)
 }
 
 func TestRegexTokenizerSplit(t *testing.T) {


[08/13] lucy git commit: Catch errors in Go binding for DH_Next().

Posted by ma...@apache.org.
Catch errors in Go binding for DH_Next().

Use the same approach we took with Hits_Next(): trap errors and capture
them to a member variable, and expect the user to check that no errors
occurred after iteration finishes.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/dd4328b3
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/dd4328b3
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/dd4328b3

Branch: refs/heads/master
Commit: dd4328b3a0c528e6d168c1c241bc07253c2e2c4b
Parents: dac0e2b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 15:35:54 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:38 2015 -0800

----------------------------------------------------------------------
 go/build.go           |  3 +++
 go/lucy/store.go      | 21 +++++++++++++++++++++
 go/lucy/store_test.go |  3 +++
 3 files changed, 27 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/dd4328b3/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 6dff074..6c55250 100644
--- a/go/build.go
+++ b/go/build.go
@@ -350,6 +350,9 @@ func specClasses(parcel *cfc.Parcel) {
 
 	dhBinding := cfc.NewGoClass(parcel, "Lucy::Store::DirHandle")
 	dhBinding.SpecMethod("Close", "Close() error")
+	dhBinding.SpecMethod("Next", "next() bool")
+	dhBinding.SpecMethod("", "Error() error")
+	dhBinding.SetSuppressStruct(true)
 	dhBinding.Register()
 
 	lockBinding := cfc.NewGoClass(parcel, "Lucy::Store::Lock")

http://git-wip-us.apache.org/repos/asf/lucy/blob/dd4328b3/go/lucy/store.go
----------------------------------------------------------------------
diff --git a/go/lucy/store.go b/go/lucy/store.go
index 6fabd16..7af8229 100644
--- a/go/lucy/store.go
+++ b/go/lucy/store.go
@@ -39,6 +39,11 @@ import "fmt"
 
 import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
 
+type DirHandleIMP struct {
+	clownfish.ObjIMP
+	err error
+}
+
 func (e *LockErrIMP) Error() string {
 	self := ((*C.lucy_LockErr)(unsafe.Pointer(e.TOPTR())))
 	return clownfish.CFStringToGo(unsafe.Pointer(C.LUCY_LockErr_Get_Mess(self)))
@@ -644,6 +649,22 @@ func OpenRAMFileHandle(path string, flags uint32, ramFile RAMFile) (fh RAMFileHa
 	return fh, err
 }
 
+func (dh *DirHandleIMP) Error() error {
+	return dh.err
+}
+
+func (dh *DirHandleIMP) next() bool {
+	var retval bool
+	dh.err = clownfish.TrapErr(func() {
+		self := (*C.lucy_DirHandle)(clownfish.Unwrap(dh, "dh"))
+		retval = bool(C.LUCY_DH_Next(self))
+	})
+	if dh.err != nil {
+		return false
+	}
+	return retval
+}
+
 func (dh *DirHandleIMP) Close() error {
 	return clownfish.TrapErr(func() {
 		self := (*C.lucy_DirHandle)(clownfish.Unwrap(dh, "dh"))

http://git-wip-us.apache.org/repos/asf/lucy/blob/dd4328b3/go/lucy/store_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/store_test.go b/go/lucy/store_test.go
index 69bb0d4..c422525 100644
--- a/go/lucy/store_test.go
+++ b/go/lucy/store_test.go
@@ -598,6 +598,9 @@ func runDirHandleCommonTests(t *testing.T, folder Folder, makeDH func() DirHandl
 			t.Errorf("Unexpected entry: '%s'", entry)
 		}
 	}
+	if got := dh.Error(); got != nil {
+		t.Errorf("Error() should return nil after iteration: %v", got)
+	}
 	if count != 2 {
 		t.Errorf("Didn't get to all entries, found only %d", count)
 	}


[11/13] lucy git commit: Tune and test Go bindings for Doc.

Posted by ma...@apache.org.
Tune and test Go bindings for Doc.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/91dd3894
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/91dd3894
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/91dd3894

Branch: refs/heads/master
Commit: 91dd3894b16cc3f5140c2ac398d193a59f4b19a0
Parents: d5063a5
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Nov 16 17:15:05 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 19:00:31 2015 -0800

----------------------------------------------------------------------
 go/build.go              |  6 ++++
 go/lucy/document.go      | 21 ++++++++++++
 go/lucy/document_test.go | 74 +++++++++++++++++++++++++++++++++++++++++++
 go/lucy/lucy.go          |  2 +-
 4 files changed, 102 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/91dd3894/go/build.go
----------------------------------------------------------------------
diff --git a/go/build.go b/go/build.go
index 3b6fc68..8db2109 100644
--- a/go/build.go
+++ b/go/build.go
@@ -159,6 +159,12 @@ func specClasses(parcel *cfc.Parcel) {
 	polyAnalyzerBinding.SetSuppressCtor(true)
 	polyAnalyzerBinding.Register()
 
+	docBinding := cfc.NewGoClass(parcel, "Lucy::Document::Doc")
+	docBinding.SpecMethod("", "GetFields() map[string]interface{}")
+	docBinding.SpecMethod("", "SetFields(map[string]interface{})")
+	docBinding.SpecMethod("Field_Names", "FieldNames() []string")
+	docBinding.Register()
+
 	indexerBinding := cfc.NewGoClass(parcel, "Lucy::Index::Indexer")
 	indexerBinding.SpecMethod("", "Close() error")
 	indexerBinding.SpecMethod("Add_Doc", "AddDoc(doc interface{}) error")

http://git-wip-us.apache.org/repos/asf/lucy/blob/91dd3894/go/lucy/document.go
----------------------------------------------------------------------
diff --git a/go/lucy/document.go b/go/lucy/document.go
index 1221810..1d8c289 100644
--- a/go/lucy/document.go
+++ b/go/lucy/document.go
@@ -48,3 +48,24 @@ func fetchDocFields(d *C.lucy_Doc) map[string]interface{} {
 	}
 	return fieldsGo
 }
+
+func (d *DocIMP) GetFields() map[string]interface{} {
+	self := (*C.lucy_Doc)(clownfish.Unwrap(d, "d"))
+	return fetchDocFields(self)
+}
+
+func (d *DocIMP) SetFields(fields map[string]interface{}) {
+	self := (*C.lucy_Doc)(clownfish.Unwrap(d, "d"))
+	ivars := C.lucy_Doc_IVARS(self)
+	oldID := uintptr(unsafe.Pointer(ivars.fields))
+	newFieldsID := registry.store(fields)
+	ivars.fields = unsafe.Pointer(newFieldsID)
+	registry.delete(oldID)
+}
+
+func (d *DocIMP) FieldNames() []string {
+	self := (*C.lucy_Doc)(unsafe.Pointer(d.TOPTR()))
+	fieldsCF := C.LUCY_Doc_Field_Names(self)
+	defer C.cfish_decref(unsafe.Pointer(fieldsCF))
+	return vecToStringSlice(fieldsCF)
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/91dd3894/go/lucy/document_test.go
----------------------------------------------------------------------
diff --git a/go/lucy/document_test.go b/go/lucy/document_test.go
new file mode 100644
index 0000000..2cf6313
--- /dev/null
+++ b/go/lucy/document_test.go
@@ -0,0 +1,74 @@
+/* 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"
+import "reflect"
+import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
+
+func TestDocMisc(t *testing.T) {
+	doc := NewDoc(1)
+	if got := doc.GetDocID(); got != 1 {
+		t.Errorf("GetDocID: %d", got)
+	}
+	doc.SetDocID(42)
+	if got := doc.GetDocID(); got != 42 {
+		t.Errorf("Set/GetDocID: %d", got)
+	}
+	fields := map[string]interface{}{"content": "foo"}
+	doc.SetFields(fields)
+	if got, ok := doc.Extract("content").(string); !ok || got != "foo" {
+		t.Errorf("Extract: %v", got)
+	}
+	doc.Store("content", "bar")
+	retrievedFields := doc.GetFields()
+	if got, ok := retrievedFields["content"].(string); !ok || got != "bar" {
+		t.Errorf("Store/GetFields: %v", got)
+	}
+	if got := doc.GetSize(); got != 1 {
+		t.Errorf("GetSize: %d", got)
+	}
+	if got := doc.FieldNames(); !reflect.DeepEqual(got, []string{"content"}) {
+		t.Errorf("FieldNames: %v", got)
+	}
+	checkDocSerialize(t, doc)
+	checkdocDumpLoad(t, doc)
+}
+
+func checkDocSerialize(t *testing.T, doc Doc) {
+	folder := NewRAMFolder("")
+	outStream, _ := folder.OpenOut("foo")
+	doc.serialize(outStream)
+	outStream.Close()
+	inStream, _ := folder.OpenIn("foo")
+	dupe := clownfish.GetClass(doc).MakeObj().(Doc).deserialize(inStream)
+	if !doc.Equals(dupe) {
+		t.Errorf("Unsuccessful serialization round trip -- expected '%v', got '%v'",
+				 doc.ToString(), dupe.ToString())
+	}
+}
+
+func checkdocDumpLoad(t *testing.T, doc Doc) {
+	t.Skip("Dump/Load are TODO")
+	return
+	dupe := clownfish.GetClass(doc).MakeObj().(Doc)
+	dupe = dupe.load(doc.dump()).(Doc)
+	if !doc.Equals(dupe) {
+		t.Errorf("Unsuccessful dump/load round trip -- expected '%v', got '%v'",
+				 doc.ToString(), dupe.ToString())
+	}
+}

http://git-wip-us.apache.org/repos/asf/lucy/blob/91dd3894/go/lucy/lucy.go
----------------------------------------------------------------------
diff --git a/go/lucy/lucy.go b/go/lucy/lucy.go
index 585a192..03307bb 100644
--- a/go/lucy/lucy.go
+++ b/go/lucy/lucy.go
@@ -273,7 +273,7 @@ func GOLUCY_Doc_init(d *C.lucy_Doc, fields unsafe.Pointer, docID C.int32_t) *C.l
 
 //export GOLUCY_Doc_Set_Fields
 func GOLUCY_Doc_Set_Fields(d *C.lucy_Doc, fields unsafe.Pointer) {
-	panic(clownfish.NewErr("Set_Fields unsupported in Go bindings"))
+	panic(clownfish.NewErr("Set_Fields unsupported from C-space in Go"))
 }
 
 //export GOLUCY_Doc_Get_Size


[06/13] lucy git commit: Consolidate Searcher Go bindings.

Posted by ma...@apache.org.
Consolidate Searcher Go bindings.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/e35becd7
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/e35becd7
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/e35becd7

Branch: refs/heads/master
Commit: e35becd7dd804ceb103e19710f0aa85fd864e150
Parents: e101aca
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Tue Nov 10 19:28:38 2015 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Fri Nov 20 16:43:37 2015 -0800

----------------------------------------------------------------------
 go/lucy/search.go | 33 +++------------------------------
 1 file changed, 3 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/e35becd7/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index a8bab6f..44f5054 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -69,15 +69,6 @@ func OpenIndexSearcher(index interface{}) (obj IndexSearcher, err error) {
 	return obj, err
 }
 
-func (obj *IndexSearcherIMP) Close() error {
-	return doClose(obj)
-}
-
-func (obj *IndexSearcherIMP) Hits(query interface{}, offset uint32, numWanted uint32,
-	sortSpec SortSpec) (hits Hits, err error) {
-	return doHits(obj, query, offset, numWanted, sortSpec)
-}
-
 // Read data into the supplied doc.
 func (s *SearcherIMP) ReadDoc(docID int32, doc interface{}) error {
 	self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
@@ -97,14 +88,14 @@ func (s *SearcherIMP) ReadDoc(docID int32, doc interface{}) error {
 	}
 }
 
-func doClose(obj Searcher) error {
-	self := ((*C.lucy_Searcher)(unsafe.Pointer(obj.TOPTR())))
+func (s *SearcherIMP) Close() error {
 	return clownfish.TrapErr(func() {
+		self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
 		C.LUCY_Searcher_Close(self)
 	})
 }
 
-func doHits(s Searcher, query interface{}, offset uint32, numWanted uint32,
+func (s *SearcherIMP) Hits(query interface{}, offset uint32, numWanted uint32,
 	sortSpec SortSpec) (hits Hits, err error) {
 	self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s"))
 	sortSpecC := (*C.lucy_SortSpec)(clownfish.UnwrapNullable(sortSpec))
@@ -118,24 +109,6 @@ func doHits(s Searcher, query interface{}, offset uint32, numWanted uint32,
 	return hits, err
 }
 
-func (obj *SearcherIMP) Close() error {
-	return doClose(obj)
-}
-
-func (obj *SearcherIMP) Hits(query interface{}, offset uint32, numWanted uint32,
-	sortSpec SortSpec) (hits Hits, err error) {
-	return doHits(obj, query, offset, numWanted, sortSpec)
-}
-
-func (obj *PolySearcherIMP) Close() error {
-	return doClose(obj)
-}
-
-func (obj *PolySearcherIMP) Hits(query interface{}, offset uint32, numWanted uint32,
-	sortSpec SortSpec) (hits Hits, err error) {
-	return doHits(obj, query, offset, numWanted, sortSpec)
-}
-
 type setScorer interface {
 	SetScore(float32)
 }