func WRAPAny(ptr unsafe.Pointer) Obj { if ptr == nil { return nil } class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr)) wrapFunc := (*wrapReg)[unsafe.Pointer(class)] if wrapFunc == nil { className := CFStringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name((*C.cfish_Class)(class)))) panic(fmt.Sprintf("Failed to find WRAP function for %s", className)) } return wrapFunc(ptr) }
// Convert a Go type into an incremented Clownfish object. If the supplied // object is a Clownfish object wrapped in a Go struct, extract the Clownfish // object and incref it before returning its address. func GoToClownfish(value interface{}, class unsafe.Pointer, nullable bool) unsafe.Pointer { klass := (*C.cfish_Class)(class) // Default to accepting any type. if klass == nil { klass = C.CFISH_OBJ } // Convert the value according to its type if possible. switch v := value.(type) { case string: if klass == C.CFISH_STRING || klass == C.CFISH_OBJ { return goToString(value, nullable) } case []byte: if klass == C.CFISH_BLOB || klass == C.CFISH_OBJ { return goToBlob(value, nullable) } case int, uint, uintptr, int64, int32, int16, int8, uint64, uint32, uint16, uint8: if klass == C.CFISH_INTEGER || klass == C.CFISH_OBJ { return goToInteger(value, nullable) } case float32, float64: if klass == C.CFISH_FLOAT || klass == C.CFISH_OBJ { return goToFloat(value, nullable) } case bool: if klass == C.CFISH_BOOLEAN || klass == C.CFISH_OBJ { return goToBoolean(value, nullable) } case []interface{}: if klass == C.CFISH_VECTOR || klass == C.CFISH_OBJ { return goToVector(value, nullable) } case map[string]interface{}: if klass == C.CFISH_HASH || klass == C.CFISH_OBJ { return goToHash(value, nullable) } case Obj: certifyCF(value, klass, nullable) return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR()))) case nil: if nullable { return nil } } // Report a conversion error. className := StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(klass))) panic(NewErr(fmt.Sprintf("Can't convert a %T to %s", value, className))) }
func BlobToGo(ptr unsafe.Pointer) []byte { blob := (*C.cfish_Blob)(ptr) if blob == nil { return nil } class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr)) if class != C.CFISH_BLOB { mess := "Not a Blob: " + StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(class))) panic(NewErr(mess)) } data := C.CFISH_Blob_Get_Buf(blob) size := C.CFISH_Blob_Get_Size(blob) if size > C.size_t(C.INT_MAX) { panic(fmt.Sprintf("Overflow: %d > %d", size, C.INT_MAX)) } return C.GoBytes(unsafe.Pointer(data), C.int(size)) }
func certifyCF(value interface{}, class *C.cfish_Class, nullable bool) { if nullable && value == nil { return } if cfObj, ok := value.(Obj); ok { o := (*C.cfish_Obj)(unsafe.Pointer(cfObj.TOPTR())) if o == nil { if nullable { return } } else if C.cfish_Obj_is_a(o, class) { return } } className := StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(class))) panic(NewErr(fmt.Sprintf("Can't convert a %T to %s", value, className))) }
func VectorToGo(ptr unsafe.Pointer) []interface{} { vec := (*C.cfish_Vector)(ptr) if vec == nil { return nil } class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr)) if class != C.CFISH_VECTOR { mess := "Not a Vector: " + StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(class))) panic(NewErr(mess)) } size := C.CFISH_Vec_Get_Size(vec) if size > C.size_t(maxInt) { panic(fmt.Sprintf("Overflow: %d > %d", size, maxInt)) } slice := make([]interface{}, int(size)) for i := 0; i < int(size); i++ { slice[i] = ToGo(unsafe.Pointer(C.CFISH_Vec_Fetch(vec, C.size_t(i)))) } return slice }
func HashToGo(ptr unsafe.Pointer) map[string]interface{} { hash := (*C.cfish_Hash)(ptr) if hash == nil { return nil } class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr)) if class != C.CFISH_HASH { mess := "Not a Hash: " + StringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name(class))) panic(NewErr(mess)) } size := C.CFISH_Hash_Get_Size(hash) m := make(map[string]interface{}, int(size)) iter := C.cfish_HashIter_new(hash) defer C.cfish_dec_refcount(unsafe.Pointer(iter)) for C.CFISH_HashIter_Next(iter) { key := C.CFISH_HashIter_Get_Key(iter) val := C.CFISH_HashIter_Get_Value(iter) m[StringToGo(unsafe.Pointer(key))] = ToGo(unsafe.Pointer(val)) } return m }