Delete CODE-LINKAGE-ELTS slot
[sbcl.git] / contrib / sb-simple-streams / strategy.lisp
blobceb2f9ebf7eb21050781d5d6027791100297fb3f
1 ;;; -*- lisp -*-
2 ;;;
3 ;;; **********************************************************************
4 ;;; This code was written by Paul Foley and has been placed in the public
5 ;;; domain.
6 ;;;
8 ;;; Sbcl port by Rudi Schlatte.
10 (in-package "SB-SIMPLE-STREAMS")
12 ;;;
13 ;;; **********************************************************************
14 ;;;
15 ;;; Strategy functions for base simple-stream classes
17 ;;;; Helper functions
19 (defun refill-buffer (stream blocking)
20 (declare (type blocking blocking))
21 (with-stream-class (simple-stream stream)
22 (let* ((unread (sm last-char-read-size stream))
23 (buffer (sm buffer stream))
24 (bufptr (sm buffer-ptr stream)))
25 (unless (or (zerop unread) (zerop bufptr))
26 (buffer-copy buffer (- bufptr unread) buffer 0 unread))
27 (let ((bytes (device-read stream nil unread nil blocking)))
28 (declare (type fixnum bytes))
29 (setf (sm buffpos stream) unread
30 (sm buffer-ptr stream) (if (plusp bytes)
31 (+ bytes unread)
32 unread))
33 bytes))))
35 (defun sc-set-dirty (stream)
36 (with-stream-class (single-channel-simple-stream stream)
37 (setf (sm mode stream)
38 (if (<= (sm buffpos stream)
39 (sm buffer-ptr stream))
40 3 ; read-modify
41 1 ; write
42 ))))
44 (defun sc-set-clean (stream)
45 (with-stream-class (single-channel-simple-stream stream)
46 (setf (sm mode stream) 0)))
48 (defun sc-dirty-p (stream)
49 (with-stream-class (single-channel-simple-stream stream)
50 (> (sm mode stream) 0)))
52 (defun flush-buffer (stream blocking)
53 (with-stream-class (single-channel-simple-stream stream)
54 (let ((ptr 0)
55 (bytes (sm buffpos stream)))
56 (declare (type fixnum ptr bytes))
57 (when (and (> (sm mode stream) 0) (> (sm buffer-ptr stream) 0))
58 ;; The data read in from the file could have been changed if
59 ;; the stream is opened in read-write mode -- write back
60 ;; everything in the buffer at the correct position just in
61 ;; case.
62 (setf (device-file-position stream)
63 (- (device-file-position stream) (sm buffer-ptr stream))))
64 (loop
65 (when (>= ptr bytes) (setf (sm buffpos stream) 0) (setf (sm mode stream) 0) (return 0))
66 (let ((bytes-written (device-write stream nil ptr nil blocking)))
67 (declare (fixnum bytes-written))
68 (when (minusp bytes-written)
69 (error "DEVICE-WRITE error."))
70 (incf ptr bytes-written))))))
72 (defun flush-out-buffer (stream blocking)
73 (with-stream-class (dual-channel-simple-stream stream)
74 (let ((ptr 0)
75 (bytes (sm outpos stream)))
76 (declare (type fixnum ptr bytes))
77 (loop
78 (when (>= ptr bytes) (setf (sm outpos stream) 0) (return 0))
79 (let ((bytes-written (device-write stream nil ptr nil blocking)))
80 (declare (fixnum bytes-written))
81 (when (minusp bytes-written)
82 (error "DEVICE-WRITE error."))
83 (incf ptr bytes-written))))))
85 (defun read-byte-internal (stream eof-error-p eof-value blocking)
86 (with-stream-class (simple-stream stream)
87 (let ((ptr (sm buffpos stream)))
88 (when (>= ptr (sm buffer-ptr stream))
89 (let ((bytes (device-read stream nil 0 nil blocking)))
90 (declare (type fixnum bytes))
91 (if (plusp bytes)
92 (setf (sm buffer-ptr stream) bytes
93 ptr 0)
94 (return-from read-byte-internal
95 (sb-impl::eof-or-lose stream eof-error-p eof-value)))))
96 (setf (sm buffpos stream) (1+ ptr))
97 (setf (sm last-char-read-size stream) 0)
98 (setf (sm charpos stream) nil)
99 (bref (sm buffer stream) ptr))))
101 ;;;; Single-Channel-Simple-Stream strategy functions
104 (declaim (ftype j-listen-fn sc-listen-ef))
105 (defun sc-listen-ef (stream)
106 (with-stream-class (simple-stream stream)
107 (let ((lcrs (sm last-char-read-size stream))
108 (buffer (sm buffer stream))
109 (buffpos (sm buffpos stream))
110 (cnt 0)
111 (char nil))
112 (declare (ignorable cnt))
113 (unwind-protect
114 (flet ((input ()
115 (when (>= buffpos (sm buffer-ptr stream))
116 (let ((bytes (refill-buffer stream nil)))
117 (cond ((= bytes 0)
118 (return-from sc-listen-ef nil))
119 ((< bytes 0)
120 (return-from sc-listen-ef t))
122 (setf buffpos (sm buffpos stream))))))
123 (incf (sm last-char-read-size stream))
124 (prog1 (bref buffer buffpos)
125 (incf buffpos)))
126 (unput (n)
127 (decf buffpos n)))
128 (setq char (octets-to-char (sm external-format stream)
129 (sm oc-state stream)
130 cnt #'input #'unput))
131 (characterp char))
132 (setf (sm last-char-read-size stream) lcrs)))))
134 (declaim (ftype j-read-char-fn sc-read-char-ef))
135 (defun sc-read-char-ef (stream eof-error-p eof-value blocking)
136 #|(declare (optimize (speed 3) (space 2) (safety 0) (debug 0)))|#
137 (with-stream-class (simple-stream stream)
138 (let* ((buffer (sm buffer stream))
139 (buffpos (sm buffpos stream))
140 (ctrl (sm control-in stream))
141 (ef (sm external-format stream))
142 (state (sm oc-state stream)))
143 (flet ((input ()
144 (when (>= buffpos (sm buffer-ptr stream))
145 (when (and (not (any-stream-instance-flags stream :dual :string))
146 (sc-dirty-p stream))
147 (flush-buffer stream t))
148 (let ((bytes (refill-buffer stream blocking)))
149 (cond ((= bytes 0)
150 (return-from sc-read-char-ef nil))
151 ((minusp bytes)
152 (return-from sc-read-char-ef
153 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
155 (setf buffpos (sm buffpos stream))))))
156 (incf (sm last-char-read-size stream))
157 (prog1 (bref buffer buffpos)
158 (incf buffpos)))
159 (unput (n)
160 (decf buffpos n)))
161 (let* ((cnt 0)
162 (char (octets-to-char ef state cnt #'input #'unput))
163 (code (char-code char)))
164 (setf (sm buffpos stream) buffpos
165 (sm last-char-read-size stream) cnt
166 (sm oc-state stream) state)
167 (when (and (< code 32) ctrl (svref ctrl code))
168 (setq char (funcall (the (or symbol function) (svref ctrl code))
169 stream char)))
170 (if (null char)
171 (sb-impl::eof-or-lose stream eof-error-p eof-value)
172 char))))))
175 (declaim (ftype j-read-char-fn sc-read-char-ef-mapped))
176 (defun sc-read-char-ef-mapped (stream eof-error-p eof-value blocking)
177 #|(declare (optimize (speed 3) (space 2) (safety 0) (debug 0)))|#
178 (declare (ignore blocking))
179 (with-stream-class (simple-stream stream)
180 (let* ((buffer (sm buffer stream))
181 (buffpos (sm buffpos stream))
182 (ctrl (sm control-in stream))
183 (ef (sm external-format stream))
184 (state (sm oc-state stream)))
185 (flet ((input ()
186 (when (>= buffpos (sm buffer-ptr stream))
187 (return-from sc-read-char-ef-mapped
188 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
189 (incf (sm last-char-read-size stream))
190 (prog1 (bref buffer buffpos)
191 (incf buffpos)))
192 (unput (n)
193 (decf buffpos n)))
194 (let* ((cnt 0)
195 (char (octets-to-char ef state cnt #'input #'unput))
196 (code (char-code char)))
197 (setf (sm buffpos stream) buffpos
198 (sm last-char-read-size stream) cnt
199 (sm oc-state stream) state)
200 (when (and (< code 32) ctrl (svref ctrl code))
201 (setq char (funcall (the (or symbol function) (svref ctrl code))
202 stream char)))
203 (if (null char)
204 (sb-impl::eof-or-lose stream eof-error-p eof-value)
205 char))))))
208 (declaim (ftype j-read-chars-fn sc-read-chars-ef))
209 (defun sc-read-chars-ef (stream string search start end blocking)
210 ;; string is filled from START to END, or until SEARCH is found
211 ;; Return two values: count of chars read and
212 ;; NIL if SEARCH was not found
213 ;; T if SEARCH was found
214 ;; :EOF if eof encountered before end
215 (declare (type simple-stream stream)
216 (type string string)
217 (type (or null character) search)
218 (type fixnum start end)
219 (type boolean blocking)
220 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#)
221 (with-stream-class (simple-stream stream)
222 (when (and (not (any-stream-instance-flags stream :dual :string))
223 (sc-dirty-p stream))
224 (flush-buffer stream t))
225 (do ((buffer (sm buffer stream))
226 (buffpos (sm buffpos stream))
227 (buffer-ptr (sm buffer-ptr stream))
228 (lcrs 0)
229 (ctrl (sm control-in stream))
230 (ef (sm external-format stream))
231 (state (sm oc-state stream))
232 (posn start (1+ posn))
233 (count 0 (1+ count)))
234 ((>= posn end)
235 (setf (sm buffpos stream) buffpos
236 (sm last-char-read-size stream) lcrs
237 (sm oc-state stream) state)
238 (values count nil))
239 (declare (type sb-int:index buffpos buffer-ptr posn count))
240 (flet ((input ()
241 (when (>= buffpos buffer-ptr)
242 (setf (sm last-char-read-size stream) lcrs)
243 (let ((bytes (refill-buffer stream blocking)))
244 (declare (type fixnum bytes))
245 (setf buffpos (sm buffpos stream)
246 buffer-ptr (sm buffer-ptr stream))
247 (unless (plusp bytes)
248 (setf (sm buffpos stream) buffpos
249 (sm last-char-read-size stream) lcrs
250 (sm oc-state stream) state)
251 (if (zerop bytes)
252 (return (values count nil))
253 (return (values count :eof))))))
254 (prog1 (bref buffer buffpos)
255 (incf buffpos)
256 (incf lcrs)))
257 (unput (n)
258 (decf buffpos n)))
259 (let* ((cnt 0)
260 (char (octets-to-char ef state cnt #'input #'unput))
261 (code (char-code char)))
262 (setq lcrs cnt)
263 (when (and (< code 32) ctrl (svref ctrl code))
264 (setq char (funcall (the (or symbol function) (svref ctrl code))
265 stream char)))
266 (cond ((null char)
267 (setf (sm buffpos stream) buffpos
268 (sm last-char-read-size stream) lcrs
269 (sm oc-state stream) state)
270 (return (values count :eof)))
271 ((and search (char= char search))
272 (setf (sm buffpos stream) buffpos
273 (sm last-char-read-size stream) lcrs
274 (sm oc-state stream) state)
275 (return (values count t)))
277 (setf (char string posn) char))))))))
280 (declaim (ftype j-read-chars-fn sc-read-chars-ef-mapped))
281 (defun sc-read-chars-ef-mapped (stream string search start end blocking)
282 ;; string is filled from START to END, or until SEARCH is found
283 ;; Return two values: count of chars read and
284 ;; NIL if SEARCH was not found
285 ;; T if SEARCH was found
286 ;; :EOF if eof encountered before end
287 (declare (type simple-stream stream)
288 (type string string)
289 (type (or null character) search)
290 (type fixnum start end)
291 (type boolean blocking)
292 (ignore blocking)
293 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#)
294 (with-stream-class (simple-stream stream)
295 ;; if stream is single-channel and mode == 3, flush buffer (if dirty)
296 (do ((buffer (sm buffer stream))
297 (buffpos (sm buffpos stream))
298 (buffer-ptr (sm buffer-ptr stream))
299 (lcrs 0)
300 (ctrl (sm control-in stream))
301 (ef (sm external-format stream))
302 (state (sm oc-state stream))
303 (posn start (1+ posn))
304 (count 0 (1+ count)))
305 ((>= posn end)
306 (setf (sm buffpos stream) buffpos
307 (sm last-char-read-size stream) lcrs
308 (sm oc-state stream) state)
309 (values count nil))
310 (declare (type sb-int:index buffpos buffer-ptr posn count))
311 (flet ((input ()
312 (when (>= buffpos buffer-ptr)
313 (return (values count :eof)))
314 (prog1 (bref buffer buffpos)
315 (incf buffpos)
316 (incf lcrs)))
317 (unput (n)
318 (decf buffpos n)))
319 (let* ((cnt 0)
320 (char (octets-to-char ef state cnt #'input #'unput))
321 (code (char-code char)))
322 (setq lcrs cnt)
323 (when (and (< code 32) ctrl (svref ctrl code))
324 (setq char (funcall (the (or symbol function) (svref ctrl code))
325 stream char)))
326 (cond ((null char)
327 (setf (sm buffpos stream) buffpos
328 (sm last-char-read-size stream) lcrs
329 (sm oc-state stream) state)
330 (return (values count :eof)))
331 ((and search (char= char search))
332 (setf (sm buffpos stream) buffpos
333 (sm last-char-read-size stream) lcrs
334 (sm oc-state stream) state)
335 (return (values count t)))
337 (setf (char string posn) char))))))))
340 (declaim (ftype j-unread-char-fn sc-unread-char-ef))
341 (defun sc-unread-char-ef (stream relaxed)
342 (declare (ignore relaxed))
343 (with-stream-class (simple-stream stream)
344 (let ((unread (sm last-char-read-size stream)))
345 (if (>= (sm buffpos stream) unread)
346 (decf (sm buffpos stream) unread)
347 (error "This shouldn't happen.")))))
349 (declaim (ftype j-write-char-fn sc-write-char-ef))
350 (defun sc-write-char-ef (character stream)
351 (when character
352 (with-stream-class (single-channel-simple-stream stream)
353 (let ((buffer (sm buffer stream))
354 (buffpos (sm buffpos stream))
355 (buf-len (sm buf-len stream))
356 (code (char-code character))
357 (ctrl (sm control-out stream)))
358 (when (and (< code 32) ctrl (svref ctrl code)
359 (funcall (the (or symbol function) (svref ctrl code))
360 stream character))
361 (return-from sc-write-char-ef character))
362 (flet ((output (byte)
363 (when (>= buffpos buf-len)
364 (setf (sm buffpos stream) buffpos)
365 (setq buffpos (flush-buffer stream t)))
366 (setf (bref buffer buffpos) byte)
367 (incf buffpos)))
368 (char-to-octets (sm external-format stream) character
369 (sm co-state stream) #'output))
370 (setf (sm buffpos stream) buffpos)
371 (sc-set-dirty stream)
372 (if (sm charpos stream) (incf (sm charpos stream))))))
373 character)
375 (declaim (ftype j-write-chars-fn sc-write-chars-ef))
376 (defun sc-write-chars-ef (string stream start end)
377 (with-stream-class (single-channel-simple-stream stream)
378 (do ((buffer (sm buffer stream))
379 (buffpos (sm buffpos stream))
380 (buf-len (sm buf-len stream))
381 (ef (sm external-format stream))
382 (ctrl (sm control-out stream))
383 (posn start (1+ posn))
384 (count 0 (1+ count)))
385 ((>= posn end) (setf (sm buffpos stream) buffpos) count)
386 (declare (type fixnum buffpos buf-len posn count))
387 (let* ((char (char string posn))
388 (code (char-code char)))
389 (unless (and (< code 32) ctrl (svref ctrl code)
390 (funcall (the (or symbol function) (svref ctrl code))
391 stream char))
392 (flet ((output (byte)
393 (when (>= buffpos buf-len)
394 (setf (sm buffpos stream) buffpos)
395 (setq buffpos (flush-buffer stream t)))
396 (setf (bref buffer buffpos) byte)
397 (incf buffpos)))
398 (char-to-octets ef char (sm co-state stream) #'output))
399 (setf (sm buffpos stream) buffpos)
400 (if (sm charpos stream) (incf (sm charpos stream)))
401 (sc-set-dirty stream))))))
404 ;;;; Dual-Channel-Simple-Stream strategy functions
406 ;; single-channel read-side functions work for dual-channel streams too
408 (declaim (ftype j-write-char-fn dc-write-char-ef))
409 (defun dc-write-char-ef (character stream)
410 (when character
411 (with-stream-class (dual-channel-simple-stream stream)
412 (let ((out-buffer (sm out-buffer stream))
413 (outpos (sm outpos stream))
414 (max-out-pos (sm max-out-pos stream))
415 (code (char-code character))
416 (ctrl (sm control-out stream)))
417 (when (and (< code 32) ctrl (svref ctrl code)
418 (funcall (the (or symbol function) (svref ctrl code))
419 stream character))
420 (return-from dc-write-char-ef character))
421 (flet ((output (byte)
422 (when (>= outpos max-out-pos)
423 (setf (sm outpos stream) outpos)
424 (setq outpos (flush-out-buffer stream t)))
425 (setf (bref out-buffer outpos) byte)
426 (incf outpos)))
427 (char-to-octets (sm external-format stream) character
428 (sm co-state stream) #'output))
429 (setf (sm outpos stream) outpos)
430 (if (sm charpos stream) (incf (sm charpos stream))))))
431 character)
434 (declaim (ftype j-write-chars-fn dc-write-chars-ef))
435 (defun dc-write-chars-ef (string stream start end)
436 (with-stream-class (dual-channel-simple-stream stream)
437 (do ((buffer (sm out-buffer stream))
438 (outpos (sm outpos stream))
439 (max-out-pos (sm max-out-pos stream))
440 (ef (sm external-format stream))
441 (ctrl (sm control-out stream))
442 (posn start (1+ posn))
443 (count 0 (1+ count)))
444 ((>= posn end) (setf (sm outpos stream) outpos) count)
445 (declare (type fixnum outpos max-out-pos posn count))
446 (let* ((char (char string posn))
447 (code (char-code char)))
448 (unless (and (< code 32) ctrl (svref ctrl code)
449 (funcall (the (or symbol function) (svref ctrl code))
450 stream char))
451 (flet ((output (byte)
452 (when (>= outpos max-out-pos)
453 (setf (sm outpos stream) outpos)
454 (setq outpos (flush-out-buffer stream t)))
455 (setf (bref buffer outpos) byte)
456 (incf outpos)))
457 (char-to-octets ef char (sm co-state stream) #'output))
458 (setf (sm outpos stream) outpos)
459 (if (sm charpos stream) (incf (sm charpos stream))))))))
461 ;;;; String-Simple-Stream strategy functions
463 (declaim (ftype j-read-char-fn str-read-char))
464 (defun str-read-char (stream eof-error-p eof-value blocking)
465 (declare (type string-input-simple-stream stream) (ignore blocking)
466 #|(optimize (speed 3) (space 2) (safety 0) (debug 0))|#
468 (with-stream-class (string-input-simple-stream stream)
469 (when (any-stream-instance-flags stream :eof)
470 (sb-impl::eof-or-lose stream eof-error-p eof-value))
471 (let* ((ptr (sm buffpos stream))
472 (char (if (< ptr (sm buffer-ptr stream))
473 (schar (sm buffer stream) ptr)
474 nil)))
475 (if (null char)
476 (sb-impl::eof-or-lose stream eof-error-p eof-value)
477 (progn
478 (setf (sm last-char-read-size stream) 1)
479 ;; do string-streams do control-in processing?
480 #|(let ((column (sm charpos stream)))
481 (declare (type (or null fixnum) column))
482 (when column
483 (setf (sm charpos stream) (1+ column))))
485 char)))))
487 (declaim (ftype j-listen-fn str-listen-e-crlf))
488 (defun str-listen-e-crlf (stream)
489 (with-stream-class (composing-stream stream)
490 ;; if this says there's a character available, it may be #\Return,
491 ;; in which case read-char will only return if there's a following
492 ;; #\Linefeed, so this really has to read the char...
493 ;; but without precluding the later unread-char of a character which
494 ;; has already been read.
495 (funcall-stm-handler j-listen (sm melded-stream stream))))
497 (declaim (ftype j-read-char-fn str-read-char-e-crlf))
498 (defun str-read-char-e-crlf (stream eof-error-p eof-value blocking)
499 (with-stream-class (composing-stream stream)
500 (let* ((encap (sm melded-stream stream))
501 (ctrl (sm control-in stream))
502 (char (funcall-stm-handler j-read-char encap nil stream blocking)))
503 ;; if CHAR is STREAM, we hit EOF; if NIL, blocking is NIL and no
504 ;; character was available...
505 (when (eql char #\Return)
506 (let ((next (funcall-stm-handler j-read-char encap nil stream blocking)))
507 ;; if NEXT is STREAM, we hit EOF, so we should just return the
508 ;; #\Return (and mark the stream :EOF? At least unread if we
509 ;; got a soft EOF, from a terminal, etc.
510 ;; if NEXT is NIL, blocking is NIL and there's a CR but no
511 ;; LF available on the stream: have to unread the CR and
512 ;; return NIL, letting the CR be reread later.
514 ;; If we did get a linefeed, adjust the last-char-read-size
515 ;; so that an unread of the resulting newline will unread both
516 ;; the linefeed _and_ the carriage return.
517 (if (eql next #\Linefeed)
518 (setq char #\Newline)
519 (funcall-stm-handler j-unread-char encap nil))))
520 (when (characterp char)
521 (let ((code (char-code char)))
522 (when (and (< code 32) ctrl (svref ctrl code))
523 (setq char (funcall (the (or symbol function) (svref ctrl code))
524 stream char)))))
525 (if (eq char stream)
526 (sb-impl::eof-or-lose stream eof-error-p eof-value)
527 char))))
529 (declaim (ftype j-unread-char-fn str-unread-char-e-crlf))
530 (defun str-unread-char-e-crlf (stream relaxed)
531 (declare (ignore relaxed))
532 (with-stream-class (composing-stream stream)
533 (funcall-stm-handler j-unread-char (sm melded-stream stream) nil)))
536 ;;; Functions to install the strategy functions in the appropriate slots
538 (defun melding-stream (stream)
539 (with-stream-class (simple-stream)
540 (do ((stm stream (sm melded-stream stm)))
541 ((eq (sm melded-stream stm) stream) stm))))
543 (defun meld (stream encap)
544 (with-stream-class (simple-stream)
545 (setf (sm melding-base encap) (sm melding-base stream))
546 (setf (sm melded-stream encap) (sm melded-stream stream))
547 (setf (sm melded-stream stream) encap)
548 (rotatef (sm j-listen encap) (sm j-listen stream))
549 (rotatef (sm j-read-char encap) (sm j-read-char stream))
550 (rotatef (sm j-read-chars encap) (sm j-read-chars stream))
551 (rotatef (sm j-unread-char encap) (sm j-unread-char stream))
552 (rotatef (sm j-write-char encap) (sm j-write-char stream))
553 (rotatef (sm j-write-chars encap) (sm j-write-chars stream))))
555 (defun unmeld (stream)
556 (with-stream-class (simple-stream)
557 (let ((encap (sm melded-stream stream)))
558 (unless (eq encap (sm melding-base stream))
559 (setf (sm melding-base encap) encap)
560 (setf (sm melded-stream stream) (sm melded-stream encap))
561 (setf (sm melded-stream encap) encap)
562 (rotatef (sm j-listen stream) (sm j-listen encap))
563 (rotatef (sm j-read-char encap) (sm j-read-char stream))
564 (rotatef (sm j-read-chars stream) (sm j-read-chars encap))
565 (rotatef (sm j-unread-char stream) (sm j-unread-char encap))
566 (rotatef (sm j-write-char stream) (sm j-write-char encap))
567 (rotatef (sm j-write-chars stream) (sm j-write-chars encap))))))
569 ;;; In cmucl, this is done with define-function-name-syntax (lists as
570 ;;; function names), we make do with symbol frobbing.
571 (defun %sf (kind name format &optional access)
572 (flet ((find-strategy-function (&rest args)
573 (let ((name
574 (find-symbol (format nil "~{~A~^-~}" (mapcar #'string args))
575 #.*package*)))
576 (if (fboundp name) (fdefinition name) nil))))
577 (or (find-strategy-function kind name format access)
578 (find-strategy-function kind name format)
579 (find-strategy-function kind name :ef access)
580 (find-strategy-function kind name :ef))))
583 (defun install-single-channel-character-strategy (stream external-format
584 access)
585 (let ((format (find-external-format external-format)))
586 ;; ACCESS is usually NIL
587 ;; May be "undocumented" values: stream::buffer, stream::mapped
588 ;; to install strategies suitable for direct buffer streams
589 ;; (i.e., ones that call DEVICE-EXTEND instead of DEVICE-READ)
590 ;; (Avoids checking "mode" flags by installing special strategy)
591 (with-stream-class (simple-stream stream)
592 (setf (sm j-listen stream)
593 (%sf 'sc 'listen (ef-name format) access)
594 (sm j-read-char stream)
595 (%sf 'sc 'read-char (ef-name format) access)
596 (sm j-read-chars stream)
597 (%sf 'sc 'read-chars (ef-name format) access)
598 (sm j-unread-char stream)
599 (%sf 'sc 'unread-char (ef-name format) access)
600 (sm j-write-char stream)
601 (%sf 'sc 'write-char (ef-name format) access)
602 (sm j-write-chars stream)
603 (%sf 'sc 'write-chars (ef-name format) access))))
604 stream)
606 (defun install-dual-channel-character-strategy (stream external-format)
607 (let ((format (find-external-format external-format)))
608 (with-stream-class (simple-stream stream)
609 (setf (sm j-listen stream)
610 (%sf 'sc 'listen (ef-name format))
611 (sm j-read-char stream)
612 (%sf 'sc 'read-char (ef-name format))
613 (sm j-read-chars stream)
614 (%sf 'sc 'read-chars (ef-name format))
615 (sm j-unread-char stream)
616 (%sf 'sc 'unread-char (ef-name format))
617 (sm j-write-char stream)
618 (%sf 'dc 'write-char (ef-name format))
619 (sm j-write-chars stream)
620 (%sf 'dc 'write-chars (ef-name format)))))
621 stream)
623 (defun install-string-character-strategy (stream)
624 (when (any-stream-instance-flags stream :input)
625 (install-string-input-character-strategy stream))
626 (when (any-stream-instance-flags stream :output)
627 (install-string-output-character-strategy stream))
628 stream)
630 (declaim (sb-ext:deprecated
631 :early ("SBCL" "1.2.15")
632 (function install-string-character-strategy
633 :replacement (install-string-input-character-strategy
634 install-string-output-character-strategy))))
636 (defun install-string-input-character-strategy (stream)
637 #| implement me |#
638 (with-stream-class (simple-stream stream)
639 (setf (sm j-read-char stream) #'str-read-char))
640 stream)
642 (defun install-string-output-character-strategy (stream)
643 #| implement me |#
644 stream)
646 (defun install-composing-format-character-strategy (stream composing-format)
647 (let ((format composing-format))
648 (with-stream-class (simple-stream stream)
649 (case format
650 (:e-crlf (setf (sm j-read-char stream) #'str-read-char-e-crlf
651 (sm j-unread-char stream) #'str-unread-char-e-crlf))))
652 #| implement me |#)
653 stream)
655 (defun compose-encapsulating-streams (stream external-format)
656 (when (consp external-format)
657 (with-stream-class (simple-stream)
658 (let ((encap (if (eq (sm melded-stream stream) stream)
660 (sm melded-stream stream))))
661 (when (null encap)
662 (setq encap (make-instance 'composing-stream))
663 (meld stream encap))
664 (setf (stream-external-format encap) (car (last external-format)))
665 (setf (sm external-format stream) external-format)
666 (install-composing-format-character-strategy stream
667 (butlast external-format))
668 ))))
670 (defmethod (setf stream-external-format) (ef (stream simple-stream))
671 (with-stream-class (simple-stream stream)
672 (setf (sm external-format stream) (find-external-format ef)))