Use SHARED-INITIALIZE instead of INITIALIZE-INSTANCE for BUFFERs.
[iolib.git] / io.streams / zeta / iobuf.lisp
blobbdf7265b9de4a8bacabf1eeb80c018900e0dc07e
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
2 ;;;
3 ;;; --- I/O buffers.
4 ;;;
6 (in-package :io.zeta-streams)
8 (declaim (optimize speed))
10 ;;;-------------------------------------------------------------------------
11 ;;; Foreign Buffers
12 ;;;-------------------------------------------------------------------------
14 (define-constant +default-iobuf-size+ (* 8 1024))
16 ;; almost 128 MB: large enough for a stream buffer,
17 ;; but small enough to fit into a fixnum
18 (deftype iobuf-index () '(unsigned-byte 27))
20 (deftype iobuf-data-vector () 'ub8-simple-vector)
22 (defstruct (iobuf (:constructor %make-iobuf (data)))
23 (lock (bt:make-lock "IObuf lock") :read-only t)
24 (data nil :type iobuf-data-vector :read-only t)
25 (start 0 :type iobuf-index)
26 (end 0 :type iobuf-index))
28 (defun make-iobuf-data-vector (size)
29 (declare (type iobuf-index size))
30 (make-array size :element-type 'ub8 :initial-element 0))
32 (defun make-iobuf (&optional (size +default-iobuf-size+))
33 (check-type size iobuf-index)
34 (%make-iobuf (make-iobuf-data-vector size)))
36 (defun iobuf-size (iobuf)
37 (declare (type iobuf iobuf))
38 (the iobuf-index (length (iobuf-data iobuf))))
40 (defun iobuf-available-octets (iobuf)
41 (declare (type iobuf iobuf))
42 (- (iobuf-end iobuf)
43 (iobuf-start iobuf)))
45 (defun iobuf-empty-p (iobuf)
46 (declare (type iobuf iobuf))
47 (zerop (iobuf-available-octets iobuf)))
49 (defun iobuf-full-p (iobuf)
50 (declare (type iobuf iobuf))
51 (= (iobuf-end iobuf)
52 (iobuf-size iobuf)))
54 (defun iobuf-reset (iobuf)
55 (declare (type iobuf iobuf))
56 (setf (iobuf-start iobuf) 0
57 (iobuf-end iobuf) 0))
59 (defun iobuf-next-data-zone (iobuf)
60 (declare (type iobuf iobuf))
61 (values (iobuf-data iobuf)
62 (iobuf-start iobuf)
63 (iobuf-end iobuf)))
65 (defun iobuf-next-empty-zone (iobuf)
66 (declare (type iobuf iobuf))
67 (values (iobuf-data iobuf)
68 (iobuf-end iobuf)
69 (iobuf-size iobuf)))
72 ;;;-------------------------------------------------------------------------
73 ;;; UNSAFE functions which *DO NOT* check boundaries
74 ;;; that must be done by their callers
75 ;;;-------------------------------------------------------------------------
77 (defun bref (iobuf index)
78 (declare (type iobuf iobuf)
79 (type iobuf-index index))
80 (aref (iobuf-data iobuf) index))
82 (defun (setf bref) (octet iobuf index)
83 (declare (type ub8 octet)
84 (type iobuf iobuf)
85 (type iobuf-index index))
86 (setf (aref (iobuf-data iobuf) index) octet))
88 (defun iobuf-pop-octet (iobuf)
89 (declare (type iobuf iobuf))
90 (let ((start (iobuf-start iobuf)))
91 (prog1 (bref iobuf start)
92 (setf (iobuf-start iobuf) (1+ start)))))
94 (defun iobuf-push-octet (iobuf octet)
95 (declare (type iobuf iobuf)
96 (type ub8 octet))
97 (let ((end (iobuf-end iobuf)))
98 (prog1 (setf (bref iobuf end) octet)
99 (setf (iobuf-end iobuf) (1+ end)))))
101 (defun replace-ub8sv->ub8sv (destination source start1 end1 start2 end2)
102 (declare (type ub8-simple-vector destination source)
103 (type iobuf-index start1 start2 end1 end2))
104 (let ((nbytes (min (- end1 start1)
105 (- end2 start2))))
106 (replace destination source
107 :start1 start1 :end1 end1
108 :start2 start2 :end2 end2)
109 (values nbytes)))
111 (defun replace-ub8sv->ub8cv (destination source start1 end1 start2 end2)
112 (declare (type ub8-simple-vector source)
113 (type ub8-complex-vector destination)
114 (type iobuf-index start1 start2 end1 end2))
115 (let ((nbytes (min (- end1 start1)
116 (- end2 start2))))
117 (replace destination source
118 :start1 start1 :end1 end1
119 :start2 start2 :end2 end2)
120 (values nbytes)))
122 (defun replace-ub8cv->ub8sv (destination source start1 end1 start2 end2)
123 (declare (type ub8-complex-vector source)
124 (type ub8-simple-vector destination)
125 (type iobuf-index start1 start2 end1 end2))
126 (let ((nbytes (min (- end1 start1)
127 (- end2 start2))))
128 (replace destination source
129 :start1 start1 :end1 end1
130 :start2 start2 :end2 end2)
131 (values nbytes)))
133 (defun iobuf->vector (iobuf vector start end)
134 (declare (type iobuf iobuf)
135 (type ub8-vector vector)
136 (type iobuf-index start end))
137 (when (iobuf-empty-p iobuf)
138 (iobuf-reset iobuf))
139 (multiple-value-bind (iobuf-data data-start data-end)
140 (iobuf-next-data-zone iobuf)
141 (declare (type iobuf-index data-start data-end))
142 (let ((nbytes
143 (etypecase vector
144 (ub8-simple-vector
145 (replace-ub8sv->ub8sv vector iobuf-data
146 start end
147 data-start data-end))
148 (ub8-complex-vector
149 (replace-ub8sv->ub8cv vector iobuf-data
150 start end
151 data-start data-end)))))
152 (setf (iobuf-start iobuf) (+ data-start (the iobuf-index nbytes)))
153 (values nbytes))))
155 (defun vector->iobuf (iobuf vector start end)
156 (declare (type iobuf iobuf)
157 (type ub8-vector vector)
158 (type iobuf-index start end))
159 (when (iobuf-empty-p iobuf)
160 (iobuf-reset iobuf))
161 (multiple-value-bind (iobuf-data data-start data-end)
162 (iobuf-next-empty-zone iobuf)
163 (declare (type iobuf-index data-start data-end))
164 (let ((nbytes
165 (etypecase vector
166 (ub8-simple-vector
167 (replace-ub8sv->ub8sv iobuf-data vector
168 data-start data-end
169 start end))
170 (ub8-complex-vector
171 (replace-ub8cv->ub8sv iobuf-data vector
172 data-start data-end
173 start end)))))
174 (setf (iobuf-end iobuf) (+ data-start (the iobuf-index nbytes)))
175 (values nbytes))))