DIRECTORY TextLooks USING [BaseRuns, Looks, noLooks, Runs]; RunReader: CEDAR DEFINITIONS = BEGIN Base: TYPE = TextLooks.BaseRuns; Looks: TYPE = TextLooks.Looks; noLooks: Looks = TextLooks.noLooks; Runs: TYPE = TextLooks.Runs; 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: BOOL _ FALSE, -- if need to change looks from base remove, add: Looks _ noLooks, -- the change runs: Runs _ NIL, -- runs that we are reading index: INT _ 0 -- index in runs ]; Create: PROC RETURNS [Ref]; SetPosition: PROC [reader: Ref, runs: Runs, index: INT _ 0]; SetIndex: PROC [reader: Ref, index: INT _ 0]; BackupIndex: PROC [reader: Ref, amount: INT]; BumpIndex: PROC [reader: Ref, amount: INT]; Position: PROC [reader: Ref] RETURNS [runs: Runs, index: INT]; GetRuns: PROC [reader: Ref] RETURNS [runs: Runs]; GetIndex: PROC [reader: Ref] RETURNS [index: INT]; ReaderProc: TYPE = PROC [reader: Ref] RETURNS [count: INT, looks: Looks]; InlineGet: ReaderProc = INLINE { current: NAT; base: Base; IF reader.changeLooks OR (current_reader.current) >= reader.after THEN {[count, looks] _ Get[reader]; 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; }; Get: ReaderProc; Backwards: ReaderProc; Peek: ReaderProc; PeekBackwards: ReaderProc; MergedGet: ReaderProc; MergedBackwards: ReaderProc; Equal: PROC [r1,r2: Runs, rdr1,rdr2: Ref] RETURNS [BOOL]; EqSubstrs: PROC [r1,r2: Runs, start1,start2,len: INT, rdr1,rdr2: Ref] RETURNS [BOOL]; GetRunReader: PROC RETURNS [reader: Ref]; FreeRunReader: PROC [reader: Ref]; END. ®RunReader.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. written by Bill Paxton, March 1981 last edit by Bill Paxton, December 22, 1981 2:02 pm Doug Wyatt, March 2, 1985 4:55:26 pm PST Michael Plass, March 21, 1985 1:39:20 pm PST RunReader provides fast sequential access to runs of Looks. designed for speed in reading a sequence of runs either forwards or backwards supports looks as defined by TextLooks.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 Inline version of Get, for the rare cases that the procedure call is too expensive. 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 -- merges adjacent runs with same looks -- regular Backwards may give same looks on successive calls -- e.g., if Concat[A,B] produces a concat-node -- and the last run in A has the same looks as the first in B -- Backwards will first return first from B, then last run from A -- MergedBackwards will combine these into a single result 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 ʘcodešœ™Kšœ Ïmœ1™K˜—š¡œžœžœ˜1K˜—š¡œžœžœ žœ˜2K˜—Kš œ žœžœžœ žœ˜IK˜š¡ œžœ˜ K™SKšœ žœ˜ K˜ šžœžœ)ž˜FKšœžœ˜'—K˜K˜Kšœžœ žœžœ+˜WK˜˜K˜——š¡œ ˜Kšœ'™'K˜—š¡ œ ˜Kšœ'™'K˜—š¡œ ˜Kšœ,™,K˜—š¡ œ ˜Kšœ+™+K˜—š¡ œ ˜Kšœ$™$šœ4™4šœ/™/Kšœ:™:Kšœ8™8Kšœ2™2K˜———š¡œ ˜Kš '™'š  œ  )™=š /™/Kš =™=Kš œ  5™AKš  œ  (™:———K™—šœ.™.K˜š¡œžœžœžœ˜9KšœF™FK˜—š¡ œžœ"žœ˜EKšžœžœ˜KšœF™Fšœ0™0Kšœ"™"—šœ5™5Kšœ7™7K˜——K™—šœR™RK˜Kš¡ œžœžœ˜)Kš¡ œžœ˜"K˜—Kšžœ˜—…—b%