Beispiel #1
0
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)
}
Beispiel #2
0
// 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)))
}
Beispiel #3
0
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))
}
Beispiel #4
0
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)))
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}