IOClassesFix.mesa
Last edited by:
MBrown on January 13, 1984 1:32 pm
Last Edited by: Spreitzer, September 14, 1984 9:00:07 pm PDT
DIRECTORY
IO,
IOClasses,
IOUtils;
IOClassesFix: CEDAR PROGRAM
IMPORTS IO, IOUtils
EXPORTS IOClasses
SHARES IO --for representation of StreamProcs
= BEGIN
STREAM: TYPE = IO.STREAM;
StreamProcs: TYPE = IO.StreamProcs;
UnsafeBlock: TYPE = IO.UnsafeBlock;
Concatenated Input Stream
CatInputStreamData: TYPE = REF CatInputStreamRecord;
CatInputStreamRecord: TYPE = RECORD [
input1, input2: STREAM,
state: CatInputStreamState];
CatInputStreamState: TYPE = { initial, swapped, closed };
CatInputStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[
variety: $input, class: $Concatenated,
getChar: CatInputStreamGetChar,
getBlock: CatInputStreamGetBlock,
unsafeGetBlock: CatInputStreamUnsafeGetBlock,
charsAvail: CatInputStreamCharsAvail,
backup: CatInputStreamBackup,
endOf: CatInputStreamEndOf,
reset: CatInputStreamReset,
close: CatInputStreamClose
];
CreateCatInputStream: PUBLIC PROC [input1, input2: STREAM] RETURNS [STREAM] = {
RETURN[IO.CreateStream[
streamProcs: CatInputStreamProcs, streamData: NEW[CatInputStreamRecord ← [
input1: input1, input2: input2, state: $initial]]]];
};
CatInputStreamGetChar: PROC [self: STREAM] RETURNS [CHAR] = {
data: CatInputStreamData = NARROW[self.streamData];
{
RETURN[data.input1.GetChar[ ! IO.EndOfStream =>
IF data.state = $initial THEN GOTO nextStream]];
EXITS nextStream => {
SwapStreams[data];
RETURN[data.input1.GetChar[]];
}
}
};
SwapStreams: PROC [data: CatInputStreamData] = {
we preserve the information for debugging purposes
temp: STREAM ← data.input1;
IF data.state # $initial THEN ERROR;
data.input1 ← data.input2;
data.input2 ← temp;
data.state ← $swapped;
};
CatInputStreamGetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT]
RETURNS [nBytesRead: NAT] = {
data: CatInputStreamData = NARROW[self.streamData];
nBytesRead ← data.input1.GetBlock[block, startIndex, count];
IF nBytesRead > 0 OR data.state = $swapped THEN RETURN [nBytesRead];
SwapStreams[data];
RETURN[data.input1.GetBlock[block, startIndex, count]];
};
CatInputStreamUnsafeGetBlock: PROC [self: STREAM, block: UnsafeBlock]
RETURNS [nBytesRead: INT] = TRUSTED {
data: CatInputStreamData = NARROW[self.streamData];
nBytesRead ← data.input1.UnsafeGetBlock[block];
IF nBytesRead > 0 OR data.state = $swapped THEN RETURN [nBytesRead];
SwapStreams[data];
RETURN[data.input1.UnsafeGetBlock[block]];
};
CatInputStreamEndOf: PROC [self: STREAM] RETURNS [BOOL] = {
data: CatInputStreamData = NARROW[self.streamData];
IF NOT data.input1.EndOf[] THEN RETURN [FALSE];
IF data.state = $swapped THEN RETURN [TRUE];
SwapStreams[data];
RETURN [data.input1.EndOf[]];
};
CatInputStreamCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] = {
data: CatInputStreamData = NARROW[self.streamData];
RETURN[data.input1.CharsAvail[wait]];
};
CatInputStreamBackup: PROC [self: STREAM, char: CHAR] = {
data: CatInputStreamData = NARROW[self.streamData];
data.input1.Backup[char];
};
CatInputStreamReset: PROC [self: STREAM] = {
data: CatInputStreamData = NARROW[self.streamData];
data.input1.Reset[];
data.input2.Reset[];
};
CatInputStreamClose: PROC [self: STREAM, abort: BOOL] = {
data: CatInputStreamData = NARROW[self.streamData];
data.input1.Close[];
data.input2.Close[];
data.state ← $closed;
self.streamProcs ← IOUtils.closedStreamProcs;
};
END.