StreamDefsImpl.mesa
Updated for Pilot Martin Newell 23-Jul-81 14:02:05
Doug Wyatt, 13-Oct-81 17:46:21
Bill Paxton, 22-Jan-82 8:35:38
Russ Atkinson, September 23, 1983 7:18 pm
Birrell, August 23, 1983 10:10 am
DIRECTORY
ConvertUnsafe,
FS,
JaMStorage USING [Zone],
IO,
Rope USING [ROPE],
StreamDefs;
StreamDefsImpl: MONITOR
IMPORTS ConvertUnsafe, FS, JaMStorage, IO
EXPORTS StreamDefs = {
OPEN StreamDefs;
ROPE: TYPE = Rope.ROPE;
zone: UNCOUNTED ZONE = JaMStorage.Zone[];
openList: LIST OF IO.STREAMNIL; -- here to keep the streams from being collected
StreamError: PUBLIC SIGNAL[stream: StreamHandle, error: StreamErrorCode] = CODE;
FileNameError: PUBLIC SIGNAL[name: LONG STRING] = CODE;
NewByteStream: PUBLIC PROC
[name: LONG STRING, access: AccessOptions] RETURNS [StreamHandle] = {
data: Data ← NIL;
s: StreamHandle ← NIL;
data ← NewStream[name,access];
s ← zone.NEW[StreamObject ← [reset: FileReset, get: FileGetChar,
putback: FilePutback, put: FilePutChar, endof: FileEndof, destroy: FileDestroy,
data: data]];
RETURN[s];
};
NewWordStream: PUBLIC PROC
[name: LONG STRING, access: AccessOptions] RETURNS [StreamHandle] = {
s: StreamHandle ← NewByteStream[name,access];
s.get ← FileGetWord; s.put ← FilePutWord;
RETURN[s];
};
Data: TYPE = LONG POINTER TO IO.STREAM;
AddStream: ENTRY PROC [stream: IO.STREAM] RETURNS [Data] = {
openList ← CONS[stream, openList];
RETURN [@openList.first];
};
RemStream: ENTRY PROC [data: Data] RETURNS [IO.STREAM] = {
lag: LIST OF IO.STREAMNIL;
FOR list: LIST OF IO.STREAM ← openList, list.rest UNTIL list = NIL DO
IF @list.first = data THEN {
IF lag = NIL
THEN openList ← list.rest
ELSE lag.rest ← list.rest;
RETURN [list.first];
};
lag ← list;
ENDLOOP;
RETURN [NIL];
};
NewStream: PROC [name: LONG STRING, access: AccessOptions] RETURNS [Data] = {
new: BOOLFALSE;
stream: IO.STREAMNIL;
rope: ROPE ← ConvertUnsafe.ToRope[name];
accessOptions: FS.AccessOptions ←
SELECT access FROM
StreamDefs.DefaultAccess, StreamDefs.Read => read,
StreamDefs.Append => append,
ENDCASE => create;
stream ← FS.StreamOpen[
fileName: rope,
accessOptions: accessOptions
! FS.Error => GO TO NotFound;
];
RETURN [AddStream[stream]];
EXITS NotFound => ERROR FileNameError[name];
};
File Stream Procedures
FileReset: PROC[s: StreamHandle] = {
data: Data ← s.data;
IO.SetIndex[data^,0];
};
FileGetChar: PROC[s: StreamHandle] RETURNS [CHAR] = {
data: Data ← s.data;
RETURN[IO.GetChar[data^]];
};
FileGetWord: PROC[s: StreamHandle] RETURNS [WORD] = {
data: Data ← s.data;
card: CARDINAL ← (IO.GetChar[data^]-0C) * 256;
card ← card + (IO.GetChar[data^]-0C);
RETURN[LOOPHOLE[card, WORD]];
};
FilePutback: PROC[s: StreamHandle, c: CHAR] = {
ERROR StreamError[s,StreamOperation];
};
FilePutChar: PROC[s: StreamHandle, c: CHAR] = {
data: Data ← s.data;
IO.PutChar[data^, c];
};
FilePutWord: PROC[s: StreamHandle, w: WORD] = {
data: Data ← s.data;
card: CARDINALLOOPHOLE[w, CARDINAL];
IO.PutChar[data^, (card / 256) + 0C];
IO.PutChar[data^, (card MOD 256) + 0C];
};
FileEndof: PROC[s: StreamHandle] RETURNS [BOOL] = {
data: Data ← s.data;
RETURN[IO.EndOf[data^]];
};
FileDestroy: PROC[s: StreamHandle] = {
data: Data ← s.data;
stream: IO.STREAM ← RemStream[data];
IF stream # NIL THEN {
IO.Close[stream];
zone.FREE[@s];
};
};
}.