Blair,
SocketReadStream does not always do what one would expect. #contents, #nextLine, #upToEnd will answer an empty collection even when the socket has data available. The #nextLine below seems to work, but I suspect that it would be happier written in terms of #contentsSpecies or something. More generally, is there some way to use #hasInput to get the stream to read from the socket before returning an empty collection? Have a good one, Bill !SocketReadStream methodsFor! nextLine "Answer a Collection consisting of the receiver contents up to (but not including) the next line delimiter. If there are no further line delimiters in the receiver, then the rest of the receiver's contents are answered. If the receiver is at its end, then an empty collection is answered. N.B. This method works for Unix and Windows line delimiters (that is CR/LF and LF sequences respectively), but not if the line delimiter consists solely of a CR." | result eol | eol := String lineDelimiter asByteArray. result := self upTo: eol last. ^(result notEmpty and: [result last = eol first]) ifTrue: [result allButLast] ifFalse: [result]! ! !SocketReadStream categoriesFor: #nextLine!accessing!public! ! -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill
You wrote in message news:bn3l85$sjlbr$[hidden email]... > > SocketReadStream does not always do what one would expect. I can only agree with that. With the benefit of hindsight we can see that it was probably a design error to subclass SocketReadStream from PositionableStream. This allows it to inherit some useful buffering implementation behaviour, but it has also picked up quite a lot of inappropriate behaviour, as SocketReadStreams are not really positionable at all. >...#contents, > #nextLine, #upToEnd will answer an empty collection even when the socket has > data available. Hmmm, I don't think #contents should be available at all. SocketReadStreams are not really ANSI <sequencedStream>s. #contents should answer a collection "that contains the receiver's past and future sequence values". This would require that the stream retain all previous data and then all subsequent data up until the associated socket is closed. I don't think that buffering all the "past sequence" values makes sense for a generic socket stream - one should write a <sequencedStream> that can be layered onto a simple <gettableStream> for that purpose. #upToEnd should answer all the "future sequence values", i.e. up to the end of stream when the socket is closed. This probably isn't that useful on Sockets either. I think the Stream implementation of #upToEnd should be copied down to SocketReadStream because the implementation in PositionableStream is inappropriate. >...The #nextLine below seems to work, but I suspect that it > would be happier written in terms of #contentsSpecies or something. Yes, although it is questionable whether #nextLine is useful on binary streams in general, I suppose it is up to the application programmer not to call it against a true binary data stream. On the other hand I would prefer it if SocketReadStream supported mutually exclusive binary or text modes, as in FileStream. >...More > generally, is there some way to use #hasInput to get the stream to read from > the socket before returning an empty collection? Well as I've said I don't think #contents should be implemented at all. Other reading methods (e.g. #next[:], #upToEnd, #upTo:, etc) should block until the input is available, or the socket is closed. #nextAvailable: should be the only non-blocking read. Unfortunately I don't think it is appropriate to change any of this in a patch level. Our policy now is to try and avoid making "breaking" changes in patches. It seems likely that changing these behaviours, incorrect as they might be, will break existing code. Regards Blair |
Free forum by Nabble | Edit this page |