Copyright (C) 1994, Digital Equipment Corp.
INTERFACEMTextRd ; IMPORT Rd, MText, Thread; TYPE T <: Public; Public = Rd.T OBJECT METHODS init (m : MText.T := NIL; start : CARDINAL := 0; rangeStart: CARDINAL := 0; rangeEnd : CARDINAL := LAST (CARDINAL); reverse : BOOLEAN := FALSE ): T RAISES {Rd.Failure, Thread.Alerted} END;
rd.init(m, ...) initializes a seekable, non-intermittent reader for the
MText m.
It is intended that this method be called more than once, to re-initialize
a reader (and avoid re-allocating storage for rd.buff); in this case, it
is permitted for m to be NIL, and the default value is the MText that
was previously used by the reader.
The reader's source may be a proper subsequence of the underlying MText,
and the reader can be initialized to read in reverse order.
src(rd) comprises the characters of m that are contained in the
interval
[first(rd) .. last(rd)]
where
first(rd)) = rangeStart
and
last(rd) = MIN (rangeEnd, MText.Length(m)) - 1]
len(rd) = MAX (last(rd) - first(rd) + 1, 0)
In a forward reader (reverse = FALSE), Rd.GetChar delivers characters
from start to last(rd). Rd.Index returns the index relative to
first(rd). Hence just after a forward reader rd is initialized,
cur(rd) = start - first(rd)
In a reverse reader, Rd.GetChar delivers characters from start-1 (not
start) to first(rd). Rd.Index returns the index relative to
last(rd)+1. Hence just after a reverse reader rd is initialized,
cur(rd) = last(rd) + 1 - start
Thus the value returned by Rd.Index increases by 1 with each call to
Rd.GetChar, regardless of the reader's direction.
The coordinate system used by Rd.Seek is consistent with Rd.Index.
If the underlying MText is modified, the reader is invalid and should be
re-initialized.
rd.init calls Rd.Seek(rd, rd.cur), which can raise Rd.Failure or
Thread.Alerted.
Synchronization: it is not possible to have several readers reading the mtext concurrently. The reason is that a read to a file node causes the mtext data structure to change. If you don't use file nodes, then it's safe. (JRM doesn't believe this.)
PROCEDURE New (m : MText.T;
start : CARDINAL := 0;
rangeStart: CARDINAL := 0;
rangeEnd : CARDINAL := LAST (CARDINAL);
reverse : BOOLEAN := FALSE ): T
RAISES {Rd.Failure, Thread.Alerted};
This is equivalent to
NEW (T).init (m, start, rangeStart, rangeEnd, reverse, alertable)
END MTextRd.