RunReader.mesa
Copyright © 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
DIRECTORY
TextLooks USING [BaseRuns, Looks, noLooks, Runs];
RunReader: CEDAR DEFINITIONS
= BEGIN
***** RunReader Declarations
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: BOOLFALSE, -- 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
];
***** RunReader Operations
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 {
Inline version of Get, for the rare cases that the procedure call is too expensive.
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;
get run, then increment reader location
Backwards: ReaderProc;
decrement reader location, then get run
Peek: ReaderProc;
get run without incrementing reader location
PeekBackwards: ReaderProc;
like Backwards, but doesn't change position
MergedGet: ReaderProc;
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
MergedBackwards: ReaderProc;
-- 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
Equal: PROC [r1,r2: Runs, rdr1,rdr2: Ref] RETURNS [BOOL];
uses readers rdr1 and rdr2 to read runs r1 and r2 to test for equality
EqSubstrs: PROC [r1,r2: Runs, start1,start2,len: INT, rdr1,rdr2: Ref]
RETURNS [BOOL];
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
GetRunReader: PROC RETURNS [reader: Ref];
FreeRunReader: PROC [reader: Ref];
END.