func (in *InStreamIMP) ReadCU32() (uint32, error) { var retval uint32 err := clownfish.TrapErr(func() { self := (*C.lucy_InStream)(clownfish.Unwrap(in, "in")) retval = uint32(C.LUCY_InStream_Read_CU32(self)) }) return retval, err }
func (in *InStreamIMP) ReadString() (string, error) { var retval string err := clownfish.TrapErr(func() { self := (*C.lucy_InStream)(clownfish.Unwrap(in, "in")) size := C.size_t(C.LUCY_InStream_Read_CU32(self)) buf := (*C.char)(C.malloc(size)) defer C.free(unsafe.Pointer(buf)) C.LUCY_InStream_Read_Bytes(self, buf, size) retval = C.GoStringN(buf, C.int(size)) }) return retval, err }
func doReadDocData(ddrC *C.lucy_DefaultDocReader, docID int32, doc interface{}) error { // Adapt for different types of "doc". var setField func(interface{}, string, interface{}) error var fields interface{} switch v := doc.(type) { case Doc: docC := (*C.lucy_Doc)(clownfish.Unwrap(v, "doc")) fieldsMap := fetchDocFields(docC) for field, _ := range fieldsMap { delete(fieldsMap, field) } fields = fieldsMap setField = setMapField case map[string]interface{}: for field, _ := range v { delete(v, field) } fields = v setField = setMapField default: // Get reflection value and type for the supplied struct. var hitValue reflect.Value if reflect.ValueOf(doc).Kind() == reflect.Ptr { temp := reflect.ValueOf(doc).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(doc)) return clownfish.NewErr(mess) } fields = hitValue setField = setStructField } ivars := C.lucy_DefDocReader_IVARS(ddrC) schema := ivars.schema datInstream := ivars.dat_in ixInstream := ivars.ix_in fieldNameCap := C.size_t(31) var fieldName *C.char = ((*C.char)(C.malloc(fieldNameCap + 1))) defer C.free(unsafe.Pointer(fieldName)) // Get data file pointer from index, read number of fields. C.LUCY_InStream_Seek(ixInstream, C.int64_t(docID*8)) start := C.LUCY_InStream_Read_U64(ixInstream) C.LUCY_InStream_Seek(datInstream, C.int64_t(start)) numFields := uint32(C.LUCY_InStream_Read_CU32(datInstream)) // Decode stored data and build up the doc field by field. for i := uint32(0); i < numFields; i++ { // Read field name. fieldNameLen := C.size_t(C.LUCY_InStream_Read_CU32(datInstream)) if fieldNameLen > fieldNameCap { fieldNameCap = fieldNameLen fieldName = ((*C.char)(C.realloc(unsafe.Pointer(fieldName), fieldNameCap+1))) } C.LUCY_InStream_Read_Bytes(datInstream, fieldName, fieldNameLen) // Find the Field's FieldType. // TODO: Creating and destroying a new string each time is // 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. 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_CU32(datInstream)) buf := ((*C.char)(C.malloc(valueLen + 1))) C.LUCY_InStream_Read_Bytes(datInstream, buf, valueLen) val := C.GoStringN(buf, C.int(valueLen)) err := setField(fields, fieldNameGo, val) if err != nil { return err } case C.lucy_FType_BLOB: valueLen := C.size_t(C.LUCY_InStream_Read_CU32(datInstream)) buf := ((*C.char)(C.malloc(valueLen))) C.LUCY_InStream_Read_Bytes(datInstream, buf, valueLen) val := C.GoBytes(unsafe.Pointer(buf), C.int(valueLen)) err := setField(fields, fieldNameGo, val) if err != nil { return err } case C.lucy_FType_FLOAT32: err := setField(fields, fieldNameGo, float32(C.LUCY_InStream_Read_F32(datInstream))) if err != nil { return err } case C.lucy_FType_FLOAT64: err := setField(fields, fieldNameGo, float64(C.LUCY_InStream_Read_F64(datInstream))) if err != nil { return err } case C.lucy_FType_INT32: err := setField(fields, fieldNameGo, int32(C.LUCY_InStream_Read_CI32(datInstream))) if err != nil { return err } case C.lucy_FType_INT64: err := setField(fields, fieldNameGo, int64(C.LUCY_InStream_Read_CI64(datInstream))) if err != nil { return err } default: return clownfish.NewErr( "Internal Lucy error: bad type id for field " + fieldNameGo) } } return nil }