UNSAFE INTERFACE FastIO; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT Text, IO; TYPE Stream <: REFANY; (* A 'FastIO.Stream' is built on top of an 'IO.Stream'. It provides very fast sequential put, get and unget operations - faster than those provided by 'IO'. There is also a 'BinaryIO' interface which provides routines for the fast binary input and output of numbers and blocks of data to a 'FastIO.Stream'. The standard 'IO' operations are already fast - comparable to an array access in the usual case. The 'FastIO' operations gain a little extra speed by using pointer access to the buffer. An example of a program which might use a 'FastIO.Stream' is a lexer which typically does a large number of sequential get character operations, possibly mixed with some ungets. Programs which do a lot of random access to a stream or frequently switch between putting and getting to the same stream should stick to a normal 'IO.Stream'. Other stream operations are also provided but they are slower than the corresponding IO operations. Note that there is no point in building a 'FastIO.Stream' on top of a line buffered or unbuffered output stream; these require a check on every put operation anyway and an extra layer on top of such a stream just makes things worse. The price paid for the extra speed of sequential puts and gets is a loss of safety. If a 'FastIO.Stream' is used by multiple threads which do not serialize access to the stream via a mutex an unchecked runtime error may result. The mutex of the underlying 'IO.Stream' is available for serializing access to a 'FastIO.Stream' A 'FastIO.Stream' is created by a call to 'FastIO.New'. This creates the stream on top of an existing 'IO.Stream'. The 'IO.Stream' is disabled and remains disabled until the 'FastIO.Stream' is destroyed by a call to 'FastIO.Close' or a stream error occurs. The only useful operations on a disabled 'IO.Stream' are 'IO.Properties', 'IO.Name'. All other operations are either illegal (and will cause a stream error if used) or are only relevant to stream error handling. As a stream cannot be both disabled and errant the latter are of little use. When a 'FastIO.Stream' is closed or a stream error occurs on the underlying 'IO.Stream' the 'FastIO.Stream' becomes useless. Any attempt to use it will cause a checked runtime error. The underlying 'IO.Stream', in contrast, is enabled after a close or stream error (though it is, of course, errant if there was a stream error) *) PROCEDURE New(s: IO.Stream): Stream RAISES {IO.Error}; (* Create a 'FastIO.Stream' on top of 's'. 's' must be a valid stream (i.e. it must not be errant, closed or disabled by another 'FastIO.Stream'. The stream created has the same properties as the underlying 'IO.Stream' i.e. it is writable if 's' is writable and so on. *) PROCEDURE SlowStream(s: Stream): IO.Stream RAISES {}; (* The 'IO.Stream' underlying 's'. This stream is only useful for locking; it provides a mutex which can be locked to serialize access to 's' *) <*INLINE*> PROCEDURE Put(s: Stream; ch: CHAR) RAISES {IO.Error}; (* Put 'ch' to 's' *) <*INLINE*> PROCEDURE PutText(s: Stream; t: Text.T) RAISES {IO.Error}; (* Put 't' to 's' *) EXCEPTION EndOfStream(Stream); <*INLINE*> PROCEDURE Get(s: Stream): CHAR RAISES {IO.Error, EndOfStream}; (* Get a character from 's'. If there are no more characters i.e. the end of stream has been reached, raise 'EndOfStream' with 's' as its argument. 's' remains usable after 'EndOfStream' is raised. *) <*INLINE*> PROCEDURE Unget(s: Stream) RAISES {IO.Error}; (* Unget a single character. This can only be done after a previous call to 'Get'; if the last operation on 's' was not a 'Get' an error will be raised *) PROCEDURE Close( s: Stream; closeStream := FALSE) : IO.Stream RAISES {IO.Error}; (* Close the given stream. If 'closeStream' is TRUE the underlying 'IO.Stream' is closed as well. After a 'Close' any attempt to use 's' will result in a checked runtime error. *) (* The remaining routines in this interface are just veneers on the corresponding routines exported by 'IO' *) PROCEDURE Flush(s: Stream) RAISES {IO.Error}; PROCEDURE GotEndOfStream(s: Stream): BOOLEAN RAISES {IO.Error}; PROCEDURE Length(s: Stream): CARDINAL RAISES {IO.Error}; PROCEDURE Truncate(s: Stream; length: CARDINAL) RAISES {IO.Error}; PROCEDURE Tell(s: Stream): CARDINAL RAISES {IO.Error}; PROCEDURE Seek( s: Stream; offset := 0; mode: IO.SeekMode := IO.SeekMode.Beginning) RAISES {IO.Error}; PROCEDURE Properties(s: Stream): IO.PropertySet RAISES {}; PROCEDURE Name(s: Stream): Text.T RAISES {}; END FastIO.