IOSimpleStreamsImpl.mesa
Last Edited by
MBrown on October 25, 1983 1:24 pm
TO DO
Input Rope Stream should use RopeReader package (via overlaid binding of RIS?)
remove "debugRopeFromROS" flag when no longer needed
DIRECTORY
IO,
IOUtils,
RefText,
Rope USING [Concat, Fetch, FromRefText, InlineFetch, InlineLength, Length, ROPE];
IOSimpleStreamsImpl: CEDAR PROGRAM
IMPORTS IO, IOUtils, RefText, Rope
EXPORTS IO
= BEGIN
STREAM: TYPE = IO.STREAM;
ROPE: TYPE = Rope.ROPE;
StreamProcs: TYPE = IO.StreamProcs;
Nowhere Stream
noWhereStream: PUBLIC STREAMIO.CreateStream[IO.CreateStreamProcs[
variety: $output, class: $Null, putChar: NoWherePutChar, close: NoWhereClose], NIL];
NoWherePutChar: PROC [self: STREAM, char: CHAR] = {};
NoWhereClose: PROC [self: STREAM, abort: BOOL] = {};
NoInput Stream
noInputStream: PUBLIC STREAM ← IO.CreateStream[
streamProcs: IO.CreateStreamProcs[
variety: $input, class: $Null,
getChar: NoInputGetChar,
endOf: NoInputEndOf,
backup: NoInputBackup,
close: NoInputClose],
streamData: NIL];
NoInputGetChar: PROC [self: STREAM] RETURNS [CHAR] = {
ERROR IO.EndOfStream[self] };
NoInputBackup: PROC [self: STREAM, char: CHAR] = {
ERROR IO.Error[$IllegalBackup, self] };
NoInputEndOf: PROC [self: STREAM] RETURNS [BOOL] = {
RETURN[TRUE] };
NoInputClose: PROC [self: STREAM, abort: BOOL] = { };
Input Stream from ROPE (RIS)
InputRopeStreamData: TYPE = REF InputRopeStreamRecord;
InputRopeStreamRecord: TYPE = RECORD [
rope: ROPE,
length: INT,
index: INT
];
InputRopeStreamProcs: REF StreamProcs = IO.CreateStreamProcs[
variety: $input, class: $ROPE,
getChar: InputRopeStreamGetChar,
endOf: InputRopeStreamEndOf,
reset: InputRopeStreamReset,
getIndex: InputRopeStreamGetIndex,
setIndex: InputRopeStreamSetIndex,
getLength: InputRopeStreamGetLength,
backup: InputRopeStreamBackup
];
RIS: PUBLIC PROC [rope: ROPE, oldStream: STREAM]
RETURNS [stream: STREAM] = {
IF oldStream = NIL THEN GOTO newStream;
WITH oldStream.streamData SELECT FROM
data: InputRopeStreamData => {
data^ ← [rope: rope, length: rope.InlineLength[], index: 0];
oldStream.streamProcs ← InputRopeStreamProcs;
RETURN[oldStream] };
ENDCASE => GOTO newStream;
EXITS newStream => RETURN[IO.CreateStream[
InputRopeStreamProcs, NEW[InputRopeStreamRecord ← [
rope: rope, length: rope.Length[], index: 0]]]];
};
InputRopeStreamGetChar: PROC [self: STREAM] RETURNS [char: CHAR] = {
data: InputRopeStreamData = NARROW[self.streamData];
IF data.index >= data.length THEN ERROR IO.EndOfStream[self];
char ← data.rope.InlineFetch[data.index];
data.index ← data.index + 1;
};
InputRopeStreamEndOf: PROC [self: STREAM] RETURNS [BOOL] = {
data: InputRopeStreamData = NARROW[self.streamData];
RETURN[data.index >= data.length];
};
InputRopeStreamBackup: PROC [self: STREAM, char: CHAR] = {
data: InputRopeStreamData = NARROW[self.streamData];
IF data.index = 0 OR data.rope.Fetch[data.index-1] # char THEN
ERROR IO.Error[$IllegalBackup, self];
data.index ← data.index - 1;
};
InputRopeStreamReset: PROC [self: STREAM] = {
data: InputRopeStreamData = NARROW[self.streamData];
data.index ← data.length;
};
InputRopeStreamGetIndex: PROC [self: STREAM] RETURNS [INT] = {
data: InputRopeStreamData = NARROW[self.streamData];
RETURN[data.index];
};
InputRopeStreamSetIndex: PROC [self: STREAM, index: INT] = {
data: InputRopeStreamData = NARROW[self.streamData];
IF index NOT IN [0 .. data.length] THEN ERROR IO.Error[$BadIndex, self];
data.index ← index;
};
InputRopeStreamGetLength: PROC [self: STREAM] RETURNS [length: INT] = {
data: InputRopeStreamData = NARROW[self.streamData];
RETURN[data.length];
};
Output Stream to ROPE (ROS)
OutputRopeStreamData: TYPE = REF OutputRopeStreamRecord;
OutputRopeStreamRecord: TYPE = RECORD [
rope: ROPE,
text: REF TEXT
];
OutputRopeStreamProcs: REF StreamProcs = IO.CreateStreamProcs[
variety: $output, class: $ROPE,
putChar: OutputRopeStreamPutChar,
eraseChar: OutputRopeStreamEraseChar,
reset: OutputRopeStreamReset,
getLength: OutputRopeStreamGetLength,
getIndex: OutputRopeStreamGetIndex,
close: OutputRopeStreamClose
];
ROS: PUBLIC PROC [oldStream: STREAM]
RETURNS [stream: STREAM] = {
IF oldStream = NIL THEN GOTO newStream;
WITH oldStream.streamData SELECT FROM
data: OutputRopeStreamData => {
data.rope ← NIL;
IF data.text = NIL THEN data.text ← RefText.ObtainScratch[100]
ELSE data.text.length ← 0;
oldStream.streamProcs ← OutputRopeStreamProcs;
RETURN[oldStream] };
ENDCASE => GOTO newStream;
EXITS newStream => RETURN[IO.CreateStream[
OutputRopeStreamProcs, NEW[OutputRopeStreamRecord ← [
rope: NIL, text: RefText.ObtainScratch[100]]]]];
};
OutputRopeStreamPutChar: PROC [self: STREAM, char: CHAR] = {
data: OutputRopeStreamData = NARROW[self.streamData];
text: REF TEXT = data.text;
IF text.length = text.maxLength THEN {
data.rope ← data.rope.Concat[Rope.FromRefText[text]];
text.length ← 0 };
text[text.length] ← char;
text.length ← text.length + 1;
};
OutputRopeStreamEraseChar: PROC [self: STREAM, char: CHAR] = {
data: OutputRopeStreamData = NARROW[self.streamData];
IF data.text.length # 0 THEN data.text.length ← data.text.length-1;
};
OutputRopeStreamReset: PROC [self: STREAM] = {
data: OutputRopeStreamData = NARROW[self.streamData];
data.rope ← NIL;
data.text.length ← 0;
};
OutputRopeStreamGetLength: PROC [self: STREAM] RETURNS [length: INT] = {
data: OutputRopeStreamData = NARROW[self.streamData];
RETURN[data.text.length + data.rope.Length[]];
};
OutputRopeStreamGetIndex: PROC [self: STREAM] RETURNS [index: INT] = {
RETURN[self.GetLength[]];
};
debugRopeFromROS: BOOLTRUE; -- crock until important clients get fixed
RopeFromROS: PUBLIC PROC [self: STREAM, close: BOOL] RETURNS [ROPE] = {
data: OutputRopeStreamData = NARROW[self.streamData];
result: ROPEIF data.text.length = 0 AND debugRopeFromROS THEN NIL
ELSE Rope.FromRefText[data.text];
IF close THEN {
RefText.ReleaseScratch[data.text];
data.text ← NIL;
self.streamProcs ← IOUtils.closedStreamProcs;
IF data.rope # NIL THEN { result ← data.rope.Concat[result]; data.rope ← NIL }
}
ELSE {
data.text.length ← 0;
result ← data.rope ← data.rope.Concat[result];
};
RETURN[result];
};
OutputRopeStreamClose: PROC [self: STREAM, abort: BOOL] = {
data: OutputRopeStreamData = NARROW[self.streamData];
data.rope ← NIL;
RefText.ReleaseScratch[data.text];
data.text ← NIL;
self.streamProcs ← IOUtils.closedStreamProcs;
};
Input Stream from REF TEXT (TIS)
InputTextStreamData: TYPE = REF InputTextStreamRecord;
InputTextStreamRecord: TYPE = RECORD [
text: REF READONLY TEXT,
index: NAT
];
InputTextStreamProcs: REF StreamProcs = IO.CreateStreamProcs[
variety: $input, class: $TEXT,
getChar: InputTextStreamGetChar,
endOf: InputTextStreamEndOf,
reset: InputTextStreamReset,
getIndex: InputTextStreamGetIndex,
setIndex: InputTextStreamSetIndex,
getLength: InputTextStreamGetLength,
backup: InputTextStreamBackup
];
TIS: PUBLIC PROC [text: REF READONLY TEXT, oldStream: STREAM]
RETURNS [STREAM] = {
IF oldStream = NIL THEN GOTO newStream;
WITH oldStream.streamData SELECT FROM
data: InputTextStreamData => {
data^ ← [text: text, index: 0];
oldStream.streamProcs ← InputTextStreamProcs;
RETURN[oldStream] };
ENDCASE => GOTO newStream;
EXITS newStream => RETURN[IO.CreateStream[
InputTextStreamProcs, NEW[InputTextStreamRecord ← [
text: text, index: 0]]]];
};
InputTextStreamGetChar: PROC [self: STREAM] RETURNS [char: CHAR] = {
data: InputTextStreamData = NARROW[self.streamData];
IF data.index >= data.text.length THEN ERROR IO.EndOfStream[self];
char ← data.text[data.index];
data.index ← data.index + 1;
};
InputTextStreamEndOf: PROC [self: STREAM] RETURNS [BOOL] = {
data: InputTextStreamData = NARROW[self.streamData];
RETURN[data.index >= data.text.length];
};
InputTextStreamBackup: PROC [self: STREAM, char: CHAR] = {
data: InputTextStreamData = NARROW[self.streamData];
IF data.index = 0 OR data.text[data.index-1] # char THEN
ERROR IO.Error[$IllegalBackup, self];
data.index ← data.index - 1;
};
InputTextStreamReset: PROC [self: STREAM] = {
data: InputTextStreamData = NARROW[self.streamData];
data.index ← data.text.length;
};
InputTextStreamGetIndex: PROC [self: STREAM] RETURNS [INT] = {
data: InputTextStreamData = NARROW[self.streamData];
RETURN[data.index];
};
InputTextStreamSetIndex: PROC [self: STREAM, index: INT] = {
data: InputTextStreamData = NARROW[self.streamData];
IF index NOT IN [0 .. data.text.length] THEN ERROR IO.Error[$BadIndex, self];
data.index ← index;
};
InputTextStreamGetLength: PROC [self: STREAM] RETURNS [length: INT] = {
data: InputTextStreamData = NARROW[self.streamData];
RETURN[data.text.length];
};
Output Stream to REF TEXT (TOS)
OutputTextStreamProcs: REF StreamProcs = IO.CreateStreamProcs[
variety: $output, class: $TEXT,
putChar: OutputTextStreamPutChar,
eraseChar: OutputTextStreamEraseChar,
reset: OutputTextStreamReset,
getLength: OutputTextStreamGetLength,
getIndex: OutputTextStreamGetIndex,
close: NIL
];
TOS: PUBLIC PROC [text: REF TEXT, oldStream: STREAM]
RETURNS [stream: STREAM] = {
IF oldStream = NIL THEN oldStream ← IO.CreateStream[OutputTextStreamProcs, NIL]
ELSE {
oldStream.streamProcs ← OutputTextStreamProcs;
WITH oldStream.streamData SELECT FROM
oldText: REF TEXT => IF text = NIL THEN text ← oldText;
ENDCASE;
};
IF text = NIL THEN text ← NEW[TEXT[100]];
text.length ← 0;
oldStream.streamData ← text;
RETURN[oldStream];
};
OutputTextStreamPutChar: PROC [self: STREAM, char: CHAR] = {
self.streamData ← RefText.InlineAppendChar[to: NARROW[self.streamData], from: char];
};
OutputTextStreamEraseChar: PROC [self: STREAM, char: CHAR] = {
text: REF TEXT = NARROW[self.streamData];
IF text.length > 0 THEN text.length ← text.length - 1;
};
OutputTextStreamReset: PROC [self: STREAM] = {
NARROW[self.streamData, REF TEXT].length ← 0;
};
OutputTextStreamGetLength: PROC [self: STREAM] RETURNS [length: INT] = {
RETURN[NARROW[self.streamData, REF TEXT].length];
};
OutputTextStreamGetIndex: PROC [self: STREAM] RETURNS [index: INT] = {
RETURN[NARROW[self.streamData, REF TEXT].length];
};
END.
Change Log
Changed by MBrown on October 25, 1983 1:24 pm
Fixed output rope stream and output text stream to implement EraseChar. Streams are prepared for Close to replace the stream procs with IOUtils.closedStreamProcs. RopeFromROS is somewhat more efficient in the normal case. RopeFromROS returns NIL when possible (work around bug in interpreter).