Files
ziutek-glib/type.go
2011-09-08 16:25:28 +02:00

293 lines
5.7 KiB
Go

// Bindings for glib
package glib
/*
#include <stdlib.h>
#include <glib-object.h>
#define _GINT_SIZE sizeof(gint)
#define _GLONG_SIZE sizeof(glong)
#cgo pkg-config: glib-2.0 gobject-2.0
*/
import "C"
import (
"strconv"
"reflect"
"unsafe"
)
type TypeGetter interface {
Type() Type
}
type PointerSetter interface {
SetPtr(p Pointer)
}
// A numerical value which represents the unique identifier of a registered type
type Type C.GType
const (
TYPE_INVALID = Type(C.G_TYPE_INVALID)
TYPE_NONE = Type(C.G_TYPE_NONE)
TYPE_INTERFACE = Type(C.G_TYPE_INTERFACE)
TYPE_CHAR = Type(C.G_TYPE_CHAR)
TYPE_UCHAR = Type(C.G_TYPE_UCHAR)
TYPE_BOOLEAN = Type(C.G_TYPE_BOOLEAN)
TYPE_INT = Type(C.G_TYPE_INT)
TYPE_UINT = Type(C.G_TYPE_UINT)
TYPE_LONG = Type(C.G_TYPE_LONG)
TYPE_ULONG = Type(C.G_TYPE_ULONG)
TYPE_INT64 = Type(C.G_TYPE_INT64)
TYPE_UINT64 = Type(C.G_TYPE_UINT64)
TYPE_ENUM = Type(C.G_TYPE_ENUM)
TYPE_FLAGS = Type(C.G_TYPE_FLAGS)
TYPE_FLOAT = Type(C.G_TYPE_FLOAT)
TYPE_DOUBLE = Type(C.G_TYPE_DOUBLE)
TYPE_STRING = Type(C.G_TYPE_STRING)
TYPE_POINTER = Type(C.G_TYPE_POINTER)
TYPE_BOXED = Type(C.G_TYPE_BOXED)
TYPE_PARAM = Type(C.G_TYPE_PARAM)
TYPE_OBJECT = Type(C.G_TYPE_OBJECT)
TYPE_VARIANT = Type(C.G_TYPE_VARIANT)
)
var (
TYPE_GTYPE Type
TYPE_GO_INT Type
TYPE_GO_UINT Type
TYPE_GO_INT32 Type
TYPE_GO_UINT32 Type
)
func (t Type) g() C.GType {
return C.GType(t)
}
func (t Type) String() string {
return C.GoString((*C.char)(C.g_type_name(t.g())))
}
func (t Type) QName() Quark {
return Quark(C.g_type_qname(t.g()))
}
func (t Type) Type() Type {
return TYPE_GTYPE
}
func (t Type) Value() *Value {
v := NewValue(t.Type())
C.g_value_set_gtype(v.g(), t.g())
return v
}
func (t Type) Parent() Type {
return Type(C.g_type_parent(t.g()))
}
func (t Type) Depth() uint {
return uint(C.g_type_depth(t.g()))
}
// Returns the type that is derived directly from root type which is also
// a base class of t
func (t Type) NextBase(root Type) Type {
return Type(C.g_type_next_base(t.g(), root.g()))
}
// If t type is a derivable type, check whether type is a descendant of
// it type. If t type is an glib interface, check whether type conforms
// to it.
func (t Type) IsA(it Type) bool {
return C.g_type_is_a(t.g(), it.g()) != 0
}
var type_getter = reflect.TypeOf((*TypeGetter)(nil)).Elem()
var object_caster = reflect.TypeOf((*ObjectCaster)(nil)).Elem()
func (t Type) Match(rt reflect.Type) bool {
if rt.Implements(object_caster) {
return t.IsA(TYPE_OBJECT)
}
if rt.Implements(type_getter) {
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
}
r := reflect.New(rt).Interface().(TypeGetter).Type()
return t.QName() == r.QName()
}
switch rt.Kind() {
case reflect.Invalid:
return t == TYPE_INVALID
case reflect.String:
return t == TYPE_STRING
case reflect.Int:
return t == TYPE_GO_INT
case reflect.Uint:
return t == TYPE_GO_UINT
case reflect.Int8:
return t == TYPE_CHAR
case reflect.Uint8:
return t == TYPE_UCHAR
case reflect.Int32:
return t == TYPE_GO_INT32
case reflect.Uint32:
return t == TYPE_GO_UINT32
case reflect.Int64:
return t == TYPE_INT64
case reflect.Uint64:
return t == TYPE_UINT64
case reflect.Bool:
return t == TYPE_BOOLEAN
case reflect.Float32:
return t == TYPE_FLOAT
case reflect.Float64:
return t == TYPE_DOUBLE
case reflect.Ptr:
return t == TYPE_POINTER
}
return false
}
// Returns the Type of the value in the interface{}.
func TypeOf(i interface{}) Type {
// Types ov values that implements TypeGetter
if o, ok := i.(TypeGetter); ok {
return o.Type()
}
// Other types
switch reflect.TypeOf(i).Kind() {
case reflect.Invalid:
return TYPE_INVALID
case reflect.Bool:
return TYPE_BOOLEAN
case reflect.Int:
return TYPE_GO_INT
case reflect.Int8:
return TYPE_CHAR
case reflect.Int32:
return TYPE_GO_INT32
case reflect.Int64:
return TYPE_INT64
case reflect.Uint:
return TYPE_GO_UINT
case reflect.Uint8:
return TYPE_UCHAR
case reflect.Uint32:
return TYPE_GO_UINT32
case reflect.Uint64:
return TYPE_UINT64
case reflect.Float32:
return TYPE_FLOAT
case reflect.Float64:
return TYPE_DOUBLE
case reflect.Ptr:
return TYPE_POINTER
case reflect.String:
return TYPE_STRING
}
panic("Can't map Go type to Glib type")
}
func TypeFromName(name string) Type {
tn := C.CString(name)
defer C.free(unsafe.Pointer(tn))
return Type(C.g_type_from_name((*C.gchar)(tn)))
}
func init() {
C.g_thread_init(nil)
C.g_type_init()
TYPE_GTYPE = Type(C.g_gtype_get_type())
int_bytes := strconv.IntSize / 8
if int_bytes == uint(C._GINT_SIZE) {
TYPE_GO_INT = TYPE_INT
TYPE_GO_UINT = TYPE_UINT
} else if int_bytes == C._GLONG_SIZE {
TYPE_GO_INT = TYPE_LONG
TYPE_GO_UINT = TYPE_ULONG
} else if int_bytes == 64 {
TYPE_GO_INT = TYPE_INT64
TYPE_GO_UINT = TYPE_UINT64
} else {
panic("Unexpectd size of 'int'")
}
int32_bytes := C.uint(4)
if int32_bytes == C._GINT_SIZE {
TYPE_GO_INT32 = TYPE_INT
TYPE_GO_UINT32 = TYPE_UINT
} else if int32_bytes == C._GLONG_SIZE {
TYPE_GO_INT32 = TYPE_LONG
TYPE_GO_UINT32 = TYPE_ULONG
} else {
panic("Neither gint nor glong are 32 bit numbers")
}
}
type Pointer C.gpointer
func gBoolean(b bool) C.gboolean {
if b {
return C.TRUE
}
return C.FALSE
}
type Quark C.GQuark
func (q Quark) GQuark() C.GQuark {
return C.GQuark(q)
}
func (q Quark) String() string {
return C.GoString((*C.char)(C.g_quark_to_string(q.GQuark())))
}
func QuarkFromString(s string) Quark {
return Quark(C.g_quark_from_static_string((*C.gchar)(C.CString(s))))
}
type Error C.GError
func (e *Error) String() string {
return C.GoString((*C.char)(e.message))
}
func (e *Error) GetDomain() Quark {
return Quark(e.domain)
}
func (e *Error) GetCode() int {
return int(e.code)
}