changeset 670: |
6856c021d084 |
parent: |
849bbe48e32d
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Mon, 23 Sep 2024 21:14:10 -0400 |
permissions: |
-rw-r--r-- |
description: |
add dir-locals to skel, fix package lock violation in castable, move .sk files |
1 ;;; std/stream.lisp --- Standard Streams 6 (in-package :std/stream) 8 (defun copy-stream (input output &key (element-type (stream-element-type input)) 10 (buffer (make-array buffer-size :element-type element-type)) 13 "Reads data from INPUT and writes it to OUTPUT. Both INPUT and OUTPUT must 14 be streams, they will be passed to READ-SEQUENCE and WRITE-SEQUENCE and must have 15 compatible element-types." 16 (check-type start non-negative-integer) 17 (check-type end (or null non-negative-integer)) 18 (check-type buffer-size positive-integer) 21 (error "END is smaller than START in ~S" 'copy-stream)) 22 (let ((output-position 0) 25 ;; FIXME add platform specific optimization to skip seekable streams 26 (loop while (< input-position start) 27 do (let ((n (read-sequence buffer input 28 :end (min (length buffer) 29 (- start input-position))))) 31 (error "~@<Could not read enough bytes from the input to fulfill ~ 32 the :START ~S requirement in ~S.~:@>" 'copy-stream start)) 33 (incf input-position n)))) 34 (assert (= input-position start)) 35 (loop while (or (null end) (< input-position end)) 36 do (let ((n (read-sequence buffer input 39 (- end input-position)))))) 42 (error "~@<Could not read enough bytes from the input to fulfill ~ 43 the :END ~S requirement in ~S.~:@>" 'copy-stream end) 45 (incf input-position n) 46 (write-sequence buffer output :end n) 47 (incf output-position n))) 49 (finish-output output)) 54 (defclass wrapped-stream (fundamental-stream) 55 ((stream :initarg :stream :reader stream-of))) 57 (defmethod stream-element-type ((stream wrapped-stream)) 58 (stream-element-type (stream-of stream))) 60 (defmethod close ((stream wrapped-stream) &key abort) 61 (close (stream-of stream) :abort abort)) 63 (defclass wrapped-character-input-stream (wrapped-stream fundamental-character-input-stream) 66 (defmethod stream-read-char ((stream wrapped-character-input-stream)) 67 (read-char (stream-of stream) nil :eof)) 69 (defmethod stream-unread-char ((stream wrapped-character-input-stream) 71 (unread-char char (stream-of stream))) 74 (with-input-from-string (input "1 2 76 (let ((counted-stream (make-instance 'counting-character-input-stream 78 (loop for thing = (read counted-stream) while thing 79 unless (numberp thing) do 80 (error "Non-number ~S (line ~D, column ~D)" thing 81 (line-count-of counted-stream) 82 (- (col-count-of counted-stream) 83 (length (format nil "~S" thing)))) 89 Non-number :FOO (line 2, column 5) 90 [Condition of type SIMPLE-ERROR] 92 (defclass counting-character-input-stream 93 (wrapped-character-input-stream) 94 ((char-count :initform 1 :accessor char-count-of) 95 (line-count :initform 1 :accessor line-count-of) 96 (col-count :initform 1 :accessor col-count-of) 97 (prev-col-count :initform 1 :accessor prev-col-count-of))) 99 (defmethod stream-read-char ((stream counting-character-input-stream)) 100 (with-accessors ((inner-stream stream-of) (chars char-count-of) 101 (lines line-count-of) (cols col-count-of) 102 (prev prev-col-count-of)) stream 103 (let ((char (call-next-method))) 104 (cond ((eql char :eof) 106 ((char= char #\Newline) 117 (defmethod stream-unread-char ((stream counting-character-input-stream) 119 (with-accessors ((inner-stream stream-of) (chars char-count-of) 120 (lines line-count-of) (cols col-count-of) 121 (prev prev-col-count-of)) stream 122 (cond ((char= char #\Newline) 132 (defclass wrapped-character-output-stream (wrapped-stream fundamental-character-output-stream) 133 ((col-index :initform 0 :accessor col-index-of))) 135 (defmethod stream-line-column ((stream wrapped-character-output-stream)) 136 (col-index-of stream)) 138 (defmethod stream-write-char ((stream wrapped-character-output-stream) 140 (with-accessors ((inner-stream stream-of) (cols col-index-of)) stream 141 (write-char char inner-stream) 142 (if (char= char #\Newline) 147 (flet ((format-timestamp (stream) 148 (apply #'format stream "[~2@*~2,' D:~1@*~2,'0D:~0@*~2,'0D] " 149 (multiple-value-list (get-decoded-time))))) 150 (let ((output (make-instance 'prefixed-character-output-stream 151 :stream *standard-output* 152 :prefix #'format-timestamp))) 153 (loop for string in '("abc" "def" "ghi") do 154 (write-line string output) 161 (defclass prefixed-character-output-stream 162 (wrapped-character-output-stream) 163 ((prefix :initarg :prefix :reader prefix-of))) 165 (defgeneric write-prefix (prefix stream) 166 (:method ((prefix string) stream) (write-string prefix stream)) 167 (:method ((prefix function) stream) (funcall prefix stream))) 169 (defmethod stream-write-char ((stream prefixed-character-output-stream) 171 (with-accessors ((inner-stream stream-of) (cols col-index-of) 172 (prefix prefix-of)) stream 174 (write-prefix prefix inner-stream))