LooksReader.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, March 1981
last edit by Bill Paxton, May 28, 1982 10:24 am
Doug Wyatt, March 2, 1985 5:01:18 pm PST
Michael Plass, March 21, 1985 2:04:00 pm PST
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
LooksReader:
CEDAR
DEFINITIONS
= BEGIN
Looks: TYPE = TextLooks.Looks;
noLooks: Looks = TextLooks.noLooks;
Runs: TYPE = TextLooks.Runs;
Ref: TYPE = REF Body;
Body:
TYPE =
PRIVATE
RECORD [
rem: INTEGER, -- 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];
create a reader for chars and looks
SetPosition:
PROC [reader: Ref, runs: Runs, index:
INT ← 0];
set position of reader
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];
return position of looks reader
GetRuns:
PROC [reader: Ref]
RETURNS [Runs];
GetIndex: PROC [reader: Ref] RETURNS [index: INT];
Get:
PROC [reader: Ref]
RETURNS [Looks];
InlineGet:
PROC [reader: Ref]
RETURNS [Looks] ~
INLINE {
IF (reader.rem←reader.rem-1) >= 0 THEN RETURN[reader.looks];
reader.rem←reader.rem+1; RETURN[Get[reader]];
};
Backwards:
PROC [reader: Ref]
RETURNS [Looks];
Peek:
PROC [reader: Ref]
RETURNS [Looks];
PeekBackwards: PROC [reader: Ref] RETURNS [Looks];
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
GetLooksReader:
PROC
RETURNS [Ref];
FreeLooksReader:
PROC[Ref];
END.