X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=glib%2Fgobject.type-designator.lisp;h=ebd1925387ffe397cc399ccccf8ca797faa5bc35;hb=47427d9e824cf990bf88b4db8fdb205565062cd2;hp=d95e9b2365d63a4a344388978a1eeff737bba5b7;hpb=37f2b465775011aea78ee020fd9b41a0d3e267b7;p=cl-gtk2.git diff --git a/glib/gobject.type-designator.lisp b/glib/gobject.type-designator.lisp index d95e9b2..ebd1925 100644 --- a/glib/gobject.type-designator.lisp +++ b/glib/gobject.type-designator.lisp @@ -2,6 +2,94 @@ (defctype g-type gsize) +(defstruct gtype name %id) + +(defvar *name-to-gtype* (make-hash-table :test 'equal)) +(defvar *id-to-gtype* (make-hash-table)) +(defvar *gtype-lock* (bt:make-lock "gtype lock")) + +(defun invalidate-gtypes () + (bt:with-lock-held (*gtype-lock*) + (clrhash *id-to-gtype*) + (iter (for (name gtype) in-hashtable *name-to-gtype*) + (setf (gtype-%id gtype) nil)))) + +(at-finalize () (invalidate-gtypes)) + +(defcfun (%g-type-from-name "g_type_from_name") g-type + (name :string)) + +(defcfun (%g-type-name "g_type_name") (:string :free-from-foreign nil) + (type g-type)) + +(defun gtype-from-name (name) + (when (null name) (return-from gtype-from-name nil)) + (bt:with-lock-held (*gtype-lock*) + (let ((type (gethash name *name-to-gtype*))) + (when type + (when (null (gtype-%id type)) + (let ((n (%g-type-from-name name))) + (if (zerop n) + (warn "GType ~A is not known to GObject" name) + (progn + (setf (gtype-%id type) n + (gethash n *id-to-gtype*) type))))) + (return-from gtype-from-name type))) + (let ((n (%g-type-from-name name))) + (when (zerop n) + (warn "GType ~A is not known to GObject" name) + (setf n nil)) + (let ((type (make-gtype :name (copy-seq name) :%id n))) + (setf (gethash n *id-to-gtype*) type + (gethash name *name-to-gtype*) type) + (return-from gtype-from-name type))))) + +(defun gtype-from-id (id) + (when (zerop id) (return-from gtype-from-id nil)) + (bt:with-lock-held (*gtype-lock*) + (let ((type (gethash id *id-to-gtype*))) + (when type + (return-from gtype-from-id type))) + (let ((name (%g-type-name id))) + (unless name + (error "GType with ~A is not known to GObject" id)) + (let ((type (gethash name *name-to-gtype*))) + (when type + (setf (gtype-%id type) id + (gethash id *id-to-gtype*) type) + (return-from gtype-from-id type)) + (let ((type (make-gtype :name name :%id id))) + (setf (gethash id *id-to-gtype*) type + (gethash name *name-to-gtype*) type) + (return-from gtype-from-id type)))))) + +(defun gtype-id (gtype) + (when (null gtype) (return-from gtype-id 0)) + (when (gtype-%id gtype) (return-from gtype-id (gtype-%id gtype))) + (bt:with-lock-held (*gtype-lock*) + (let ((n (%g-type-from-name (gtype-name gtype)))) + (when (zerop n) + (warn "GType ~A is not known to GObject" (gtype-name gtype)) + (return-from gtype-id 0)) + (setf (gtype-%id gtype) n + (gethash n *id-to-gtype*) gtype) + n))) + +(defun %gtype (thing) + (etypecase thing + (null nil) + (gtype thing) + (string (gtype-from-name thing)) + (integer (gtype-from-id thing)))) + +(defun gtype (thing) + (%gtype thing)) + +(define-compiler-macro gtype (&whole whole thing) + (if (constantp thing) + `(load-time-value (%gtype ,thing)) + whole)) + (define-foreign-type g-type-designator () ((mangled-p :initarg :mangled-p :reader g-type-designator-mangled-p @@ -65,4 +153,12 @@ Example: } @arg[name]{a string - name of GType} @return{an integer}" - (name :string)) \ No newline at end of file + (name :string)) + +(defun g-type= (type-1 type-2) + (= (g-type-numeric type-1) + (g-type-numeric type-2))) + +(defun g-type/= (type-1 type-2) + (/= (g-type-numeric type-1) + (g-type-numeric type-2)))