DIRECTORY TiogaLooks, RunReader; LooksReader: CEDAR DEFINITIONS IMPORTS RunReader = BEGIN Offset: TYPE = TiogaLooks.Offset; Looks: TYPE = TiogaLooks.Looks; noLooks: Looks = TiogaLooks.noLooks; Runs: TYPE = TiogaLooks.Runs; Ref: TYPE = REF Body; Body: TYPE = PRIVATE RECORD [ rem: NAT, -- remainder of current run len: NAT, -- length of current run looks: Looks, -- looks for current run runreader: RunReader.Ref -- reader for runs ]; Create: PROC [] RETURNS [Ref]; SetPosition: PROC [reader: Ref, runs: Runs, index: Offset _ 0] = INLINE { reader.rem _ reader.len _ 0; RunReader.SetPosition[reader.runreader, runs, index] }; SetIndex: PROC [reader: Ref, index: Offset _ 0] = INLINE { reader.rem _ reader.len _ 0; RunReader.SetIndex[reader.runreader, index] }; BackupIndex: PROC [reader: Ref, amount: Offset] = INLINE { SetIndex[reader, GetIndex[reader]-amount] }; BumpIndex: PROC [reader: Ref, amount: Offset] = INLINE { SetIndex[reader, GetIndex[reader]+amount] }; Position: PROC [reader: Ref] RETURNS [runs: Runs, index: Offset] = INLINE { RETURN [GetRuns[reader], GetIndex[reader]] }; GetRuns: PROC [reader: Ref] RETURNS [Runs] = INLINE { RETURN [RunReader.GetRuns[reader.runreader]] }; GetIndex: PROC [reader: Ref] RETURNS [index: Offset] = INLINE { RETURN [ RunReader.GetIndex[reader.runreader]-reader.rem]}; ReaderProc: TYPE = PROC [reader: Ref] RETURNS [Looks]; Get: ReaderProc = INLINE { rem: NAT; IF (rem_reader.rem) = 0 THEN { -- go to the next run len: Offset; [len, reader.looks] _ RunReader.Get[reader.runreader]; IF len > LAST[NAT] THEN { RunReader.BackupIndex[reader.runreader,len-LAST[NAT]]; len _ LAST[NAT] }; reader.len _ rem _ len}; reader.rem _ rem-1; RETURN[reader.looks]}; Backwards: ReaderProc = INLINE { rem: NAT; IF (rem_reader.rem) >= reader.len THEN { -- go to the previous run len: Offset; [len, reader.looks] _ RunReader.Backwards[reader.runreader]; IF len > LAST[NAT] THEN { RunReader.BumpIndex[reader.runreader,len-LAST[NAT]]; len _ LAST[NAT] }; reader.len _ len; rem _ 0 }; reader.rem _ rem+1; RETURN[reader.looks]}; Peek: ReaderProc = INLINE { looks: Looks; IF reader.rem = 0 THEN [,looks] _ RunReader.Peek[reader.runreader] ELSE looks _ reader.looks; RETURN [looks]}; PeekBackwards: ReaderProc = INLINE { looks: Looks; IF reader.rem >= reader.len THEN [,looks] _ RunReader.PeekBackwards[reader.runreader] ELSE looks _ reader.looks; RETURN [looks]}; GetLooksReader: PROC RETURNS [Ref]; FreeLooksReader: PROC[Ref]; END. RLooksReader.mesa; written by Bill Paxton, March 1981 edited by Bill Paxton, May 27, 1983 2:14 pm edited by McGregor, February 8, 1983 11:51 am LooksReader provides fast inline access to looks designed for speed in reading a sequence of looks either forwards or backwards supports looks as defined by TextLooks.Mesa create a reader by calling Create reader: LooksReader.Ref _ Create[]; position it where you want to read by SetPosition LooksReader.SetPosition[reader, runs, index]; where runs is TextLooks.Runs to read from and index is the initial position for the reader you can reposition a reader at any time read its position in the following ways: [runs, index] _ LooksReader.Position[reader]; runs _ LooksReader.GetRuns[reader]; index _ LooksReader.GetIndex[reader]; to read in ascending order (left to right) initialize position before first looks to be read for example, use 0 to start at beginning then call Get which reads to the right and increments the position looks _ LooksReader.Get[reader]; to read in descending order (right to left) initialize position after first looks to be read for example, use Size[runs] to start at end then call Backwards which reads to the left and decrements the position looks _ LooksReader.Backwards[reader]; can also get looks without changing the reader position to look at the next looks that Get would return, call Peek looks _ LooksReader.Peek[reader]; to look at what Backwards would return, call PeekBackwards looks _ LooksReader.PeekBackwards[reader]; can intermix reading or peeking to left and right don't need to reinitialize the reader to change direction create a reader for chars and looks set position of reader return position of looks reader get looks, then increment reader location decrement reader location, then get looks get looks without incrementing reader location like Backwards, but doesn't change position the following two routines implement a small cache of looks readers so can avoid creating a lot of garbage but don't use unless sure will not free more than once no harm if fail to free (garbage collector will get it) but chaos if free twice ʾ˜Jšœ5™5Jšœ+™+Jšœ-™-J˜šœ0™0šœ1™1Jšœ™J˜——Jšœ+™+J˜šœ!™!Jšœ#™#J˜—šœ1™1Jšœ-™-Jšœ)™)Jšœ0™0Jšœ'™'J˜—šœ(™(Jšœ-™-Jšœ#™#Jšœ%™%J˜—šœ*™*šœ1™1Jšœ(™(—šœB™BJšœ ™ J˜——šœ+™+šœ0™0Jšœ+™+—šœG™GJšœ&™&J˜——šœ7™7šœ:™:Jšœ!™!—šœ:™:Jšœ*™*J˜——šœ1™1Jšœ9™9J˜—šÏk ˜ J˜ J˜ J˜—šœ ˜Jšœ ˜—Jš˜J˜Jšœœ˜!Jšœœ˜Jšœ$˜$Jšœœ˜J˜Jšœœœ˜šœœœœ˜JšœœÏc˜%Jšœœž˜"Jšœž˜&Jšœž˜+J˜J˜—šÏnœœœ˜Jšœ#™#J˜—šŸ œœ/˜@Jšœ˜Jšœ™J˜J˜7J˜—šŸœœ$œ˜:J˜J˜.J˜—šŸ œœ!œ˜:J˜,J˜—šŸ œœ!œ˜8J˜,J˜—šŸœœœ˜BJšœ™Jšœœ'˜6J˜—šŸœœœ œ˜5Jšœ)˜/J˜—š Ÿœœœœœ˜HJ˜2J˜—JšŸ œœœœ ˜6J˜šœœ˜Jšœ)™)Jšœœ˜ šœœž˜4J˜ J˜6šœœœœ˜Jšœ+œœ˜6Jšœœœ˜—J˜—J˜Jšœ˜J˜—šœœ˜ Jšœ)™)Jšœœ˜ šœ œž˜BJ˜ J˜<šœœœœ˜Jšœ)œœ˜4Jšœœœ˜—J˜—J˜Jšœ˜J˜—šœœ˜Jšœ.™.J˜ šœœ˜J˜+—Jšœ˜Jšœ ˜J˜—šœœ˜$Jšœ+™+J˜ šœ˜ J˜4—Jšœ˜Jšœ ˜J˜—šœC™CJšœ&™&Jšœ6™6Jšœ7™7Jšœ™J˜—JšŸœœœ˜#J˜JšŸœœ˜J˜Jšœ˜J˜—…— ´Ä