(*
    Title: 	Streams - Implementation
    LastEdit:	Fri May 25 16:43:19 1984
    Author: 	Mick Jordan
		Acorn Research Centre;  hacked by LDS.
*)

IMPLEMENTATION MODULE Streams;

FROM SYSTEM      IMPORT WORD, ADDRESS;
FROM SystemTypes IMPORT LongINTEGER, LongCARDINAL;
FROM Storage     IMPORT ALLOCATE, DEALLOCATE;
FROM StreamRep    IMPORT Procs;
IMPORT Slist;

TYPE  
      StreamProcs = Procs;
      
      StreamLISTPTR = POINTER TO StreamLIST;
      StreamLIST = RECORD
            link: StreamLISTPTR;
            stream: Stream;
        END (* record *);

VAR StreamList : StreamLISTPTR;

PROCEDURE Initialise();
    BEGIN
        StreamList := NIL;
    END Initialise;

PROCEDURE Finalise();
    VAR  this, next : StreamLISTPTR;
    BEGIN
        next := StreamList;
        WHILE next # NIL DO
            this := next;  
            next := next^.link;  (* because its DISPOSed *)
            Delete(this^.stream);
            DISPOSE(this);
        END;
    END Finalise;

PROCEDURE Create(procs: StreamProcs; instanceData: WORD) : Stream;
    VAR s : Stream;  
        sl: StreamLISTPTR;
    BEGIN
        NEW(s); NEW(sl);
        s^.procs := procs;
        s^.status := Success;  
        s^.extension := WORD(NIL);
        s^.instanceData := instanceData;
        sl^.stream := s;
        Slist.AddE(StreamList, sl);
        RETURN s;
    END Create;

PROCEDURE Delete(s : Stream);
    VAR
        sl, nsl: StreamLISTPTR;
    BEGIN
        sl := StreamList;
        WHILE sl # NIL DO
            nsl := sl^.link;
            IF sl^.stream = s THEN
                s^.status := Success;
                s^.procs^.Delete(s);
                Slist.Remove(StreamList, sl);
                RETURN
            END (* if *);
            sl := nsl;
        END (* while *);
    END Delete;

PROCEDURE Flush(s : Stream);
    BEGIN
        s^.status := Success;
        s^.procs^.Flush(s);
    END Flush;

PROCEDURE ElementSize(s : Stream) : CARDINAL;
    BEGIN
        s^.status := Success;
        RETURN s^.procs^.elementSize;
    END ElementSize;

PROCEDURE Get(s : Stream): WORD;
    BEGIN
        s^.status := Success;
        RETURN s^.procs^.Get(s);
    END Get;

PROCEDURE Put(s : Stream;  element : WORD);
    BEGIN
        s^.status := Success;
        s^.procs^.Put(s, element);
    END Put;

PROCEDURE Backspace(s: Stream);
    BEGIN
        s^.status := Success;
        s^.procs^.Backspace(s);
    END Backspace;

PROCEDURE Implements(s: Stream; f: OptionalFunction): BOOLEAN;
    BEGIN
        s^.status := Success;
        RETURN s^.procs^.Implements(s, f);
    END Implements;

PROCEDURE PutN(s : Stream; address : ADDRESS;  nreq : CARDINAL) : CARDINAL;
    BEGIN
        s^.status := Success;
        RETURN s^.procs^.PutN(s, address, nreq);
    END PutN;

PROCEDURE GetN(s : Stream;  address : ADDRESS;  nreq : CARDINAL) : CARDINAL;
    VAR  ngot: CARDINAL;
    BEGIN
        s^.status := Success;
        RETURN s^.procs^.GetN(s, address, nreq);
    END GetN;


PROCEDURE Seek(s : Stream;  seekmode : SeekMode;  offset : LongINTEGER);
    BEGIN
        s^.status := Success;
        s^.procs^.Seek(s, seekmode, offset);
    END Seek;

PROCEDURE Tell(s : Stream;  VAR p : LongCARDINAL);
    BEGIN
        s^.status := Success;
        s^.procs^.Tell(s, p);
    END Tell;

BEGIN
    Initialise();
END Streams.
