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; noWhereStream: PUBLIC STREAM _ IO.CreateStream[IO.CreateStreamProcs[ variety: $output, class: $Null, putChar: NoWherePutChar, close: NoWhereClose], NIL]; NoWherePutChar: PROC [self: STREAM, char: CHAR] = {}; NoWhereClose: PROC [self: STREAM, abort: BOOL] = {}; 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] = { }; 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]; }; 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: BOOL _ TRUE; -- crock until important clients get fixed RopeFromROS: PUBLIC PROC [self: STREAM, close: BOOL] RETURNS [ROPE] = { data: OutputRopeStreamData = NARROW[self.streamData]; result: ROPE _ IF 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; }; 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]; }; 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. Ψ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 Nowhere Stream NoInput Stream Input Stream from ROPE (RIS) Output Stream to ROPE (ROS) Input Stream from REF TEXT (TIS) Output Stream to REF TEXT (TOS) 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). Κ a– "Cedar" style˜JšΟc™šœ™Jšœ™"—J™™J™NJ™4—J˜šΟk ˜ Jšžœ˜Jšœ˜Jšœ˜JšœžœAžœ˜QJ˜—J˜šΠblœžœžœ˜#Jšžœžœ˜"Jšžœž˜ Jšœž˜Jšžœžœžœžœ˜Jšžœžœžœ˜Jšœ žœžœ ˜#—head™š œžœžœžœžœ˜DJšœOžœ˜T—JšΟnœžœžœžœ˜5Jš  œžœžœ žœ˜4—™šœžœžœ˜/šœ"˜"Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ žœ˜—š  œžœžœžœžœ˜6Jšžœžœ˜—š  œžœžœžœ˜2Jšžœžœ˜'—š   œžœžœžœžœ˜4Jšžœžœ˜—Jš  œžœžœ žœ˜5—šœžœ™Jšœžœžœ˜7šœžœžœ˜&Jšœžœ˜ Jšœžœ˜ Jšœž˜ J˜—J˜šœžœ$˜=Jšœ˜Jšœ ˜ J˜J˜J˜"J˜"J˜$Jšœ˜J˜—unitš Πknœžœžœžœ žœ˜0Jšžœ žœ˜Jšžœ žœžœžœ ˜'šžœžœž˜%šœ˜Jšœ<˜Jšžœžœ˜%—J˜Jšœ˜—š œžœžœ˜-Jšœžœ˜4Jšœ˜Jšœ˜—š  œžœžœžœžœ˜>Jšœžœ˜4Jšžœ ˜Jšœ˜—š œžœžœ žœ˜Jšœ˜J˜!J˜%J˜J˜%J˜#Jšœ˜J˜—š‘œžœžœ žœ˜$Jšžœ žœ˜Jšžœ žœžœžœ ˜'šžœžœž˜%šœ˜Jšœ žœ˜Jšžœ žœžœ'˜>Jšžœ˜Jšœ.˜.Jšžœ˜—Jšžœžœ ˜—šžœžœžœ˜*šœžœ˜5Jšœžœ'˜0——Jšœ˜—š œžœžœžœ˜Jšœžœ˜5Jšžœžœ'˜CJšœ˜—š œžœžœ˜.Jšœžœ˜5Jšœ žœ˜J˜Jšœ˜—š  œžœžœžœ žœ˜HJšœžœ˜5Jšžœ(˜.Jšœ˜—š  œžœžœžœ žœ˜FJšžœ˜Jšœ˜—Lšœžœžœ*˜Iš  œžœžœžœ žœžœžœ˜GJšœžœ˜5š œžœžœžœžœž˜DJšžœ˜!—šžœžœ˜Jšœ"˜"Jšœ žœ˜Jšœ-˜-Jšžœ žœžœ3žœ˜OJ˜—šžœ˜Jšœ˜Jšœ.˜.J˜—Jšžœ ˜Jšœ˜—š œžœžœ žœ˜;Jšœžœ˜5Jšœ žœ˜Jšœ"˜"Jšœ žœ˜Jšœ-˜-Jšœ˜——šœžœ™ Jšœžœžœ˜7šœžœžœ˜&Jšœžœžœžœ˜Jšœž˜ Jšœ˜—J˜šœžœ$˜=Jšœ˜J˜ J˜J˜J˜"J˜"J˜$Jšœ˜Jšœ˜—J˜š‘œžœžœžœžœžœ žœ˜=Jšžœžœ˜Jšžœ žœžœžœ ˜'šžœžœž˜%šœ˜Jšœ˜Jšœ-˜-Jšžœ˜—Jšžœžœ ˜—šžœžœžœ˜*šœžœ˜3Jšœ˜——Jšœ˜—J˜š  œžœžœžœžœ˜DJšœžœ˜4Jšžœ žœžœ˜BJ˜J˜Jšœ˜—J˜š  œžœžœžœžœ˜Jšœžœ˜4Jšžœ ˜Jšœ˜J˜—š œžœžœ žœ˜Jšœ˜J˜!J˜%J˜J˜%J˜#Jšœž˜ Jšœ˜—J˜š  œžœžœžœžœ žœ˜4Jšžœ žœ˜Jš žœ žœžœ žœ%žœ˜Ošžœ˜Jšœ.˜.šžœžœž˜%Jš œ žœžœžœžœžœ˜7Jšžœ˜—J˜—Jš žœžœžœžœžœ˜)Jšœ˜Jšœ˜Jšžœ ˜Jšœ˜—š œžœžœžœ˜Jšœžœžœžœ˜)Jšžœžœ˜6Jšœ˜—š œžœžœ˜.Jšžœžœžœ ˜-Jšœ˜—š  œžœžœžœ žœ˜HJšžœžœžœžœ ˜1Jšœ˜—š  œžœžœžœžœ˜FJšžœžœžœžœ ˜1Jšœ˜——J˜Jšžœ˜head1š ™ body™-Nš¨™¨———…—%z5³