LooksReader.mesa; written by Bill Paxton, March 1981
edited by Bill Paxton, May 27, 1983 2:14 pm
edited by McGregor, February 8, 1983 11:51 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 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
DIRECTORY
TiogaLooks,
RunReader;
LooksReader: CEDAR DEFINITIONS
IMPORTS RunReader =
BEGIN
Offset: TYPE = TiogaLooks.Offset;
Looks: TYPE = TiogaLooks.Looks;
noLooks: Looks = TiogaLooks.noLooks;
Runs: TYPE = TiogaLooks.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: RunReader.Ref -- reader for runs
];
Create: PROC [] RETURNS [Ref];
create a reader for chars and looks
SetPosition: PROC [reader: Ref, runs: Runs, index: Offset ← 0] =
INLINE {
set position of reader
reader.rem ← reader.len ← 0;
RunReader.SetPosition[reader.runreader, runs, index] };
SetIndex: PROC [reader: Ref, index: Offset ← 0] = INLINE {
reader.rem ← reader.len ← 0;
RunReader.SetIndex[reader.runreader, 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] =
return position of looks reader
INLINE { RETURN [GetRuns[reader], GetIndex[reader]] };
GetRuns: PROC [reader: Ref] RETURNS [Runs] = INLINE {
RETURN [RunReader.GetRuns[reader.runreader]] };
GetIndex: PROC [reader: Ref] RETURNS [index: Offset] = INLINE { RETURN [
RunReader.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: Offset;
[len, reader.looks] ← RunReader.Get[reader.runreader];
IF len > LAST[NAT] THEN {
RunReader.BackupIndex[reader.runreader,len-LAST[NAT]];
len ← LAST[NAT] };
reader.len ← rem ← 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: Offset;
[len, reader.looks] ← RunReader.Backwards[reader.runreader];
IF len > LAST[NAT] THEN {
RunReader.BumpIndex[reader.runreader,len-LAST[NAT]];
len ← LAST[NAT] };
reader.len ← 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] ← RunReader.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] ← RunReader.PeekBackwards[reader.runreader]
ELSE looks ← reader.looks;
RETURN [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.