ReadWriteStream Issues
Richard A. O'Keefe
ok at cs.otago.ac.nz
Tue May 6 02:18:20 UTC 2003
Time for a look at the ANSI standard. (Not for a full and final legal
settlement, but for some guidance, is all.)
(Part of) the protocol hierarchy looks like this,
using a Javaish syntax (because protocols aren't classes,
and because it's hard to draw a DAG in ASCII):
protocol "sequenced stream"
close // dissociate stream from backing store
contents // return complete contents of stream.
isEmpty // self contents isEmpty, NOT at end
position // return current logical position
position: n // set logical position
reset // same as self position: 0
setToEnd // same as self position: (self contents size)
(I must say that having position/position: in the Stream class in
Squeak is a *major* pain. Nearly every stream I've ever written
has been unable to inherit from Stream because of that. I also
note that #contents is unimplementable for streams connnected to
many kinds of devices.)
protocol "collection stream" extends "sequenced stream"
contents // returns same class as aColl select: [...]
// where aColl is underlying collection; the
// answer might or might not be aColl itself.
protocol "gettable stream"
atEnd // at end of readable data yet?
do: aBlock // [self atEnd] whileFalse: [aBlock value: self next]
next // return next item (undefined when atEnd)
next: n // return collection of next n items
nextLine // return next line
nextMatchFor: x // return self next = x
peek // return next item but don't move over it, nil atEnd
peekFor: x // return self atEnd not and: [self peek = x]
skip: n // skip next n items, stop early atEnd
skipTo: x // [self atEnd] whileFalse: [self next = x ifTrue:
// [^true]]. ^false
upTo: x // collect items; stop collecting just before x;
// stop reading just after x or AtEnd.
(#nextLine is clearly the odd man out here. What does
(ReadStream on: #(1 2 3 4)) nextLine mean?)
protocol ReadStream extends "gettable stream", "collection stream"
next: n // returns same class as self contents
upTo: x // returns same class as self contents
protocol "puttable stream"
cr // self nextPut: Character cr.
flush // "update backing store".
nextPut: x // write x. If position is at end, append, else
// replace & step over next element.
nextPutAll: xs // xs do: [:x | self nextPut: x]
space // self nextPut: Character space.
tab // self nextPut: Character tab.
protocol WriteStream extends "puttable stream", "collection stream"
// no extra methods, no changes to semantics.
protocol ReadWriteStream extends ReadStream, WriteStream
// no extra methods, no changes to semantics.
factory ReadStream
on: aCollection // return a ReadStream reading from aCollection
Past sequence values: none.
Future sequence values: the elements of aCollection.
In effect, the position is 0 and the read limit is aCollection size.
factory WriteStream
with: aCollection // return a WriteStream writing to aCollection
Past sequence values: the elements of aCollection.
Future sequnce values: none.
In effect, the position and the write limit are both aCollection size.
factory ReadWriteStream
with: aCollection // return a ReadWriteStream based on aCollection
Past sequence values: the elements of aCollection.
Future sequnce values: none.
In effect, the position, read limit, and write limit are all
aCollection size.
What we _don't_ find is a definition for ReadWriteStream>>on:
Let's look at Squeak 2.8.
Stream
PositionableStream
ReadStream
WriteStream
ReadWriteStream
PositionableStream class>>on: aCollection
^self basicNew on: aCollection
PositionableStream class>>on: aCollection from: first to: last
"You were maybe expecting something clever, maybe?"
^self basicNew on: (aCollection copyFrom: first to: last)
PositionableStream>>on: aCollection
collection := aCollection.
readLimit := aCollection size.
position := 0.
self reset "position := 0 again."
WriteStream class>>on: aCollection
"inherited from PositionableStream"
WriteStream class>>on: aCollection from: first to: last
^self basicNew on: aCollection from: first to: last
WriteStream class>>with: aCollection
^self basicNew with: aCollection
WriteStream class>>with: aCollection from: first to: last
^self basicNew with: (aCollection copyFrom: first to: last)
WriteStream>>on: aCollection "boils down to"
collection := aCollection.
position := 0.
readLimit := 0. "OOPS"
writeLimit := aCollection size.
WriteStream>>on: aCollection from: first to: last "boils down to"
collection := aCollection.
readLimit := writeLimit := aCollection size min: last.
position := first - 1 max: 0.
WriteStream>>with: aCollection "boils down to"
collection := aCollection.
position := readLimit := writeLimit := aCollection size.
We see a strange thing here.
WriteStream on: aColl
sets readLimit to 0, but
WriteStream on: aColl from: 1 to: aColl size
sets readLimit to aColl size.
ReadWriteStream class
"inherits #on:, #on:from:to:, #with:, #with:from:to:"
ReadWriteStream
"inherits #on:, #on:from:to:, #with:"
It looks very much as if WriteStream>>on: aCollection
should read
self on: aCollection from: 1 to: aCollection size.
This doesn't seem to be a new problem; I was looking at the code in 2.8.
More information about the Squeak-dev
mailing list
|