[cffi-devel] Shareable Byte Vectors for SBCL
Faré
fahree at gmail.com
Thu Sep 22 01:22:58 UTC 2005
Here's a code snippet I've used in my patch to sb-bsd-sockets, that
implements something similar to your "Shareable Byte Vectors" for
SBCL. Tested with recvfrom and sendto.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
The ultimate result of shielding men from the effects of folly is
to fill the world with fools. -- Herbert Spencer
;;; This little protocol could and should be used in a whole lot of
I/O functions.
;;; It silently assumes that buffers are big enough to fit the length required,
;;; and are either subtypes of characters or integer, and that data will fit.
(deftype iobuffer () "buffer for direct I/O"
'(simple-array (unsigned-byte 8) (*)))
(defun iobufferp (x) "check if X is a proper iobuffer"
(typep x '(iobuffer)))
(defun iobuffer-to-data (buffer data &optional (length (length buffer)))
"copy contents of iobuffer to data array"
(if (subtypep (array-element-type data) 'integer)
(replace data buffer :end1 length)
(loop for i from 0 below length
do (setf (char data i) (code-char (aref buffer i))))))
(defun data-to-iobuffer (data buffer &optional (length (length data)))
"copy contents of data array to iobuffer"
(if (subtypep (array-element-type data) 'integer)
(replace buffer data :end1 length)
(loop for i from 0 below length
do (setf (aref buffer i) (char-code (char data i))))))
(defun ensure-iobuffer-from-data (data &optional (length (length data)))
"if data is not an iobuffer already, create a new one with similar contents"
(if (iobufferp data)
data
(let ((buffer (make-array (list length) :element-type
'(unsigned-byte 8))))
(data-to-iobuffer data buffer length)
buffer)))
(defun prepare-iobuffer-for-data (data &optional length)
"if data is not an iobuffer already, create a new one with same length"
(if (iobufferp data)
data
(make-array (list length) :element-type '(unsigned-byte 8))))
(defun commit-iobuffer-to-data (buffer data &optional length)
"if data is not an iobuffer already, replace its contents with
those of given buffer"
(unless (eq buffer data)
(iobuffer-to-data buffer data length)))
(defmacro with-iobuffer-sap ((buffer data &key (direction :input)
length) &body body)
"bind buffer with an iobuffer suitable for I/O of given direction,
to be committed to/from the contents of data array data"
(let ((data-tn (gensym)) (length-tn (gensym)))
`(let* ((,data-tn ,data) (,length-tn ,length)
(,buffer (ecase ,direction
(:input (prepare-iobuffer-for-data ,data-tn ,length-tn))
((:output :io) (ensure-iobuffer-from-data
,data-tn ,length-tn)))))
(prog1
(sb-sys:with-pinned-objects (,buffer)
(let ((,buffer (sb-sys:vector-sap ,buffer)))
, at body))
(case ,direction
((:input :io) (commit-iobuffer-to-data ,buffer ,data-tn
,length-tn)))))))
;;; Should I add a :start argument for the data?
;;; Have :start and :end instead of :start and :length?
More information about the cffi-devel
mailing list