(* Title: Streams - Definitions LastEdit: "Mon Sep 17 15:47:20 1984" Author: Mick Jordan Acorn Research Centre *) DEFINITION MODULE Streams; (* Streams defines an abstract object called a `Stream' and a set of valid operations on such objects. The source (for Input streams) or sink (for Output streams) is not defined by this module, which only provides generic procedures that are valid for all stream classes. A specific class is defined by an implementation which maps the generic procedures into specific operations. This module makes no assumptions about the type of object being stored on the stream; this is defined by an implementation and will typically be characters or bytes, but could certainly be words or bits. The 'size' of a stream element (in bits) can always by found by the function 'ElementSize'. The `StreamRep' module provides details on how to implement a specific stream class. *) FROM SYSTEM IMPORT WORD, ADDRESS; FROM SystemTypes IMPORT LongCARDINAL, LongINTEGER; EXPORT QUALIFIED Stream, StreamProcs, ErrorCode, StreamErrorCodeType, OptionalFunction, SeekMode, Initialise, Finalise, Create, Implements, Put, Get, Backspace, Flush, Delete, ElementSize, PutN, GetN, Seek, Tell; (* EXCEPTIONs *) (* EndOfStream, StreamError, WrongClass, FunctionNotImplemented ; *) TYPE ErrorCode = (Success, (* everything Ok *) EndOfStream, (* no more elements on (input) stream *) StreamError, (* stream-specific error *) WrongClass); (* wrong type of stream given to stream class implementation *) (* These errors are generic to all stream classes. Further details on the nature of a `StreamError' can be found by interrogating the `StreamErrorCode' procedure exported by a given stream class. 'status' will be set to Success by the relevant procedures in the package unless an error occurred. *) (* EXCEPTION EndOfStream, StreamError, WrongClass, FunctionNotImplemented; *) TYPE OptionalFunction = (OptPutN, OptGetN, OptSeek, OptTell); TYPE StreamProcs; (* a handle on the stream class procedures *) TYPE StreamErrorCodeType = WORD; (* Specific stream classes use the 'streamError' field of the stream block to store a handle on the actual error. The StreamErrorCode procedure then provides a mapping from this type to a more class specific type. The StreamErrorCodeType type avoids the client importing the WORD type. *) TYPE Stream = POINTER TO RECORD procs : StreamProcs; (* stream class procedures *) status : ErrorCode; (* EndOfStream... etc. *) extension : WORD; (* user-level hook... *) instanceData : WORD; (* the type is class specific; *) streamError : StreamErrorCodeType; (* type is class specific *) END (* record *); (* data is instance specific *) PROCEDURE Initialise(); (* Package Initialisation. It is called during the module initialisation process and should not need to be called by the user unless it is desired to restart after a call to Finalise; *) PROCEDURE Finalise(); (* Closes all open streams by a call to `Delete' (see below). The order of closure is undefined. *) PROCEDURE Create(procs: StreamProcs; instanceData: WORD) : Stream; (* Creates a new stream instance, with "procs" defining the procedures to be called by the generic operations. "procs" and "instanceData" are stored in the allocated Stream record; *) PROCEDURE Delete(s : Stream) (* RAISES {StreamError} *); (* Closes the stream denoted by `s'. In order that status can be returned from the delete at the stream class level, 's' is not DISPOSEd. *) PROCEDURE ElementSize(s : Stream) : CARDINAL; (* returns the size in BITS of an element of stream 's'. *) PROCEDURE Get(s: Stream): WORD (* RAISES {EndOfStream, StreamError} *); (* Returns the next element on stream `s'. *) PROCEDURE Put(s : Stream; element : WORD) (* RAISES {StreamError} *); (* Outputs `element' to stream `s'. *) PROCEDURE Flush(s : Stream) (* RAISES {StreamError} *); (* Flushes the (output side of) stream `s'. *) PROCEDURE Backspace(s: Stream) (* RAISES {EndOfStream, StreamError} *); (* Performs a one element backspace on stream `s'. Repeated calls are not guaranteed to have any additional effect. *) PROCEDURE Implements(s: Stream; f: OptionalFunction): BOOLEAN; (* Returns TRUE iff the optional function `f' is implemented by stream `s'. This procedure must be called if you wish to use the procedures described below and are not sure of the characteristics of a particular stream instance. *) (* ******************************************************************** *) (* The following procedures are not guaranteed to be implemented by *) (* all streams. If they are called on streams which do not implement *) (* them, the package will raise the FunctionNotImplemented exception *) PROCEDURE GetN(s : Stream; address : ADDRESS; nreq : CARDINAL) : CARDINAL (* RAISES {EndOfStream, StreamError, FunctionNotImplemented} *); (* Gets the next 'nreq' elements (at most) from stream `s', and places them at increasing addresses starting at 'address'. The size of the individual elements is determined by the stream implementation. The number of elements actually taken off is returned as result. *) PROCEDURE PutN(s : Stream; address : ADDRESS; nreq : CARDINAL) : CARDINAL (* RAISES {StreamError, FunctionNotImplemented} *); (* Outputs `nreq' elements to stream `s', from increasing addresses starting at 'address'. The result is the number actually put. The size of the individual elements is determined by the stream implementation. *) TYPE SeekMode = (Beginning, Current, End); PROCEDURE Seek(s : Stream; seekmode : SeekMode; offset : LongINTEGER) (* RAISES {StreamError, FunctionNotImplemented} *); (* Sets the 'next element' pointer on stream `s' to a position specified by offset taken relative to 'seekmode'. *) PROCEDURE Tell(s : Stream; VAR p : LongCARDINAL) (* RAISES {StreamError, FunctionNotImplemented} *); (* Sets p to the 'current element' pointer on stream `s'. Can be passed back to Seek if 'seekmode = beginning'. *) END Streams.