Switch Doc to `map[string]interface{}`.

Change from Clownfish Hash to Go map.


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

Branch: refs/heads/master
Commit: 8223307d126898cee43286e1e7bafb6f6d149c25
Parents: a41f86c
Author: Marvin Humphrey <[email protected]>
Authored: Tue Sep 15 20:25:31 2015 -0700
Committer: Marvin Humphrey <[email protected]>
Committed: Mon Sep 28 12:54:38 2015 -0700

----------------------------------------------------------------------
 go/lucy/document.go |   6 +--
 go/lucy/index.go    |  24 +++++------
 go/lucy/lucy.go     | 107 +++++++++++++++++++++++------------------------
 go/lucy/search.go   |  11 ++---
 4 files changed, 69 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/8223307d/go/lucy/document.go
----------------------------------------------------------------------
diff --git a/go/lucy/document.go b/go/lucy/document.go
index 3196986..1221810 100644
--- a/go/lucy/document.go
+++ b/go/lucy/document.go
@@ -39,12 +39,12 @@ func NewHitDoc(docID int32, score float32) HitDoc {
        return WRAPHitDoc(unsafe.Pointer(retvalCF))
 }
 
-func fetchDocFields(d *C.lucy_Doc) *C.cfish_Hash {
+func fetchDocFields(d *C.lucy_Doc) map[string]interface{} {
        ivars := C.lucy_Doc_IVARS(d)
        fieldsID := uintptr(ivars.fields)
-       fieldsGo, ok := registry.fetch(fieldsID).(clownfish.Hash)
+       fieldsGo, ok := registry.fetch(fieldsID).(map[string]interface{})
        if !ok {
                panic(clownfish.NewErr(fmt.Sprintf("Failed to fetch doc %d from 
registry ", fieldsID)))
        }
-       return (*C.cfish_Hash)(clownfish.Unwrap(fieldsGo, "fieldsGo"))
+       return fieldsGo
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/8223307d/go/lucy/index.go
----------------------------------------------------------------------
diff --git a/go/lucy/index.go b/go/lucy/index.go
index 6543c99..1662d3e 100644
--- a/go/lucy/index.go
+++ b/go/lucy/index.go
@@ -35,7 +35,7 @@ import 
"git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
 
 type IndexerIMP struct {
        clownfish.ObjIMP
-       fieldNames map[string]clownfish.String
+       fieldNames map[string]string
 }
 
 type OpenIndexerArgs struct {
@@ -74,7 +74,9 @@ func (obj *IndexerIMP) AddDoc(doc interface{}) error {
        self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR())))
        stockDoc := C.LUCY_Indexer_Get_Stock_Doc(self)
        docFields := fetchDocFields(stockDoc)
-       C.CFISH_Hash_Clear(docFields)
+       for field := range docFields {
+               delete(docFields, field)
+       }
 
        // TODO: Support map as doc in addition to struct as doc.
 
@@ -96,11 +98,8 @@ func (obj *IndexerIMP) AddDoc(doc interface{}) error {
        for i := 0; i < docValue.NumField(); i++ {
                field := docType.Field(i).Name
                value := docValue.Field(i).String()
-               fieldC := obj.findFieldC(field)
-               valueC := clownfish.NewString(value)
-               C.CFISH_Hash_Store(docFields,
-                       (*C.cfish_String)(unsafe.Pointer(fieldC)),
-                       C.cfish_inc_refcount(unsafe.Pointer(valueC.TOPTR())))
+               realField := obj.findRealField(field)
+               docFields[realField] = value
        }
 
        // TODO create an additional method AddDocWithBoost which allows the
@@ -113,10 +112,10 @@ func (obj *IndexerIMP) AddDoc(doc interface{}) error {
        return err
 }
 
-func (obj *IndexerIMP) findFieldC(name string) *C.cfish_String {
+func (obj *IndexerIMP) findRealField(name string) string {
        self := ((*C.lucy_Indexer)(unsafe.Pointer(obj.TOPTR())))
        if obj.fieldNames == nil {
-               obj.fieldNames = make(map[string]clownfish.String)
+               obj.fieldNames = make(map[string]string)
        }
        f, ok := obj.fieldNames[name]
        if !ok {
@@ -127,13 +126,12 @@ func (obj *IndexerIMP) findFieldC(name string) 
*C.cfish_String {
                        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
+                               f = field
+                               obj.fieldNames[name] = field
                        }
                }
        }
-       return (*C.cfish_String)(unsafe.Pointer(f.TOPTR()))
+       return f
 }
 
 func (obj *IndexerIMP) Commit() error {

http://git-wip-us.apache.org/repos/asf/lucy/blob/8223307d/go/lucy/lucy.go
----------------------------------------------------------------------
diff --git a/go/lucy/lucy.go b/go/lucy/lucy.go
index 50ac2c9..36868bd 100644
--- a/go/lucy/lucy.go
+++ b/go/lucy/lucy.go
@@ -183,6 +183,7 @@ import "C"
 import "unsafe"
 import "fmt"
 import "regexp"
+import "reflect"
 import 
"git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
 
 var registry *objRegistry
@@ -253,7 +254,8 @@ func GOLUCY_RegexTokenizer_Tokenize_Utf8(rt 
*C.lucy_RegexTokenizer, str *C.char,
 func GOLUCY_Doc_init(d *C.lucy_Doc, fields unsafe.Pointer, docID C.int32_t) 
*C.lucy_Doc {
        ivars := C.lucy_Doc_IVARS(d)
        if fields == nil {
-               fieldsID := registry.store(clownfish.NewHash(0))
+               fieldsGo := make(map[string]interface{})
+               fieldsID := registry.store(fieldsGo)
                ivars.fields = unsafe.Pointer(fieldsID)
        } else {
                ivars.fields = fields
@@ -269,21 +271,25 @@ func GOLUCY_Doc_Set_Fields(d *C.lucy_Doc, fields 
unsafe.Pointer) {
 
 //export GOLUCY_Doc_Get_Size
 func GOLUCY_Doc_Get_Size(d *C.lucy_Doc) C.uint32_t {
-       hash := fetchDocFields(d)
-       return C.uint32_t(C.CFISH_Hash_Get_Size(hash))
+       fields := fetchDocFields(d)
+       return C.uint32_t(len(fields))
 }
 
 //export GOLUCY_Doc_Store
 func GOLUCY_Doc_Store(d *C.lucy_Doc, field *C.cfish_String, value 
*C.cfish_Obj) {
-       hash := fetchDocFields(d)
-       C.CFISH_Hash_Store(hash, field, 
C.cfish_inc_refcount(unsafe.Pointer(value)))
+       fields := fetchDocFields(d)
+       fieldGo := clownfish.CFStringToGo(unsafe.Pointer(field))
+       valGo := clownfish.ToGo(unsafe.Pointer(value))
+       fields[fieldGo] = valGo
 }
 
 //export GOLUCY_Doc_Serialize
 func GOLUCY_Doc_Serialize(d *C.lucy_Doc, outstream *C.lucy_OutStream) {
        ivars := C.lucy_Doc_IVARS(d)
-       hash := fetchDocFields(d)
-       C.lucy_Freezer_serialize_hash(hash, outstream)
+       fields := fetchDocFields(d)
+       hash := clownfish.GoToClownfish(fields, unsafe.Pointer(C.CFISH_HASH), 
false)
+       defer C.cfish_decref(hash)
+       C.lucy_Freezer_serialize_hash((*C.cfish_Hash)(hash), outstream)
        C.LUCY_OutStream_Write_C32(outstream, C.uint32_t(ivars.doc_id))
 }
 
@@ -291,7 +297,9 @@ func GOLUCY_Doc_Serialize(d *C.lucy_Doc, outstream 
*C.lucy_OutStream) {
 func GOLUCY_Doc_Deserialize(d *C.lucy_Doc, instream *C.lucy_InStream) 
*C.lucy_Doc {
        ivars := C.lucy_Doc_IVARS(d)
        hash := unsafe.Pointer(C.lucy_Freezer_read_hash(instream))
-       fieldsID := registry.store(clownfish.WRAPAny(hash))
+       defer C.cfish_decref(hash)
+       fields := clownfish.ToGo(hash)
+       fieldsID := registry.store(fields)
        ivars.fields = unsafe.Pointer(fieldsID)
        ivars.doc_id = C.int32_t(C.LUCY_InStream_Read_C32(instream))
        return d
@@ -299,15 +307,20 @@ func GOLUCY_Doc_Deserialize(d *C.lucy_Doc, instream 
*C.lucy_InStream) *C.lucy_Do
 
 //export GOLUCY_Doc_Extract
 func GOLUCY_Doc_Extract(d *C.lucy_Doc, field *C.cfish_String) *C.cfish_Obj {
-       hash := fetchDocFields(d)
-       val := C.CFISH_Hash_Fetch(hash, field)
-       return C.cfish_inc_refcount(unsafe.Pointer(val))
+       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_Field_Names
 func GOLUCY_Doc_Field_Names(d *C.lucy_Doc) *C.cfish_Vector {
-       hash := fetchDocFields(d)
-       return C.CFISH_Hash_Keys(hash)
+       fields := fetchDocFields(d)
+       vec := clownfish.NewVector(len(fields))
+       for key, _ := range fields {
+               vec.Push(key)
+       }
+       return (*C.cfish_Vector)(C.cfish_incref(clownfish.Unwrap(vec, "vec")))
 }
 
 //export GOLUCY_Doc_Equals
@@ -319,9 +332,10 @@ func GOLUCY_Doc_Equals(d *C.lucy_Doc, other *C.cfish_Obj) 
C.bool {
        if !C.cfish_Obj_is_a(other, C.LUCY_DOC) {
                return false
        }
-       hash := fetchDocFields(d)
-       otherHash := (*C.cfish_Obj)(unsafe.Pointer(fetchDocFields(twin)))
-       return C.CFISH_Hash_Equals(hash, otherHash)
+       fields := fetchDocFields(d)
+       otherFields := fetchDocFields(twin)
+       result := reflect.DeepEqual(fields, otherFields)
+       return C.bool(result)
 }
 
 //export GOLUCY_Doc_Destroy
@@ -332,7 +346,10 @@ func GOLUCY_Doc_Destroy(d *C.lucy_Doc) {
        C.cfish_super_destroy(unsafe.Pointer(d), C.LUCY_DOC)
 }
 
-func fetchEntry(ivars *C.lucy_InverterIVARS, field *C.cfish_String) 
*C.lucy_InverterEntry {
+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 {
@@ -366,7 +383,7 @@ func GOLUCY_DefDocReader_Fetch_Doc(ddr 
*C.lucy_DefaultDocReader,
        schema := ivars.schema
        datInstream := ivars.dat_in
        ixInstream := ivars.ix_in
-       fields := C.cfish_Hash_new(1)
+       fields := make(map[string]interface{})
        fieldNameCap := C.size_t(31)
        var fieldName *C.char = ((*C.char)(C.malloc(fieldNameCap + 1)))
 
@@ -391,43 +408,40 @@ func GOLUCY_DefDocReader_Fetch_Doc(ddr 
*C.lucy_DefaultDocReader,
                // 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)
+               fieldNameGo := C.GoStringN(fieldName, C.int(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)))
+                       val := C.GoStringN(buf, C.int(valueLen))
+                       fields[fieldNameGo] = val
                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)))
+                       val := C.GoBytes(unsafe.Pointer(buf), C.int(valueLen))
+                       fields[fieldNameGo] = val
                case C.lucy_FType_FLOAT32:
-                       value = 
((*C.cfish_Obj)(C.cfish_Float_new(C.double(C.LUCY_InStream_Read_F32(datInstream)))))
+                       fields[fieldNameGo] = 
float32(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))))
+                       fields[fieldNameGo] = 
float64(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)))))
+                       fields[fieldNameGo] = 
int32(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)))))
+                       fields[fieldNameGo] = 
int32(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))))
+                               fieldNameGo))
                }
-
-               // Store the value.
-               C.CFISH_Hash_Store_Utf8(fields, fieldName, fieldNameLen, value)
        }
        C.free(unsafe.Pointer(fieldName))
 
-       fieldsID := registry.store(clownfish.WRAPAny(unsafe.Pointer(fields)))
+       fieldsID := registry.store(fields)
        retval := C.lucy_HitDoc_new(unsafe.Pointer(fieldsID), docID, 0.0)
        return retval
 }
@@ -441,15 +455,7 @@ func GOLUCY_Inverter_Invert_Doc(inverter *C.lucy_Inverter, 
doc *C.lucy_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))
-               }
-
+       for field, val := range(fields) {
                inventry := fetchEntry(ivars, field)
                inventryIvars := C.lucy_InvEntry_IVARS(inventry)
                fieldType := inventryIvars._type
@@ -470,22 +476,13 @@ func GOLUCY_Inverter_Invert_Doc(inverter 
*C.lucy_Inverter, doc *C.lucy_Doc) {
                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))
+                       panic(clownfish.NewErr("Internal Lucy error: bad type 
id for field " + field))
                }
+               temp := inventryIvars.value
+               valCF := clownfish.GoToClownfish(val, 
unsafe.Pointer(expectedType), false)
+               inventryIvars.value = C.cfish_inc_refcount(valCF)
+               C.cfish_decref(unsafe.Pointer(temp))
 
                C.LUCY_Inverter_Add_Field(inverter, inventry)
        }
-       C.cfish_dec_refcount(unsafe.Pointer(iter))
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/8223307d/go/lucy/search.go
----------------------------------------------------------------------
diff --git a/go/lucy/search.go b/go/lucy/search.go
index 7f6ce76..ed1b5e4 100644
--- a/go/lucy/search.go
+++ b/go/lucy/search.go
@@ -150,19 +150,14 @@ func (obj *HitsIMP) Next(hit interface{}) bool {
        defer C.cfish_dec_refcount(unsafe.Pointer(docC))
 
        fields := fetchDocFields((*C.lucy_Doc)(unsafe.Pointer(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))
+       for key, val := range fields {
+               stringVal := val.(string) // TODO type switch
                match := func(name string) bool {
                        return strings.EqualFold(key, name)
                }
                structField := hitValue.FieldByNameFunc(match)
                if structField != (reflect.Value{}) {
-                       structField.SetString(val)
+                       structField.SetString(stringVal)
                }
        }
        return true

Reply via email to