DIRECTORY TiogaLooks, TiogaLooksSupport; RunReader: CEDAR DEFINITIONS IMPORTS TiogaLooksSupport = BEGIN Base: TYPE = TiogaLooks.BaseRuns; Looks: TYPE = TiogaLooks.Looks; noLooks: Looks = TiogaLooks.noLooks; Runs: TYPE = TiogaLooks.Runs; Offset: TYPE = TiogaLooks.Offset; NoMoreRuns: ERROR; -- if try to read off end Ref: TYPE = REF Body; Body: TYPE = PRIVATE RECORD [ current: NAT _ 0, -- index of current run first: NAT _ 0, -- index of first run to read after: NAT _ 0, -- index beyond last run to read base: Base, -- current array of runs changeLooks: BOOLEAN _ FALSE, -- if need to change looks from base remove, add: Looks _ noLooks, -- the change runs: Runs _ NIL, -- runs that we are reading index: Offset _ 0 -- index in runs ]; Create: PROC RETURNS [Ref]; SetPosition: PROC [reader: Ref, runs: Runs, index: Offset _ 0] = INLINE { IF runs # GetRuns[reader] OR index # GetIndex[reader] THEN reader^ _ [0,0,0,NIL,FALSE,noLooks,noLooks,runs,index]; }; SetIndex: PROC [reader: Ref, index: Offset _ 0] = INLINE { IF index # GetIndex[reader] THEN { runs: Runs _ GetRuns[reader]; reader^ _ [0,0,0,NIL,FALSE,noLooks,noLooks,runs,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: Runs] = INLINE { RETURN [reader.runs] }; GetIndex: PROC [reader: Ref] RETURNS [index: Offset]; ReaderProc: TYPE = PROC [reader: Ref] RETURNS [count: Offset, looks: Looks]; Get: ReaderProc = INLINE { current: NAT; base: Base; IF (current_reader.current) >= reader.after THEN { [count, looks] _ ReadRun[reader, get]; RETURN }; reader.current _ current+1; base _ reader.base; count _ IF current=0 THEN base[0].after ELSE base[current].after-base[current-1].after; looks _ base[current].looks; IF reader.changeLooks THEN looks _ TiogaLooksSupport.ModifyLooks[looks,reader.remove,reader.add] }; Backwards: ReaderProc = INLINE { current: NAT; base: Base; IF (current_reader.current) <= reader.first THEN { [count, looks] _ ReadRun[reader, backwards]; RETURN }; base _ reader.base; count _ IF (reader.current _ current _ current-1)=0 THEN base[0].after ELSE base[current].after-base[current-1].after; looks _ base[current].looks; IF reader.changeLooks THEN looks _ TiogaLooksSupport.ModifyLooks[looks,reader.remove,reader.add] }; Peek: ReaderProc = INLINE { current: NAT; base: Base; IF (current_reader.current) >= reader.after THEN { [count, looks] _ ReadRun[reader, peek]; RETURN }; base _ reader.base; count _ IF current=0 THEN base[0].after ELSE base[current].after-base[current-1].after; looks _ base[current].looks; IF reader.changeLooks THEN looks _ TiogaLooksSupport.ModifyLooks[looks,reader.remove,reader.add] }; PeekBackwards: ReaderProc = INLINE { current: NAT; base: Base; IF (current_reader.current) <= reader.first THEN { [count, looks] _ ReadRun[reader, backwards]; RETURN }; base _ reader.base; count _ IF (current _ current-1)=0 THEN base[0].after ELSE base[current].after-base[current-1].after; looks _ base[current].looks; IF reader.changeLooks THEN looks _ TiogaLooksSupport.ModifyLooks[looks,reader.remove,reader.add] }; MergedGet: ReaderProc; Mode: PRIVATE TYPE = {get, backwards, peek, peekbackwards}; ReaderEscProc: TYPE = PROC [reader: Ref, mode: Mode] RETURNS [Offset, Looks]; ReadRun: PRIVATE ReaderEscProc; Equal: PROC [r1,r2: Runs, rdr1,rdr2: Ref] RETURNS [BOOLEAN] = INLINE { RETURN [EqSubstrs[r1,r2,0,0,LAST[Offset],rdr1,rdr2]] }; EqSubstrs: PROC [r1,r2: Runs, start1,start2,len: Offset, rdr1,rdr2: Ref] RETURNS [BOOLEAN]; GetRunReader: PROC RETURNS [reader: Ref]; FreeRunReader: PROC [reader: Ref]; END. ÄRunReader.mesa; written by Bill Paxton, March 1981 last edit by McGregor, February 8, 1983 11:52 am last edit by Bill Paxton, June 1, 1983 11:18 am RunReader provides fast inline access to look runs designed for speed in reading a sequence of runs either forwards or backwards supports looks as defined by TiogaLooks.Mesa create a reader by RunReader.Create reader: RunReader.Ref _ RunReader.Create[]; position it where you wanto to read by SetPosition RunReader.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 current position in the following ways: [runs, index] _ RunReader.Position[reader]; runs _ RunReader.GetRuns[reader]; index _ RunReader.GetIndex[reader]; to read in ascending order (left to right) initialize position before first character to be read for example, use 0 to start at beginning then call Get which reads to the right and increments the position [count, looks] _ RunReader.Get[reader]; to read in descending order (right to left) initialize position after first run to be read for example, use size of rope to start at end then call Backwards which reads to the left and decrements the position [count, looks] _ RunReader.Backwards[reader]; can also get a run without changing the reader position to look at the next run that Get would return, call Peek [count, looks] _ RunReader.Peek[reader]; to look at what Backwards would return, call PeekBackwards [count, looks] _ RunReader.PeekBackwards[reader]; can intermix reading or peeking to left and right don't need to reinitialize the reader to change direction if read off either end, you will get an error ***** RunReader Declarations ***** RunReader Operations returns the current position of the reader get run, then increment reader location decrement reader location, then get run get run without incrementing reader location like Backwards, but doesn't change position merges adjacent runs with same looks regular Get may give same looks on successive calls e.g., if Concat[A,B] produces in a concat-node and the last run in A has the same looks as the first in B Get will first return last run from A, then first from B MergedGet will combine these into a single result1 here are some operations making use of readers uses readers rdr1 and rdr2 to read runs r1 and r2 to test for equality uses readers rdr1 and rdr2 to read runs r1 and r2 to test for equality returns TRUE if r1 starting at start1 is same as len looks of r2 starting at start2 returns FALSE if not enough looks available in either i.e., if start1+len > size[r1] or start2+len > size[r2] the next routines provide caches of readers so can avoid creating a lot of garbage Ê@˜Jšœ3™3Jšœ0™0Jšœ/™/J˜šœ2™2šœ0™0Jšœ™J˜——Jšœ,™,J˜šœ#™#Jšœ+™+J˜—šœ2™2Jšœ+™+Jšœ*™*Jšœ0™0Jšœ'™'J˜—šœ0™0Jšœ+™+Jšœ!™!Jšœ#™#J˜—šœ*™*šœ5™5Jšœ(™(—šœB™BJšœ'™'J˜——šœ+™+šœ.™.Jšœ-™-—šœG™GJšœ-™-J˜——šœ7™7šœ8™8Jšœ(™(—šœ:™:Jšœ1™1J˜——šœ1™1Jšœ9™9J˜—Jšœ-™-J˜JšÏk ˜ J˜J˜šœ ˜Jšœ˜—Jš˜J˜Jšœ™J˜Jšœœ˜!Jšœœ˜Jšœ$˜$Jšœœ˜Jšœœ˜!J˜Jšœ œÏc˜,J˜Jšœœœ˜šœœœœ˜Jšœ œž˜)Jšœœž˜-Jšœœž ˜0Jšœ ž˜$Jšœ œœž$˜BJšœž ˜+Jšœ œž˜-Jšœž˜"J˜J˜—Jšœ™J˜JšÏnœœœ˜J˜šŸ œœ/˜@Jšœ˜šœœ˜:Jšœœœ˜7—J˜J˜—šŸœœ$œ˜:šœœ˜"J˜Jšœœœ˜9J˜——šŸ œœ!œ˜:J˜,J˜—šŸ œœ!œ˜8J˜,J˜—šŸœœ˜Jšœœ˜.—šœ*™*Jšœ'˜-J˜—šŸœœ˜Jšœœœ˜7J˜—JšŸœœœ˜5J˜JšŸ œœœœ˜LJ˜Jšœœ˜šœ'™'Jšœ œ˜ J˜ šœ*˜0Jšœ)œ˜2—J˜J˜šœœ œ˜,J˜*—J˜šœ˜J˜HJ˜——Jšœœ˜ šœ'™'Jšœ œ˜ J˜ šœ*˜0Jšœ/œ˜8—J˜šœœ*œ˜KJ˜*—J˜šœ˜J˜HJ˜——Jšœœ˜šœ,™,Jšœ œ˜ J˜ šœ*˜0Jšœ*œ˜3—J˜šœœ œ˜,J˜*—J˜šœ˜J˜HJ˜——Jšœœ˜$šœ+™+Jšœ œ˜ J˜ šœ*˜0Jšœ/œ˜8—J˜šœœœ˜:J˜*—J˜šœ˜J˜HJ˜——˜Jšœ$™$šœ4™4šœ/™/Jšœ:™:Jšœ8™8Jšœ2™2J˜———Jšœœœ)˜;JšŸ œœœœ˜MJšœ œ˜J˜Jšœ.™.J˜š Ÿœœœœœ˜FJšœF™FJšœœ˜7J˜—šŸ œœ9˜HJšœœ˜JšœF™Fšœ0™0Jšœ"™"—šœ5™5Jšœ7™7J˜——šœ,™,Jšœ&™&J˜—JšŸ œœœ˜)JšŸ œœ˜"J˜Jšœ˜J˜—…—( ,