Oberon || Library || Module Index || Search Engine || Definition || Module
(* Whence = (fromStart, fromPos, fromEnd); *) CONST fromStart = 0; fromPos = 1; fromEnd = 2; (* capabilities of a stream *) CONST read = 0; write = 1; addrio = 2; bufio = 3; seek = 4; tell = 5; CONST trunc = 6; flush = 7; close = 8; holes = 9; handler = 10; (* BufMode = (nobuf, linebuf, onebuf, bufpool); *) CONST nobuf = 0; linebuf = 1; onebuf = 2; bufpool = 3;
TYPE Address = LONGINT; TYPE Count = LONGINT; TYPE Whence = SHORTINT; TYPE CapabilitySet = SET; (* OF Capability *) TYPE Modes = SET; (* OF Mode; *) TYPE BufMode = SHORTINT; TYPE ErrorCode = SHORTINT; (* see below *) TYPE Stream = POINTER TO StreamRec; TYPE Message = RECORD (Objects.ObjectRec) END;
TYPE AddrIOProc = PROCEDURE (s: Stream; ptr: Address; cnt: Count) : Count; TYPE BufIOProc = PROCEDURE (s: Stream; VAR buf: ARRAY OF BYTE; off, cnt: Count) : Count; TYPE SeekProc = PROCEDURE (s: Stream; cnt: Count; whence: Whence) : BOOLEAN; TYPE TellProc = PROCEDURE (s: Stream; VAR cnt: Count) : BOOLEAN; TYPE ReadProc = PROCEDURE (s: Stream; VAR byte: BYTE) : BOOLEAN; TYPE WriteProc = PROCEDURE (s: Stream; byte: BYTE) : BOOLEAN; TYPE TruncProc = PROCEDURE (s: Stream; cnt: Count) : BOOLEAN; TYPE FlushProc = PROCEDURE (s: Stream) : BOOLEAN; TYPE CloseProc = PROCEDURE (s: Stream) : BOOLEAN; TYPE HandlerProc = PROCEDURE (s: Stream; VAR msg: Message);
TYPE Interface = POINTER TO InterfaceRec; TYPE InterfaceRec = RECORD (Objects.ObjectRec) addrread: AddrIOProc; (* read, addrio *) addrwrite: AddrIOProc; (* write, addrio *) bufread: BufIOProc; (* read, bufio *) bufwrite: BufIOProc; (* write, bufio *) read: ReadProc; (* read *) write: WriteProc; (* write *) seek: SeekProc; (* seek *) tell: TellProc; (* tell *) trunc: TruncProc; (* trunc *) flush: FlushProc; (* flush *) close: CloseProc; (* close *) handler: HandlerProc; (* handler *) END;
TYPE StreamRec = RECORD (Services.ObjectRec) (* following components are set after i/o-operations *) count: Count; (* resulting count of last operation *) errors: INTEGER; (* incremented for each error; may be set to 0 *) error: BOOLEAN; (* last operation successful? *) lasterror: ErrorCode; (* error code of last error *) eof: BOOLEAN; (* last read-operation with count=0 returned *) END;
TYPE Event = POINTER TO EventRec; TYPE EventRec = RECORD (Events.EventRec) stream: Stream; errorcode: ErrorCode; END;
VAR null: Stream; (* accepts any output; does not return input *) VAR stdin, stdout, stderr: Stream; VAR errormsg: ARRAY errorcodes OF Events.Message; VAR error: Events.EventType;
PROCEDURE Init(s: Stream; if: Interface; caps: CapabilitySet; bufmode: BufMode); PROCEDURE GetBufMode(s: Stream) : BufMode; PROCEDURE LineTerm(s: Stream; termch: BYTE); PROCEDURE Tie(in, out: Stream); PROCEDURE SetBufferPoolSize(s: Stream; nbuf: INTEGER); PROCEDURE GetBufferPoolSize(s: Stream; VAR nbuf: INTEGER); PROCEDURE Capabilities(s: Stream) : CapabilitySet;
PROCEDURE GetFlushEvent(s: Stream; VAR type: Events.EventType); PROCEDURE GetCloseEvent(s: Stream; VAR type: Events.EventType);
PROCEDURE Close(s: Stream) : BOOLEAN; PROCEDURE Release(s: Stream); PROCEDURE CloseAll;
PROCEDURE ReadByte(s: Stream; VAR byte: BYTE) : BOOLEAN; PROCEDURE ReadPart(s: Stream; VAR buf: ARRAY OF BYTE; off, cnt: Count) : BOOLEAN; PROCEDURE Read(s: Stream; VAR buf: ARRAY OF BYTE) : BOOLEAN; PROCEDURE ReadPacket(s: Stream; VAR buf: ARRAY OF BYTE; off, maxcnt: Count) : Count;
PROCEDURE WriteByte(s: Stream; byte: BYTE) : BOOLEAN; PROCEDURE WritePart(s: Stream; (* read-only *) VAR buf: ARRAY OF Byte; off, cnt: Count) : BOOLEAN; PROCEDURE Write(s: Stream; (* read-only *) VAR buf: ARRAY OF Byte) : BOOLEAN; PROCEDURE WritePartC(s: Stream; buf: ARRAY OF Byte; off, cnt: Count) : BOOLEAN; PROCEDURE WriteC(s: Stream; buf: ARRAY OF Byte) : BOOLEAN;
PROCEDURE Seek(s: Stream; offset: Count; whence: Whence) : BOOLEAN; PROCEDURE Tell(s: Stream; VAR offset: Count) : BOOLEAN; PROCEDURE GetPos(s: Stream; VAR offset: Count); PROCEDURE SetPos(s: Stream; offset: Count);
PROCEDURE Trunc(s: Stream; length: Count) : BOOLEAN;
PROCEDURE Back(s: Stream) : BOOLEAN; PROCEDURE Insert(s: Stream; byte: BYTE) : BOOLEAN;
PROCEDURE Flush(s: Stream) : BOOLEAN; PROCEDURE InputInBuffer(s: Stream) : BOOLEAN; PROCEDURE OutputInBuffer(s: Stream) : BOOLEAN; PROCEDURE OutputWillBeBuffered(s: Stream) : BOOLEAN; PROCEDURE Touch(s: Stream);
PROCEDURE Send(s: Stream; VAR message: Message);
PROCEDURE Copy(source, dest: Stream; maxcnt: Count) : BOOLEAN;
A stream is a data structure which references two components: a sequence of bytes and a position. Each byte of a sequence has an address: the first byte of a stream has address 0, the second byte 1, etc. The current position is the address of the byte to be affected by the next read or write operation. Thus the current position cannot be negative. Read and write requests cause the position to advance by the returned byte count which is less or equal to the requested count. Failures of read or write operations (count value equals zero) do not modify the current position.
The length of a stream is defined to be the highest byte address plus one. The length is infinite if the highest byte address is not defined (in case of infinite streams). In normal case a current position is valid if and only if it ranges from 0 to the stream length. Streams with holes may invalidate positions within this range or allow positions beyond the stream length.
Bidirectional streams reference a communication channel and do not maintain a current position. Instead, reading a character removes it from the input queue and writing a character appends it to the output queue. Streams are bidirectional if they support read and write operations but neither seek nor tell operations.
An interface defines a set of procedures which implement a Streams-abstraction for a specific form of input and/or output. Not every interface procedure needs to be implemented. The set of implemented procedures is given by the caps parameter of Init. At least read or write must be provided. Note that the byte-wise read or write operation must always be given even if additional read/write-operations are supported (bufio or addrio). All other operations (seek, tell, trunc, close, and handler) are optional. The interface procedures should meet following specifications:
The interface procedures of type AddrIOProc and BufIOProc must be equivalent to multiple calls of read or write (until the first failure) for buffered streams. Positive counts returned by reading procedures which are less than the requested count are not interpreted as failure. If necessary, Streams repeats reading until all requested bytes are read or a zero count is returned.
Init initializes the stream s for the interface specified by if and caps with buffering mode bufmode. Note that Init does not allocate s. Buffering mode is one of
GetBufMode returns the buffering mode associated with s.
LineTerm allows to change the line terminator for line buffered streams. The default line terminator is newline (0AX).
Tie ties the line buffered stream in to the stream out, i.e. read operations on in cause out to be flushed. Bidirectional line buffered streams are always tied to themselves, so Tie must not be called if in is equal to out. Streams may be untied by calling Tie with out set to NIL.
GetBufferPoolSize and SetBufferPoolSize return and set the number of buffers. The number of buffers may only be modified if bufpool has been taken as buffering mode.
Capabilities returns the capabilities of the given stream.
GetFlushEvent returns an event type which will be raised before executing any flush operations (either call Flush or internal flush operations). This event type is suitable for bidirectional streams and allows to empty the input queue before the output queue gets flushed.
GetCloseEvent returns like GetFlushEvent an event type which will be raised before the stream is shut by the close operation. Streams assures that this event will be raised with a priority which is greater than the current priority (see Events). This event type allows some final operations to be called. Note that Streams protects against recursive calls of Close or Release (in this case a NestedCall error would be returned for the first call).
Close closes s. The value of s remains unchanged to allow examination of the public components (this is useful in case of errors). Release works like Close but does not return a BOOLEAN value. Note that Streams maintains a list of open streams which may need some cleanup on termination (i.e. streams which have a close interface procedure or are buffered). These streams are therefore not subject to the garbage collection as long as Close has not been called for them.
Streams supports the mechanisms of Resources:
ReadByte assigns the byte at the current position to byte and increments the current position by one. ReadByte returns FALSE in case of end of stream (current position equals the stream length) or errors. WriteByte assigns byte to the byte at the current position and increments the current position by one. ReadByte and WriteByte are much faster than Read and Write for single bytes.
ReadPart and WritePart allow to read and write parts of buf: off specifies the start position and cnt the number of bytes to be read or written. Read and Write call ReadPart and WritePart with off = 0 and cnt = LEN(buf).
Note that WritePart and Write take buf as VAR parameter to avoid the overhead of an unnecessary copy. Neither WritePart nor Write modify buf. If an arbitrary expression is to be passed, WritePartC and WriteC may be used instead.
ReadPart tries to read the given number of bytes even when multiple calls of the read interface procedure are necessary. This may not be appropriate in cases where the first read operation wouldn't block but subsequent ones. ReadPacket returns available input from the associated buffer or, in case of unbuffered streams or empty buffers, invokes one read operation. maxcnt specifies the maximal number of bytes to be read and ReadPart returns the number of bytes actually copied into buf.
Seek sets the current position in dependence of whence and cnt to:
Tell returns the current position. This position can differ from the real position of the underlying implementation in case of buffered streams. Touch allows to synchronize both positions.
GetPos and SetPos work like Tell and Seek (whence = fromStart) without returning a BOOLEAN value.
Trunc truncates the length of the stream to cnt. Thus all bytes with addresses greater or equal to cnt are deleted. This call does not modify the current position.
Stream buffering allows to undo read operations. At least one successful undo operation is guaranteed. Further undo operations require seek ability. Back decrements the current position by one. Insert works like Back but causes byte to be returned on next read operation.
Flush and Touch synchronize buffered streams with the underlying implementation. Flush is useful for output streams and causes the buffer to be flushed. The current position remains unchanged. Touch calls Flush, causes any buffer contents to be forgotten, and sets the current position to that of the underlying implementation.
InputInBuffer and OutputInBuffer return TRUE if any bytes are buffered for reading or writing resp. OutputWillBeBuffered returns TRUE if the next byte passed to one of the writing procedures will be buffered.
Send passes the given message to the handler associated with s.
Copy copies from the current position of source to the current position of dest until end of file is reached or maxcnt bytes are copied (if maxcnt is non-negative).
Some streams are predefined.
The
null-stream accepts any output and returns read requests with zero counts.
The standard streams
stdin, stdout, and
stderr
are initialized to
null
but are possibly reinitialized by other modules
(e.g. UnixFiles initializes them to the UNIX standard files).
Note that Read, ReadPart, Write, WritePart, WriteC, and WritePartC return TRUE only if they were able to read or write the full amount of bytes as requested. In case of partial read or writes, the count component tells how many bytes were actually read or written.
Following error codes are currently implemented:
Valid error numbers range from 0 to errorcodes-1. The array errormsg contains readable error messages for all valid error numbers.
All stream related errors lead to events of type error which are passed to RelatedEvents for further handling. Modules calling Init are expected to decide whether stream related events are to be queued or to be forwarded to another object. By default, events of type error are ignored.
An assertion of Init fails in case of invalid interfaces (e.g. empty set of capabilities).
Oberon || Library || Module Index || Search Engine || Definition || Module