-- LooksReader.mesa -- written by Bill Paxton, March 1981 -- last edit by Bill Paxton, March 25, 1981 10:18 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 TiogaLooks.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 DIRECTORY Inline, TextLooks, RunReader; LooksReader: DEFINITIONS IMPORTS RunReader, Inline = BEGIN OPEN looksI:TextLooks, readerI:RunReader; Card: TYPE = LONG CARDINAL; Looks: TYPE = looksI.Looks; noLooks: Looks = looksI.noLooks; Runs: TYPE = looksI.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: readerI.Ref -- reader for runs ]; Create: PROC [] RETURNS [Ref] = INLINE { -- create a reader for chars and looks RETURN [NEW[Body _ [0,0,noLooks,NEW[readerI.Body]]]] }; SetPosition: PROC [reader: Ref, runs: Runs, index: Card _ 0] = INLINE { -- set position of reader reader.rem _ reader.len _ 0; readerI.SetPosition[reader.runreader, runs, index] }; SetIndex: PROC [reader: Ref, index: Card _ 0] = INLINE { reader.rem _ reader.len _ 0; readerI.SetIndex[reader.runreader, index] }; BackupIndex: PROC [reader: Ref, amount: Card] = INLINE { SetIndex[reader, GetIndex[reader]-amount] }; BumpIndex: PROC [reader: Ref, amount: Card] = INLINE { SetIndex[reader, GetIndex[reader]+amount] }; Position: PROC [reader: Ref] RETURNS [runs: Runs, index: Card] = -- return position of looks reader INLINE { RETURN [GetRuns[reader], GetIndex[reader]] }; GetRuns: PROC [reader: Ref] RETURNS [Runs] = INLINE { RETURN [readerI.GetRuns[reader.runreader]] }; GetIndex: PROC [reader: Ref] RETURNS [index: Card] = INLINE { RETURN [ readerI.GetIndex[reader.runreader]-reader.rem]}; ReaderProc: TYPE = PROC [reader: Ref] RETURNS [Looks]; Get: ReaderProc = INLINE { -- get looks, then increment reader location rem: NAT; IF (rem_reader.rem) = 0 THEN { -- go to the next run len: Card; [len, reader.looks] _ readerI.Get[reader.runreader]; IF len > LAST[NAT] THEN { readerI.BackupIndex[reader.runreader,len-LAST[NAT]]; len _ LAST[NAT] }; reader.len _ rem _ LOOPHOLE[Inline.LowHalf[len]]}; reader.rem _ rem-1; RETURN[reader.looks]}; Backwards: ReaderProc = INLINE { -- decrement reader location, then get looks rem: NAT; IF (rem_reader.rem) >= reader.len THEN { -- go to the previous run len: Card; [len, reader.looks] _ readerI.Backwards[reader.runreader]; IF len > LAST[NAT] THEN { readerI.BumpIndex[reader.runreader,len-LAST[NAT]]; len _ LAST[NAT] }; reader.len _ LOOPHOLE[Inline.LowHalf[len]]; rem _ 0 }; reader.rem _ rem+1; RETURN[reader.looks]}; Peek: ReaderProc = INLINE { -- get looks without incrementing reader location looks: Looks; IF reader.rem = 0 THEN [,looks] _ readerI.Peek[reader.runreader] ELSE looks _ reader.looks; RETURN [looks]}; PeekBackwards: ReaderProc = INLINE { -- like Backwards, but doesn't change position looks: Looks; IF reader.rem >= reader.len THEN [,looks] _ readerI.PeekBackwards[reader.runreader] ELSE looks _ reader.looks; RETURN [looks]}; END. (635)