<> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <<[runs, index] _ RunReader.Position[reader];>> <> <> <> <> <> <> <<[count, looks] _ RunReader.Get[reader];>> <> <> <> <> <<[count, looks] _ RunReader.Backwards[reader];>> <> <> <<[count, looks] _ RunReader.Peek[reader];>> <> <<[count, looks] _ RunReader.PeekBackwards[reader];>> <> <> <> 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: 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 ]; <<>> <<***** 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 { <> 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; <<-- 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>> <<>> <> Equal: PROC [r1,r2: Runs, rdr1,rdr2: Ref] RETURNS [BOOL]; <> EqSubstrs: PROC [r1,r2: Runs, start1,start2,len: INT, rdr1,rdr2: Ref] RETURNS [BOOL]; <> <> <> <> < size[r1] or start2+len > size[r2]>> <<>> <> GetRunReader: PROC RETURNS [reader: Ref]; FreeRunReader: PROC [reader: Ref]; END.