Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 110 lines (102 sloc) 4.934 kb
8e9374c @froydnj add read from/write to streams support
authored
1 ;;;; streams.lisp -- reading/writing signed/unsigned bytes to streams
2
3 (cl:in-package :nibbles)
4
fb472c5 @froydnj factor out read-n-bytes-into from read-byte*
authored
5 (defun read-n-bytes-into (stream n-bytes v)
6 (dotimes (i n-bytes v)
8e9374c @froydnj add read from/write to streams support
authored
7 ;; READ-SEQUENCE would likely be more efficient here, but it does
8 ;; not have the semantics we want--in particular, the blocking
9 ;; semantics of READ-SEQUENCE are potentially bad. It's not clear
10 ;; that READ-BYTE is any better here, though...
fb472c5 @froydnj factor out read-n-bytes-into from read-byte*
authored
11 (setf (aref v i) (read-byte stream))))
12
13 (declaim (inline read-byte* write-byte*))
14 (defun read-byte* (stream n-bytes reffer)
15 (let ((v (make-array n-bytes :element-type '(unsigned-byte 8))))
16 (declare (dynamic-extent v))
17 (read-n-bytes-into stream n-bytes v)
18 (funcall reffer v 0)))
8e9374c @froydnj add read from/write to streams support
authored
19
20 (defun write-byte* (integer stream n-bytes setter)
21 (let ((v (make-array n-bytes :element-type '(unsigned-byte 8))))
22 (declare (dynamic-extent v))
a13f890 @froydnj redo streams code to use new setters
authored
23 (funcall setter v 0 integer)
8e9374c @froydnj add read from/write to streams support
authored
24 (write-sequence v stream)
25 integer))
26
d102838 @froydnj add interfaces for reading vectors of values
authored
27 (declaim (inline read-into-vector*))
28 (defun read-into-vector* (stream vector start end n-bytes reffer)
29 (declare (type function reffer))
30 (let ((v (make-array n-bytes :element-type '(unsigned-byte 8))))
31 (declare (dynamic-extent v))
32 (loop for i from start below end
33 do (read-n-bytes-into stream n-bytes v)
34 (setf (aref vector i) (funcall reffer v 0))
35 finally (return vector))))
36
372b33b @froydnj make non-consing readers more akin to READ-SEQUENCE
authored
37 (defun read-into-list* (stream list start end n-bytes reffer)
38 (declare (type function reffer))
39 (do ((end (or end) (length list))
40 (v (make-array n-bytes :element-type '(unsigned-byte 8)))
41 (rem (nthcdr start list) (rest rem))
42 (i start (1+ i)))
43 ((or (endp rem) (>= i end)) list)
44 (declare (dynamic-extent v))
45 (read-n-bytes-into stream n-bytes v)
46 (setf (first rem) (funcall reffer v 0))))
47
a13f890 @froydnj redo streams code to use new setters
authored
48 #.(loop for i from 0 upto #b10111
49 for bitsize = (ecase (ldb (byte 2 3) i)
50 (0 16)
51 (1 32)
52 (2 64))
53 for readp = (logbitp 2 i)
54 for signedp = (logbitp 1 i)
55 for big-endian-p = (logbitp 0 i)
253298b @froydnj use LOOP iteration variables directly instead of LET
authored
56 for name = (stream-ref-fun-name bitsize readp signedp big-endian-p)
57 for n-bytes = (truncate bitsize 8)
58 for byte-fun = (if readp
59 (byte-ref-fun-name bitsize signedp big-endian-p)
60 (byte-set-fun-name bitsize signedp big-endian-p))
d102838 @froydnj add interfaces for reading vectors of values
authored
61 for byte-arglist = (if readp '(stream) '(integer stream))
253298b @froydnj use LOOP iteration variables directly instead of LET
authored
62 for subfun = (if readp 'read-byte* 'write-byte*)
d102838 @froydnj add interfaces for reading vectors of values
authored
63 for element-type = `(,(if signedp 'signed-byte 'unsigned-byte) ,bitsize)
64 collect `(defun ,name ,byte-arglist
65 (,subfun ,@byte-arglist ,n-bytes #',byte-fun)) into forms
66 if readp
a405fba @froydnj make vector stream readers/writers use sequences
authored
67 collect `(defun ,(stream-seq-fun-name bitsize t signedp big-endian-p)
68 (result-type stream count)
63b781b @froydnj add documentation to sequence readers and writers
authored
69 ,(format-docstring "Return a sequence of type RESULT-TYPE, containing COUNT elements read from STREAM. Each element is a ~D-bit ~:[un~;~]signed integer read in ~:[little~;big~]-endian order. RESULT-TYPE must be either CL:VECTOR or CL:LIST. STREAM must have an element type of (UNSIGNED-BYTE 8)."
70 bitsize signedp big-endian-p)
a405fba @froydnj make vector stream readers/writers use sequences
authored
71 (case result-type
72 (list
73 (let ((list (make-list count)))
74 (read-into-list* stream list 0 count
75 ,n-bytes #',byte-fun)))
76 (vector
77 (let ((vector (make-array count
78 :element-type ',element-type)))
79 (read-into-vector* stream vector 0 count
80 ,n-bytes #',byte-fun))))) into forms
873ad09 @froydnj add interfaces for writing vectors of values
authored
81 else
a405fba @froydnj make vector stream readers/writers use sequences
authored
82 collect `(defun ,(stream-seq-fun-name bitsize nil signedp big-endian-p)
83 (seq stream &key (start 0) end)
63b781b @froydnj add documentation to sequence readers and writers
authored
84 ,(format-docstring "Write elements from SEQ between START and END as ~D-bit ~:[un~;~]signed integers in ~:[little~;big~]-endian order to STREAM. SEQ may be either a vector or a list. STREAM must have an element type of (UNSIGNED-BYTE 8)."
85 bitsize signedp big-endian-p)
a405fba @froydnj make vector stream readers/writers use sequences
authored
86 (etypecase seq
87 (list
d53bfef @froydnj fix list stream writer implementation
authored
88 (mapc (lambda (e) (,name e stream))
89 (subseq seq start end))
a405fba @froydnj make vector stream readers/writers use sequences
authored
90 seq)
91 (vector
92 (loop with end = (or end (length seq))
93 for i from start below end
94 do (,name (aref seq i) stream)
95 finally (return seq))))) into forms
c4437f0 @froydnj add READ-SEQUENCE-like interfaces for reading vectors of values
authored
96 if readp
372b33b @froydnj make non-consing readers more akin to READ-SEQUENCE
authored
97 collect `(defun ,(intern (format nil "READ-~:[U~;S~]B~D/~:[LE~;BE~]-INTO-SEQUENCE"
c4437f0 @froydnj add READ-SEQUENCE-like interfaces for reading vectors of values
authored
98 signedp bitsize big-endian-p))
372b33b @froydnj make non-consing readers more akin to READ-SEQUENCE
authored
99 (seq stream &key (start 0) end)
63b781b @froydnj add documentation to sequence readers and writers
authored
100 ,(format-docstring "Destructively modifies SEQ by replacing the elements of SEQ between START and END with elements read from STREAM. Each element is a ~D-bit ~:[un~;~]signed integer written in ~:[little~;big~]-endian order. SEQ may be either a vector or a list. STREAM must have an element type of (UNSIGNED-BYTE 8)."
101 bitsize signedp big-endian-p)
372b33b @froydnj make non-consing readers more akin to READ-SEQUENCE
authored
102 (etypecase seq
103 (list (read-into-list* stream seq start end
104 ,n-bytes #',byte-fun))
105 (vector
c61308f @froydnj fix one last typo in READ-*-INTO-SEQUENCE
authored
106 (let ((end (or end (length seq))))
25bc4ad @froydnj fix thinko in call to READ-INTO-VECTOR*
authored
107 (read-into-vector* stream seq start end
372b33b @froydnj make non-consing readers more akin to READ-SEQUENCE
authored
108 ,n-bytes #',byte-fun))))) into forms
8e9374c @froydnj add read from/write to streams support
authored
109 finally (return `(progn ,@forms)))
Something went wrong with that request. Please try again.