<> <> <> <> <> <> <<>> DIRECTORY LooksReader, RunReader; LooksReaderImpl: CEDAR MONITOR IMPORTS RunReader EXPORTS LooksReader = BEGIN OPEN LooksReader; Create: PUBLIC PROC [] RETURNS [new: Ref] = { <> new _ NEW[Body]; new^ _ [0,0,noLooks,RunReader.Create[]]; }; SetPosition: PUBLIC PROC [reader: Ref, runs: Runs, index: INT _ 0] = { reader.rem _ reader.len _ 0; RunReader.SetPosition[reader.runreader, runs, index] }; SetIndex: PUBLIC PROC [reader: Ref, index: INT _ 0] = { reader.rem _ reader.len _ 0; RunReader.SetIndex[reader.runreader, index] }; BackupIndex: PUBLIC PROC [reader: Ref, amount: INT] = { SetIndex[reader, GetIndex[reader]-amount] }; BumpIndex: PUBLIC PROC [reader: Ref, amount: INT] = { SetIndex[reader, GetIndex[reader]+amount] }; Position: PUBLIC PROC [reader: Ref] RETURNS [runs: Runs, index: INT] = { RETURN [GetRuns[reader], GetIndex[reader]] }; GetRuns: PUBLIC PROC [reader: Ref] RETURNS [Runs] = { RETURN [RunReader.GetRuns[reader.runreader]] }; GetIndex: PUBLIC PROC [reader: Ref] RETURNS [index: INT] = { RETURN [ RunReader.GetIndex[reader.runreader]-reader.rem] }; Get: PUBLIC PROC [reader: Ref] RETURNS [Looks] = { <> rem: NAT; IF (rem_reader.rem) = 0 THEN { -- go to the next run len: INT; [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: PUBLIC PROC [reader: Ref] RETURNS [Looks] = { <> rem: NAT; IF (rem_reader.rem) >= reader.len THEN { -- go to the previous run len: INT; [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: PUBLIC PROC [reader: Ref] RETURNS [Looks] = { <> looks: Looks; IF reader.rem = 0 THEN [,looks] _ RunReader.Peek[reader.runreader] ELSE looks _ reader.looks; RETURN [looks] }; PeekBackwards: PUBLIC PROC [reader: Ref] RETURNS [Looks] = { <> looks: Looks; IF reader.rem >= reader.len THEN [,looks] _ RunReader.PeekBackwards[reader.runreader] ELSE looks _ reader.looks; RETURN [looks] }; <<>> lksrdr1, lksrdr2, lksrdr3: Ref; -- shared looks readers GetLooksReader: PUBLIC ENTRY PROC RETURNS [reader: Ref] = { IF lksrdr3 # NIL THEN { reader _ lksrdr3; lksrdr3 _ NIL } ELSE IF lksrdr2 # NIL THEN { reader _ lksrdr2; lksrdr2 _ NIL } ELSE IF lksrdr1 # NIL THEN { reader _ lksrdr1; lksrdr1 _ NIL } ELSE reader _ Create[]; }; FreeLooksReader: PUBLIC ENTRY PROC [reader: Ref] = { SetPosition[reader, NIL]; IF lksrdr3 = reader OR lksrdr2 = reader OR lksrdr1 = reader THEN ERROR; IF lksrdr3 = NIL THEN lksrdr3 _ reader ELSE IF lksrdr2 = NIL THEN lksrdr2 _ reader ELSE IF lksrdr1 = NIL THEN lksrdr1 _ reader; }; END.