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