;; License along with this library; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-;; $Id: genums.lisp,v 1.4 2004-11-06 21:39:58 espen Exp $
+;; $Id: genums.lisp,v 1.8 2005-02-10 20:27:54 espen Exp $
(in-package "GLIB")
(defun query-enum-values (type)
(%query-enum-or-flags-values #'%enum-class-values '%enum-value type))
+(defun enum-int (enum type)
+ (funcall (to-alien-function type) enum))
+
+(defun int-enum (int type)
+ (funcall (from-alien-function type) int))
+
+(defun enum-mapping (type)
+ (rest (type-expand-to 'enum type)))
+
+
+;;;; Named enum types
+
+(defmacro define-enum-type (name &rest args)
+ (let ((enum-int (intern (format nil "~A-TO-INT" name)))
+ (int-enum (intern (format nil "INT-TO-~A" name))))
+ `(progn
+ (deftype ,name () '(enum ,@args))
+ (defun ,enum-int (value)
+ (ecase value
+ ,@(%map-enum args :enum-int)))
+ (defun ,int-enum (value)
+ (ecase value
+ ,@(%map-enum args :int-enum)))
+ (defmethod to-alien-form (form (type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (list ',enum-int form))
+ (defmethod from-alien-form (form (type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (list ',int-enum form))
+ (defmethod to-alien-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ #',enum-int)
+ (defmethod from-alien-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ #',int-enum)
+ (defmethod writer-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (let ((writer (writer-function 'signed)))
+ #'(lambda (enum location &optional (offset 0))
+ (funcall writer (,enum-int enum) location offset))))
+ (defmethod reader-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (let ((reader (reader-function 'signed)))
+ #'(lambda (location &optional (offset 0))
+ (,int-enum (funcall reader location offset))))))))
;;;; Generic flags type
(declare (ignore type))
`(loop
for mapping in ',(%map-enum args :int-flags)
- unless (zerop (logand int (first mapping)))
+ unless (zerop (logand ,int (first mapping)))
collect (second mapping)))
(defmethod to-alien-function ((type (eql 'flags)) &rest args)
(%query-enum-or-flags-values #'%flags-class-values '%flags-value type))
+;;;; Named flags types
-;;;;
-
-(defun expand-enum-type (type-number &optional options)
+(defmacro define-flags-type (name &rest args)
+ (let ((flags-int (intern (format nil "~A-TO-INT" name)))
+ (int-flags (intern (format nil "INT-TO-~A" name))))
+ `(progn
+ (deftype ,name () '(flags ,@args))
+ (defun ,flags-int (value)
+ (ecase value
+ ,@(%map-enum args :flags-int)))
+ (defun ,int-flags (value)
+ (ecase value
+ ,@(%map-enum args :int-flags)))
+ (defmethod to-alien-form (form (type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (list ',flags-int form))
+ (defmethod from-alien-form (form (type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (list ',int-flags form))
+ (defmethod to-alien-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ #',flags-int)
+ (defmethod from-alien-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ #',int-flags)
+ (defmethod writer-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (let ((writer (writer-function 'signed)))
+ #'(lambda (flags location &optional (offset 0))
+ (funcall writer (,flags-int flags) location offset))))
+ (defmethod reader-function ((type (eql ',name)) &rest args)
+ (declare (ignore type args))
+ (let ((reader (reader-function 'signed)))
+ #'(lambda (location &optional (offset 0))
+ (,int-flags (funcall reader location offset))))))))
+
+
+
+;;;; Type definition by introspection
+
+(defun expand-enum-type (type-number forward-p options)
+ (declare (ignore forward-p))
(let* ((super (supertype type-number))
(type (type-from-number type-number))
(mappings (getf options :mappings))
#'(lambda (mapping) (eq (second mapping) nil)) mappings))))
`(progn
(register-type ',type ,(find-type-name type-number))
- (deftype ,type () '(,super ,@expanded-mappings)))))
+ ,(ecase super
+ (enum `(define-enum-type ,type ,@expanded-mappings))
+ (flags `(define-flags-type ,type ,@expanded-mappings))))))
(register-derivable-type 'enum "GEnum" 'expand-enum-type)