chiark / gitweb /
fe40137971f7d106ef1d0c0d8a5f4bcd88b048ce
[clg] / glib / glib.lisp
1 ;; Common Lisp bindings for GTK+ v1.2.x
2 ;; Copyright (C) 1999-2005 Espen S. Johnsen <espen@users-sf-net>
3 ;;
4 ;; This library is free software; you can redistribute it and/or
5 ;; modify it under the terms of the GNU Lesser General Public
6 ;; License as published by the Free Software Foundation; either
7 ;; version 2 of the License, or (at your option) any later version.
8 ;;
9 ;; This library is distributed in the hope that it will be useful,
10 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 ;; Lesser General Public License for more details.
13 ;;
14 ;; You should have received a copy of the GNU Lesser General Public
15 ;; License along with this library; if not, write to the Free Software
16 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18 ;; $Id: glib.lisp,v 1.29 2005-04-18 10:34:51 espen Exp $
19
20
21 (in-package "GLIB")
22
23 (use-prefix "g")
24
25
26 ;;;; Memory management
27
28 (defbinding (allocate-memory "g_malloc0") () pointer
29   (size unsigned-long))
30
31 (defbinding (reallocate-memory "g_realloc") () pointer
32   (address pointer)
33   (size unsigned-long))
34
35 (defbinding (deallocate-memory "g_free") () nil
36   (address pointer))
37 ;; (defun deallocate-memory (address)
38 ;;   (declare (ignore address)))
39
40 (defun copy-memory (from length &optional (to (allocate-memory length)))
41   #+cmu(system-area-copy from 0 to 0 (* 8 length))
42   #+sbcl(system-area-ub8-copy from 0 to 0 length)
43   to)
44
45
46 ;;;; User data mechanism
47
48 (internal *user-data* *user-data-count*)
49
50 (defvar *user-data* (make-hash-table))
51 (defvar *user-data-count* 0)
52
53 (defun register-user-data (object &optional destroy-function)
54   (check-type destroy-function (or null symbol function))
55   (incf *user-data-count*)
56   (setf
57    (gethash *user-data-count* *user-data*)
58    (cons object destroy-function))
59   *user-data-count*)
60
61 (defun find-user-data (id)
62   (check-type id fixnum)
63   (multiple-value-bind (user-data p) (gethash id *user-data*)
64     (values (car user-data) p)))
65
66 (defun user-data-exists-p (id)
67   (nth-value 1 (find-user-data id)))
68
69 (defun update-user-data (id object)
70   (check-type id fixnum)
71   (multiple-value-bind (user-data exists-p) (gethash id *user-data*)
72     (cond
73      ((not exists-p) (error "User data id ~A does not exist" id))
74      (t 
75       (when (cdr user-data)
76         (funcall (cdr user-data) (car user-data)))
77       (setf (car user-data) object)))))
78
79 (defun destroy-user-data (id)
80   (check-type id fixnum)
81   (let ((user-data (gethash id *user-data*)))
82     (when (cdr user-data)
83       (funcall (cdr user-data) (car user-data))))
84   (remhash id *user-data*))
85
86
87 ;;;; Quarks
88
89 (deftype quark () 'unsigned)
90
91 (defbinding %quark-from-string () quark
92   (string string))
93
94 (defun quark-intern (object)
95   (etypecase object
96     (quark object)
97     (string (%quark-from-string object))
98     (symbol (%quark-from-string (format nil "clg-~A:~A" 
99                                  (package-name (symbol-package object)) 
100                                  object)))))
101
102 (defbinding quark-to-string () (copy-of string)
103   (quark quark))
104
105
106 ;;;; Linked list (GList)
107
108 (deftype glist (type) 
109   `(or (null (cons ,type list))))
110
111 (defbinding (%glist-append "g_list_append") () pointer
112   (glist pointer)
113   (nil null))
114
115 (defun make-glist (type list)
116   (loop
117    with writer = (writer-function type)
118    for element in list
119    as glist = (%glist-append (or glist (make-pointer 0)))
120    do (funcall writer element glist)
121    finally (return glist)))
122
123 (defun glist-next (glist)
124   (unless (null-pointer-p glist)
125     (sap-ref-sap glist +size-of-pointer+)))
126   
127 ;; Also used for gslists
128 (defun map-glist (seqtype function glist element-type)
129   (let ((reader (reader-function element-type)))
130     (case seqtype 
131      ((nil)
132       (loop
133        as tmp = glist then (glist-next tmp)
134        until (null-pointer-p tmp)
135        do (funcall function (funcall reader tmp))))
136      (list
137       (loop
138        as tmp = glist then (glist-next tmp)
139        until (null-pointer-p tmp)
140        collect (funcall function (funcall reader tmp))))
141      (t
142       (coerce 
143        (loop
144         as tmp = glist then (glist-next tmp)
145         until (null-pointer-p tmp)
146         collect (funcall function (funcall reader tmp)))
147        seqtype)))))
148
149 (defbinding (glist-free "g_list_free") () nil
150   (glist pointer))
151
152 (defun destroy-glist (glist element-type)
153   (loop
154    with destroy = (destroy-function element-type)
155    as tmp = glist then (glist-next tmp)
156    until (null-pointer-p tmp)
157    do (funcall destroy tmp 0))
158   (glist-free glist))
159
160 (defmethod alien-type ((type (eql 'glist)) &rest args)
161   (declare (ignore type args))
162   (alien-type 'pointer))
163
164 (defmethod size-of ((type (eql 'glist)) &rest args)
165   (declare (ignore type args))
166   (size-of 'pointer))
167
168 (defmethod to-alien-form (list (type (eql 'glist)) &rest args)
169   (declare (ignore type))
170   (destructuring-bind (element-type) args    
171     `(make-glist ',element-type ,list)))
172
173 (defmethod to-alien-function ((type (eql 'glist)) &rest args)
174   (declare (ignore type))
175   (destructuring-bind (element-type) args    
176     #'(lambda (list)
177         (make-glist element-type list))))
178
179 (defmethod from-alien-form (glist (type (eql 'glist)) &rest args)
180   (declare (ignore type))
181   (destructuring-bind (element-type) args
182     `(let ((glist ,glist))
183       (unwind-protect
184            (map-glist 'list #'identity glist ',element-type)
185         (destroy-glist glist ',element-type)))))
186
187 (defmethod from-alien-function ((type (eql 'glist)) &rest args)
188   (declare (ignore type))
189   (destructuring-bind (element-type) args
190     #'(lambda (glist)
191         (unwind-protect
192              (map-glist 'list #'identity glist element-type)
193           (destroy-glist glist element-type)))))
194
195 (defmethod copy-from-alien-form (glist (type (eql 'glist)) &rest args)
196   (declare (ignore type))
197   (destructuring-bind (element-type) args
198     `(map-glist 'list #'identity ,glist ',element-type)))
199
200 (defmethod copy-from-alien-function ((type (eql 'glist)) &rest args)
201   (declare (ignore type))
202   (destructuring-bind (element-type) args
203     #'(lambda (glist)
204         (map-glist 'list #'identity glist element-type))))
205
206 (defmethod cleanup-form (glist (type (eql 'glist)) &rest args)
207   (declare (ignore type))
208   (destructuring-bind (element-type) args
209     `(destroy-glist ,glist ',element-type)))
210
211 (defmethod cleanup-function ((type (eql 'glist)) &rest args)
212   (declare (ignore type))
213   (destructuring-bind (element-type) args
214     #'(lambda (glist)
215         (destroy-glist glist element-type))))
216
217 (defmethod writer-function ((type (eql 'glist)) &rest args)
218   (declare (ignore type))
219   (destructuring-bind (element-type) args
220     #'(lambda (list location &optional (offset 0))
221         (setf 
222          (sap-ref-sap location offset)
223          (make-glist element-type list)))))
224
225 (defmethod reader-function ((type (eql 'glist)) &rest args)
226   (declare (ignore type))
227   (destructuring-bind (element-type) args
228     #'(lambda (location &optional (offset 0))
229         (unless (null-pointer-p (sap-ref-sap location offset))
230           (map-glist 'list #'identity (sap-ref-sap location offset) element-type)))))
231
232 (defmethod destroy-function ((type (eql 'glist)) &rest args)
233   (declare (ignore type))
234   (destructuring-bind (element-type) args
235     #'(lambda (location &optional (offset 0))
236         (unless (null-pointer-p (sap-ref-sap location offset))
237           (destroy-glist (sap-ref-sap location offset) element-type)
238           (setf (sap-ref-sap location offset) (make-pointer 0))))))
239
240
241
242 ;;;; Single linked list (GSList)
243
244 (deftype gslist (type) `(or (null (cons ,type list))))
245
246 (defbinding (%gslist-prepend "g_slist_prepend") () pointer
247   (gslist pointer)
248   (nil null))
249
250 (defun make-gslist (type list)
251   (loop
252    with writer = (writer-function type)
253    for element in (reverse list)
254    as gslist = (%gslist-prepend (or gslist (make-pointer 0)))
255    do (funcall writer element gslist)
256    finally (return gslist)))
257
258 (defbinding (gslist-free "g_slist_free") () nil
259   (gslist pointer))
260
261 (defun destroy-gslist (gslist element-type)
262   (loop
263    with destroy = (destroy-function element-type)
264    as tmp = gslist then (glist-next tmp)
265    until (null-pointer-p tmp)
266    do (funcall destroy tmp 0))
267   (gslist-free gslist))
268
269 (defmethod alien-type ((type (eql 'gslist)) &rest args)
270   (declare (ignore type args))
271   (alien-type 'pointer))
272
273 (defmethod size-of ((type (eql 'gslist)) &rest args)
274   (declare (ignore type args))
275   (size-of 'pointer))
276
277 (defmethod to-alien-form (list (type (eql 'gslist)) &rest args)
278   (declare (ignore type))
279   (destructuring-bind (element-type) args    
280     `(make-sglist ',element-type ,list)))
281
282 (defmethod to-alien-function ((type (eql 'gslist)) &rest args)
283   (declare (ignore type))
284   (destructuring-bind (element-type) args    
285     #'(lambda (list)
286         (make-gslist element-type list))))
287
288 (defmethod from-alien-form (gslist (type (eql 'gslist)) &rest args)
289   (declare (ignore type))
290   (destructuring-bind (element-type) args
291     `(let ((gslist ,gslist))
292       (unwind-protect
293            (map-glist 'list #'identity gslist ',element-type)
294         (destroy-gslist gslist ',element-type)))))
295
296 (defmethod from-alien-function ((type (eql 'gslist)) &rest args)
297   (declare (ignore type))
298   (destructuring-bind (element-type) args
299     #'(lambda (gslist)
300         (unwind-protect
301              (map-glist 'list #'identity gslist element-type)
302           (destroy-gslist gslist element-type)))))
303
304 (defmethod copy-from-alien-form (gslist (type (eql 'gslist)) &rest args)
305   (declare (ignore type))
306   (destructuring-bind (element-type) args
307     `(map-glist 'list #'identity ,gslist ',element-type)))
308
309 (defmethod copy-from-alien-function ((type (eql 'gslist)) &rest args)
310   (declare (ignore type))
311   (destructuring-bind (element-type) args
312     #'(lambda (gslist)
313         (map-glist 'list #'identity gslist element-type))))
314
315 (defmethod cleanup-form (gslist (type (eql 'gslist)) &rest args)
316   (declare (ignore type))
317   (destructuring-bind (element-type) args
318     `(destroy-gslist ,gslist ',element-type)))
319
320 (defmethod cleanup-function ((type (eql 'gslist)) &rest args)
321   (declare (ignore type))
322   (destructuring-bind (element-type) args
323     #'(lambda (gslist)
324         (destroy-gslist gslist element-type))))
325
326 (defmethod writer-function ((type (eql 'gslist)) &rest args)
327   (declare (ignore type))
328   (destructuring-bind (element-type) args
329     #'(lambda (list location &optional (offset 0))
330         (setf 
331          (sap-ref-sap location offset)
332          (make-gslist element-type list)))))
333
334 (defmethod reader-function ((type (eql 'gslist)) &rest args)
335   (declare (ignore type))
336   (destructuring-bind (element-type) args
337     #'(lambda (location &optional (offset 0))
338         (unless (null-pointer-p (sap-ref-sap location offset))
339           (map-glist 'list #'identity (sap-ref-sap location offset) element-type)))))
340
341 (defmethod destroy-function ((type (eql 'gslist)) &rest args)
342   (declare (ignore type))
343   (destructuring-bind (element-type) args
344     #'(lambda (location &optional (offset 0))
345         (unless (null-pointer-p (sap-ref-sap location offset))
346           (destroy-gslist (sap-ref-sap location offset) element-type)
347           (setf (sap-ref-sap location offset) (make-pointer 0))))))
348
349
350 ;;; Vector
351
352 (defun make-c-vector (type length &optional content location)
353   (let* ((size-of-type (size-of type))
354          (location (or location (allocate-memory (* size-of-type length))))
355          (writer (writer-function type)))
356     (etypecase content
357       (vector
358        (loop
359         for element across content
360         for i from 0 below length
361         as offset = 0 then (+ offset size-of-type)
362         do (funcall writer element location offset)))
363       (list
364        (loop
365         for element in content
366         for i from 0 below length
367         as offset = 0 then (+ offset size-of-type)
368         do (funcall writer element location offset))))
369     location))
370
371
372 (defun map-c-vector (seqtype function location element-type length)
373   (let ((reader (reader-function element-type))
374         (size-of-element (size-of element-type)))
375     (case seqtype 
376      ((nil)
377       (loop
378        for i from 0 below length
379        as offset = 0 then (+ offset size-of-element)
380        do (funcall function (funcall reader location offset))))
381      (list
382       (loop
383        for i from 0 below length
384        as offset = 0 then (+ offset size-of-element)
385        collect (funcall function (funcall reader location offset))))
386      (t
387       (loop
388        with sequence = (make-sequence seqtype length)
389        for i from 0 below length
390        as offset = 0 then (+ offset size-of-element)
391        do (setf 
392            (elt sequence i)
393            (funcall function (funcall reader location offset)))
394        finally (return sequence))))))
395
396
397 (defun destroy-c-vector (location element-type length)
398   (loop
399    with destroy = (destroy-function element-type)
400    with element-size = (size-of element-type)
401    for i from 0 below length
402    as offset = 0 then (+ offset element-size)
403    do (funcall destroy location offset))
404   (deallocate-memory location))
405
406
407 (defmethod alien-type ((type (eql 'vector)) &rest args)
408   (declare (ignore type args))
409   (alien-type 'pointer))
410
411 (defmethod size-of ((type (eql 'vector)) &rest args)
412   (declare (ignore type args))
413   (size-of 'pointer))
414
415 (defmethod to-alien-form (vector (type (eql 'vector)) &rest args)
416   (declare (ignore type))
417   (destructuring-bind (element-type &optional (length '*)) args
418     (if (eq length '*)
419         `(let* ((vector ,vector)
420                 (location (sap+
421                            (allocate-memory (+ ,+size-of-int+ 
422                                                (* ,(size-of element-type) 
423                                                   (length vector))))
424                            ,+size-of-int+)))
425           (make-c-vector ',element-type (length vector) vector location)
426           (setf (sap-ref-32 location ,(- +size-of-int+)) (length vector))
427           location)       
428       `(make-c-vector ',element-type ,length ,vector))))
429
430 (defmethod from-alien-form (c-vector (type (eql 'vector)) &rest args)
431   (declare (ignore type))
432   (destructuring-bind (element-type &optional (length '*)) args
433     (if (eq length '*)
434         (error "Can't use vector of variable size as return type")
435       `(let ((c-vector ,c-vector))
436         (prog1
437             (map-c-vector 'vector #'identity c-vector ',element-type ,length)
438           (destroy-c-vector c-vector ',element-type ,length))))))
439
440 (defmethod copy-from-alien-form (c-vector (type (eql 'vector)) &rest args)
441   (declare (ignore type))
442   (destructuring-bind (element-type &optional (length '*)) args
443     (if (eq length '*)
444         (error "Can't use vector of variable size as return type")
445       `(map-c-vector 'vector #'identity ,c-vector ',element-type ',length))))
446
447 (defmethod copy-from-alien-function ((type (eql 'vector)) &rest args)
448   (declare (ignore type))
449   (destructuring-bind (element-type &optional (length '*)) args
450     (if (eq length '*)
451         (error "Can't use vector of variable size as return type")
452       #'(lambda (c-vector)
453           (map-c-vector 'vector #'identity c-vector element-type length)))))
454
455 (defmethod cleanup-form (location (type (eql 'vector)) &rest args)
456   (declare (ignore type))
457   (destructuring-bind (element-type &optional (length '*)) args
458     `(let* ((location ,location)
459             (length ,(if (eq length '*)
460                          `(sap-ref-32 location ,(- +size-of-int+))
461                          length)))
462       (loop
463        with destroy = (destroy-function ',element-type)
464        for i from 0 below length
465        as offset = 0 then (+ offset ,(size-of element-type))
466        do (funcall destroy location offset))
467       (deallocate-memory ,(if (eq length '*) 
468                               `(sap+ location  ,(- +size-of-int+))
469                             'location)))))
470
471 (defmethod writer-function ((type (eql 'vector)) &rest args)
472   (declare (ignore type))
473   (destructuring-bind (element-type &optional (length '*)) args
474     #'(lambda (vector location &optional (offset 0))
475         (setf 
476          (sap-ref-sap location offset)
477          (make-c-vector element-type length vector)))))
478
479 (defmethod reader-function ((type (eql 'vector)) &rest args)
480   (declare (ignore type))
481   (destructuring-bind (element-type &optional (length '*)) args
482     (if (eq length '*)
483         (error "Can't create reader function for vector of variable size")
484       #'(lambda (location &optional (offset 0))
485           (unless (null-pointer-p (sap-ref-sap location offset))
486             (map-c-vector 'vector #'identity (sap-ref-sap location offset) 
487              element-type length))))))
488
489 (defmethod destroy-function ((type (eql 'vector)) &rest args)
490   (declare (ignore type))
491   (destructuring-bind (element-type &optional (length '*)) args
492     (if (eq length '*)
493         (error "Can't create destroy function for vector of variable size")
494       #'(lambda (location &optional (offset 0))
495           (unless (null-pointer-p (sap-ref-sap location offset))
496             (destroy-c-vector 
497              (sap-ref-sap location offset) element-type length)
498             (setf (sap-ref-sap location offset) (make-pointer 0)))))))
499
500
501 ;;;; Null terminated vector
502
503 (defun make-0-vector (type content &optional location)
504   (let* ((size-of-type (size-of type))
505          (location (or 
506                     location 
507                     (allocate-memory (* size-of-type (1+ (length content))))))
508          (writer (writer-function type)))
509     (etypecase content
510       (vector
511        (loop
512         for element across content
513         as offset = 0 then (+ offset size-of-type)
514         do (funcall writer element location offset)
515         finally (setf (sap-ref-sap location offset) (make-pointer 0))))
516       (list
517        (loop
518         for element in content
519         as offset = 0 then (+ offset size-of-type)
520         do (funcall writer element location offset)
521         finally (setf (sap-ref-sap location (+ offset size-of-type)) (make-pointer 0)))))
522     location))
523
524
525 (defun map-0-vector (seqtype function location element-type)
526   (let ((reader (reader-function element-type))
527         (size-of-element (size-of element-type)))
528     (case seqtype 
529      ((nil)
530       (loop
531        as offset = 0 then (+ offset size-of-element)
532        until (null-pointer-p (sap-ref-sap location offset))
533        do (funcall function (funcall reader location offset))))
534      (list
535       (loop
536        as offset = 0 then (+ offset size-of-element)
537        until (null-pointer-p (sap-ref-sap location offset))
538        collect (funcall function (funcall reader location offset))))
539      (t
540       (coerce 
541        (loop
542         as offset = 0 then (+ offset size-of-element)
543         until (null-pointer-p (sap-ref-sap location offset))
544         collect (funcall function (funcall reader location offset)))
545        seqtype)))))
546
547
548 (defun destroy-0-vector (location element-type)
549   (loop
550    with destroy = (destroy-function element-type)
551    with element-size = (size-of element-type)
552    as offset = 0 then (+ offset element-size)
553    until (null-pointer-p (sap-ref-sap location offset))
554    do (funcall destroy location offset))
555   (deallocate-memory location))
556
557 (deftype null-terminated-vector (element-type) `(vector ,element-type))
558
559 (defmethod alien-type ((type (eql 'null-terminated-vector)) &rest args)
560   (declare (ignore type args))
561   (alien-type 'pointer))
562
563 (defmethod size-of ((type (eql 'null-terminated-vector)) &rest args)
564   (declare (ignore type args))
565   (size-of 'pointer))
566
567 (defmethod to-alien-form (vector (type (eql 'null-terminated-vector)) &rest args)
568   (declare (ignore type))
569   (destructuring-bind (element-type) args
570     `(make-0-vector ',element-type ,vector)))
571
572 (defmethod from-alien-form (c-vector (type (eql 'null-terminated-vector)) &rest args)
573   (declare (ignore type))
574   (destructuring-bind (element-type) args
575     `(let ((c-vector ,c-vector))
576        (prog1
577            (map-0-vector 'vector #'identity c-vector ',element-type)
578          (destroy-0-vector c-vector ',element-type)))))
579
580 (defmethod copy-from-alien-form (c-vector (type (eql 'null-terminated-vector)) &rest args)
581   (declare (ignore type))
582   (destructuring-bind (element-type) args
583     `(map-0-vector 'vector #'identity ,c-vector ',element-type)))
584
585 (defmethod cleanup-form (location (type (eql 'null-terminated-vector)) &rest args)
586   (declare (ignore type))
587   (destructuring-bind (element-type) args
588     `(destroy-0-vector ,location ',element-type)))
589
590 (defmethod writer-function ((type (eql 'null-terminated-vector)) &rest args)
591   (declare (ignore type))
592   (destructuring-bind (element-type) args
593     (unless (eq (alien-type element-type) (alien-type 'pointer))
594       (error "Elements in null-terminated vectors need to be of pointer types"))
595     #'(lambda (vector location &optional (offset 0))
596         (setf 
597          (sap-ref-sap location offset)
598          (make-0-vector element-type vector)))))
599
600 (defmethod reader-function ((type (eql 'null-terminated-vector)) &rest args)
601   (declare (ignore type))
602   (destructuring-bind (element-type) args
603     (unless (eq (alien-type element-type) (alien-type 'pointer))
604       (error "Elements in null-terminated vectors need to be of pointer types"))
605     #'(lambda (location &optional (offset 0))
606         (unless (null-pointer-p (sap-ref-sap location offset))
607           (map-0-vector 'vector #'identity (sap-ref-sap location offset) 
608            element-type)))))
609
610 (defmethod destroy-function ((type (eql 'null-terminated-vector)) &rest args)
611   (declare (ignore type))
612   (destructuring-bind (element-type) args
613     (unless (eq (alien-type element-type) (alien-type 'pointer))
614       (error "Elements in null-terminated vectors need to be of pointer types"))
615     #'(lambda (location &optional (offset 0))
616           (unless (null-pointer-p (sap-ref-sap location offset))
617             (destroy-0-vector 
618              (sap-ref-sap location offset) element-type)
619             (setf (sap-ref-sap location offset) (make-pointer 0))))))
620
621 (defmethod unbound-value ((type (eql 'null-terminated-vector)) &rest args)
622   (declare (ignore type args))
623   (values t nil))
624
625
626 ;;; Counted vector
627
628 (defun make-counted-vector (type content)
629   (let* ((size-of-type (size-of type))
630          (length (length content))
631          (location 
632           (allocate-memory (+ +size-of-int+ (* size-of-type length)))))
633     (setf (sap-ref-32 location 0) length)
634     (make-c-vector type length content (sap+ location +size-of-int+))))
635
636 (defun map-counted-vector (seqtype function location element-type)
637   (let ((length (sap-ref-32 location 0)))
638     (map-c-vector 
639      seqtype function (sap+ location +size-of-int+)
640      element-type length)))
641
642 (defun destroy-counted-vector (location element-type)
643   (loop
644    with destroy = (destroy-function element-type)
645    with element-size = (size-of element-type)
646    for i from 0 below (sap-ref-32 location 0)
647    as offset = +size-of-int+ then (+ offset element-size)
648    do (funcall destroy location offset))
649   (deallocate-memory location))
650
651
652 (deftype counted-vector (element-type) `(vector ,element-type))
653
654 (defmethod alien-type ((type (eql 'counted-vector)) &rest args)
655   (declare (ignore type args))
656   (alien-type 'pointer))
657
658 (defmethod size-of ((type (eql 'counted-vector)) &rest args)
659   (declare (ignore type args))
660   (size-of 'pointer))
661
662 (defmethod to-alien-form (vector (type (eql 'counted-vector)) &rest args)
663   (declare (ignore type))
664   (destructuring-bind (element-type) args
665     `(make-counted-vector ',element-type ,vector)))
666
667 (defmethod from-alien-form (c-vector (type (eql 'counted-vector)) &rest args)
668   (declare (ignore type))
669   (destructuring-bind (element-type) args
670     `(let ((c-vector ,c-vector))
671        (prog1
672            (map-counted-vector 'vector #'identity c-vector ',element-type)
673          (destroy-counted-vector c-vector ',element-type)))))
674
675 (defmethod copy-from-alien-form (c-vector (type (eql 'counted-vector)) &rest args)
676   (declare (ignore type))
677   (destructuring-bind (element-type) args
678     `(map-counted-vector 'vector #'identity ,c-vector ',element-type)))
679
680 (defmethod copy-from-alien-function ((type (eql 'counted-vector)) &rest args)
681   (declare (ignore type))
682   (destructuring-bind (element-type) args
683     #'(lambda (c-vector)
684         (map-counted-vector 'vector #'identity c-vector element-type))))
685
686 (defmethod cleanup-form (location (type (eql 'counted-vector)) &rest args)
687   (declare (ignore type))
688   (destructuring-bind (element-type) args
689     `(destroy-counted-vector ,location ',element-type)))
690
691 (defmethod writer-function ((type (eql 'counted-vector)) &rest args)
692   (declare (ignore type))
693   (destructuring-bind (element-type) args
694     #'(lambda (vector location &optional (offset 0))
695         (setf 
696          (sap-ref-sap location offset)
697          (make-counted-vector element-type vector)))))
698
699 (defmethod reader-function ((type (eql 'counted-vector)) &rest args)
700   (declare (ignore type))
701   (destructuring-bind (element-type) args
702     #'(lambda (location &optional (offset 0))
703         (unless (null-pointer-p (sap-ref-sap location offset))
704           (map-counted-vector 'vector #'identity 
705            (sap-ref-sap location offset) element-type)))))
706
707 (defmethod destroy-function ((type (eql 'counted-vector)) &rest args)
708   (declare (ignore type))
709   (destructuring-bind (element-type) args
710     #'(lambda (location &optional (offset 0))
711         (unless (null-pointer-p (sap-ref-sap location offset))
712           (destroy-counted-vector 
713            (sap-ref-sap location offset) element-type)
714           (setf (sap-ref-sap location offset) (make-pointer 0))))))