Skip to content
  • mevenson@1c010e3e-69d0-11dd-93a8-456734b0d56f's avatar
    Fix gray streams for FLEXI-STREAMS. · 8a3fbb66
    From Theam Yang Chew, who writes on
    http://article.gmane.org/gmane.lisp.armedbear.devel/3059:
    
    Hi all,
    
    I inadvertently discovered some bugs in the gray-streams
    implementation due to a stale flexi-streams that did not get upgraded
    properly.
    
    There were quite a few things that needed tidying - the type checking
    using EQ is wrong. Also, after trying to hunt around CLHS, I think
    BYTE is not a CL type (though I may be mistaken). This could be a
    reflection of some Corman Lisp specific feature in the past (Yes!
    These bugs seem to have been around ABCL for that long!)
    
    Some test examples (avoiding flexi-streams or other dependencies)
    
    ;; ----- setup
    
    (require 'gray-streams)
    
    (defclass test-gray-binary-input-stream
    (gray-streams:fundamental-binary-input-stream)
     ())
    
    (defclass test-gray-character-input-stream
    (gray-streams:fundamental-character-input-stream)
     ())
    
    (let ((bytes (list 65 66 67 68 69))
         (pos -1))
     (defmethod gray-streams::stream-read-byte ((stream
    test-gray-binary-input-stream))
       (elt bytes (mod (incf pos) 5))))
    
    (let ((chars (list #\A #\B #\C #\D #\E))
         (pos -1))
     (defmethod gray-streams::stream-read-char ((stream
    test-gray-character-input-stream))
       (elt chars (mod (incf pos) 5))))
    
    ;; -----
    
    (let ((s (make-instance 'test-gray-binary-input-stream)))
     (loop repeat 10 collect (read-byte s)))
    => (65 66 67 68 69 65 66 67 68 69)
    
    (let ((arr (make-array 10 :initial-element nil)))
     (list (read-sequence arr
                          (make-instance 'test-gray-binary-input-stream)
                          :start 2 :end 7)
           arr))
    
    Expected (7 #(NIL NIL 65 66 67 68 69 NIL NIL NIL)), but got an error
    instead, ... no applicable method...
    
    I guess implementors of gray streams would normally define both
    read-byte & read-sequence. But ABCL's default/fallback method does try
    to support binary streams, it just isn't being dispatched on the right
    class.
    
    Also, read-sequence should return the "final" array index, not the
    number of bytes/characters read. Similarly, write-sequence needs to do
    its work, then return the sequence itself.
    
    Attached is a patch with what I hope are the required fixes, please
    review.
    
    Two additional notes,
    
    1. Even after loading my proposed fixes, I'd would still get this,
    which is ok, but the error message is not obvious enough. This is
    actually a method not found error, not a type error. There appears
    to be some type guessing going on, so perhaps the message should
    indicate failure to dispatch on STREAM or similar.
    
    (gray-streams::stream-element-type
    (make-instance 'test-gray-binary-input-stream))
    The value #<TEST-GRAY-BINARY-INPUT-STREAM {500BBBF9}> is not of type STREAM.
      [Condition of type TYPE-ERROR]
    
    So we just need something like this,
    
    (defmethod gray-streams::stream-element-type ((stream
    test-gray-binary-input-stream))
     '(unsigned-byte 8))
    
    2. I also don't understand this snippet in the original code,
    converting unsigned-bytes/integers (basically the wrong type) to a
    character?
    
    (#+nil ccl:int-char code-char (elt sequence n))
    
    
    Of course, after patching the above, I discovered that re-compiling
    flexi-streams
    got rid of my particular set of problems :-)
    8a3fbb66